查看原文
其他

智能语音应用开发之DPL2.0高级特性

半吊子全栈工匠 喔家ArchiSelf 2023-11-10

自从智能屏上市以来,智能语音交互演化成了多模态智能交互,智能语音应用的开发与Web 开发越来越类似,开发者基于DuerOS研发智能语音技能的成本也相应地逐渐降低了。如果把基于模版的技能开发看作是静态的网页开发,那么DPL1.0 就可以类比为DHTML,DPL2.0 就已经有了现代web 编程的味道。

本文对照web 的开发,逐一来类比DPL 2.0 中的一些高级特性,看一下DPL2.0 给多模态智能语音交互带来了哪些便利。

Web 中的CSS <---> DPL 中的样式

在W3C中,CSS 样式的布局基于“盒模型”,如下图所示: 

关于CSS“盒模型”的详细描述可以参考https://www.w3.org/TR/css-box-3/。

在DPL中, 所有组建同样基于CSS的“盒模型”,支持以下通用的规则样式: 


每个元素都可视作一个盒子,目前,设备端样式属性对于长度单位目前仅支持dp和px。盒模型的 box-sizing 默认为 border-box,即盒子的宽高包含内容、内边距和边框的宽度,不包含外边距的宽度。一个图片在DPL中使用样式的示例代码如下:

{
"type": "Image",
"styles": {
"width": "400dp",
"height": "200dp",
"margin-left": "20dp"
},
"props": {
"src": "https://www.baidu.com/img/bd_logo1.png"
}
}

为了所有页面元素的排版能够一致可预测,同时页面布局能适应各种设备或者屏幕尺寸,强烈推荐使用 flex 而非使用绝对定位的方式来进行页面结构的布局。DuerOS的设备端以将Flexbox 是默认且唯一的布局模型,所以无需手动为元素添加 display: flex; 属性。

Dueros 的设备端样式属性支持 position 定位,用法与 CSS position 类似。为元素设置 position 后,可通过 top、right、bottom、left 四个属性设置元素坐标。目前不支持 z-index 设置元素层级关系,但靠后的元素层级更高,因此,对于层级高的元素,可将其排列在后面。下面是一个简单层级布局: 

 对应的示例代码如下:

{
"type": "Container",
"styles": {
"position": "absolute",
"top": "0",
"right": "0",
"bottom": "0",
"left": "0",
"background-color": "#cccccc"
},
"items": [{
"type": "Container",
"styles": {
"width": "400dp",
"height": "400dp",
"position": "absolute",
"top": "0",
"left": "0",
"background-color": "#ff0000"
}
}, {
"type": "Container",
"styles": {
"width": "400dp",
"height": "400dp",
"position": "absolute",
"top": "150dp",
"left": "150dp",
"background-color": "#0055dd"
}
}, {
"type": "Container",
"styles": {
"width": "400dp",
"height": "400dp",
"position": "absolute",
"top": "300dp",
"left": "300dp",
"background-color": "#00ff49"
}
}]
}

Web 的页面逻辑处理 <---> DPL中的表达式和条件执行

Web 页面中的本地逻辑处理一般是通过Javascript 函数 实现的,在DPL2.0中,表达式语法使用了近似 JavaScript 表达式的语法形式,但仅限于可使用已提供的表达式语法内容,并避免引用变量与表达式运算符、函数名重名(会导致引用变量失效)。

DPL2.0中表达式的格式是<%= 表达式内容 %>,表达式内容可以是基于数字常量、字符串常量、document.dataSource 中属性引用,通过简单数学运算、内建函数或自定义函数的组合表达式。表达内容的计算是在DuerOS设备端进行的,会在页面渲染前实时计算;如果一个属性的值是表达式,那么该属性的值为表达式的实时计算结果;当表达式中存在对 document.dataSource 中的属性引用时,若 dataSource 中对应属性发生变化,页面会自动重新渲染,实时更新基于表达式语法绑定的对应部分内容。简单说,就是实现了数据的单向绑定。

官网中给出的示例如下:

为了更好的利用表达式带来的灵活性,DPL2.0提供了基于引用端上实时数据计算执行表达式判断结果的条件执行,让端上的模板渲染可以基于实时数据驱动,指令的执行与否也可以基于当前的实时数据状态值来决定。

条件执行主要有三种类型:dShow,dWhen 和dFor。

实时展现条件判断时, dShow 为 false 在页面渲染时也会渲染,在初次的时候渲染状态会稍慢一些,但状态的切换不会导致组件重新被渲染。通常更推荐使用 dShow 在一些状态需要被频繁改变或切换的组件上,优化后续交互中的渲染与展示速度。

dWhen 为 false 在页面渲染时不会被渲染,在初次的时候渲染状态会稍快一些,但状态的切换可能导致组件重新被渲染,并触发组件的 onLoaded 事件,通常更推荐使用 dWhen 在一些状态不需要被频繁改变或切换的组件上,可提升首次页面模板中的渲染与展示速度。

早基于组件模板绑定的列表数据内容实时渲染组件是,dFor 的对应属性值,应为一个列表数组数据,决定了该组件模板会基于列表数据拷贝出多少个同级组件,dFor 可应用到任意组件类型上;绑定列表数据的变动,会让组件展现同步更新;其中,定义了两个引用变量:$ITEM(数组数据中的对应项)、$INDEX(数组数据中对应项的下标值),用来作为组件模板的引用数据源。

官网中给出的利用表达式来条件执行的示例如下:

Web 中的localstorage <---> DPL中的本地存储

在现代web中一般有两种本地存储Localstorage 和sessionstorage,为web 应用提供了很多的便利。在DPL2.0 中同样引入了本地存储,每个DPL2.0的技能都可以有自己的本地存储),可以通过以下 API 对本地存储进行读写和清理。

  • setStorage:将数据存储在本地存储指定的 key 中,会覆盖掉原来该 key 对应的内容。

  • getStorage:从本地缓存中获取指定 key 对应的内容。

  • getStorageInfo:获取当前技能下本地存储的相关信息。

  • removeStorage:从本地存储中移除指定 key 以及对应的数据信息。

  • clearStorage:清空当前所有的本地数据存储。

这些方法的调用都是通过 InvokeMethod 指令完成的,将方法名作为参数传入,并支持以 callbackCommands 的指令声明方式接收其异步结果,来进行下一步的交互,并可通过在指令中以表达式引用$EVENT_ARGS[0]获取异步结果数据信息。其中,获取本地存储相关信息的示例代码如下:

{
"type": "InvokeMethod",
"componentId": "DPL",
"methodName": "getStorageInfo",
"params": {
"callbackCommands": [
{
"type": "SendEvent",
"arguments": ["getStorageInfo", "<%= $EVENT_ARGS[0].state%>"]
"componentId": "DPL"
}
]
}
}

需要注意的是,同一个用户使用同一个 DPL2.0 技能时,可用的本地存储空间上限为 1MB 。在用户退出登录时,会清空掉当前所有技能使用的本地存储数据。同一个账户退出登录后重新登录,由于退登清理策略,原账户的本地存储数据将会丢失。因此,不建议将关键信息全部存在本地存储的数据中,以防出现用户频繁切换账户或用户换设备的情况。

官网中给出的本地存储使用方法的示例如下:

Web 中弹框 <---> DPL2.0中的浮层

Web应用中的弹框一般是通过JavaScript实现的,而在 DPL技能中,为了更好滴提升用户与技能间的交互体验,以及对业务场景下,能够有一个通用实现的信息提醒机制,DPL2.0 提供了多类全局的浮层,并可以通过提供简单的调用方式、内容更新,来完成技能模板与用户使用过程中更为丰富的交互,例如信息提醒或消息推送能力等等等。

当前,DPL提供了三类全局浮层类型:Modal 模态窗、Toast 提示、Loading 进行态,通过调用浮层的打开与关闭方法(或声明打开的持续时间),可以提供用户与bot之间部分信息交互提示能力,但如果希望当前用户在交互中,对应类型的全局浮层的打开、关闭或正负反馈与超时能够通过触发某些事件来进一步的更新场景或让 bot 感知到,则可以通过在DPL document 中明确的声明对应全局浮层的事件以及相关的指令绑定来达到需求。浮层事件声明的描述用例如下:

{
"type":"DPL",
"version":"2.0",
"duration": 120000,
"dataSource":
"mainTemplate":{{COMPONENTS_STRUCTURE}},
"extraLayers": {
"{{layerType}}": {
"events": {
"{{eventType}}": [{{COMMAND}}, ...],
...
}
}
}
}

在DPL2.0页面中的展现优先层级由低到高为:MainTemplate => Modal => Toast => Loading (当前最上级展示层次)。通过使用通用的 DPL 方法调用指令 InvokeMethod,可以方便的打开与关闭对应类型的全局浮层,示例如下:

{
"type": "InvokeMethod",
"componentId": "DPL",
"methodName": "show",
"params": {
"arguments": [
"{{layerType}}",
{{layerParams}},
{{isReopen}}
]
}
}

其中,全局的模态框用于包含多类信息内容,并可以作为能够获取到交互反馈的 Confirm、Alert、Prompt 等多类灵活样式的展示方式。官网给出的示例如下:

小结

DPL2.0 推出了很多高级特性,例如样式,本地逻辑处理和本地存储,通用全局浮层机制等等, 使得基于DuerOS 的智能语音技能开发与现代的web 开发更为接近, 开发者可以使用DPL 的高级特性来进一步提升DuerOS 语音技能的用户体验,更多的事件应用可以参考DPL2.0 高级特性的实践应用。

【关联阅读】


继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存