近来将RedMine的源代码下下来进行研究,主要目的是研究它的Report功能是如何实现的
目前研究结果总结为几点:
1)Remine界面上支持PDF,CSV,HTML输出,但没有单独的报表运行中心,只有在Issue及Gant界面有报表输出功能
2)新建两个用户a和b,a用户在创建时默认语言选择“English”,b用户选择"Chinese(Simple)",进行报表打印时发现第一个用户打印出来的PDF报表中文显示为乱码,第二个用户打印的PDF报表中文显示正常
对于以上两点,进行了代码跟踪,得出了以下结论
1)报表输出的代码写在IssuesController,关键代码如下:
代码中很清晰看到CSV、PDF 的输出调用的是 issues_to_csv,issues_to_pdf(Gant界面的报表调用的是gant_to_pdf)
从名字可猜测Redmine中的报表打印并不通用,只是针对特定的报表进行了固定的输出处理
issue_to_pdf,issues_to_pdf,gant_to_pdf都包含在pdf.rb中,代码如下:
而issues_to_csv包含在IssuesHelper中
由以上的代码可以得出结论:RedMine中只有甘特图、问题界面支持报表输出,而且不是每一个地方都支持PDF与CSV两种格式的
2)为什么默认语言类型不同的用户输出相同的报表会得到不一样的结果(关于中文乱码)
要解释这个问题,重点在pdf.rb中
RedMine中对PDF的输出用的是FPDF,FPDF中支持中文输出,它内嵌了GB、Big5字体,对于中文的输出需要做两步
1、在输出PDF之前设置输出字体为 GB或Big5
2、对于中文在输出之前进行字符集转换,从UTF-8转换成支持中文的字符集(如GBK,GB2312)
那么PDF是怎么做的呢?
首先,看以下代码:
对于默认语言为“English”的用户,登陆后观察current_language的值,发现为"en"
对于默认语言为"Chinese(Simple)"的用户,登陆后观察current_language的值,发现为"zh"
那么current_language的值是怎么得到的呢?
在Redmine中有些配置文件,其中涉及到default_language的设置,默认都设置为"en",尝试改为"zh",发现current_language的值没有发生改变
在研究了其他的源代码发现current_language的值与数据表users中的LANGUAGE字段关联
在ApplicationController中发现以下代码:
既然a用户和b用户因为默认语言不一样导致current_language不一样,那么如果在PDF.initilize中将current_language强制设置为"zh",是否就能得到一样的结果呢?测试结果发现,即使这样设置,a用户打印的PDF报表中文仍然是乱码,不同的是,乱码与之前的不一样。
问题到底出在哪呢?
继续研究,发现PDF中的Cell方法(FPDF输出的关键方法之一)中有这么一句:
原来在这里进行了字符集转换,那么a用户与b用户得到的 l(:general_pdf_encoding)是否用相同呢,测试发现,
a用户进入系统后得到的值为"ISO-8859-1"
b用户进入系统后得到的值为"gb18030"
单独FPDF输出报表进行测试,发现
在选择 GB 字体的情况下,
Iconv.conv("gb18030","UTF-8","测试")与 Iconv.conv("ISO-8859-1","UTF-8","测试")得到的结果不一样,前者是正常显示中文,后者则显示乱码
至此,以上两点疑问都得到了解释,这些就是到目前研究RedMine报表应用得到的结论