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
JC)oOA{}()9KIQ-b
literal 0
HcmV?d00001
diff --git a/sales/admin.py b/sales/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/sales/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/sales/apps.py b/sales/apps.py
new file mode 100644
index 0000000..354fa6c
--- /dev/null
+++ b/sales/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class SalesConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'sales'
diff --git a/sales/migrations/__init__.py b/sales/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/sales/migrations/__pycache__/__init__.cpython-39.pyc b/sales/migrations/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6aa84f3b7209584a94ec32e64f2ca32076b30d0d
GIT binary patch
literal 169
zcmYe~<>g`kg2d&vX(0MBh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wy*(xTqIJKxa
z#?Z*p&>+SozdSD|KQW~^#w9B;FFilrImkCYxU#q;HCHz`5l9uq6es4S7RTgfrWYla
kWaj4;$Hd2H=4F<|$LkeT-r}&y%}*)KNwovn^BIU400gxvqW}N^
literal 0
HcmV?d00001
diff --git a/sales/models.py b/sales/models.py
new file mode 100644
index 0000000..13abf4b
--- /dev/null
+++ b/sales/models.py
@@ -0,0 +1,66 @@
+from django.db import models
+
+
+# Create your models here.
+
+class ModelManager(models.Manager):
+ def get_queryset(self):
+ return super(ModelManager, self).get_queryset().filter(isValid=1)
+
+
+# 营销机会模型
+class SaleChance(models.Model):
+ # 信息来源
+ chanceSource = models.CharField(max_length=300, db_column='chance_source')
+ # 客户id
+ customerId = models.IntegerField(db_column='customer_id')
+ # 客户名称
+ customerName = models.CharField(max_length=100, db_column='customer_name')
+ # 成功几率
+ cgjl = models.IntegerField(db_column='cgjl')
+ # 概要
+ overview = models.CharField(max_length=300, db_column='overview')
+ # 联系人
+ linkMan = models.CharField(max_length=20, db_column='link_man')
+ # 联系电话
+ linkPhone = models.CharField(max_length=20, db_column='link_phone')
+ # 描述
+ description = models.CharField(max_length=1000, db_column='description')
+ # 创建人
+ createMan = models.CharField(max_length=20, db_column='create_man')
+ # 分配给谁
+ assignMan = models.CharField(max_length=20, db_column='assign_man')
+ # 分配时间
+ assignTime = models.DateTimeField(db_column='assign_time')
+ # 状态:1-如果有分配就是已分配状态,0-未分配
+ state = models.CharField(max_length=20, db_column='state')
+ # 开发状态:0=未开发 1=开发中 2=开完完成 3=开发失败
+ devResult = models.CharField(max_length=20, db_column='dev_result')
+ isValid = models.IntegerField(db_column='is_valid', default=1)
+ createDate = models.DateTimeField(db_column='create_date', auto_now_add=True)
+ updateDate = models.DateTimeField(max_length=20, db_column='update_date')
+ objects = ModelManager()
+
+ class Meta:
+ db_table = 't_sale_chance'
+
+
+# 客户计划模型
+class CusDevPlan(models.Model):
+ # 关联营销机会
+ saleChance = models.ForeignKey(SaleChance, db_constraint=False,
+ db_column='sale_chance_id',
+ on_delete=models.DO_NOTHING)
+ # 计划内容
+ planItem = models.CharField(max_length=300, db_column='plan_item')
+ # 计划时间
+ planDate = models.DateTimeField(max_length=20, db_column='plan_date')
+ # 执行效果
+ exeAffect = models.CharField(max_length=100, db_column='exe_affect')
+ isValid = models.IntegerField(db_column='is_valid')
+ createDate = models.DateTimeField(db_column='create_date')
+ updateDate = models.DateTimeField(max_length=20, db_column='update_date')
+ objects = ModelManager()
+
+ class Meta:
+ db_table = 't_cus_dev_plan'
diff --git a/sales/tests.py b/sales/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/sales/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/sales/urls.py b/sales/urls.py
new file mode 100644
index 0000000..3380bca
--- /dev/null
+++ b/sales/urls.py
@@ -0,0 +1,38 @@
+from django.urls import path, include
+from . import views
+
+app_name = 'sales'
+urlpatterns = [
+ path('index/', views.sales_index, name='sales_index'),
+ path('list/', views.select_sale_chance_list, name='select_sale_chance_list'),
+
+ # 添加/修改营销机会
+ path('create_or_update/', views.create_or_update_sales,
+ name='create_or_update_sales'),
+ path('customer/', views.select_customer, name='select_customer'),
+ path('create/', views.create_sale_chance, name='create_sale_chance'),
+ path('update/', views.update_sale_chance, name='update_sale_chance'),
+
+ # 删除营销机会
+ path('delete/', views.delete_sale_chance, name='delete_sale_chance'),
+
+ path('cus_dev_plan/index/', views.cus_dev_plan_index, name='cus_dev_plan_index'),
+
+ path('cus_dev_plan/detail/', views.cus_dev_plan_index_detail,
+ name='cus_dev_plan_index_detail'),
+ path('cus_dev_plan/list/', views.select_cus_dev_plan_list,
+ name='select_cus_dev_plan_list'),
+
+ # 添加/修改/删除开发计划
+ path('cus_dev_plan/create_or_update/', views.create_or_update_cus_dev_plan,
+ name='create_or_update_cus_dev_plan'),
+ path('cus_dev_plan/create/', views.create_cus_dev_plan,
+ name='create_cus_dev_plan'),
+ path('cus_dev_plan/update/', views.update_cus_dev_plan,
+ name='update_cus_dev_plan'),
+ path('cus_dev_plan/delete/', views.delete_cus_dev_plan,
+ name='delete_cus_dev_plan'),
+
+ path('cus_dev_plan/dev_result/', views.update_dev_result,
+ name='update_dev_result'),
+]
diff --git a/sales/views.py b/sales/views.py
new file mode 100644
index 0000000..c42f611
--- /dev/null
+++ b/sales/views.py
@@ -0,0 +1,319 @@
+from datetime import datetime
+
+from django.shortcuts import render
+import pymysql
+from django.core.paginator import Paginator
+from django.http import JsonResponse
+from django.shortcuts import render
+from django.views.decorators.clickjacking import xframe_options_exempt
+from django.views.decorators.csrf import csrf_exempt
+from django.views.decorators.http import require_GET
+
+from customer.models import Customer, LinkMan
+from sales.models import SaleChance, CusDevPlan
+from system.models import TUser
+
+
+@xframe_options_exempt
+@require_GET
+def sales_index(request):
+ """跳转营销管理首页"""
+ return render(request, 'sales/sale_chance.html')
+
+
+@require_GET
+def select_sale_chance_list(request):
+ try:
+ page_num = request.GET.get('page') # 页号
+ page_size = request.GET.get('limit') # 页容量
+
+ state = request.GET.get('state')
+ # 客户名称
+ customerName = request.GET.get('customerName')
+ # 创建人
+ createMan = request.GET.get('createMan')
+ # 开发状态(客户开发计划使用)
+ devResult = request.GET.get('devResult')
+
+ if customerName:
+ users = SaleChance.objects.filter(isValid=1, customerName=customerName).values()
+ elif createMan:
+ users = SaleChance.objects.filter(isValid=1, createMan=createMan).values()
+ elif state:
+ users = SaleChance.objects.filter(isValid=1, state=state).values()
+ elif devResult:
+ users = SaleChance.objects.filter(isValid=1, devResult=devResult).values()
+ else:
+ users = SaleChance.objects.filter(isValid=1).values()
+
+ paginator = Paginator(users, page_size)
+ users_list = paginator.page(page_num).object_list
+
+ context = {
+ 'code': 0,
+ 'msg': '',
+ 'count': len(users),
+ 'data': list(users_list)
+ }
+
+ return JsonResponse(context)
+
+ except Exception as e:
+ return JsonResponse({'code': 400, 'msg': 'error'})
+
+
+@xframe_options_exempt
+@require_GET
+def create_or_update_sales(request):
+ """跳转添加/修改营销机会页面"""
+ # 获取营销机会主键
+ saleChanceId = request.GET.get('saleChanceId')
+ context = None
+ if saleChanceId:
+ # 根据营销机会主键查询
+ sc = SaleChance.objects.get(pk=saleChanceId)
+ context = {'sc': sc}
+ return render(request, 'sales/add_update.html', context)
+
+
+@require_GET
+def select_customer(request):
+ """查询客户"""
+ customer = Customer.objects.values("id", 'name') \
+ .filter(isValid=1).order_by('-id').all()
+ return JsonResponse(list(customer), safe=False)
+
+
+@csrf_exempt
+@require_GET
+def create_sale_chance(request):
+ """添加营销机会和联系人"""
+ try:
+ # 接收参数
+ customerId = request.GET.get('customer')
+ customerName = request.GET.get('customerName')
+ chanceSource = request.GET.get('chanceSource')
+ linkMan = request.GET.get('linkMan')
+ linkPhone = request.GET.get('linkPhone')
+ cgjl = request.GET.get('cgjl')
+ overview = request.GET.get('overview')
+ description = request.GET.get('description')
+ assignMan = request.GET.get('assignMan')
+ # 如果有联系人还要添加联系人表数据
+ if linkMan:
+ lm = LinkMan(cusId=customerId, linkName=linkMan, phone=linkPhone)
+ lm.save()
+ # 如果有分配人,添加分配时间,分配状态为已分配
+ if assignMan != '0':
+ sc = SaleChance(customerId=customerId, customerName=customerName,
+ chanceSource=chanceSource, linkMan=linkMan,
+ linkPhone=linkPhone,
+ cgjl=cgjl, overview=overview, description=description,
+ assignMan=assignMan, assignTime=datetime.now(), state=1,
+ devResult=0,
+ createMan=request.session.get('user')['username'])
+ else:
+ sc = SaleChance(customerId=customerId, customerName=customerName,
+ chanceSource=chanceSource, linkMan=linkMan,
+ linkPhone=linkPhone,
+ cgjl=cgjl, overview=overview, description=description,
+ state=0, devResult=0,
+ createMan=request.session.get('user')['username'])
+ # 插入数据
+ sc.save()
+ # 返回提示信息
+ return JsonResponse({'code': 200, 'msg': '添加成功'})
+ except Exception as e:
+ return JsonResponse({'code': 400, 'msg': '添加失败'})
+
+
+@csrf_exempt
+@require_GET
+def update_sale_chance(request):
+ """修改营销机会和联系人"""
+ try:
+ # 接收参数
+ id = request.GET.get('id')
+ customerId = request.GET.get('customer')
+ customerName = request.GET.get('customerName')
+ chanceSource = request.GET.get('chanceSource')
+ linkMan = request.GET.get('linkMan')
+ linkPhone = request.GET.get('linkPhone')
+ cgjl = request.GET.get('cgjl')
+ overview = request.GET.get('overview')
+ description = request.GET.get('description')
+ assignMan = request.GET.get('assignMan')
+ # 根据主键查询营销机会
+ sc = SaleChance.objects.get(pk=id)
+ # 如果有联系人还要修改联系人表数据
+ if linkMan != sc.linkMan:
+ LinkMan.objects.filter(cusId=customerId) \
+ .update(linkName=linkMan, phone=linkPhone, updateDate=datetime.now())
+ # 如果用户取消了分配人,要改变分配状态为未分配
+ if assignMan == '0':
+ sc.state = 0
+ sc.assignMan = None
+ sc.assignTime = None
+ else:
+ sc.state = 1
+ sc.assignMan = assignMan
+ sc.assignTime = datetime.now()
+ # 重新赋值
+ sc.customerId = customerId
+ sc.customerName = customerName
+ sc.chanceSource = chanceSource
+ sc.linkMan = linkMan
+ sc.linkPhone = linkPhone
+ sc.cgjl = cgjl
+ sc.overview = overview
+ sc.description = description
+ sc.updateDate = datetime.now()
+ # 保存
+ sc.save()
+ # 返回提示信息
+ return JsonResponse({'code': 200, 'msg': '修改成功'})
+ except Exception as e:
+ return JsonResponse({'code': 400, 'msg': '修改失败'})
+
+
+@csrf_exempt
+@require_GET
+def delete_sale_chance(request):
+ """删除营销机会"""
+ try:
+ # 接收参数
+ ids = request.GET.get('ids')
+ id_list = list(map(int, ids.split(",")))
+ SaleChance.objects.filter(pk__in=id_list).delete()
+
+ return JsonResponse({'code': 200, 'msg': '删除成功'})
+ except Exception as e:
+ return JsonResponse({'code': 400, 'msg': '删除失败'})
+
+
+@xframe_options_exempt
+@require_GET
+def cus_dev_plan_index(request):
+ """跳转营销机会管理首页"""
+ return render(request, 'sales/cus_dev_plan.html')
+
+
+@xframe_options_exempt
+@require_GET
+def cus_dev_plan_index_detail(request):
+ """跳转客户开发计划详情页"""
+ # 接收参数
+ saleChanceId = request.GET.get('saleChanceId')
+ # 根据主键查询营销机会
+ sc = SaleChance.objects.get(pk=saleChanceId)
+ context = {'sc': sc}
+ return render(request, 'sales/cus_dev_plan_detail.html', context)
+
+
+@require_GET
+def select_cus_dev_plan_list(request):
+ """查询客户开发计划详细列表"""
+ try:
+ # 获取第几页
+ page_num = request.GET.get('page', 1)
+ # 获取每页多少条
+ page_size = request.GET.get('limit', 10)
+ # 获取客户营销机会主键
+ saleChanceId = request.GET.get('saleChanceId')
+ # 查询
+ cdp_list = CusDevPlan.objects.extra(select={'planDate': 'date_format(plan_date, "%%Y-%%m-%%d")'}) \
+ .values('id', 'planItem', 'planDate', 'exeAffect', 'saleChance') \
+ .filter(saleChance=saleChanceId).order_by('-id')
+ # 初始化分页对象
+ p = Paginator(cdp_list, page_size)
+ # 获取指定页数的数据
+ data = p.page(page_num).object_list
+ # 返回总条数
+ count = p.count
+ # 返回数据,按照 layuimini 要求格式构建
+ context = {
+ 'code': 0,
+ 'msg': '',
+ 'count': count,
+ 'data': list(data)
+ }
+ return JsonResponse(context)
+ except Exception as e:
+ return JsonResponse({'code': 400, 'msg': 'error'})
+
+
+@xframe_options_exempt
+@require_GET
+def create_or_update_cus_dev_plan(request):
+ """跳转客户开发计划添加/修改页面"""
+ # 获取营销机会主键
+ saleChanceId = request.GET.get('saleChanceId')
+ # 获取客户开发计划主键
+ id = request.GET.get('id')
+ context = {'saleChanceId': saleChanceId}
+ if id:
+ cusDevPlan = CusDevPlan.objects.get(pk=id)
+ context['cusDevPlan'] = cusDevPlan
+ return render(request, 'sales/cus_dev_plan_add_update.html', context)
+
+
+@csrf_exempt
+@require_GET
+def create_cus_dev_plan(request):
+ """添加客户开发计划"""
+ # 接收参数
+ data = request.GET.dict()
+ # 弹出营销机会主键
+ saleChanceId = data.pop('saleChanceId')
+ # 删除主键
+ del data['id']
+ # 获取营销机会对象
+ sc = SaleChance.objects.get(pk=saleChanceId)
+ data['saleChance'] = sc
+ # 添加客户开发计划
+ CusDevPlan.objects.create(**data)
+ # 修改营销机会的开发状态为开发中
+ sc.devResult = 1
+ sc.updateDate = datetime.now()
+ sc.save()
+ return JsonResponse({'code': 200, 'msg': '添加成功'})
+
+
+@csrf_exempt
+@require_GET
+def update_cus_dev_plan(request):
+ """修改客户开发计划"""
+ # 接收参数
+ data = request.GET.dict()
+ # 弹出营销机会主键
+ saleChanceId = data.pop('saleChanceId')
+ # 删除主键
+ id = data.pop('id')
+ # 修改时间
+ data['updateDate'] = datetime.now()
+ # 修改客户开发计划
+ CusDevPlan.objects.filter(pk=id).update(**data)
+ return JsonResponse({'code': 200, 'msg': '修改成功'})
+
+
+@csrf_exempt
+@require_GET
+def delete_cus_dev_plan(request):
+ """删除客户开发计划"""
+ # 获取主键
+ id = request.GET.get('id')
+ # 逻辑删除客户开发计划
+ CusDevPlan.objects.filter(pk=id).update(isValid=0, updateDate=datetime.now())
+ return JsonResponse({'code': 200, 'msg': '删除成功'})
+
+
+@csrf_exempt
+@require_GET
+def update_dev_result(request):
+ """开发成功或者开发失败"""
+ # 接收参数
+ saleChanceId = request.GET.get('saleChanceId')
+ devResult = request.GET.get('devResult')
+ SaleChance.objects.filter(pk=saleChanceId).update(devResult=devResult,
+ updateDate=datetime.now())
+ return JsonResponse({'code': 200, 'msg': '操作成功'})
diff --git a/serve/__init__.py b/serve/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/serve/__pycache__/__init__.cpython-39.pyc b/serve/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6110a856d98172096be528c3ed00149bc2e2a317
GIT binary patch
literal 158
zcmYe~<>g`kf)n%lQb6=$5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!HsvsFxJacWU<
zjG>XGp+SsGetBL_equ^-j7wHxUV47KbC7R*aAk2xYOZc>B9JPI0je%bjfs!X%*!l^
ZkJl@xyv1RYo1apelWGSt{4)?U004ufCb<9r
literal 0
HcmV?d00001
diff --git a/serve/__pycache__/admin.cpython-39.pyc b/serve/__pycache__/admin.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..904df5ff9a3978aa8093daf6aa0b9487e13d6f98
GIT binary patch
literal 199
zcmYe~<>g`kf)n%lQtW~BV-N=!FabFZKwK;UBvKes7;_kM8KW2(8B&;n88n$+0!0}#
z8E>&BrsQVk`Drpm@ug%X=B4NBCFkdr6lEqAfecv5P{a(Rz{D>HXRDad;?$zz7(*jV
zLxUKX{PMh<{KS;v7#Fb4c;_JB_~6RolGI$?+(aN%6a!RUmKp=LLa(6m7Kcr4eoARh
NsvRTH(9b~3008l5G6Mhr
literal 0
HcmV?d00001
diff --git a/serve/__pycache__/apps.cpython-39.pyc b/serve/__pycache__/apps.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..675367ec3eab5099eea2f3775f5e93ba82399f2f
GIT binary patch
literal 433
zcmYjNy-ve05Vqq~D*agyD-vr4BFY9r(9#MfI#97hku1YGQIYdQ+a1+5=Mv4FdsQCW_QJej8tRM{4e$q?1&3)cfrh#zX&2I=9_+3X_{5Lzy^l}tJu>a}x&)rzfB8xL+$Q7?
z1nW-#;28{!LJ&a=f7U~8Mi!Vqe??bjP8O8ni3-t_iyfy?kFhfL?xZ
z?Xi9F5E|!W+dG_VQ}
z;E~I#{7>jT8)Xg8@*%iE^O@AhB^HKlBWIpTt|YXeHmsK^30gjr)vS<9fesOLUp}5n
zWw+`XH+d-&s&`}f^Z>-F$pmG-@bJXG9&RN5
z;8>cJ4GdqUk>k(ElO#}m@K@U?kjX|+4wIf2a;^W}Nx=TM0rEV8+3Em%0`rsP-g_(x
z&!z1gzD(8Exhw?hxb0p**%jV1Y7fOe2-a`1dfF5(uJiKT)lT8{W_w4NBS^R7vfa9X
zxWMAZ`?;&zszMIc3~aD&;e0l%PF=;6YpVF$sgZC;x@}Yox9--_U;wsTmjmbZt=F#3
zCo(fyVG=%+E;R%N=2w3TBJ%nhZwx4;-anxqH{U+3-_UcOCrJpW!`+Do;=ImjySc~f
d2wLvmbH*Rq-$q~5_uZG+Ejk1d2eCg4{{`#a!K(lO
literal 0
HcmV?d00001
diff --git a/serve/__pycache__/urls.cpython-39.pyc b/serve/__pycache__/urls.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c7a0a631c99498080b94b34523739180fdceb3e2
GIT binary patch
literal 534
zcmZ9JO-=$a6o6Z1h8Y+@SeSSP7Bb>aLeK=Zx{$ablT0SOieTp_?Eo@&&?C6_1YW^2
zbnA*M=*CxOOpI;%`o7op{WWYh>jcNg>kGV7LOwP89W{h2Tylj12vANUI-`_81q@z^
zjG2MDIWrjriy12ms$f4GNDfjJY9-Z?Y;a3zAUV)1sfAR7BTWlyR)_YKbUS;DN4iv*
zX_!6iF*Oa=X34fvS(1qj%a4aL6N8LJDGxI?@|H2MCr`PD)8IhbK^#UbxA;dgt$G|+j8Dxz?-(47|gGlYvmx%dc6&zOki8xd`NpvBkac;Me*X43DU
zU-ZxXNwST35`y$6hiJk0_BxpEB=+Sr3UL$up$=bX(MxyA8Ab`LIUDJwO6{{j8x_-N
I(QpF
literal 0
HcmV?d00001
diff --git a/serve/__pycache__/views.cpython-39.pyc b/serve/__pycache__/views.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..03749bd00e2dcdaf2c66269da5b923078fad9b88
GIT binary patch
literal 3025
zcmai0-H#l_5ufgvot>SX-TO4b{MU=cnHiGVl`!Lkh~k_qx%6nS;hXqoOi&)&?=
zrhC@+q1h2#7@uKd^k+fi33%kkAeg~OWW+|(AgI%b#I#AZZboKo
zH7%`MQ7N{Y_W$Ums2n>@N89bF61z=T>*c5#dreR4PE?EQ%{no-!#!4E?nPsRY>?&{
zw5rU*R&!kYYOG%PCb$dUF*aVbCv|&*O&0AbHZ^B7ruQHMqd}CzS}9M%n1fzGM?{cT;dw11T0qnu7nL7Ygn_
zb$TAWwUa%WCNURtTwLG*#RU{U6W)mJNqFR85R7C-+t?wD4hSO$jga(dN;89*8M(vA
z=!OX~SUv1|?SuEOU4CnKdvo~W;OaYrt6RSrZe6_c;opWYzIJWn^4?$mxHouTIX%fm
z2Nta?)YfYtF7O9uX`7y(eK93-8Tucns_
zF#(-Ef8yk^g`dG>a^azefAG-Jg;U8&CrVmOE}Uw&I!lRv^6VLZZcV}jN8%Q|#Df0x
z!iA8p$l30is_M2M0=TQ=Fr`Ew3~SmJQ}7N5wu)a3-k6{oCdd$D{nG*_1d8^rgJv=d
zT9lQT&C1MSm2InUrnGIgt;}TZCfO+sj2)X*2V|!_F#1+8i#H(sQdSZyv)WEpVzo_j
z!&e8No!R17+Gn$|5#KoY%2`=#YhRg7pf9at7HkylJDIcNW@JFx)qW*&+FsvflWZz;
z(^^*9AZ!{|S550#b%Xren1eh>$F|5C6igpNT)!)=vjgl7_O)$_e%m-_usi$SFTJ_q
zebhJ#8l=O)-u-~h@Pjw6T;AS&|JPUl`nxM1zCC>7703lhfxSP!e)W}$!{^@`KL76S
zYj0lr`|HZ;wwCxF0<20=7>DT|g1df9@`wlN-KS2>pZ1^p>De0>i9Aw2R>WBtTFV{w1OfcssMfc(lS_WOJwI3%BsrTV3x-*0TM
zi^INhY{OD+9_2g)sm6;{KZ}dj7B^qSDXaoFpA>auhCJwX^GL{4Nv7H=zKOUxK~eJ!
z(ww@k`+kU3)CxONRdn{xuXSM}@og9)^nO5bD=SDCS7t1iR4GV$om5#6Nh{of9;(EJ
zNW>*7?!hsKKs?hJS0*rxz$y_H5UQL!*M^;x(0er%EoEP5MNrSmNdz#N|J<4~TT!I!
z#V~@x6v#qi8V6SMfqoRqRD1_5mR7MeRps<*z%}(XYNC!72NTKf^kP-fnhe)@6Y3h%
z$Y)^y1OhxF)+A61!Xmzf0;5%=E0DzWM+BC?B3v^|E+)}3QOuMR1ug_9k&lBgOiJst
zZc?KE|FP{!LjUVn9T>T0Otx=r4&UCotvrXny}bK}e+Vo_Q3auB
z$Sx5@yUU6Oa(znU0Nm|sC1-G3c-UR<{k^DR0*L!iXfn6-P6;^F4Gpt+6g8yq5uoci
z!YhebUW}5JGvJlD3SeW65<@TVP;N1dvcS!&7!%mjV~jpm~^w
zLBBmXuOJZ}<2mRcZ4gGur4ZJSLAxa^ob5(f88mK&m609FfX@3AG!su~Oao>vQ}O-O
z!lNZ4%sOs#rombQ>(e)^Hl)V&9%az&b{P&D%A8HouG|8Yi?cC*xi>m@qp040$#`;svN`V4>jDV
zYK+B?&}ep(Zk|xM$I9#^D>q>mn9s`2c`(O5Pca}syjtY>rHlQxB=ZVF*4-G)B9U@%
zAMo#xIy_jqcM=k3;q2AOkXHwgGBIIpqc!lrb$ax3*Y%P?drv-@xmg{Cn61c
zsnlhl4j1P9_Q5zzhSxng8$@BS+-?QSVP{ETVyJKY->z`U6Xh@MqSxU-m!_w~oQ;9X
zBbmd8*BZ?{x|nq8=}1QsRzs$_&p8f5dl7#ej|KSv2*hUOPrVXSpI4>CeNbzzmKBs=
E04>opSpWb4
literal 0
HcmV?d00001
diff --git a/serve/admin.py b/serve/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/serve/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/serve/apps.py b/serve/apps.py
new file mode 100644
index 0000000..4737b95
--- /dev/null
+++ b/serve/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class ServeConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'serve'
diff --git a/serve/migrations/__init__.py b/serve/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/serve/migrations/__pycache__/__init__.cpython-39.pyc b/serve/migrations/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d3ccb2711fcd2e04acf77888267f5f9a466162b0
GIT binary patch
literal 169
zcmYe~<>g`kg2d&vX(0MBh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wy*(xTqIJKxa
z#?Z*p&>+SozdSD|KQW~^#w9B;FFilrImkCYxU#q;HCHz`5l9uq09BWz#^h$E7bTWt
j=I0g1#K&jmWtPOp>lIYq;;_lhPbtkwwFBAn8HgDG2MsE)
literal 0
HcmV?d00001
diff --git a/serve/models.py b/serve/models.py
new file mode 100644
index 0000000..e34cee6
--- /dev/null
+++ b/serve/models.py
@@ -0,0 +1,49 @@
+from django.db import models
+
+# Create your models here.
+
+from django.db import models
+
+
+class ModelManager(models.Manager):
+ def get_queryset(self):
+ return super(ModelManager, self).get_queryset().filter(isValid=1)
+
+
+# 服务模型
+class CustomerServe(models.Model):
+ # 服务类型 咨询/建议/投诉
+ serveType = models.CharField(db_column='serve_type', max_length=50)
+ # 概要
+ overview = models.CharField(db_column='overview', max_length=500)
+ # 客户
+ customer = models.CharField(db_column='customer', max_length=30)
+ # 新创建/已分配/已处理/已归档
+ state = models.CharField(db_column='state', max_length=10)
+ # 服务请求
+ serviceRequest = models.CharField(db_column='service_request', max_length=500)
+ # 创建人
+ createPeople = models.CharField(db_column='create_people', max_length=100)
+ # 分配人
+ assigner = models.CharField(db_column='assigner', max_length=100)
+ # 分配日期
+ assignTime = models.DateTimeField(db_column='assign_time')
+ # 服务处理
+ serviceProce = models.CharField(db_column='service_proce', max_length=500)
+ # 服务处理人
+ serviceProcePeople = models.CharField(db_column='service_proce_people',
+ max_length=50)
+ # 服务处理日期
+ serviceProceTime = models.DateTimeField(db_column='service_proce_time')
+ # 服务处理结果
+ serviceProceResult = models.CharField(db_column='service_proce_result',
+ max_length=500)
+ # 客户满意度
+ myd = models.CharField(db_column='myd', max_length=50)
+ isValid = models.IntegerField(db_column='is_valid', default=1)
+ createDate = models.DateTimeField(db_column='create_date', auto_now_add=True)
+ updateDate = models.DateTimeField(db_column='update_date', auto_now_add=True)
+ objects = ModelManager()
+
+ class Meta:
+ db_table = 't_customer_serve'
diff --git a/serve/tests.py b/serve/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/serve/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/serve/urls.py b/serve/urls.py
new file mode 100644
index 0000000..f1c4cfc
--- /dev/null
+++ b/serve/urls.py
@@ -0,0 +1,12 @@
+from django.urls import path
+from . import views
+
+app_name = 'serve'
+
+urlpatterns = [
+ path('/index/', views.serve_index, name='serve_index'),
+ path('list/', views.select_serve_list, name='select_serve_list'),
+ path('/workflow/', views.serve_workflow, name='serve_workflow'),
+ path('create/', views.create_serve, name='create_serve'),
+ path('update/', views.update_serve, name='update_serve'),
+]
diff --git a/serve/views.py b/serve/views.py
new file mode 100644
index 0000000..aaaf23e
--- /dev/null
+++ b/serve/views.py
@@ -0,0 +1,121 @@
+from datetime import datetime
+
+from django.core.paginator import Paginator
+from django.http import JsonResponse
+from django.shortcuts import render
+from django.shortcuts import render
+from django.views.decorators.clickjacking import xframe_options_exempt
+from django.views.decorators.csrf import csrf_exempt
+from django.views.decorators.http import require_GET
+
+from serve.models import CustomerServe
+
+
+# Create your views here.
+
+@xframe_options_exempt
+@require_GET
+def serve_index(request, template):
+ """跳转服务管理各个功能首页"""
+ context = {'username': request.session.get('user')['username']}
+ '''
+ create 创建 assign 分配
+ handle 处理
+ feedback 反馈 archive 归档
+ '''
+ return render(request, 'serve/%s.html' % template, context)
+
+
+@require_GET
+def select_serve_list(request):
+ """工作流程中多个页面的公共查询"""
+ try:
+ # 获取第几页
+ page_num = request.GET.get('page', 1)
+ # 获取每页多少条
+ page_size = request.GET.get('limit', 10)
+ # 查询
+ select_dict = {
+ 'assignTime': 'select DATE_FORMAT(assign_time, "%%Y-%%m-%%d-%%H:%%i:%%s")',
+ 'serviceProceTime': 'select DATE_FORMAT(service_proce_time, "%%Y-%%m-%%d-%%H:%%i:%%s")',
+ 'createDate': 'select DATE_FORMAT(create_date, "%%Y-%%m-%%d-%%H:%%i:%%s")',
+ 'updateDate': 'select DATE_FORMAT(update_date, "%%Y-%%m-%%d-%%H:%%i:%%s")',
+ }
+ queryset = CustomerServe.objects.extra(select=select_dict) \
+ .values().order_by('-id').all()
+ # 条件查询
+ # 服务状态:1 新创建 / 2 已分配 / 3 已处理 / 4 已反馈
+ state = request.GET.get('state')
+ if state:
+ queryset = queryset.filter(state=state)
+ # 客户
+ customer = request.GET.get('customer')
+ if customer:
+ queryset = queryset.filter(customer__icontains=customer)
+ # 服务类型:6 咨询 / 7 投诉 / 8 建议
+ serveType = request.GET.get('serveType')
+ if serveType:
+ queryset = queryset.filter(serveType=serveType)
+ # 初始化分页对象
+ p = Paginator(queryset, page_size)
+ # 获取指定页数的数据
+ data = p.page(page_num).object_list
+ # 返回总条数
+ count = p.count
+ # 返回数据,按照 layuimini 要求格式构建
+ context = {
+ 'code': 0,
+ 'msg': '',
+ 'count': count,
+ 'data': list(data)
+ }
+ return JsonResponse(context)
+ except Exception as e:
+ return JsonResponse({'code': 400, 'msg': 'error'})
+
+
+@xframe_options_exempt
+@require_GET
+def serve_workflow(request, template):
+ """工作流程中多个子页面的公共函数"""
+ context = {'username': request.session.get('user')['username']}
+ # 获取服务主键
+ id = request.GET.get('id')
+ if id:
+ context['cs'] = CustomerServe.objects.get(pk=id)
+ return render(request, 'serve/%s_serve.html' % template, context)
+
+
+@csrf_exempt
+@require_GET
+def create_serve(request):
+ """创建服务"""
+ # 接收参数
+ data = request.GET.dict()
+ # 添加
+ CustomerServe.objects.create(**data)
+ return JsonResponse({'code': 200, 'msg': '创建成功'})
+
+
+@csrf_exempt
+@require_GET
+def update_serve(request):
+ """修改服务公共函数"""
+ # 接收参数
+ serve = request.GET.dict()
+ # 弹出主键
+ id = serve.pop('id')
+ # 获取分配状态
+ state = serve.get('state')
+ # 如果是 2 已分配,修改分配时间
+ if state == '2':
+ serve['assignTime'] = datetime.now()
+ # 如果是 3 已处理,修改处理时间
+ elif state == '3':
+ serve['serviceProceTime'] = datetime.now()
+ # 当条记录修改时间
+ serve['updateDate'] = datetime.now()
+ CustomerServe.objects.filter(pk=id).update(**serve)
+ return JsonResponse({'code': 200, 'message': '操作成功'})
+
+