康虎云报表解决了浏览器不能直接调用打印机打印报表的痛点,但是个人感觉康虎软件工作室给出的文档不算特别详细,其中开发遇到各种问题,还是需要去官方QQ群讨教,十分感谢石头哥给我的指导及免费开放的如此优秀的软件.本文记录一下自己在odoo中集成康虎云报表的过程.
项目目录
- addons
- cfprint # 康虎云报表官方模块
...
- my_cfprint # 个人集成模块
- data
- template_data.xml # 模板数据,直接写入省去安装模块后再上传模板
- models
- __init__.py
- cf_template.py # 继承康虎云模板模型增加字段
- views
- cf_template_view.xml # 继承康虎云模板模型增加字段
- report
- button.xml # 按钮视图
- sell_delivery_report.xml # 继承report模板改为康虎云报表
- __init__.py
- __manifest__.py
- 按钮视图
<?xml version="1.0"?>
<openerp>
<data>
<!--销售发货单打印按钮-->
<report
id="report_sale_order"
string="直接打印"
model="sell.delivery"
report_type="qweb-html"
<!--指定调用的report.xml文件-->
file="my_cfprint.sell_delivery_report"
name="my_cfprint.sell_delivery_report"
/>
</data>
</openerp>
这样就可以在对应模型的视图上选择打印菜单即可出现按钮
form视图在中间
tree勾选记录后打印
image.png
- sell_delivery_report.xml
<?xml version="1.0"?>
<odoo>
<data>
<!-- id要与上面申明的一致-->
<template id="sell_delivery_report">
<!--这个可以看作html的根节点,所有页面内容都需要放在这里面-->
<t t-call="report.html_container">
<!-- 在页面上显示一个提示 -->
<h3 style="width:100%; padding-top: 50px;">
<!--docs便是所有记录,使用判断语句进行输出-->
<t t-if="len(docs) >= 0">正在打印,请稍候...</t>
<t t-if="len(docs) < 1">没有可打印的记录!</t>
</h3>
</t>
<script type="text/javascript">
<!--JS代码...-->
</script>
</template>
</data>
</odoo>
使用QWEB渲染引擎自己定义一个模板,因为我们只需要通过这个报表界面运行康虎的JS代码,将数据传给伺服机从而进行打印,所以报表可以随便简单点设计,重要的是里面的js代码
- JS
首先定义最基本的参数配置
/* 打印伺服机的ip地址 */
var cfprint_addr = "127.0.0.1";
/* 打印完成后关闭窗口的延时时长(毫秒), -1则表示不关闭 */
var _delay_close = 1000;
/* 接下来要生成json了,json结构的外框架如下 */
var _data = {
"template": "base64:<t t-esc="cf_template(user.env, 'report_sell_delivery')" />",
"Copies": 3, /*打印份数,支持指定打印份数。*/
"Duplex": 1, /*可选。是否双面打印,0:默认,不双面,1:垂直,2:水平,3:单面打印(simplex)。*/
"Tables":[]
}
这是康虎云JS里定义的两个变量名,所以名字不可以更改,其中_data里的template是设置报表模板,有多种设置方式,这种将模板上传到模型数据库种再调用个人感觉是最方便的,这样不用要求伺服机本地要有模板文件,而是通过odoo将模板数据一同传输.这里的'report_sell_delivery'只要设置为你自己的模板ID就可以了
image.png最后参数里的"Tables"就是我们要填入的数据,数据为json格式
var _tableCompany = {
"Name": "Company",
"Cols":[
{ "type": "str", "size": 4, "name": "id", "required": false },
{ "type": "str", "size": 255, "name": "text", "required": false },
{ "type": "str", "size": 20, "name": "currdate", "required": false },
],
"Data":[
{
"id": "<t t-esc="res_company.id" />",
"text": "<t t-esc="res_company.name"/><t t-esc="res_company.rml_header1"/><t t-esc="res_company.phone"/> ",
"currdate": "<t t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"/>",
}
]
}
name 为表名,cols为字段定义,data为每条数据明细
- cols里有四个属性分别为"type": 字段类型,可选值:String,Str,Integer,Int,Smallint,Float,Long, Blob...
"size": 字段长度
"name": 字段名称,必须与打印模板中字段名相同
"required": 字段是否必填,该字段可以不设置 - data 格式类似字典,使用键值对将数据写入
<t t-esc=" "/> 为QWEB的语法用于传入值
对于单独的数值我们可以一个个这么传值,但对于多条明细就需要使用循环了,前面说过docs即使模型的所有记录集合
<t t-foreach="docs" t-as="doc">
var data = {
"delivery_id": "<t t-esc="doc.id"/>",
"name": "<t t-esc="doc.name"/>",
}
<!--循环生成记录然后存入data中-->
_tableCompany.Data.push(data)
</t>
最后将数据集放入_data的Tables中
_data["Tables"].push(_tableCompany);
/* 可以放入多个表的JSON格式 */
_data["Tables"].push(XXXXXX);
/* 最后把json结构转成字符串 */
var _reportData = JSON.stringify(_data);
/* 在浏览器控制台上打印一下json,以便于排错 */
console.log(_reportData);
-
康虎伺服机
image.png
双击设计随便填点数据就能进入模板设计器了
- 个人改动部分
康虎的js中没有连接成功时只有console中有提示信息,正常用户无法得知,因此我增加了一个alert作为用户提示,另外原本的康虎是关闭新增的报表页面,可是我的odoo10中报表并没有新弹出个页面,而是在原本的页面,所以我将延时后关闭页面改为了回退上个页面,也就是打印报表之前的页面了,这些改动都在cfprint\static\src\js\cfprint_ext.js进行更改。
cfprint.log("连接已断开,正在重新连接。");
// 在这增加连接失败提示
alert("未连接到打印服务器,请检查打印机并打开康虎云打印");
if(_delay_close>0)
//改为延时后退回打印前界面
setTimeout(function(){window.history.back(-1);}, _delay_close);
另一个方面,康虎云打印要在js中指定伺服器打印地址(因为知道地址后js才能和伺服机进行通信),如果打印机都在本机那就好说了可以写死为127.0.0.1,而在常规使用中一般是一个局域网内一台电脑连接打印机,而其他机器都是远程打印的,所以我在模型中添加了一个ip字段,用于存储连接了打印机电脑的ip地址.
class OdooModel(models.Model):
_inherit = "cf.template"
ip = fields.Char(u"伺服机ip地址", default="127.0.0.1")
之后我们在js配置中将cfprint_addr改为i从模型中取值,这样就避免了多次改动代码,可以通过模板中的ip地址手动选择伺服机的ip地址
var cfprint_addr = "<t t-esc="user.env['cf.template'].search([('templ_id', '=', 'report_sell_delivery')], limit=1).ip" />";
image.png
网友评论