您的位置:澳门402永利com > 关于计算机 > ThinkPHP表单自动提交验证实例教程,openerp模块收

ThinkPHP表单自动提交验证实例教程,openerp模块收

发布时间:2019-09-23 20:45编辑:关于计算机浏览(147)

    本文以实例讲述了ThinkPHP表单自动提交验证的实现过程,详细步骤如下所示:

    基于Lodop的报表打印模块

    原文:

    前段时间写了个小模块,来解决OE中报表打印不方便的问题。
    借鉴了 @buke 兄的 openerp-web-pdf-preview-print 模块的部分代码。

    介绍:
    Lodop是一款优秀的国产打印控件(activeX): 
    ActiveX只支持windows,所以本控件不适用linux,mac osx.

    模块使用mako标签,html的模版。

    我只贴代码,不加附件,这样各位会体会更深。

    模块结构:
    图片 1

    __openerp__.py

    程序代码: 

    {
        "name": "Lodop控件报表",
        "category": "web",
        "description":
            """
            Lodop控件模块, 针对于报表。
            """,
        "version": "6.0.5.6",
        "depends": [],
        "js": ["static/lib/Lodop6.145/*.js", "static/js/*.js"],
        'active':True,
        'installable': True,
        'active': False,
        'application':False,
    }
    

    服务端的controller(没啥一样的,继续借鉴@buke):

    程序代码: 

    # -*- coding: utf-8 -*-
    
    
    import openerp.addons.web.http as openerpweb
    from openerp.addons.web.controllers.main import View
    
    import urllib2
    import simplejson
    import base64
    import time
    import zlib
    import cPickle
    import hashlib
    
    
    class LodopReport(View):
        _cp_path = "/web/lodop/report"
        POLLING_DELAY = 0.25
    
        @openerpweb.jsonrequest
        def index(self, req, action):
            action = simplejson.loads(action)
            report_srv = req.session.proxy("report")
            context = dict(req.context)
            context.update(action["context"])
            report_data = {}
            report_ids = context["active_ids"]
            if 'report_type' in action:
                report_data['report_type'] = action['report_type']
            if 'datas' in action:
                if 'ids' in action['datas']:
                    report_ids = action['datas'].pop('ids')
                report_data.update(action['datas'])
            report_id = report_srv.report(
                req.session._db, req.session._uid, req.session._password,
                action["report_name"], report_ids,
                report_data, context)
            report_struct = None
            while True:
                report_struct = report_srv.report_get(
                    req.session._db, req.session._uid, req.session._password, report_id)
                if report_struct["state"]:
                    break
                time.sleep(self.POLLING_DELAY)
    
            report = base64.b64decode(report_struct['result'])
            return dict(report = report)
    

    主要部分是js部分:

    程序代码: 

    openerp.fg_lodop = function(instance) {
    
        instance.web.ActionManager = instance.web.ActionManager.extend({
    
            init: function (parent, action) {
                this._super(parent);
                //activex的标签放在页面里。
                var obj_string = '<object style="width:0px;height:0px;" id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0><embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0 pluginspage="/fg_lodop/static/lib/lodop6.145/install_lodop32.exe"></embed></object>';
                $(obj_string).appendTo("body");
            },
    
            ir_actions_report_xml: function(action, options) {
                var self = this;
                instance.web.blockUI();
                return instance.web.pyeval.eval_domains_and_contexts({
                    contexts: [action.context],
                    domains: []
                }).then(function(res) {
                    action = _.clone(action);
                    action.context = res.context;
                    var os = navigator.platform || "Unknown OS";
                    linux = os.indexOf("Linux") > -1;
                    mac = os.indexOf("Mac") > -1;
    
                    self.rpc("/web/lodop/report", {
                        action: JSON.stringify(action)
                    }).done(function(result) {
                        if(result.error){
                            instance.web.unblockUI();
                            self.dialog_stop();
                            return;
                        }
                        instance.web.unblockUI();
                        self.dialog_stop();
                        if(linux || mac) { 
                            //不支持linux, mac, 这点没考虑过。
                            report_window=window.open('','','width=600,height=500');
                            report_window.document.write(result.report);
                            report_window.focus();
                        }
                        else {
                            //do magic.
                            // 等会解释这个由来。
                            format_obj = action.attachment.split(',');
    
                            LODOP=getLodop(document.getElementById('LODOP'),document.getElementById('LODOP_EM'));  
                            LODOP.SET_LICENSES("","xxxxxx","","");  //不设置授权码照样可以打印。
                            LODOP.PRINT_INIT("FG ERP Order");
                            LODOP.SET_PRINT_PAGESIZE(1, 2300, 1390, 'fg_lodop_print_job'); //公司用的各种单据的打印纸都是统一规格,所以写死了。
    
                            var tables = $.parseHTML(result.report);
                            $.each( tables, function( i, el ) {
                                if(el.nodeName == "TABLE"){
                                    LODOP.ADD_PRINT_TABLE(format_obj[0],format_obj[1],format_obj[2], format_obj[3], el.outerHTML);
                                    LODOP.NEWPAGE();
                                }
                            });
                            LODOP.PREVIEW();
                        }
                    });
                });
            },
        });
    
    
    };
    

    安装后,本模块将会替代系统默认的报表动作。

    使用方法:

    程序代码: 

    <report auto="False" id="report_fg_sale_cust_order_html" model="fg_sale.cust.order"
                    name="fg_sale.cust.order.html" rml="fg_sale/report/cust_order.html"
                    string="定制单" report_type="mako2html" attachment="0mm,0mm,220mm,98mm"/>
    

    因为需要确定打印的范围,所以借用了attachment这个属性----实在是不想修改系统的rng文件了。
    * 这就是刚才代码 “format_obj = action.attachment.split(',');” 这一行的原因。

    mako的html模版大概是这样的:

    程序代码: 

    # -*- coding: utf-8 -*-
                % for o in objects:
                    % if o.state == 'review':
                        <table border="0" cellspacing="2" cellpadding="2" bordercolor="#000000" style="font-size:14px;width:850px;">
                          <thead>
                              <tr>
                                <td colspan="8" align="center">
                                  定制清单   ${ o.name }</td>
                              </tr>
                              <tr>
                                  <td colspan="1"  height="18">客户名称: 
                                    ${ o.partner_id.name }
                                  </td>
                                  <td colspan="3"  height="18">要求到货日期: ${ o.date_arrival_req or '' }</td>
                                  <td colspan="4" height="18">
                                      交货日期: ${ o.date_delivery or '' }
                                  </td>
                              </tr>
                              % if o.contact or o.phone or o.delivery_addr:
                              <tr>
                                <td colspan="1">联系人: ${ o.contact or '' }</td>
                                <td colspan="3">联系电话: ${ o.phone or '' }</td>
                                <td colspan="3">交货地址: ${ o.delivery_addr or '' }</td>
                              </tr>
                              % endif
                              <tr>
                                <td colspan="1">已付金额: ${ o.amount_paid or '' }</td>
                                <td colspan="3">付款方式: ${ o.amount_paid_method or '' }</td>
                                <td colspan="3">发票: 
                                  % if o.invoice_type == 'common':
                                  普通发票
                                  % elif o.invoice_type == 'va':
                                  增值发票
                                  % else:
                                  暂不开票
                                  % endif
                                </td>
                              </tr>
                              <tr>
                                <td colspan="1">定制版面:  ${ o.client }</td>
                                <td colspan="3">运费承担方: ${ o.delivery_fee or '' }</td>
                                <td colspan="3">送货方式: ${ o.delivery_method or '' }</td>
                              </tr>
                              <tr height="18">
                                 <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">品名</td>
                                 <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">数量(只)</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">开票价</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">版费</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">已发货</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">小计</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">附注</td>
                              </tr>
                          </thead>
                          <tbody>
                              % for line in o.order_line:
                              <tr>
                                  <td height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" >${ line.product_id.name }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.product_uom_qty }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" >${ line.unit_price }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.cust_price }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.delivered and '是' or '否' }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.subtotal_amount }</td>
                                  <td width="20%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.note or '' }</td>
                                </tr>
                              % endfor
                          </tbody>
                          <tfoot>
                              <tr>
                                <td colspan="1" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;text-align:right;" tdata="allSum" format="#,##0.00" tindex="6">
                                    共计: #
                                </td>
                                <td colspan="4" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" tdata="allSum" format="UpperMoney" tindex="6">
                                    #
                                </td>
                                <td colspan="2" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" tdata="subSum" format="#,##0.00">
                                    本页小计: #
                                </td>
                              </tr>
                              <tr>
                                  <td colspan="2">
                                    开单人: ${ o['user_id']['name'] } &nbsp;&nbsp;
                                    开单日期:${ o.date_order } 
                                  </td>
                                  <td colspan="4">
                                    业务部确认: ${ o['confirmer_id']['name'] }&nbsp;&nbsp;
                                    业务经办人:${ o.employee_id.name }
                                  </td>
                                  <td colspan="1" style="font-size:14px;height:18px;text-align:right;">第#页-共#页</td>
                              </tr>
                          </tfoot>
                        </table>
                % endif
          % endfor
    

    注意:

    1. 模版只包含table标签,支持多table(多单打印)。
    2. lodop的使用方法请参看其文档。

    大功告成。

    献丑了。如需改进,有问题请 @杨振宇_

     

    lodop里,addprinttable方法可以把table里面 <theader>标签转为你说的,表头,tfoot标签转换为页脚。
    tbody里,就是明细部分了,自动根据页面高度分页。

    另外lodop还支持一些标签,比如,总页数,当前页数,数字大写转换,统计,等。

    一、模板部分:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <TITLE>ThinkPHP示例:表单提交、自动验证和自动填充</TITLE>
    </HEAD>
    <BODY>
    <div class="main">
    <FORM METHOD=POST ACTION="__URL__/insert">
    <TABLE cellpadding=2 cellspacing=2>
    <TR>
     <TD width="12%">标题:</TD>
     <TD ><INPUT TYPE="text" NAME="title" style="height:23px" class="large bLeft"></TD>
    </TR>
    <TR>
     <TD >邮箱:</TD>
     <TD ><INPUT TYPE="text" NAME="email" style="height:23px" class="large bLeft"></TD>
    </TR>
    <TR>
     <TD>内容:</TD>
     <TD><TEXTAREA NAME="content" class="large bLeft" ROWS="8" COLS="25"></TEXTAREA></TD>
    </TR>
    <TR>
     <TD>验证码:</TD>
     <TD><INPUT TYPE="text" NAME="verify" style="height:23px" class="small" > <img src="__URL__/verify" align="absmiddle" /> 输入对应的数字</TD>
    </TR>
    <TR>
     <TD></TD>
     <TD><INPUT TYPE="submit" class="button" value="提 交"> <INPUT TYPE="reset" class="button" value="清 空"></TD>
    </TR>
    <TR>
    <TD></TD>
     <TD ><HR></TD>
    </TR>
    <volist name="list" id="vo">
    <TR>
    <TD></TD>
     <TD style="border-bottom:1px dotted silver">{$vo.title} [{$vo.email} {$vo.create_time|date='Y-m-d H:i:s',###}]</TD>
    </TR>
    <TR >
    <TD></TD>
     <TD ><div class="content">{$vo.content|nl2br}</div></TD>
    </TR>
    </volist>
    </TABLE>
     </FORM>
    </div>
    </BODY>
    </HTML>
    

    二、模型部分form类程序代码:

    <?php 
    class FormModel extends Model {
     // 自动验证设置
     protected $_validate  =  array(//这里必须定义为$_validata用来验证
     array('title','require','标题必须!',1),
     array('email','email','邮箱格式错误!',2),
     array('content','require','内容必须'),
     array('verify','require','验证码必须!'),
     array('verify','CheckVerify','验证码错误',0,'callback'),//callback 使用方法验证,前面定义的验证规则是一个当前 Model 类的方法 
    //这里如果有不太理解的话可以看本类的最后一个方法
     array('title','','标题已经存在',0,'unique','add'),//附加验证unique,unique 验证是否唯一,系统会根据字段目前的值查询数据库来判断是否存在相同的值
     );
     /*think的验证机制,省去了不少麻烦非空:equire 邮箱:email 验证码正确:CheckVerify
     array()数组内容array(验证字段,验证规则,错误提示,验证条件,附加规则,验证时间)
     验证条件
     EXISTS_TO_VAILIDATE 或者 0 存在字段就验证 (默认)
     MUST_TO_VALIDATE 或者1 必须验证
     VALUE_TO_VAILIDATE 或者 2 值不为空的时候验证
     附加规则 配合验证规则使用,包括:
     function 使用函数验证,前面定义的验证规则是一个函数名
     callback 使用方法验证,前面定义的验证规则是一个当前 Model 类的方法
     confirm 验证表单中的两个字段是否相同,前面定义的验证规则是一个字段名
     equal 验证是否等于某个值,该值由前面的验证规则定义
     in 验证是否在某个范围内,前面定义的验证规则必须是一个数组
     unique 验证是否唯一,系统会根据字段目前的值查询数据库来判断是否存在相同的值
     regex 使用正则进行验证,表示前面定义的验证规则是一个正则表达式(默认)
     */
     // 自动填充设置
     //由上面推导,下面这个是自动填充字段了,方便明了
     protected $_auto  =  array(//同样这里必须定义为$_auto
     array('status','1','ADD'),
     array('create_time','time','ADD','function'),//这里指明填充使用函数time()
     );
     /*
     数组因子:
     array(填充字段,填充内容,填充条件,附加规则)
     填充条件包括:
     ADD 新增数据的时候处理(默认方式)
     Update 更新数据的时候处理
     ALL 所有情况下都进行处理
    
     附加规则包括:
     function 使用函数
     callback 回调方法
     field 用其它字段填充
     string 字符串(默认方式)
     */
    
     public function CheckVerify() {
      return md5($_POST['verify']) == $_SESSION['verify'];
     }
    }
    ?>
    

    三、控制器部分indexaction类程序代码:

    <?php 
    class IndexAction extends Action{
     // 首页
     public function index(){
      $Form = D("Form");//创建一个对象
      $list = $Form->top6('','*','id desc');//从数据库中读取最新6条记录,并且安id倒序输出
      $this->assign('list',$list);//把数据传到模板里
      $this->display();
     }
     // 处理表单数据
     public function insert() {//此方法对应表单的ACTION="__URL__/insert"
      $Form = D("Form");
      if($Form->create()) {//创建 Form 数据对象,默认通过表单提交的数据进行创建,为下面写入数据库做准备
       $Form->add();// 新增表单提交的数据 ,吧上面创建的数据对象提交
       $this->redirect();//返回上一个模块,页面跳转可以说是
      }else{
       header("Content-Type:text/html; charset=utf-8");
       exit($Form->getError().' [ <A href="javascript:history.back()" rel="external nofollow" >返 回</A> ]');
      }
     }
     // 生成验证码
     //这个方法没什么好说的,固定格式
     public function verify() {
      import("ORG.Util.Image");
       Image::buildImageVerify(); //这里两个冒号是调用静态方法
     }
    } 
    ?>
    

    本文由澳门402永利com发布于关于计算机,转载请注明出处:ThinkPHP表单自动提交验证实例教程,openerp模块收

    关键词: