在我的Grails项目中,我使用PDF插件从gsp页面生成PDF。
效果很好,但我想为用户添加更多功能,所以我想允许用户编辑PDF基本模板(在gsp页面中定义),特别是我想允许编辑模板中的文本并将其存储在某处。
有人知道怎么办?
答案 0 :(得分:1)
如果您只想更改文本,可以将编辑后的文本存储在具有用户ID的数据库中,并将其加载到gsp页面而不是标准文本中。
如果您还想更改页面样式,可以尝试将整个gsp页面存储在数据库中,然后让用户使用HTML编辑器对其进行编辑。
这就是我的开始,也许有人有更好的主意
答案 1 :(得分:1)
pdf插件的基础组件并不严格要求.gsp文件。它只是使用.gsps呈现为字符串并将它们提供给flyingsaucer lib。因此,您可以使用WYSIWYG类型编辑器来允许用户创建html片段,以某种方式保存这些字符串,然后自己将这些字符串提供给flyingsaucer库。只需查看插件的附带服务方法即可。这可能听起来很可怕,但实际上并不复杂。
当然,您可能希望用自己的HTML标记包装用户生成的内容,以达到理智和样式目的,但您想要的想法是完全可行的。
答案 2 :(得分:1)
你可以拥有一种表现出两种不同方式的GSP。首先,GSP将呈现为可编辑状态。在这种状态下,用户可以在GSP的某些部分进行一些编辑。之后,GSP将呈现为预览状态,用户可以检查他在上一步中所做的修改(在此状态下无法编辑任何内容)。最后,GSP将呈现为PDF(使用Grails渲染插件)。
请注意,用户不会编辑GSP本身。例如,您需要允许他通过HTML元素编辑为文本区域。在这种情况下,我们使用的是WYSWYG编辑器。该编辑器允许用户将文本设置为Bold,Italic等。
因此,该解决方案最重要的步骤是区分同一GSP中的两个状态。为此,您可以使用布尔变量(例如,称为编辑)。此变量(如果为true)将为GSP提供允许他在文档中执行更改的元素。另一方面,如果编辑变量为false,则GSP将仅使用文本呈现,不允许任何类型的编辑。
用户可以选中或取消选中复选框(显示或隐藏文档的某些部分),并在文本区域元素中写入或更改文本。
下面我将展示此解决方案的工作原理。
<强> GSP 强>
GSP是模板GSP,名为_quote.gsp
下面的代码段显示了编辑变量的使用。请注意,如果editing = true,则会呈现textarea,用户可以编辑该文本。有一个标准文本可以更改。
post变量保留用户在编辑阶段后所做的操作。我们使用JQuery序列化来获取所有参数并将其传递给Grails控制器。
<p>
<g:if test="${editing}">
<pgs:textArea html="true" autosize="true" name="fraseInicial" rows="2" cols="80">
${post?.fraseInicial?post.fraseInicial:"Conforme sua solicitação, a empresa tem a satisfação de informar-lhe os métodos e preços."}
</pgs:textArea>
</g:if>
<g:else>
${post.fraseInicial}
</g:else>
</p>
pgs:textArea是此系统的特定标记库,用于呈现WYSWYG编辑器,您可以将其替换为简单的TextArea HTML元素。
带复选框的示例:
<g:if test="${editing || post.temPrazoAnalise}">
<h1>
Teste teste
</h1>
<g:if test="${editing}"><g:checkBox name="temPrazoAnalise" value="${!post?true:post?.temPrazoAnalise == null?false:true}"/></g:if>
<g:if test="${editing || post.temPrazoAnalise}">
<p>Teste teste teste </p>
</g:if>
</g:if>
<强>控制器强>
从AJAX调用中调用previewQuote(),该调用序列化(通过JQuery)GSP的所有参数。
back()动作允许用户从预览状态返回编辑状态。这就是我们在previewQuote()中设置session [“paramsReport”] = params的原因。这样做可以在back()中使用session [“paramsReport”]并恢复用户改变的值。
def editQuote() {
def quote = Quote.get(params.id)
render(template: "/quote/report/quote", model: [editing:true, quote:quote])
}
def previewQuote() {
Quote quote = Quote.get(params.id)
session["paramsReport"] = params
render(template: "/quote/report/quote", model: [quote:quote, post:params])
}
def back() {
def quote = Quote.get(params.id)
if (session["paramsReport"]) {
render(template: "/quote/report/quote", model: [editing:true, post:session["paramsReport"], quote:quote])
}
}
def generateQuote() {
Quote quote = Quote.get(params.id)
def f = new File(grailsApplication.mainContext.servletContext.getRealPath("/app/temp/${quote.code}.pdf"))
if (f.exists())
f.delete()
f.withOutputStream { os ->
pdfRenderingService.render([template: '/quote/report/quote', model: [quote:this, post:session["paramsReport"], pdf:true]], os)
}
}
这个解决方案是由wanderson-santos(https://stackoverflow.com/users/128857/wanderson-santos)和我开发的。
我希望您了解解决方案的整体构思。据我所知,第一种观点可能有点复杂。无论如何,这是一种允许灵活满足此类要求的解决方案(即允许用户在生成PDF之前自定义报告)。