此产品的文档集力求使用非歧视性语言。在本文档集中,非歧视性语言是指不隐含针对年龄、残障、性别、种族身份、族群身份、性取向、社会经济地位和交叉性的歧视的语言。由于产品软件的用户界面中使用的硬编码语言、基于 RFP 文档使用的语言或引用的第三方产品使用的语言,文档中可能无法确保完全使用非歧视性语言。 深入了解思科如何使用包容性语言。
思科采用人工翻译与机器翻译相结合的方式将此文档翻译成不同语言,希望全球的用户都能通过各自的语言得到支持性的内容。 请注意:即使是最好的机器翻译,其准确度也不及专业翻译人员的水平。 Cisco Systems, Inc. 对于翻译的准确性不承担任何责任,并建议您总是参考英文原始文档(已提供链接)。
本文档介绍使用BOSH的Finesse连接背后的架构,以及如何诊断BOSH连接问题。
Cisco 建议您了解以下主题:
本文档中的信息基于以下软件和硬件版本:
本文档中的信息都是基于特定实验室环境中的设备编写的。本文档中使用的所有设备最初均采用原始(默认)配置。如果您的网络处于活动状态,请确保您了解所有命令的潜在影响。
使用同步HTTP上的双向流的连接称为BOSH。
可扩展消息传送和在线状态协议(XMPP)(也称为Jabber)是客户端 — 服务器模型中的状态协议。XMPP允许将小片结构化可扩展标记语言(XML)数据从一个实体快速传输到另一个实体。XMPP/Jabber广泛用于即时消息(IM)和在线状态应用。
所有XMPP实体都通过其Jabber ID(JID)进行标识。
JID编址方案:user@domain/resource
用户 |
XMPP服务器上的客户端用户名或会议室的名称 |
域 |
XMPP服务器完全限定域名(FQDN) |
资源 |
用户特定实体/终端的标识符(例如,笔记本电脑、智能手机等)、会话标识符或公共节点名称 |
注意:所有三种JID组件并非在所有情况下都使用。服务器通常仅由域定义,会议室由user@domain定义,客户端由user@domain/resource定义。
XMPP消息称为标准。XMPP有三个核心标准:
1. <message>:一个方向,一个收件人
2. <presence>:一个方向,向多个用户发布
3. <iq>:信息/查询 — 请求/响应
所有stanzas均具有往返地址,并且大多数stanzas也具有type、id和xml:langattributes。
Stanza属性 |
目的 |
到 |
目的JID |
从 |
源JID |
类型 |
消息的用途 |
ID |
用于将请求与<iq>标准响应链接起来的唯一标识符 |
xml:lang |
定义stanza中任何可读的XML的默认语言 |
<message to='person1@example' from='person2@example' type='chat'>
<subject> Team meeting </subject>
<body>Hey, when is our meeting today? </body>
<thread>A4567423</thread>
</message>
如果Web应用程序需要与XMPP配合使用,则会出现多个问题。浏览器本身不支持基于传输控制协议(TCP)的XMPP,因此所有XMPP流量必须由在浏览器中运行的程序处理。Web服务器和浏览器通过超文本传输协议(HTTP)消息进行通信,因此Finesse和其他Web应用程序将XMPP消息包装在HTTP消息内。
此方法的第一个困难是HTTP是无状态协议。 这意味着每个HTTP请求与任何其他请求都不相关。但是,这个问题可以通过应用方法(例如使用cookie/post数据)来解决。
第二个困难是HTTP的单向行为。只有客户端发送请求,服务器只能响应。服务器无法推送数据,因此通过HTTP实施XMPP是不自然的。
原始XMPP核心规范(RFC 6120)中不存在此问题,其中XMPP与TCP绑定。但是,如果您想解决绑定到HTTP的XMPP的问题,例如,由于Javascript可以发送HTTP请求,所以有两种可能的解决方案。两者都需要HTTP和XMPP之间的网桥。
推荐的解决方案包括:
1.轮询(传统协议):重复的HTTP请求,请求在XEP-0025中定义的新数据:Jabber HTTP轮询
2.长轮询也称为BOSH:传输协议,它通过高效地使用多个同步HTTP请求/响应对来模拟两个实体之间长期、双向TCP连接的语义,而无需使用XEP-0124:HTTP Binding中定义并由XEP-0206:XMPP Over BOSH扩展的频繁轮询
Finesse实施BOSH是因为从服务器负载角度和流量角度来看它非常高效。使用BOSH是为了掩盖服务器不必在出现请求时立即作出响应这一事实。响应延迟到指定的时间,直到服务器有客户端的数据,然后作为响应发送。客户端收到响应后,便发出新的请求,以此类推。
Finesse桌面客户端(Web应用)每30秒通过TCP端口7443建立陈旧的BOSH连接。30秒后,如果没有来自Finesse通知服务的更新,通知服务将发送一个HTTP应答,其中包含200 OK和(几乎)空响应正文。例如,如果通知服务更新了座席或对话(呼叫)事件的状态,则数据将立即发送到Finesse Web客户端。
此示例显示了Finesse客户端和Finesse服务器之间共享的第一个XMPP消息请求响应,用于设置BOSH连接。
Finesse client request:
<body xmlns="http://jabber.org/protocol/httpbind" xml:lang="en-US" xmlns:xmpp="urn:xmpp:xbosh" hold="1" ver="1.9" to="fin1.ucce.local" wait="30" xmpp:version="1.0" from="47483648@fin1.ucce.local" rid="704654808"/>
Finesse server response:
<body xmlns="http://jabber.org/protocol/httpbind" xmlns:stream="http://etherx.jabber.org/streams" authid="26779701" sid="26779701" secure="true" requests="4" inactivity="60" polling="5" wait="30" hold="1" ack="704654808" maxpause="300" ver="1.6"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features></body>
综述:
Finesse还实施XMPP规范XEP-0060:Publish-Subscribe。此规范的目的在于允许XMPP服务器(通知服务)获取发布到XMPP节点的信息(主题),然后发送XMPP事件到订阅该节点的实体。对于Finesse,计算机电话集成(CTI)服务器会向Finesse Web服务发送CTI消息,以告知Finesse有关配置更新的信息,例如但不限于座席或联系服务队列(CSQ)的创建或呼叫信息。然后,此信息将转换为Finesse Web服务发布到Finesse通知服务的XMPP消息。然后,Finesse通知服务通过BOSH将XMPP消息发送到订用到某些XMPP节点的代理。
Finesse Web Services Developer Guide中定义的一些Finesse API对象是XMPP节点。代理和Supervisor Finesse Web客户端可以订用某些XMPP节点的事件更新,以获得有关实时事件(例如呼叫事件、状态事件等)的最新信息。此表显示启用了pubsub的XMPP节点。
Finesse API对象 |
目的 |
订用 |
/finesse/api/User/<LoginID> |
显示座席的状态和组映射 |
座席和主管 |
/finesse/api/User/<LoginID>/对话框 |
显示座席处理的呼叫 |
座席和主管 |
/finesse/api/User/<LoginID>/ClientLog |
用于从Send Error Report(发送错误报告)按钮捕获客户端日志 |
座席和主管 |
/finesse/api/User/<LoginID>/Queue/<queueID> |
显示队列统计信息(如果已启用) |
座席和主管 |
/finesse/api/Team/<TeamID>/Users |
显示属于特定组的座席,包括状态信息 |
主管 |
/finesse/api/SystemInfo |
显示Finesse服务器的状态。用于确定是否需要故障切换 |
座席和主管 |
步骤1:下载并安装XMPP客户端Pidgin。
第二步:导航到帐户>修改>基本并配置登录选项:
第三步:导航到帐户>修改>高级并配置:
注意:仅因为Finesse Web客户端可以使用端口7443连接到通知服务,所以才使用端口5222。
第四步:导航到工具>插件并启用XMPP控制台。
第五步:导航到工具> XMPP控制台> XMPP控制台以打开XMPP控制台。
第六步:执行此<iq>消息以查看存在的所有XMPP节点。
例如:
在配置了两个座席和两个CSQ的实验室环境中,Finesse响应中包含以下输出:
每个浏览器都有一组开发工具。开发人员工具的Network选项卡显示Finesse Web客户端(浏览器)发送和接收的HTTP消息。例如,此图像显示Finesse Web客户端如何发送SystemInfo请求,该请求每分钟检查Finesse Tomcat状态作为故障切换检查。此外,还会显示来自BOSH连接的http-bind消息。如果在Web客户端订阅的XMPP节点上没有要发布的更新,Finesse服务器将在30秒内发回响应。
当发生BOSH断开连接时,错误为Lost connection to {Finesse Server FQDN}。Please wait for a reachable Finesse Server to be found...(请等待找到可访问的Finesse服务器……)显示在Finesse桌面顶部的红色横幅中。
此时会显示此消息,因为此时无法从Cisco Finesse通知服务接收XMPP订用事件。因此,状态信息和呼叫详细信息不能显示在座席桌面上。
对于UCCX,在浏览器断开连接60秒后,代理将进入“注销”状态。座席可以处于“就绪”或“未就绪”状态,以便注销发生。
对于UCCE,Finesse最多需要120秒来检测代理关闭浏览器或浏览器崩溃的时间,并且Finesse在向CTI服务器发送强制注销请求之前等待60秒,这会导致CTI服务器将代理置于“未就绪”状态。在这些情况下,Finesse最多需要180秒才能注销代理。与UCCX不同,代理将进入“未就绪”状态而不是“注销”状态。
注:UCCE中的CTI断开未就绪与注销状态行为由PG /LOAD参数控制。根据Unified Contact Center Enterprise & Hosted版本10.0(1)的版本说明,从UCCE 10.0开始,/LOAD参数已弃用。
有关UCCE Finesse桌面行为的详细信息,请参阅Cisco Finesse管理指南中Cisco Finesse故障切换机制一章的桌面行为部分。
注意:以后可根据产品要求更改计时器值。
Finesse和UCCX通知服务日志可以通过RTMT或CLI收集:
文件get activelog /desktop recurs compress
注意:仅在重现问题时设置调试级别日志。重现问题后关闭调试。
注意:Finesse 9.0(1)没有调试级别日志记录。调试级别日志记录在Finesse 9.1(1)中引入。与Finesse 10.0(1)- 11.6(1)相比,在9.1(1)中启用日志记录的流程有所不同。有关此过程,请参阅Finesse管理和适用性指南。
启用Unified Contact Center Express(UCCX)的通知服务调试日志,如下所示:
admin:utils uccx notification-service log enable
WARNING! Enabling Cisco Unified CCX Notification Service logging can affect system performance
and should be disabled when logging is not required.
Do you want to proceed (yes/no)? yes
Cisco Unified CCX Notification Service logging enabled successfully.
NOTE: Logging can be disabled automatically if Cisco Unified CCX Notification Service is restarted.
启用Unified Contact Center Enterprise(UCCE)(Finesse独立)的通知服务调试日志,如下所示:
admin:utils finesse notification logging enable
Checking that the Cisco Finesse Notification Service is started...
The Cisco Finesse Notification Service is started.
Cisco Finesse Notification Service logging is now enabled.
WARNING! Cisco Finesse Notification Service logging can affect system performance
and should be disabled when logging is not required.
Note: Logging can be disabled automatically if you restart the Cisco Finesse Notification Service
这些日志位于/desktop/logs/openfire文件夹中,名为debug.log。
如图所示,通知服务(Openfire)debug.log显示与桌面的http绑定以及代理PC的IP地址和端口。
如图所示,最近的0毫秒活动表明会话仍处于活动状态。
Openfire关闭空闲会话表示座席注销可以在60秒内触发,Finesse可以将原因代码为255的强制注销发送到CTI服务器。在这些条件下桌面的实际行为取决于UCCE中Logout on Agent Disconnect(LOAD)的设置。在UCCX中,这始终是行为。
如果Finesse客户端不向Finesse服务器发送http-bind消息,日志可以显示会话运行时间并显示会话关闭。
2017.06.17 00:14:34 Session (id=f382a015) was last active 0 ms ago: 1001003@xxxxx.xxxx.xxx.cisco.com/desktop 2017.06.17 00:15:04 Session (id=f382a015) was last active 13230 ms ago: 1001003@xxxxx.xxxx.xxx.cisco.com/desktop 2017.06.17 00:15:34 Session (id=f382a015) was last active 43230 ms ago: 1001003@xxxxx.xxxx.xxx.cisco.com/desktop 2017.06.17 00:16:04 Session (id=f382a015) was last active 63231 ms ago: 1001003@xxxxx.xxxx.xxx.cisco.com/desktop 2017.06.17 00:17:04 Unable to route packet. No session is available so store offline. <message from="pubsub. xxxxx.xxxx.xxx.cisco. com" to="1001003@xxxxx.xxxx.xxx.cisco.com.cisco.com" id="/finesse/api/User/1001003__1001003@xxxxx.xxxx.xxx.cisco.com__o5Aqb"><event xmlns="http://jabber.org/protocol/pubsub#event"><items node="/finesse/api/User/1001003"><item id="0d78a283-466d-4477-a07e-6e33a856fce388"><notification xmlns="http://jabber.org/protocol/pubsub"><Update>
这些日志位于/desktop/logs/openfire文件夹中,名为info.log。 如果Finesse客户端不向Finesse服务器发送http-bind消息,日志可以显示会话变为非活动状态。
2017.06.17 00:16:04 Closing idle session (id=f382a015): 1001003@xxxxx.xxxx.xxx. cisco.com/desktop
after inactivity for more than threshold value of 60 2017.06.17 00:16:04 A session is closed for 1001003@xxxxx.xxxx.xxx. cisco.com/desktop
这些日志位于/desktop/logs/webservices文件夹中,名为Desktop-webservices.YYYY-MM-DDTHH-MM-SS.sss.log。 如果Finesse客户端在指定的时间内未向Finesse服务器发送http-bind消息,则日志可以显示代理在线状态变为不可用,并且60秒后,可能会发生在线状态驱动的注销。
0000001043: XX.XX.XX.XXX: Jun 17 2017 00:16:04.630 +0530: %CCBU_Smack Listener Processor (1)-6-PRESENCE_NOTIFICATION_RECIEVED: %[FROM JID=1001003@xxxxx.xxxx.xxx.cisco.com/desktop][PRESENCE_TYPE=unavailable]:Finesse received a presence notifcation 0000000417: XX.XX.XX.XXX: Jun 17 2017 00:16:04.631 +0530: %CCBU_Smack Listener Processor (1)-6-UNSUBSCRIBE_REQUEST_SUCCESS: %[NodeId=/finesse/api/User/1001003/ClientLog][user_id=1001003@xxxxx.xxxx.xxx.cisco.com]: Sucessfully unsubscribed from a node on the XMPP server 0000001044: XX.XX.XX.XXX: Jun 17 2017 00:16:04.631 +0530: %CCBU_Smack Listener Processor (1)-6-AGENT_PRESENCE_MONITOR: %[message_string=Adding agent 1001003 into the expiry hash.]: 0000001051: XX.XX.XX.XXX: Jun 17 2017 00:16:35.384 +0530: %CCBU_pool-8-thread-1-6-AGENT_PRESENCE_MONITOR: %[message_string=[Expired] Removed agent from cache 1001003]: 0000001060: XX.XX.XX.XXX:: Jun 17 2017 00:17:04.632 +0530: %CCBU_CoreImpl-worker12-6-PRESENCE DRIVEN LOGOUT: %[agent_id=1001003]: Performing CTI Logout on basis of the agents unavailable presence 0000001061: XX.XX.XX.XXX:: Jun 17 2017 00:17:04.633 +0530: %CCBU_CoreImpl-worker12-6-MESSAGE_TO_CTI_SERVER: %[cti_message=Invoke id :39 , agentstate :
1, workmode : 0, reason code: 255, forceflag :1, agentcapacity: 1, agentext: 1001003, agentid: 1001003, supervisorid: null, ssoFlag=false][cti_message_name=SetAgentStateReq]: Message going to the backend cti server 0000001066: XX.XX.XX.XXX:: Jun 17 2017 00:17:04.643 +0530: %CCBU_CTIMessageEventExecutor-0-6-DECODED_MESSAGE_FROM_CTI_SERVER: %[cti_message=CTIAgentStateEvent [skillGroupState=1 (LOGOUT), stateDuration=0,
skillGroupNumber=-1, skillGroupPriority=0, agentState=1 (LOGOUT), eventReasonCode=255, numFltSkillGroups=0, CTIClientSignature=null, agentID=1001003, agentExtension=1001003, agentInstrument=null, agentID_Long=1001003,
duration=null, nextAgentState=null, fltSkillGroupNumberList=[], fltSkillGroupIDList=[], fltSkillGroupPriorityList=[], fltSkillGroupStateList=[], MRDId=1, agentMode=0]CTIMessageBean [invokeID=null, cti_sequence_id=105,
msgID=30, timeTracker={"id":"AgentStateEvent","CTI_MSG_RECEIVED":1497638824642,"CTI_MSG_DISPATCH":1497638824643}, msgName=AgentStateEvent, deploymentType=CCX]][cti_response_time=1][dispatch_phase=DnD-CHECKPOINT-3B]:
Decoded Message to Finesse from backend cti server
BOSH连接由Web客户端设置,Finesse服务器确定代理在线状态是否不可用。这些问题几乎总是与浏览器、代理计算机或网络相关的客户端问题,因为启动连接的责任由客户端承担。
检查以下问题:
1.网络问题:
每分钟,客户端都会连接到Finesse服务器,以计算漂移和网络延迟:
<PC date-time with GMT offset>: : <Finesse FQDN>: <Finesse server date-time with offset>:
Header : Client: <date-time>, Server: <date-time>, Drift: <drift> ms, Network Latency (round trip): <RTT> ms
2019-01-11T12:24:14.586 -05:00: : fin1.ucce.local: Jan 11 2019 11:24:14.577 -0600: Header : Client: 2019-01-1
如果出现任何日志收集问题,请参阅排除Cisco Finesse桌面持久性日志记录问题
2.不支持的浏览器和/或版本:
根据兼容性列表使用支持的浏览器/版本和设置:
3.由于其他选项卡/窗口的内容/处理导致浏览器卡住的情况:
检查座席工作流程以查看他们是否执行以下操作:
4.计算机进入睡眠状态:
检查代理是否在注销Finesse之前使其计算机进入睡眠状态,或其计算机睡眠设置计时器是否很低。
5.客户端计算机上的CPU使用率高或内存不足问题:
6.第三方小工具在后台执行意外、有问题的活动:
在删除所有第三方小工具的情况下测试Finesse桌面行为。
7.服务器或客户端上的NTP问题:
检查以下问题:
1. Cisco Unified Communications Manager CTIManager服务断开。 如果UCCX的所有CTIManager提供程序都处于关闭或崩溃状态,则UCCX代理会看到红色横幅错误。如果发生这种情况,UCCE代理不会看到红色标语,但呼叫无法正确路由到代理。
注意:核心转储文件名使用的格式为:core.<ProcessID>.<SignalNumber>.<ProcessName>.<EpochTime>。
示例:core.24587.6.CTIManager.1533441238
因此,碰撞的时间可以从纪元时间确定。
2. Finesse/UCCX通知服务已停止或崩溃:
如果怀疑发生崩溃,请重新启动Cisco Finesse Tomcat和通知服务。只有在网络发生故障时才会建议这样做,否则会重新启动断开代理与Finesse服务器的连接。
UCCE的步骤:
UCCX的步骤:
如果不了解所需的步骤并了解Fiddler的工作方式,配置Fiddler可能会有些困难。Fiddler是一个中间人Web代理,位于Finesse客户端(Web浏览器)和Finesse服务器之间。由于Finesse客户端和Finesse服务器之间的连接是安全的,这为Fiddler配置增加了一层复杂性,以便查看安全的消息。
由于Fiddler位于Finesse客户端和Finesse服务器之间,因此Fiddler应用需要为所有需要证书的Finesse TCP端口创建签名证书:
Cisco Finesse Tomcat服务证书
Cisco Finesse(Unified CCX)通知服务证书
必须启用HTTPS解密,Fiddler才能代表Finesse服务器动态生成证书。默认情况下未启用此功能。
如果未配置HTTPS解密,则会看到与通知服务的初始隧道连接,但不会显示http-bind流量。Fiddler仅显示:
Tunnel to <Finesse server FQDN>:7443
然后,客户端必须信任Fiddler签名的Finesse证书。如果这些证书不受信任,则无法通过Finesse登录的Establishing encrypted connection.. stage。
在某些情况下,从登录接受证书例外无法工作,并且需要浏览器手动信任证书。
注意:提供的示例配置适用于实验室环境中的Windows 7 x64上.NET 4.5的Fiddler v5.0.20182.28034和Mozilla Firefox 64.0.2(32位)。这些步骤不能推广到所有版本的Fiddler、所有浏览器或所有计算机操作系统。 如果您的网络处于活动状态,请确保您了解任何配置的潜在影响。有关详细信息,请参阅官方Fiddler文档。
步骤1:下载Fiddler
第二步:启用HTTPS解密。导航到工具>选项> HTTPS,然后选中解密HTTPS流量复选框。
第三步:系统会打开一个警告消息框,要求信任Fiddler根证书。 选择是。
第四步:系统打开一个警告消息框,显示消息“您将要安装来自证书颁发机构(CA)的证书,该证书声明表示: DO_NOT_TRUST_FiddlerRoot.....是否要安装此证书?"。选择是。
第五步:手动将Finesse发布服务器和订用服务器证书添加到计算机或浏览器证书信任库。确保端口8445、7443和443(仅适用于UCCE)。例如,在Firefox上,无需从Finesse Operating System Administration页面下载证书即可完成此操作:
Options > Find in Options(search)> Certificates > Servers > Add Exception > Location > Enter https://<Finesse server>:port用于两个Finesse服务器的相关端口。
第六步:登录Finesse并查看http-bind消息通过Fiddler将Finesse客户端发送到Finesse服务器。
在提供的示例中,前5条消息显示由Finesse服务器响应的http-bind消息。第一条 消息包含消息正文中返回的1571字节数据。正文包含有关代理事件的XMPP更新。最终http-bind消息已由Finesse客户端发送,但尚未从Finesse服务器获得响应。当您看到HTTP结果为null(-)且响应正文中的字节数为null(-1)时,可以确定这一点。
更近的数据视图:
XMPP消息的响应正文:
Wireshark是常用的数据包嗅探工具,可用于嗅探和解码HTTPS流量。HTTPS流量是通过传输层安全(TLS)保护的HTTP流量。 TLS为主机提供完整性、身份验证和机密性。它通常用于Web应用程序,但可以与任何使用TCP作为传输层协议的协议配合使用。安全套接字层(SSL)是TLS协议的旧版本,由于不安全,因此不再使用。这些名称经常互换使用,用于SSL或TLS流量的Wireshark过滤器是ssl。
注意:提供的示例配置适用于实验室环境中Windows7 x64上的Wireshark 2.6.6(v2.6.6-0-gdf942cd8)和Mozilla Firefox 64.0.2(32位)。这些步骤不能推广到所有版本的Fiddler、所有浏览器或所有计算机操作系统。 如果您的网络处于活动状态,请确保您了解任何配置的潜在影响。有关详细信息,请参阅官方Wireshark SSL文档。需要Wireshark 1.6或更高版本。
注:此方法只能用于Firefox和Chrome。此方法对Microsoft Edge不起作用。
步骤1: 在代理的Windows PC上,导航到控制面板>系统和安全>系统>高级系统设置环境变量……
第二步:导航到User <username> > New...的用户变量。
创建名为SSLKEYLOGFILE的变量。
创建一个文件,将SSL预主密钥存储在专用目录中:SSLKEYLOGFILE=</path/to/private/directory/with/logfile>
注:创建系统变量而不是用户变量并/或将文件存储在非专用目录中,但系统上的所有用户都可以访问安全性较低的premaster密钥。
第三步:如果Firefox或Chrome处于打开状态,请关闭应用程序。重新打开后,它们可以开始写入SSLKEYLOGFILE。
第四步:在Wireshark上,导航到编辑>首选项……
导航到协议> SSL。
第五步:输入步骤2中配置的预置主机加密日志文件名的位置。
第六步:使用Wireshark filter tcp.port==7443 && ssl,Finesse客户端和Finesse服务器(通知服务)之间的安全HTTP通信被视为已解密。
版本 | 发布日期 | 备注 |
---|---|---|
2.0 |
31-May-2023 |
更新的标题、简介、PII、有偏见的语言、SEO、替换文本、品牌要求、样式要求、机器翻译、德语、格式设置。 |
1.0 |
23-Jun-2017 |
初始版本 |