在Alfastrakhovanie中,我们积极使用“ Wiki”,其引擎是Atlassian Confluence。 第一次认真尝试(试图在其中创建内容)时,我缺乏“动态性”-我希望能够以编程方式形成页面的一部分,并与其他系统进行交互等。
有一段时间,他把头撞在不同的墙壁上,但是后来他看到“房子里没有一堵墙壁”。 我想分享我的经验-如何在Confluence中添加发言人。 我希望这对使用它的人有用。 而且,像往常一样,对每个人都有好奇心。
动态维基
最初,Confluence提出了一种扩展其功能的通用方法-插件。 他可能很好,只有一个缺点-较高的入门门槛(您需要学习很多知识)。
简要回顾一下(按空间标准)后,有两种更简单的方法来扩展其功能:标准宏“ HTML”和“ HTML Include”,在本文中,我将更详细地介绍后者。
这些方法有一个操作原理-HTML代码嵌入在Confluence页面中,它可以是静态的(对于非标准页面格式,这也可能是有趣的),可以是动态的(包括服务器组件)。
示例:对帐请求
让我们通过一个简单的示例(文档批准列表)来看看扩展Confluence功能的建议方法。
我们想要做的是:在页面上添加批准列表,以便每个人都可以看到谁应就该文档达成一致,是否达成一致以及何时达成一致。
为方便起见,我们将列表项设为按钮,并在其中输入协调器的名称。 如果协调员查看了该页面,则该按钮将处于活动状态,而在所有其他情况下,该按钮将不处于活动状态。
批准后,按钮“将不再是按钮”-而不是批准后的按钮,我们在页面上以文本形式(批准者名称和批准日期)绘制批准事实。 在最草稿的版本(无设计)中,可能看起来像这样:

互动方案

评论-运作方式:
- Confluence中的页面包含多个宏“ html包含”-实际上是带有参数的HTTP GET请求(我们将在下面更详细地考虑)
- 呈现页面时,这些请求(python脚本)在应用程序服务器上执行,结果(生成的HTML)绘制在页面上
- 例如,在脚本的工作过程中,如果页面尚未被签名者“签名”,则脚本将使用页面签名的历史记录与数据库联系-HTML将包含一个按钮(如上所述)
- 当您单击按钮时,将提交-另一个python脚本被调用(用于处理对帐事实的脚本)
- 该脚本将有关登录事实的信息保存到数据库中,并将用户重定向到原始页面(渲染时将考虑签名事实-单击“签名”按钮)
言语有点复杂,让我们尝试澄清代码。
所以我们需要创建两个脚本
- 用于形成“签名”按钮的脚本(我将其称为“按钮”脚本)
- 一个用于计算签名事实的脚本(对按钮单击的反应-我将其称为“处理程序”)
让我们从按钮开始创建它们。
脚本按钮
从原理上讲,按钮脚本是如何工作的:
date = getSignDate() if date:
该脚本应该是有效的HTML文档,其主体以最小的形式是一个表单
- 表单的动作包含脚本的URL
- 活动按钮已提交
- 隐藏的表单字段包含处理程序的其他参数(在我们的示例中,页面名称和签名者登录名)
脚本的大概视图(为简洁起见,我丢弃了所有不必要的内容-参见github上的完整工作代码)
form = cgi.FieldStorage() signee = form["signee"].value
脚本“处理程序”
处理程序的任务非常简单-修复按下“同意”按钮的事实。 然后重定向回请求来自的页面-呈现页面时,已经考虑到协调的事实(请参见上面的描述)。
一个示例(缩写)脚本“ handler”(完整版本-请参见github)
form = cgi.FieldStorage() signee = form["signee"].value
汇合页
Confluence中的页面包含三个带有不同参数的宏HTML包含(请参见下面的代码),最简单的版本如下所示:

Wiki标记格式的页面代码-在这里您可以看到参数
<h1> </h1> <p> , </p> <h1> </h1> <ul> <li> <ac:structured-macro ac:macro-id="..." ac:name="html-include" ac:schema-version="1"> <ac:parameter ac:name="url"> <ri:url ri:value="http://z14-0510-wiksap.vesta.ru/misc/sign_btn.py?signee=boss&actual=korolevmv&id=wikitools_sign"/> </ac:parameter> </ac:structured-macro> </li> <li> <ac:structured-macro ac:macro-id="..." ac:name="html-include" ac:schema-version="1"> <ac:parameter ac:name="url"> <ri:url ri:value="http://z14-0510-wiksap.vesta.ru/misc/sign_btn.py?signee=korolevmv&actual=korolevmv&id=wikitools_sign"/> </ac:parameter> </ac:structured-macro> </li> <li> <ac:structured-macro ac:macro-id="..." ac:name="html-include" ac:schema-version="1"> <ac:parameter ac:name="url"> <ri:url ri:value="http://z14-0510-wiksap.vesta.ru/misc/sign_btn.py?signee=maxvar&actual=korolevmv&id=wikitools_sign"/> </ac:parameter> </ac:structured-macro> </li> </ul>
关于设置的一点
为了使所描述的方案起作用,有必要考虑以下因素
HTML包含宏的可用性
有时,管理员“隐藏”它-这样做有很多其他麻烦(可能性的另一面)。
此宏是免费的,并且是Confluence的一部分-如果您没有宏,请与管理员联系,让他们看看...
融合白名单
Confluence不会执行托管在未知来源上的脚本,托管脚本的主机应位于所谓的“白名单”中(请与管理员联系)。 这仅适用于“按钮”脚本-处理程序的脚本已由按钮调用,Confluence限制不适用于该按钮。
脚本执行
脚本(按钮和处理程序)必须是可执行的-将URL复制到浏览器,它应该可以工作并生成HTML,如果没有发生,请对其进行调试。
脚本错误
如果任何脚本因错误而崩溃-您将看不到任何好消息,请在将其发布到Confluence之前进行正确的调试。
脚本选项
询问者可能会注意脚本参数-一方面,它们是多余的(例如,放置批准按钮的页面名称-是否已知,为什么要填写?)。 另一方面,它们是不安全的(在我们的示例中,“攻击者”可以将批准者的名称更改为自己的名称,也可以完全删除对帐按钮)。
冗余可以被用户宏“克服”(我很久以来一直想知道-它们在实际中如何有用?我将在另一篇文章中简短地写一下)。 页面历史记录确保了Confluence的安全性-记录了所有“动作”,您可以更改任何内容,在Confluence中,还有一个很棒的“审核线索”,可让您详细了解谁更改了内容和时间。
页面互动
在我们的实践中,有些情况下我们不得不解析页面代码以收集数据(例如,这就是我们管理项目组合的方式)。 这是可能的,甚至不是太困难。 从进化上,我们得出的结论是,如果仅页面上的某些信息仅用于解释该信息的代码,则此信息更易于立即在代码本身中表达(例如,以JSON的形式):以页面编辑模式进行编辑非常简单,它是由程序绘制的,但在解析和节省的可靠性方面可节省大量资金。
更多例子
为什么我们还要简短地使用这些宏(作为想法-突然证明有用)
页面设计:如果要以非标准方式设计页面-使用CSS标记,HTML包含在HTML块中
假期日历 :我们使用一些简单的JS日历,将JSON中的数据填充到其中,然后直接在页面代码中进行编辑,我们得到了一个漂亮的图板,其中列出了假期(年,月,周)的详细信息。
打印Scrum板的任务卡 :我们在Wiki页面(HTML块)中的表单中设置参数(Jira中的任务号和其他属性),服务器端以适合发送给打印机的形式形成卡片。
项目组合管理 :我们有这样的想法。 在Wiki上对地图进行了评分(分数地图是一个特殊标记的页面),这些地图收集了一个大块计划,该计划以甘特图的形式绘制精美。
词汇表 :可以从通用词典中可视化术语(对页面各个单词的解释)并以“弹出窗口”的形式发布词典条目的能力。 字典本身会自动收集在页面底部。
图表 :如果您需要绘制某种简单的图表,则可以通过将HTML块嵌入到任何标准包(Google图表,HighCharts等)中来完成此操作,这非常简单
表格 :在Confluence中任何表格的顶部,您都可以“挂起”数据表-我们获得了带有“分页”功能的经过过滤的表格,非常方便。
该列表可以持续足够长的时间,在操作过程中,注意到一个重大的不便之处:服务器代码中的错误被捕获得很差-500个错误的可视化效果很差,并且实际上不包含任何信息。 否则,请进行实验-足够安全。
总结一下
上面描述的增加Confluence的动态性的简单方法使您能够解决许多不同的问题。 要使用它,不需要特殊的工具和技能。 使用足够安全。 我推荐。
在下一篇文章中,我将讨论在Confluence中使用自定义宏的经验-在我看来,借助它们的帮助确实可以改善这种体验。
编程中的一切皆有可能-仅是时间和动力问题。