设计 所见即所得编辑器 例程库过程详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

设计所见即所得编辑器例程库过程详

设计"所见即所得编辑器"例程库过程详解2011-04-06 12:11设计"所见即所得编辑器"例程库过程详解
发表于2007,January 18,5:14 PM
也许你已经习惯于使用Word进行文档的编写和编辑,因为它提供了强大的"所见即所得"类型的编辑器,使得对文档的编排更容易进行,但是Word毕竟是只能在单机使用,如果也想在Web上使用类似Word的功能怎么办呢?这个问题
其实很多的论坛程序已经给出了答案:集成Web形式的"所见即所得"编辑器控
件(这里说的控件并不是指微软的ActiveX)。

目前比较成熟的Web形式的"所见
即所得"编辑器有两个:TinyMCE和FCKEditor。

其中的TinyMCE,从名字中就可以看出,Tiny本来就有小的意思,其实它
并不小,而是轻量级的,集成它特别简单,简单到只需两行代码(当然其它的图片资源文件是要首先放在合适的位置),然而轻量级并不意味着简单,TinyMCE
能实现Word的许多基本功能,并且程序支持自定义,可以简易的对其进行扩展。

FCKEditor可以说是Web形式的"所见即所得"编辑器的大哥大,从其网站
上面的演示即可看出,它提供了许多的工具栏,并且加入了Web中经常使用的
一些元素的直接操作(按钮),可完全定制的样式和工具栏按钮显示,多种语言
的自动检测并显示,等等等等,要查看关于它的更多信息,请访问它的网站。

值得一提的还有另外一件事:上面提到的两个Web形式的"所见即所得"编
辑器都是OpenSource的,不必担心侵权:-)
本文将以集成TinyMCE为例进行讲解,毕竟集成它还是比较简单的:-)
本文将按照真实项目的方式来讲解,其中涉及到需求报告的形成、概要设计、详细设计、编码、测试、发布、维护等等阶段。

^_^看了上面的介绍是不是很兴奋?本文作者也想那样写,不过毕竟这是个人作品,没有太多的条条框框的束缚,能省的就省了:-)
本文将按照下面的步骤进行讲解:
程序界面构思及界面区域划分,根据界面区域划分,确定每个区域需要实现的功能
设计第二点中的功能(编写各种数据库元素,比如表单、视图、子表单、代理等)
集成TinyMCE
测试并发布
第一节程序界面构思及界面区域划分
为了能更好的表现完成后的作品,以及对其进行介绍,例库使用三个页面来表现:本数据库简介、编辑器演示和所有演示文档。

其中"本数据库简介"页面主要用来对本数据库进行介绍以及对TinyMCE进行一些简单的介绍,让使用者首先了解一些基本的内容;"编辑器演示"页面就是集成TinyMCE之后的页面,用以对其功能进行演示;"所有演示文档"页面用来显示所有保存的演示文档,任何人都可以对其进行编辑和删除。

界面基本上就是这三个页面,但是为了让例库更美观,需要加入网页设计中常用的Banner和Footer。

Banner使用作者设计的图片,图中显示了编辑器一部分,可以直观的看出本数据库的用途,Footer部分主要是版权的显示。

构思好的界面以及区域划分见下图。

第二节子表单设计
经过规划好的界面,需要使用一种设计元素来表现出来,在DreamWeaver 等工具中,这个过程就是创建"页面",而在Domino中,页面的作用已经不是很大,表单承担起了几乎全部界面的表现和动态执行等工作,其实也可以理解,
因为在DreamWeaver中,页面里面是需要嵌入一个或者多个表单,这样的页面
才是"有生命"的页面。

在第一节中,已经将界面规划好了,共三个表单,每个表单分为三个部分:顶部的Banner,中间的内容部分、底部的Copyright部分。

由于每个表单都有
顶部的Banner和底部的Copyright部分,所以这两部分可以做成一种通用的元素,在Domino中已经考虑到了这个需求,那就是:子表单。

子表单可以在数据库标签里面的"共享代码"里面找到。

下面讲解建立子表单的过程。

要建立子表单,需要在数据库标签中展开"共享代码",然后单击其中的"子表单"项,之后在Designer右侧的视图中就显示出此数据库中已经存在的子表单,如果是新建的数据库,列表就是空的,单击列表上方的"新建子表单"按钮,Designer打开一个空白的子表单设计界面,我们可以在其中进行设计工作,下
面我们以建立用于表现顶部Banner部分的子表单为例来讲解。

顶部的Banner为了取得比较好的视觉效果,我们用图片来表现它,这时就需要使用我们掌握的HTML知识了,表现图片的HTML方式的代码如下:
上面代码中的jpg只是图片的一种类型,当然也可以换成其它类型,为了
让图片路径更简单,我们可以直接将图片放到数据库的资源里面,然后在需要
使用的地方就可以用"/数据库名/图片名"的方式来调用图片了,设计好的顶部Banner子表单(命名为"TopBanner")的界面如下图所示
图中的"ThisDB"域是一个"显示时计算"的域,计算公式为:
@WebDbName
就是取当前数据库的名称(带路径),然后加上斜线和图片名字,最后还要
将这行代码内置为HTML(选中要内置的行,然后选择菜单中的"文本"-"内置HTML"),都设计好之后,将子表单保存,然后关闭。

底部Footer部分的设计过程和Banner部分的类似,只不过使用了更复杂的HTML代码,用表格的形式来表现,设计好的footer部分的子表单如下图所示:
这样一来,表现顶部的Banner部分和底部的Footer部分的子表单就设计好了,如何在设计过程中使用子表单,请查看本文的"表单设计"一节(第三节)
第三节表单设计
上面第二节中讲过,在Domino的Web开发中,主要是使用表单来表现用户界面,本节就讲述表单的设计过程。

经过第二节的子表单的设计,一些通用的元素已经设计出来了,为了在表单中取得当前服务器的CGI信息,本例库中还设计了一个"CGI"子表单,用来取得CGI的值,首先将CGI子表单加入到表单中。

注意:某些域的放置顺序(表单的上面和下面)都有关系,注意将下面用到其值的域放在上面。

要建立表单,需要在左侧的数据库书签中找到表单分类,然后在右侧的表单列表中单击"新建表单"按钮,一个空白的表单就显示在Designer中,要将CGI子表单加入到表单中,需要单击菜单:创建--资源-插入子表单,然后在弹出的对话框中选择"CGI"子表单,如下图所示:
单击"确定"按钮,即可将子表单插入到表单中的光标位置,如果为了在设计界面中显示更多的其它元素,还可以将子表单做成计算类型的,那样就需要在"插入子表单"对话框中,选中对话框底部的"根据公式插入子表单"复选框,这样就不能用鼠标选定子表单来插入,而要先单击对话框中的"确定"按钮,然后在表单中显示的"计算子表单"上面单击一下,在下面的代码框中填写要插入的子表单的名字,如下图所示:
插入子表单后,还要进行表单功能以及界面的设计,这就需要用到基本的Web页面语言HTML了,还有就是要使用Domino本身的的设计元素来实现所需要的功能(比如用按钮来触发某个事件),为了让Domino服务器能正确解释我们输入的HTML代码,我们需要将输入的HTML代码内置为HTML(选中需要内置的
部分,选择菜单:文本--内HTML),这样Domino服务器就能正确按照我们所写
的代码来显示表单,下图为设计好的"HTMLFormAdv"表单(此表单用来实现"所见即所得"编辑器的功能)。

图中的HTML代码在此不做解释,因为在任何一本讲解Web开发的入门书籍中都有对它们的解释,下面主要讲解其中的Domino特有的设计元素:域和按钮。


Domino中的域有两种,一种是域名的域,还有另外一种域是用来输入或者
显示内容的域,也就是HTML语言中的input类型为文本的元素,本文主要讲解后一种域。

Domino中的域比HTML中的简单的文本输入框要复杂的多,它可以被设置
成各种类型(比如文本、密码、RTF、数值、单选按钮、复选按钮等等,可以通
过域的属性窗口进行调整),上图所示表单中的"Subject"域的属性窗口如下图
所示:
从图中可以看到,Domino的域可以设置将近20种类型,并且可以通过类
型右侧的下拉列表选择域是否可以输入还是使用计算方式显示。

本例库中的Subject域只是用来输入文档的标题,所以就只设置为"文本"
类型,并且可以编辑(也就是可以输入内容),并且默认值为空,也就是在用这
个表单新建文档的时候,这个域是空白的,如下图所示:
在标题域的下面,还有一个"yimingstudio"域,类型为RTF,可编辑类型,由于集成"所见即所得"编辑器需要一个HTML Area元素,而在Domino中只有RTF类型的域在Web中能自动转换成这种类型,所以我们把它作为"所见即所得"编辑器的载体,关于集成TinyMCE的讲解将在后面详细阐述,这个域的属性如下图所示:
HTML属性如下图所示:
按钮
Domino中的按钮和HTML中的功能相同,都是用来触发某些事件。

不过Domino中的按钮使用起来更灵活一些,可以自由设定其显示效果,可以通过CSS来进行效果的调整等等。

本例库中的按钮分为两类:一类是在Web页面中能看到的按钮,一类是在Web页面中看不到的按钮。

[blockquote style="margin-right:0px;"dir="ltr"]
在Web中能看到的按钮
此类按钮用来在Web页面中来实现各种功能的提示以及执行事件之前的确认,比如在删除之前的确认,可见按钮的图片如下:
此表单共有三个可见按钮,用来实现对文档的操作(保存、编辑和删除),并且每个按钮都有不同的隐藏条件,因为按钮需要在文档的不同状态下显示(编辑状态和读状态);另外还需要为每个按钮编写相应的代码,才能让它在界面中显示出来,如果没有为按钮编写任何代码,在浏览器中将不会显示按钮。

要设置按钮的隐藏条件,需要打开按钮属性对话框,并选择相应的标签,如下图所示:
上图是"编辑文档"按钮的属性窗口中的隐藏条件标签,从图中可以看出,只是勾选了几个复选框,就可以实现简单的隐藏,如果需要隐藏的元素有很多需要满足的条件,那就需要在下面的公式窗口中编写隐藏公式了,本文不对隐藏公式做介绍。

图中勾选的意思就是当文档处于编辑状态时,隐藏编辑文档按钮,另外两个可见按钮的隐藏属性设置类似,不再赘述。

功能复杂的可见按钮有时需要得到用户确认才能继续执行,执行时一般是调用后台代理,而JavaScript代码调用代理很麻烦(要用到微软的XHTTP),所以就去调用页面中的不可见按钮,来达到执行代理的目的;功能简单的可见按钮就可以直接执行相关的公式来达到简化代码设计的目的("编辑文档"按钮就是直接使用公式来使文档转换到编辑状态),下图是"删除文档"按钮的代码,从中可以看到,要执行删除操作,需要先得到用户确认,然后才能继续执行删除。

代码中的document.all("deldoc").click();就是调用不可见按钮的代码,不可见按钮有个名称,在其属性窗口的最后一个标签中可以进行设置。

Web中看不到的按钮
在Web中看不到的按钮一般用来执行后台代理,达到操作文档的目的。


见按钮将会调用相应的不可见按钮,来执行相关的代理,而在执行代理之前,
可以取得用户的确认(JavaScript代码就是设计用来在客户端执行确认操作的),由于不可见按钮都是通过DOM中的名称来调用的,所以需要设置其名称,要设
置其名称,需要打开其属性窗口,选择最后的一个HTML标签,如下图所示:
从图中可以看到,按钮执行的是"deldocument"代理,设置的名称为"deldoc"。

[/blockquote]
表单中其它内容
表单中的其它内容都是配合上面介绍的域和按钮而编写的HTML代码,主要作用是使表单中的各种元素显示的更美观一些,可以参照讲解HTML的书籍进行查看。

表单作为Domino的Web开发中的主要表现元素,其中的元素不外乎上面介绍的几种:域、按钮和HTML代码等,复杂的Web应用中,表单中的元素可能更多一些,但是对于入门的程序员来说,这些元素足够来构建常见的应用程序了。

下面的章节将介绍配合表单运行的"视图"、"代理"等元素,由于代理中要
使用相关的视图,所以视图和代理将放在一个章节中进行介绍。

第四节代理和视图设计
上一节中介绍的表单设计中,还有一部分没有介绍,因为涉及到了表单执
行动作所用的代码部分,本节进行介绍。

要保存录入的内容,只要单击页面中的"保存文档"按钮,为了让"保存按钮"能够在Web页面中显示出来并且执行正确的功能,需要为其编写代码,上一节
中看到的"删除文档"按钮的代码是JavaScript,保存按钮需要验证的内容更多,所以也用JavaScript来编写,查看脚本时会发现,只有一句话:
doSubmit();
这是什么意思呢?其实它执行的是一个函数,这个函数在表单的"JS Header"中编写,代码如下:
function doSubmit()
{
var objForm=document.forms[0];
if(objForm.Subject.value=="")
{
alert("请输入标题")
objForm.Subject.focus();
return false;
}
tinyMCE.triggerSave(true);
if(objForm.yimingstudio.value=="")
{
alert("请输入内容");
return false;
}
objForm.runagent.click();
}
这段代码的作用就是验证表单中的某些需要录入文字的地方是否为空,如
果为空,就提示用户录入,中间的tinyMCE.triggerSave(true);作用是调用TinyMCE的函数,来保存内容;最后的objForm.runagent.click();是执行保
存Domino文档的代码,它去执行了表单中一个不可见按钮的单击事件,按钮再去执行后台的代理。

我们来看看那个按钮的单击事件中的代码:
@Command([ToolsRunMacro];"savethis")
这个公式就是去执行本数据库中的"savethis"代理,要查看代理,需要打
开数据库的"共享代码"分类,然后单击其中的"代理"标签,右侧的视图中就会
显示出当前数据库中所有的代理。

我们找到"savethis"代理,双击可以打开它,打开它的时候,Designer会自动打开代理属性对话框,如下图所示:
注意图片最下面的Runtime分类里的"Target"下拉列表,在新建代理的时候,默认是"All Selected Documents",需要修改成"none",否则执行代理的
时候会报告一个运行时错误。

如果代理被设计用来定时或定期执行,就需要在"Trigger"(触发)单选框中选择"On schedule"选项,然后在下面选择对应的选项,在此不再做深入介绍,有兴趣的可以自行试验。

代理属性窗口中还有一个"Security"标签(就是一个小钥匙的那个),可以
用来设置运行代理的权限,如下图所示:
为了能使代理为很多登录Domino服务器的用户服务,我们可以勾选"Run
as web user"复选框,这样就不只是签名代理的用户能运行此代理了,这个代
理设计时允许所有用户都可以运行它(包括匿名用户:Anonymous),所以不必勾选此项;下面还有一个下拉列表框:Set runtime security level:",这个选项用来控制当前用户是否可以执行某些限制性的操作,比如删除文档和编辑文
档,共分为三个等级,第一级是最安全的,但是在使用的时候有些不太方便,第三个级别权限最大,相应来说也最不安全,但是在局域网的条件下,可以选用第三个选项来获得更多的易操作性。

下面分析一下代理的代码,看看代理都执行了哪些操作来保存文档,代码如下:
(Options)部分:
Option Public Option Declare
此部分代码的第一行是新建代理时Designer自动创建的,第二行是自行添加的,作用是:在编写程序时必须先声明变量,然后才能使用变量,否则编译时报错。

Initialize部分:
Sub Initialize On Error Goto handle_error Dim vWebSession As New notessession Dim vThisDatabase As notesdatabase Dim vThisDocument As notesdocument Dim vRichStyle As NotesRichTextStyle Dim vRTItem As Variant Dim vHTMLCode As Variant Set
vThisDatabase=vWebSession.CurrentDatabase Set
vThisDocument=vWebSession.DocumentContext Set
vRichStyle=vWebSession.CreateRichTextStyle
vRichStyle.PassThruHTML=True Set
vRTItem=vThisDocument.GetFirstItem("yimingstudio")
If(vRTItem.Type=RICHTEXT)Then
vHTMLCode=vRTItem.GetUnFormattedText()
Call vThisDocument.RemoveItem("yimingstudio")
Set vRTItem=vThisDocument.CreateRichTextItem("yimingstudio")
Call vRTitem.AppendStyle(vRichStyle)
Call vRTitem.AppendText(vHTMLCode)
End If vThisDocument.form="HTMLFormAdv"
Call vThisDocument.Save(True,True)
Print|[script
language="javascript"]|[br/]Print|window.location="[a
href="color="#808000"]color="#808000"]|+vThisDocument.WebDBName(0)+|/ all/|+Cstr(vThisDocument.Universa
lID)+|?opendocument"|[br/]Print|[/script]|
Exit Sub handle_error:
Exit Sub End Sub
此部分是整个代理的主体部分,几乎所有的功能都要在这里实现,这段代
码的主要功能是保存当前用户录入的内容,将其保存为一个Domino文档,并且保留了编辑器中的各种格式。

要实现上述功能,其实只需要对当前表单中的一个RTF类型的域进行操作
即可实现,从代码中可以看出,主要就是围绕着那个名字为"yimingstudio"的RTF域来进行操作:
1.从当前表单中找到这个域,然后判断其是否为RTF类型
2.如果是RTF类型,就先把其中的内容和格式先赋到变量中,然后将其删

3.再新建一个同名的RTF域,再把变量中保存的内容和格式赋给此域
至于RTF域为何进行如此复杂的操作,笔者也不太清楚(板砖的不要:-)),只是从邮件模板中看到了此种方法,并且屡试不爽,于是借鉴了一下(看来需要好好研究一下邮件模板了)。

在操作完RTF域之后,就需要把当前表单保存为一个文档了,调用了document的save函数来完成保存。

后面的print部分是将浏览器页面转到刚刚保存的文档的页面,并使其在只读状态下打开;最后的"handle_error:"标签是错误处理部分。

这个代理的内容比较简单,涉及到的操作也不是很多,我们来看看"删除文档"按钮所执行的代理,这个代理更具有代表性。

之所以说删除文档的代理具有代表性,是因为它涉及到了代理的安全性,还有针对视图和文档的操作,这些内容在一个稍微复杂一些的应用中是很常见的操作,删除文档代理的属性窗口的"Security"标签如下图所示:
为了能让Anonymous(匿名用户)删除文档,我们就需要对"deldocument"代理进行安全性设置,并且调整其安全级别为2级,这样一来,在删除文档的时候就不会提示"无权进行此操作"了,代理的"Initialize"部分的代码如下:
Sub Initialize Dim session As New NotesSession Dim db As NotesDatabase Dim note As NotesDocument Dim view As NotesView Dim docunid As String Dim doc4del As NotesDocument Set
db=session.CurrentDatabase Set note=session.DocumentContext Set
view=db.GetView("all4del")
docunid=note.UniversalID Set
doc4del=view.GetDocumentByKey(docunid)
If Not(doc4del Is Nothing)Then Call doc4del.Remove(True)
End If Print|[script language="javascript"]|
Print|window.location="+note.Server_Name(0)+|:
|+note.Server_Port(0)+|/|+note.WebDBName(0)+|/AllDoc?openform";|
Print|[/script]|
End Sub
为了删除当前文档,需要在后台找到它来删除,如果直接删除当前文档(documentcontext)的话,会得到一个运行时错误:不能删除当前文档。

这样一来,只能从后台来执行删除操作。

要找到这个文档,还需要了解一下Domino各种元素的包含关系:数据库中包含视图,视图中包含文档。

这也就给我们指明了找到文档的方法,需要先找到包含文档的数据库(当前session的当前数据库),当前数据库中包含当前文档的视图(此视图的选择条件需要包含创建此文档的表单的名字,稍后进行讲解),然后就能找到文档了。

对应到上面的代码里面,大家可以依次看到上述的包含关系,找到当前文档的方法使用了N种方法中的一种:Set
doc4del=view.GetDocumentByKey(docunid),通过文档的UNID来搜索文档,由于每个文档有一个唯一的UNID,所以找到它并不困难,找到文档后,就对其进行删除操作:Call doc4del.Remove(True),使用了文档的Remove函数。

最后的print部分和上面的保存代理类似,还是将浏览器的页面转到另外的URL。

在使用上面的GetDocumentByKey(docunid)函数的时候,需要注意一个问题,那就是对视图的要求,在GetDocumentByKey(docunid)函数的帮助文档的描述中,可以知道:为了让这个函数正常工作,需要视图满足下列要求:
第一列为函数参数所要求的内容
第一列为排序列,升序降序随意
所以在设计视图时,就需要根据上面的两个条件进行设计,设计好的视图如下图所示:
由图中可以看出,第一列的值是一个公式:@Text(@DocumentUniqueID),将文档的UNID转换为普通文本(如果只是文档的UNID,将不会显示任何文字,需要特别注意),并且此列设置了升序排序,这样就符合了代理中的GetDocumentByKey(docunid)函数的要求,可以直接用当前文档的UNID来找到文档了。

本节简要介绍了例库中的两个代理及其属性设置,可见还是比较简单的,
在复杂的应用中,代理的代码量可能很大,但是基本操作不过如此,只是逻辑
更加复杂而已,只要业务精通,几乎可以实现任何逻辑。

下一节将介绍此例库的重点:集成"所见即所得"编辑器,以TinyMCE为例
进行讲解。

第五节集成TinyMCE
本文前面介绍过TinyMCE,还有另外一种方案是使用FCKEditor,但由于FCKEditor的"体积"比TinyMCE庞大很多,并且TinyMCE的功能也在逐步完善,故而本文采用集成TinyMCE的方式来实现web上的"所见即所得"编辑器。

TinyMCE是一个软件包,其中包含了界面显示所需的图片以及JavaScript
和HTML文件等,可以从上找到TinyMCE项目并下载,下载的是一个压缩包,将压缩包解压缩之后,就可以看到其目录结构了,如下图所示:
其中有一个"examples"目录,里面有三个.htm文件,打开任意一个,就可
以看到TinyMCE的庐山真面目了。

在页面顶端还有其它集成方式的链接,单击
后可看到相应的效果。

由各种效果中可以看到,Advanced方式提供的功能更多,并且可以对其工具条中的按钮进行定制,所以本例库就采用Advanced方式来集成它。

要将其集成到Domino中,还要看一下HTML页面中的实现方式,因为最后
在Domino中实现后也是要在浏览器中显示。

用记事本打开Advanced方式的那个.htm文件,查看它的HTML代码,可以看到代码并不复杂,开始处引用了TinyMCE的一个JavaScript文件,紧接着是一段脚本,脚本中定义了几个JS
函数,最开始的tinyMCE.init就是初始化TinyMCE编辑器的代码,后面的函数以备表单载入后使用,JS脚本如下图所示:
余下的代码是标准的HTML代码,主要作用是在页面中构建textarea,以
备TinyMCE使用,代码如下图所示:
由上面的代码可以看到,要使TinyMCE编辑器工作,需要引入它的JavaScript文件,并编写对其初始化的代码,然后在页面中准备好TinyMCE要
使用的textarea元素就可以了。

那么在Domino中如何实现引入文件和进行初
始化呢?这需要对Domino中使用文件的方式有一定了解。

要在Domino的表单中引入文件,有两种方式可以选择:
将文件放在Domino服务器的data目录中的domino目录里面的html目录
将文件直接存放在Domino数据库中
两种方式各有优缺点:放在html目录中的方式,可有效减小Domino数据
库的大小,但是在发布时,需要注意将html目录中相应的文件也拷贝到发布到的服务器的html目录中,如果忘记了拷贝,应用将不会正常运行;将文件直接存放在Domino数据库中,会减少发布时的繁琐,但是相应增加了Domino数据
库的大小。

权衡两种方式,为了发布时方便一些,本例库采用直接存放到Domino数据库中的方式。

要将文件存放到Domino数据库中,需要用Designer打开数据库,找到Shared Resources分类中的Files分类,选择它之后,右侧的视图将显示当前数据库中已经存在的文件资源。

要将文件添加到Files分类下面,需要单
击列表上面的New File Resource按钮,之后会弹出一个用来选择文件的对话框,可以选择多个文件,找到要添加的文件后,单击对话框中的Open按钮,稍候文件就保存到了Domino数据库中。

在集成TinyMCE时,需要注意一点:要保持存放到Domino数据库中的相关文件的"目录"结构不变,要做到保持原目录不变,需要将已经添加到Domino数据库中的文件改名,要给文件改名,可双击文件列表中需要修改名称的文件,
弹出文件属性窗口,在其名称前加上相应的目录名即可,如果要把a.htm文件
改动到相应的bb目录下面,则可将文件名称修改成这样:
bb/a.htm
当然在修改时还需要细心一点,不要搞错了名称,在使用的时候也要注意
添加文件的文件的"目录",否则将不会正常工作。

将文件保存到Domino数据库中之后的列表如下图所示:。

相关文档
最新文档