代码发布 04

今日内容概要

  • 发布任务单新增页面
  • 发布流程前端实时展示

任务列表的展示为了更加人性化,可以增加当前项目的项目名和环境

# 先简单的手动处理数据 完成添加功能
from app01.myforms.base import BaseModelForm
from app01 import models


class TaskModelForm(BaseModelForm):
    class Meta:
        model = models.DeployTask
        fields = '__all__'
        # 项目唯一标识 应该是自动生成的无需用户填写
        # 项目由于已经带了主键值了 所以也无需用户填写
        # 创建的任务单默认状态就是待发布 所以也无需展示
        exclude = ['uid','project','status']

    def __init__(self,project_id,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.project_id = project_id

    def save(self, commit=True):
        # 添加数据
        self.instance.uid = 'sadjasdj'
        self.instance.project_id = self.project_id
        # 调用父类的save方法保存数据
        super().save(commit=True)

接下来,我们针对任务的添加页面,单独开设一个html

并在该html页面上划分三块区域展示不同的信息

  • 当前任务关联的项目基本信息展示

  • 基本配置

  • 脚本书写

针对四个钩子脚本,我们想要实现可以保存的功能

# 初始化字段
    def __init__(self,project_obj,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.project_obj = project_obj
        # 初始化选择框内容
        self.init_hook()

    def init_hook(self):
        # 给所有的下拉框先添加一个 请选择选项
        # <option value="0">请选择</option>  (0,'请选择')
        self.fields['before_download_select'].choices = [(0,'请选择')]
        self.fields['after_download_select'].choices = [(0,'请选择')]
        self.fields['before_deploy_select'].choices = [(0,'请选择')]
        self.fields['after_deploy_select'].choices = [(0,'请选择')]

创建表存储用户填写的想要保存的模版信息

class HookTemplate(models.Model):
    """保存钩子脚本"""
    title = models.CharField(verbose_name='标题',max_length=32)
    content = models.TextField(verbose_name='脚本内容')
    # 我想实现钩子与钩子之间模版互不影响
    hook_type_choices = (
        (2,'下载前'),
        (4,'下载后'),
        (6,'发布前'),
        (8,'发布后')
    )
    hook_type = models.IntegerField(verbose_name='钩子类型',choices=hook_type_choices)

什么时候需要操作上述表保存数据???

判断依据是用户是否点击了checkbox按钮

在我们重写的save方法中 做判断!!!

# 判断用户是否点击checkbox
        if self.cleaned_data.get("before_download_template"):
            # 获取模版名称
            title = self.cleaned_data.get("before_download_title")
            # 获取脚本内容
            content = self.cleaned_data.get("before_download_script")
            # 保存到表中
            models.HookTemplate.objects.create(
                title=title,
                content=content,
                hook_type=2
            )

        if self.cleaned_data.get("after_download_template"):
            # 获取模版名称
            title = self.cleaned_data.get("after_download_title")
            # 获取脚本内容
            content = self.cleaned_data.get("after_download_script")
            # 保存到表中
            models.HookTemplate.objects.create(
                title=title,
                content=content,
                hook_type=4
            )

        if self.cleaned_data.get("before_deploy_template"):
            # 获取模版名称
            title = self.cleaned_data.get("before_deploy_title")
            # 获取脚本内容
            content = self.cleaned_data.get("before_deploy_script")
            # 保存到表中
            models.HookTemplate.objects.create(
                title=title,
                content=content,
                hook_type=6
            )

        if self.cleaned_data.get("after_deploy_template"):
            # 获取模版名称
            title = self.cleaned_data.get("after_deploy_title")
            # 获取脚本内容
            content = self.cleaned_data.get("after_deploy_script")
            # 保存到表中
            models.HookTemplate.objects.create(
                title=title,
                content=content,
                hook_type=8
            )

数据库模版名称前端展示,以及用户点击实时获取模版内容

    def init_hook(self):
        # 给所有的下拉框先添加一个 请选择选项
        # <option value="0">请选择</option>  (0,'请选择')

        before_download = [(0,'请选择')]
        # 还应该去数据库中查询是否有对应的模版名称
        extra_list = models.HookTemplate.objects.filter(hook_type=2).values_list('pk','title')
        before_download.extend(extra_list)
        self.fields['before_download_select'].choices = before_download

        after_download = [(0,'请选择')]
        extra_list = models.HookTemplate.objects.filter(hook_type=4).values_list('pk', 'title')
        after_download.extend(extra_list)
        self.fields['after_download_select'].choices = after_download

        before_deploy = [(0,'请选择')]
        extra_list = models.HookTemplate.objects.filter(hook_type=6).values_list('pk', 'title')
        before_deploy.extend(extra_list)
        self.fields['before_deploy_select'].choices = before_deploy

        after_deploy = [(0,'请选择')]
        extra_list = models.HookTemplate.objects.filter(hook_type=8).values_list('pk', 'title')
        after_deploy.extend(extra_list)
        self.fields['after_deploy_select'].choices = after_deploy

前端用户点击模版动态展示内容

给前端所有的select标签绑定文本域变化事件(change事件)

<script>
        // 直接给hooks类标签内所有的select绑定事件
        $('.hooks').find('select').change(function () {
            {#alert($(this).val())  获取用户输入的模版主键值 #}
            var $that = $(this);
            // 朝后端发送请求 获取对应的脚本内容
            $.ajax({
                url:'/hook/template/'+$that.val()+'/',
                type:'get',
                dataType:'JSON',
                success:function (args) {
                    // 获取脚本内容 渲染到对应下拉框下面的textarea框中
                    {#alert(args.content)#}
                    // 标签查找
                    $that.parent().parent().next().find('textarea').val(args.content);
                }

            })
        })
    </script>

优化

  • 用户一旦点击了checkbox按钮,那么就必须填写模版名称

    # 钩子函数 全局钩子 局部钩子
    # 全局钩子 
        # 全局钩子校验用户是否点击checkbox
        def clean(self):
            if self.cleaned_data.get('before_download_template'):
                # 获取用户输入的模版名称 判断是否有值
                title = self.cleaned_data.get("before_download_title")
                if not title:
                    # 展示提示信息
                    self.add_error('before_download_title','请输入模版名称')
    
            if self.cleaned_data.get('after_download_template'):
                # 获取用户输入的模版名称 判断是否有值
                title = self.cleaned_data.get("after_download_title")
                if not title:
                    # 展示提示信息
                    self.add_error('after_download_title','请输入模版名称')
    
            if self.cleaned_data.get('before_deploy_template'):
                # 获取用户输入的模版名称 判断是否有值
                title = self.cleaned_data.get("before_deploy_title")
                if not title:
                    # 展示提示信息
                    self.add_error('before_deploy_title','请输入模版名称')
    
            if self.cleaned_data.get('after_deploy_template'):
                # 获取用户输入的模版名称 判断是否有值
                title = self.cleaned_data.get("after_deploy_title")
                if not title:
                    # 展示提示信息
                    self.add_error('after_deploy_title','请输入模版名称')

    注意,前端需要预留一部分内容展示错误信息否则会出现布局错乱的问题

    <div class="form-group" style="height: 60px">
                                            <div class="col-sm-3">
                                                <div class="checkbox">
    
                                                    <label for="">{{ form_obj.after_deploy_template }}保存模版</label>
                                                </div>
                                            </div>
                                            <div class="col-sm-9">
                                                {{ form_obj.after_deploy_title }}
                                                <span style="color: red">{{ form_obj.after_deploy_title.errors.0 }}</span>
                                            </div>
    
                                        </div>

    发布任务

    Ps:静态文件可以全局也可以在局部

    静态文件配置

    # 1 配置文件中直接配置
    STATICFILES_DIRS = [
      os.path.join(BASE_DIR,'static1'),
      os.path.join(BASE_DIR,'static2'),
    ]
    
    # 2 模版语法直接配置
    {% load staticfiles %}
    <script src="{% static 'js/go.js' %}"></script>
    <script>
            // 由于ws和diagram需要在其他函数内使用 所以定义成全局变量
            var ws;
            var diagram;
    
            function initWebSocket() {
                ws = new WebSocket('ws://127.0.0.1:8000/publish/{{ task_obj.pk }}/');
    
                // 一旦服务端有消息 会自动触发onmessage方法
                ws.onmessage = function (args) {
                    // args.data
                    var res = JSON.parse(args.data);
                    if (res.code==='init'){
                        // 操作gojs渲染图表
                        diagram.model = new go.TreeModel(res.data)
                    }
                }
            }
    
            function initTable() {
                var $ = go.GraphObject.make;
                diagram = $(go.Diagram, "diagramDiv", {
                    layout: $(go.TreeLayout, {
                        angle: 0,
                        nodeSpacing: 20,
                        layerSpacing: 70
                    })
                });
                // 生成一个节点模版
                diagram.nodeTemplate = $(go.Node, "Auto",
                    $(go.Shape, {
                        figure: "RoundedRectangle",
                        fill: 'yellow',
                        stroke: 'yellow'
                    }, new go.Binding("figure", "figure"), new go.Binding("fill", "color"), new go.Binding("stroke", "color")),
                    $(go.TextBlock, {margin: 8}, new go.Binding("text", "text"))
                );
                // 生成一个箭头模版
                diagram.linkTemplate = $(go.Link,
                    {routing: go.Link.Orthogonal},
                    $(go.Shape, {stroke: 'yellow'}, new go.Binding('stroke', 'link_color')),
                    $(go.Shape, {toArrow: "OpenTriangle", stroke: 'yellow'}, new go.Binding('stroke', 'link_color'))
                );
                // 数据集合  以后替换ajax请求   注意使用key和parent来规定箭头的指向
                {#var nodeDataArray = [#}
                {#    {key: "start", text: '开始', figure: 'Ellipse', color: "lightgreen"},#}
                {#    {key: "download", parent: 'start', text: '下载代码', color: "lightgreen", link_text: '执行中...'},#}
                {#    {key: "compile", parent: 'download', text: '本地编译', color: "lightgreen"},#}
                {#    {key: "zip", parent: 'compile', text: '打包', color: "red", link_color: 'red'},#}
                {#    {key: "c1", text: '服务器1', parent: "zip"},#}
                {#    {key: "c11", text: '服务重启', parent: "c1"},#}
                {#    {key: "c2", text: '服务器2', parent: "zip"},#}
                {#    {key: "c21", text: '服务重启', parent: "c2"},#}
                {#    {key: "c3", text: '服务器3', parent: "zip"},#}
                {#    {key: "c31", text: '服务重启', parent: "c3"},#}
                {#];#}
                {#diagram.model = new go.TreeModel(nodeDataArray);#}
                // 动态控制节点颜色变化   后端给一个key值 即可查找图表并修改
    
                /*
                var node = diagram.model.findNodeDataForKey("zip");
                diagram.model.setDataProperty(node, "color", "lightgreen");
                }
                */
    
            }
    
            // 页面加载完毕 先自动执行两个函数 给全局变量赋值
            $(function () {
                initWebSocket();
                initTable()
            });
    
            function createDiagram() {
                ws.send('init')
            }
    
    
    
        </script>

猜你喜欢

转载自www.cnblogs.com/zhangchaocoming/p/12528986.html
04