使用自己的stark组件实现crm系统

因为stark用到了templates里面的html页面文件,所以要整合在一个app里,在stark里面创建名字为templates的Python Package,将之前的html页面拷贝在stark组件里面的templates里面,然后拷贝stark组件

二、实现crm逻辑

CRM即客户关系管理,是指企业用CRM技术来管理与客户之间的关系

1、创建数据库

在app01应用下的models.py文件:

from django.db import models
class Department(models.Model):
    """
    部门表
    市场部     1000
    销售       1001
    """
    title = models.CharField(verbose_name='部门名称', max_length=16)
    code = models.IntegerField(verbose_name='部门编号', unique=True, null=False)
    def __str__(self):
        return self.title
class UserInfo(models.Model):
    """
    员工表
    """
    name = models.CharField(verbose_name='员工姓名', max_length=16)
    email = models.EmailField(verbose_name='邮箱', max_length=64)
    depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="code")
    def __str__(self):
        return self.name
class Course(models.Model):
    """
    课程表
    如:
        Linux基础
        Linux架构师
        Python自动化开发精英班
        Python自动化开发架构师班
        Python基础班
go基础班
    """
    name = models.CharField(verbose_name='课程名称', max_length=32)
    def __str__(self):
        return self.name
class School(models.Model):
    """
    校区表
    如:
        北京沙河校区
        上海校区
    """
    title = models.CharField(verbose_name='校区名称', max_length=32)
    def __str__(self):
        return self.title
class ClassList(models.Model):
    """
    班级表
    如:
        Python全栈  面授班  5期  10000  2017-11-11  2018-5-11
    """
    school = models.ForeignKey(verbose_name='校区', to='School')
    course = models.ForeignKey(verbose_name='课程名称', to='Course')
    semester = models.IntegerField(verbose_name="班级(期)")
    price = models.IntegerField(verbose_name="学费")
    start_date = models.DateField(verbose_name="开班日期")
    graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)
    memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True, )
    # teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart_id__in':[1003,1004],})
    teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo', related_name="abc",
                         limit_choices_to={"depart_id__in":[1002,1003]}             )
    tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',
                              limit_choices_to={"depart": 1005})
    def __str__(self):
        return "{0}({1}期)".format(self.course.name, self.semester)
class Customer(models.Model):
    """
    客户表
    """
    qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一')
    name = models.CharField(verbose_name='学生姓名', max_length=16)
    gender_choices = ((1, '男'), (2, '女'))
    gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)
    education_choices = (
        (1, '重点大学'),
        (2, '普通本科'),
        (3, '独立院校'),
        (4, '民办本科'),
        (5, '大专'),
        (6, '民办专科'),
        (7, '高中'),
        (8, '其他')
    )
    education = models.IntegerField(verbose_name='学历', choices=education_choices, blank=True, null=True, )
    graduation_school = models.CharField(verbose_name='毕业学校', max_length=64, blank=True, null=True)
    major = models.CharField(verbose_name='所学专业', max_length=64, blank=True, null=True)
    experience_choices = [
        (1, '在校生'),
        (2, '应届毕业'),
        (3, '半年以内'),
        (4, '半年至一年'),
        (5, '一年至三年'),
        (6, '三年至五年'),
        (7, '五年以上'),
    ]
    experience = models.IntegerField(verbose_name='工作经验', blank=True, null=True, choices=experience_choices)
    work_status_choices = [
        (1, '在职'),
        (2, '无业')
    ]
    work_status = models.IntegerField(verbose_name="职业状态", choices=work_status_choices, default=1, blank=True,
                                      null=True)
    company = models.CharField(verbose_name="目前就职公司", max_length=64, blank=True, null=True)
    salary = models.CharField(verbose_name="当前薪资", max_length=64, blank=True, null=True)
    source_choices = [
        (1, "qq群"),
        (2, "内部转介绍"),
        (3, "官方网站"),
        (4, "百度推广"),
        (5, "360推广"),
        (6, "搜狗推广"),
        (7, "腾讯课堂"),
        (8, "广点通"),
        (9, "高校宣讲"),
        (10, "渠道代理"),
        (11, "51cto"),
        (12, "智汇推"),
        (13, "网盟"),
        (14, "DSP"),
        (15, "SEO"),
        (16, "其它"),
    ]
    source = models.SmallIntegerField('客户来源', choices=source_choices, default=1)
    referral_from = models.ForeignKey(
        'self',
        blank=True,
        null=True,
        verbose_name="转介绍自学员",
        help_text="若此客户是转介绍自内部学员,请在此处选择内部学员姓名",
        related_name="internal_referral"
    )
    course = models.ManyToManyField(verbose_name="咨询课程", to="Course")
    status_choices = [
        (1, "已报名"),
        (2, "未报名")
    ]
    status = models.IntegerField(
        verbose_name="状态",
        choices=status_choices,
        default=2,
        help_text=u"选择客户此时的状态"
    )
    consultant = models.ForeignKey(verbose_name="课程顾问", to='UserInfo', related_name='consultanter',
                                   limit_choices_to={'depart_id': 1001})
    date = models.DateField(verbose_name="咨询日期", auto_now_add=True)
    recv_date = models.DateField(verbose_name="当前课程顾问的接单日期", null=True)
    last_consult_date = models.DateField(verbose_name="最后跟进日期", )
    def __str__(self):
        return self.name
class ConsultRecord(models.Model):
    """
    客户跟进记录
    """
    customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer')
    consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo',limit_choices_to={"depart_id":1001})
    date = models.DateField(verbose_name="跟进日期", auto_now_add=True)
    note = models.TextField(verbose_name="跟进内容...")
    def __str__(self):
        return self.customer.name + ":" + self.consultant.name
class Student(models.Model):
    """
    学生表(已报名)
    """
    customer = models.OneToOneField(verbose_name='客户信息', to='Customer')
    emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人')
    class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True)
    company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True)
    location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True)
    position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True)
    salary = models.IntegerField(verbose_name='薪资', blank=True, null=True)
    welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True)
    date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True)
    memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True)
    def __str__(self):
        return str(self.customer)
class ClassStudyRecord(models.Model):
    """
    上课记录表 (班级记录)
    """
    class_obj = models.ForeignKey(verbose_name="班级", to="ClassList")
    day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")
    teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo', limit_choices_to={"depart_id__in": [1002, 1003]})       #过滤id为1002和1003的部门
    date = models.DateField(verbose_name="上课日期", auto_now_add=True)
    course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True)
    course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True)
    has_homework = models.BooleanField(default=True, verbose_name="本节有作业")
    homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True)
    homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True)
    exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True)
    def __str__(self):
        return "{0} day{1}".format(self.class_obj, self.day_num)
class StudentStudyRecord(models.Model):
    '''
    学生记录
    '''
    class_study_record = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord")
    student = models.ForeignKey(verbose_name="学员", to='Student')
    record_choices = (('checked', "已签到"),
                      ('vacate', "请假"),
                      ('late', "迟到"),
                      ('noshow', "缺勤"),
                      ('leave_early', "早退"),
                      )
    record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64)
    score_choices = ((100, 'A+'),
                     (90, 'A'),
                     (85, 'B+'),
                     (80, 'B'),
                     (70, 'B-'),
                     (60, 'C+'),
                     (50, 'C'),
                     (40, 'C-'),
                     (0, ' D'),
                     (-1, 'N/A'),
                     (-100, 'COPY'),
                     (-1000, 'FAIL'),
                     )
    score = models.IntegerField("本节成绩", choices=score_choices, default=-1)
    homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True)
    note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True)
    homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None)
    stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True)
    date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True)
    def __str__(self):
        return "{0}-{1}".format(self.class_study_record, self.student)
        
        
        
#数据库实例化,使用下面的命令
#python3 manage.py makemigrations
#python3 manage.py migrate

2、相关项目设置

settings.py文件设置内容:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    "stark.apps.StarkConfig"
]
STATIC_URL = '/static/'
STATICFILES_DIRS= [
    os.path.join(BASE_DIR,"static")
]

注:

#static目录下面是Highcharts-6.1.0,是显示后面的柱形图所需的插件

#下载地址: https://www.hcharts.cn/download

3、逻辑部分及显示页面

urls.py文件:

from django.conf.urls import url
from django.contrib import admin
from stark.service.sites import site
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^stark/', site.urls),
]

stark组件service目录下sites.py文件:

from django.conf.urls import url
from django.shortcuts import HttpResponse, render, redirect
from django.utils.safestring import mark_safe
from django.urls import reverse
class Show_List(object):
    def __init__(self, config, data_list):
        self.config = config
        self.data_list = data_list
    def get_header(self):
        # 处理表头
        # header_list=["ID","名称","价格"]
        header_list = []
        for field in self.config.new_list_display():
            if isinstance(field, str):
                if field == "__str__":
                    val = self.config.model._meta.model_name.upper()
                else:
                    field_obj = self.config.model._meta.get_field(field)
                    val = field_obj.verbose_name
            else:
                val = field(self.config, is_header=True)
            header_list.append(val)
        return header_list
    def get_body(self):
        # 处理表单数据
        new_data_list = []
        for obj in self.data_list:
            temp = []
            for field in self.config.new_list_display():  # ["nid","title","price","authors",edit]    ['__str__']     ["title","price"]
                if isinstance(field, str):
                    try:
                        from django.db.models.fields.related import ManyToManyField
                        field_obj = self.config.model._meta.get_field(field)
                        if isinstance(field_obj, ManyToManyField):
                            l = []
                            for i in getattr(obj, field).all():
                                l.append(str(i))
                            val = ",".join(l)
                        else:
                            val = getattr(obj, field)
                            print("val", val)
                    except Exception as e:
                        val = getattr(obj, field)
                else:
                    val = field(self.config, obj)
                temp.append(val)
            new_data_list.append(temp)
        return new_data_list
    def get_new_actions(self):
        action_list = []
        for i in self.config.actions:  # [patch_init,]
            action_list.append({
                "desc": i.desc,
                "name": i.__name__,
            })
        return action_list
class ModelStark():
    list_display = ["__str__", ]
    search_fields = []
    actions = []
    def __init__(self, model, site):
        self.model = model
        self.site = site
    def edit(self, obj=None, is_header=False):
        if is_header:
            return "操作"
        return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    def delete(self, obj=None, is_header=False):
        if is_header:
            return "操作"
        return mark_safe("<a href='%s/delete'>删除</a>" % obj.pk)
    def checkbox(self, obj=None, is_header=False):
        if is_header:
            return "选择"
        return mark_safe("<input type='checkbox' name='selected_pk' value=%s>" % obj.pk)
    def get_list_url(self):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_list" % (app_label, model_name))
        return _url
    def new_list_display(self):
        temp = []
        temp.append(ModelStark.checkbox)
        temp.extend(self.list_display)
        temp.append(ModelStark.edit)
        temp.append(ModelStark.delete)
        return temp
    def get_search_condition(self, request):
        from django.db.models import Q
        search_condition = Q()
        val = request.GET.get("q")
        if val:
            search_condition.connector = "or"
            for field in self.search_fields:
                search_condition.children.append((field + "__contains", val))
        return search_condition
    def list_view(self, request):
        if request.method == "POST":
            action = request.POST.get("action")
            selected_pk = request.POST.getlist("selected_pk")
            action = getattr(self, action)
            action(selected_pk)
        # search
        search_condition = self.get_search_condition(request)
        # fliter
        from django.db.models import Q
        filter_condition = Q()
        for key, value in request.GET.items():
            filter_condition.children.append((key, value))
        data_list = self.model.objects.all().filter(search_condition).filter(filter_condition)
        print("list_display", self.list_display)  # ["nid","title","price",edit]
        sl = Show_List(self, data_list)
        return render(request, "list_view.html", locals())
    def get_mdoelForm(self):
        from django.forms import ModelForm
        class DemoModelForm(ModelForm):
            class Meta:
                model = self.model
                fields = "__all__"
        return DemoModelForm
    def add(self, request):
        if request.method == "POST":
            form = self.get_mdoelForm()(request.POST)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
            else:
                return render(request, "add.html", locals())
        form = form = self.get_mdoelForm()()
        return render(request, "add.html", locals())
    def change(self, request, id):
        obj = self.model.objects.filter(pk=id).first()
        if request.method == "POST":
            form = self.get_mdoelForm()(request.POST, instance=obj)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
        form = self.get_mdoelForm()(instance=obj)
        return render(request, "change.html", locals())
    def delete_view(self, request, id):
        if request.method == "POST":
            self.model.objects.get(pk=id).delete()
            return redirect(self.get_list_url())
        url = self.get_list_url()
        return render(request, "delete.html", locals())
    def extra_url(self):
        return []
    def get_urls2(self):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp = [
            url("^add/$", self.add, name="%s_%s_add" % (app_label, model_name)),
            url("^$", self.list_view, name="%s_%s_list" % (app_label, model_name)),
            url("^(\d+)/change/$", self.change, name="%s_%s_change" % (app_label, model_name)),
            url("^(\d+)/delete/$", self.delete_view, name="%s_%s_delete" % (app_label, model_name)),
        ]
        temp.extend(self.extra_url())                                      #额外添加一条url
        return temp
    @property
    def urls2(self):
        return self.get_urls2(), None, None
        
class StarkSite():
    def __init__(self, ):
        self._registry = {}
    # 一级分发
    def get_urls(self):
        temp = []
        for model, model_class_obj in self._registry.items():  # {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....}
            app_name = model._meta.app_label
            model_name = model._meta.model_name
            temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2))
        return temp
    @property
    def urls(self):
        return self.get_urls(), None, None
    def register(self, model, admin_class=None, **options):
        if not admin_class:
            admin_class = ModelStark
        self._registry[model] = admin_class(model, self)
site = StarkSite()

app01应用下的stark.py文件:

from stark.service.sites import site,ModelStark
from django.utils.safestring import mark_safe
from app01 import models
from django.conf.urls import url
from django.shortcuts import HttpResponse,redirect,render
from django.http import JsonResponse
site.register(models.Department)
site.register(models.School)
site.register(models.UserInfo)
site.register(models.Course)
site.register(models.ClassList)

class Studentconfig(ModelStark):                                  #学生表的配置类
    def display_score(self,obj=None,is_header=False):
        if is_header:
            return "个人成绩"
        return mark_safe("<a href='score/%s'>个人成绩</a>"%obj.pk)
    list_display = ["customer","class_list",display_score]        #定义显示学生字段增加客户信息,已报班级,个人成绩三组字段
    def score(self,request,sid):
        if request.is_ajax():
            cid=request.GET.get("cid")
            sid=request.GET.get("sid")
            ret=student_study_record_list=list(models.StudentStudyRecord.objects.filter(student_id=sid,class_study_record__class_obj_id=cid).values_list("class_study_record__day_num","score"))
            print(ret)
            ret=[["day"+str(i[0]),i[1]] for i in ret]
            # print(ret)
            return JsonResponse(ret,safe=False)
        student=models.Student.objects.get(pk=sid)
        class_list=student.class_list.all()
        return render(request,"score.html",locals())
    def extra_url(self):
        temp=[]
        temp.append(url("score/(\d+)",self.score))
        return temp
        
site.register(models.Student,Studentconfig)
site.register(models.Customer)
site.register(models.ConsultRecord)

class ClassStudyRecordConfig(ModelStark):
    def detail(self,obj=None,is_header=False):
        if is_header:
            return "详细信息"
        return mark_safe("<a href='/stark/app01/studentstudyrecord/?class_study_record=%s'>详细信息</a>"%obj.pk)  #url跳转到当前班级的详细信息
    def record_score(self, obj=None, is_header=False):
        if is_header:
            return "录入成绩"
        return mark_safe("<a href='record_score/%s'>录入成绩</a>"%obj.pk)                                   #url跳转到当前班级的录入成绩
    list_display = ["class_obj","day_num",detail,record_score]
    def patch_init(self,selected_pk):                           #定义批量初始化,对所有班级批量生成对应的学生记录对象
        classstudyrecord_list=self.model.objects.filter(pk__in=selected_pk)
        for classstudyrecord in classstudyrecord_list:
            student_list=models.Student.objects.filter(class_list=classstudyrecord.class_obj)
            for student in student_list:
                models.StudentStudyRecord.objects.create(class_study_record=classstudyrecord,student=student)
    patch_init.desc="批量初始化"
    actions = [patch_init]
    def record_score(self,request,id):
        csr = models.ClassStudyRecord.objects.get(pk=id)              #班级学习对象
        student_study_record_list = models.StudentStudyRecord.objects.filter(class_study_record=csr)
        score_choices = models.StudentStudyRecord.score_choices
        update=False
        if request.method=="POST":                                 #提交数据
            print("POST",request.POST)
            for key,val in request.POST.items():                    #页面取到的键值进行处理
                if key=="csrfmiddlewaretoken":continue
                field,pk=key.rsplit("_",1)                          #以下划线作为分割标准,取右边第一个
                dic={field:val}
                models.StudentStudyRecord.objects.filter(pk=pk).update(**dic)    #更新的字典,使用**
            update=True
        return render(request,"record_score.html",locals())
    def extra_url(self):
        temp=[]
        temp.append(url("record_score/(\d+)",self.record_score))
        return temp
        
site.register(models.ClassStudyRecord,ClassStudyRecordConfig)

class StudentStudyRecordConfig(ModelStark):
    def display_record(self,obj=None,is_header=False):
        if is_header:
            return "考勤"
        return obj.get_record_display()                       #返回需要的考勤状态
    def display_score(self,obj=None,is_header=False):
        if is_header:
            return "成绩"
        return obj.get_score_display()                           #显示对应的后面的字母表示的成绩,而不是数字
    list_display = ["student","class_study_record",display_record,display_score]
    def patch_late(self,selected_pk):                             #批量修改考勤状态为迟到
        self.model.objects.filter(pk__in=selected_pk).update(record="late")
    patch_late.desc="迟到"
    actions = [patch_late]
    
site.register(models.StudentStudyRecord,StudentStudyRecordConfig)

record_score.html录入成绩页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.css">
</head>
<body>
<h3>录入成绩</h3>
<div>
    <div>
        <div>
            <form action="" method="post">
                {% csrf_token %}
                <table class="table table-bordered table-striped table-hover">
                    <thead>
                    <tr>
                        <th>编号</th>
                        <th>姓名</th>
                        <th>考勤</th>
                        <th>成绩</th>
                        <th>批语</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for student_study_record in  student_study_record_list %}
                        <tr>
                            <td>{{ forloop.counter }}</td>
                            <td>{{ student_study_record.student }}</td>
                            <td>
                                {{ student_study_record.get_record_display }}
                            </td>
                            <td>
                                <select name="score_{{ student_study_record.pk }}" id="">     {#下拉框显示当前学生成绩#}
                                    {% for foo in score_choices %}
                                        {% if student_study_record.score == foo.0 %}
                                         <option selected value="{{ foo.0 }}">{{ foo.1 }}</option>          {#已经有成绩的显示器成绩,没有的显示默认#}
                                        {% else %}
                                         <option value="{{ foo.0 }}">{{ foo.1 }}</option>
                                        {% endif %}
                                    {% endfor %}
                                </select>
                            </td>
                            <td><textarea name="homework_note_{{ student_study_record.pk }}" id="" cols="40" rows="5">{{ student_study_record.homework_note|default_if_none:"" }}</textarea>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
                <input type="submit" class="btn btn-warning pull-right" value="保存">                           {#保存按钮#}
                {% if update %}
                <span style="color:green">更新成功</span>
                {% endif %}
            </form>
        </div>
    </div>
</div>
</body>

<script>
setTimeout(function(){document.getElementById("show_text").style.display="none";},2000);      {# 更新成功显示2秒后消失 #}
</script>
</html>

score.html查看个人成绩页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.css">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script src="/static/Highcharts-6.1.0/code/highcharts.js"></script>
</head>
<body>
<h2>查看{{ student }}成绩</h2>
<div>
    <div>
        <div class="col-md-8 col-md-offset-1">
            <table class="table table-bordered table-striped table-hover">
                <thead>
                <tr>
                    <th>编号</th>
                    <th>班级</th>
                    <th>班主任</th>
                    <th>成绩柱状图</th>
                </tr>
                </thead>
                <tbody>
                {% for cls in  class_list %}
                    <tr>
                        <td>{{ forloop.counter }}</td>
                        <td>{{ cls.course }}({{ cls.semester }})</td>
                        <td>{{ cls.tutor }}</td>
                        <td><a cid="{{ cls.pk }}">成绩柱状图</a></td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
<div id="container" style="width: 600px"></div>

<script>
                $(".chart_score").click(function () {
                    var cid=$(this).attr("cid");
                    $.ajax({
                        url:"",
                        type:"get",
                        data:{
                            sid:"{{ student.pk }}",
                            cid:cid
                        },
                        success:function (data) {
                             var chart = Highcharts.chart('container', {
                        chart: {
                            type: 'column'
                        },
                        title: {
                            text: '个人成绩分布图'
                        },
                        subtitle: {
                            text: '数据截止 2017-03,来源: <a href="https://en.wikipedia.org/wiki/List_of_cities_proper_by_population">Wikipedia</a>'
                        },
                        xAxis: {
                            type: 'category',
                            labels: {
                                rotation: -45  // 设置轴标签旋转角度
                            }
                        },
                        yAxis: {
                            min: 0,
                            title: {
                                text: '分数'
                            }
                        },
                        legend: {
                            enabled: false
                        },
                        tooltip: {
                            pointFormat: '分数: <b>{point.y:.2f} 百万</b>'
                        },
                        series: [{
                            name: '总人口',
                            data: data,
                            dataLabels: {
                                enabled: true,
                                rotation: -90,
                                color: 'red',
                                align: 'right',
                                format: '{point.y:.1f}',        // :.1f 为保留 1 位小数
                                y: 10
                            }
                        }]
                    });
                        }
                    })
                })
            </script>
</body>
</html>

页面显示效果图如下:

原文地址:http://blog.51cto.com/qidian510/2133704

时间: 2024-10-09 01:24:14

使用自己的stark组件实现crm系统的相关文章

crm 使用stark组件

# Create your models here. from django.db import models class Department(models.Model): """ 部门表 市场部 1000 销售 1001 """ title = models.CharField(verbose_name='部门名称', max_length=16) code = models.IntegerField(verbose_name='部门编号',

crm——stark组件核心原理

关于stark组件的简要介绍: 启动后.路由加载前定制一段代码. a. 创建一个 stark  app 组件 b. 编写ready方法 1 from django.apps import AppConfig 2 3 4 class StarkConfig(AppConfig): 5 name = 'stark' 6 7 def ready(self): 8 from django.utils.module_loading import autodiscover_modules 9 # 当程序启动

CRM【第二篇】: stark组件

介绍: stark组件,是一个帮助开发者快速实现数据库表的增删改查+的组件.目标: 10s 中完成一张表的增删改查. 前戏: django项目启动时,自定义执行某个py文件. django启动时,且在读取项目中 路由加载 之前执行某个py文件. 在任意app的apps.py中的Config类中定义ready方法,并调用autodiscover_modules from django.apps import AppConfig from django.utils.module_loading im

使用SSIS对Dynamics CRM 系统进行数据迁移

嗨,各位.最近项目一直都很忙,并且自己也一直在思考职业发展的问题,所以有很长一段时间没静下心写几篇Blog了.最近我参与的项目是Dynamics CRM 2011 到 Dynamics CRM 2013 Online的数据迁移,刚好接着今天这个机会和大家分析一下数据迁移的心得吧. 读过我之前文章的朋友肯定记得我把Dynamics CRM的接口分为了两大类:1)功能接口,2)数据接口.今天要说的数据迁移可以理解为数据接口,实现数据接口的方式有很多种,比如C#制作的程序,数据库层的SQL 脚本,以及

自定义组件之crm的业务逻辑

我们先在app01下的models中添加crm需要用的表.然后数据库迁移,要记得在app01下 的stark将这几张表注册,不然不能进入访问后台. 录入数据之前,我们先来说几个知识点, 在models表中,有这样几个字段, 一对多字段和多对多字段在使用modelform的时候,会在页面上渲染成select标签,而select标签会显示各自关联表下的所有数据,而 limit_choices_to={"depart_id__in":[100,101,]}  的作用就是限制选项,只显示{&q

Stark组件 (一)

Stark组件构建 1.启动所有app下的stark.py文件,的配置实现步骤 1.创建一个Django项目crm,并创建  app1 ,app2, stark 三个app 2.在crm 项目的settings中配置: INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.

CRM系统简析

寄语: 简单阐述一下对CRM系统应用的理解,此内容参考网上资料所整理. CRM是Customer Relationship Management的缩写,简称客户关系管理. CRM系统可以从三个方面来分析它的价值:

CRM系统PaaS化,满足企业个性化需求

一千个人,有千种长像,一千个企业,有各种需求.有千种流程,标准模式的CRM系统很难满足个性化流程及需求的企业,那么CRM系统要Paas化,才能满足个性化需求的企业. PaaS是什么? PaaS是Platform-as-a-Service的缩写,意思是平台即服务. 把服务器平台作为一种服务提供的商业模式.通过网络进行程序提供的服务称之为SaaS(Software as a Service),而云计算时代相应的服务器平台或者开发环境作为服务进行提供就成为了PaaS(Platform as a Ser

Day4作业:蛋疼CRM系统

先上流程图,还得27寸4K显示器,画图各种爽: ReadMe: #博客地址:http://www.cnblogs.com/ccorz/ #GitHub:https://github.com/ccorzorz #Mail:[email protected]163.com #Auther:成晨 为什么写两个版本: 武sir这期的作业不是很难,但有一个需求的逻辑个人感觉不是很合理:普通用户可以选择管理员操作的选项. 当然银角的目的是为了我们把装饰器运用到实际程序中. 一般页面展示中,管理员操作选项对于