2024年1月

socket.d.js 是基于 websocket 包装的 socket.d 协议的实现。就是用 ws 传输数据,但功能更强大。

功能 原生 websocket socket.d 说明
listen 监听消息
send 发消息
sendAndRequest 发消息并接收一个响应(类似于 http)
sendAndSubscribe 发消息并接收多个响应(也叫订阅)
event(or path) 消息有事件或路径(可对消息,进行业务路由)
meta(or header) 消息有元信息或头信息(可为数据,标注业务语义)
自动心跳
断开后自动重链

下面感受下开发方面的差异!

1、客户端示例代码

使用时,可以根据自己的业务对原生接口包装,进一步简化使用。

<script src="js/socket.d.js"></script>
<script>
async function init(){
    //构建事件监听
    const eventListener = await SocketD.newEventListener().doOnMessage((s,m)=>{
       //监听所有消息(可能不需要)
    }).doOn("/im/user.upline", (s,m)=>{ //事件的应用
        //监听用户上线
        let user_id = m.meta("user_id");
    }).doOn("/im/user.downline", (s,m)=>{
        //监听用户下线
         let user_id = m.meta("user_id"); //元信息的应用
    });

    //创建单例
    window.clientSession = SocketD.createClient("sd:ws://127.0.0.1:8602/?u=a&p=2")
            .listen(eventListener)
            .open();
}

function join(){
    clientSession.sendAndRequest("/user/join", SocketD.newEntity()).thenReply(r->{
        //加入成功
    });
}

init();
</script>

Socket.D 有三个发消息的接口:

接口 说明
send 像 websocket。多了事件与元信息属性
sendAndRequest 像 http
sendAndSubscribe 像 reactive stream 。多了事件与元信息属性

2、服务端示例代码(用 java 演示)

public class Demo {
    public static void main(String[] args) throws Throwable {
        List<Session> userSessions = new ArrayList<Session>();
        //创建监听器
        Listener listener = new EventListener().doOnOpen(s->{
            //鉴权
            if("a".equals(s.param("u")) == false){
                s.close();
            }else{
                //加入用户表
                s.attrPut("user_id", s.param("u"));
                userSessions.add(s);
            }
        }).doOn("/user/join", (s,m)->{
            if(m.isRequest()){
                s.reply(m, new StringEntity());
            }
            
            for(Session s1: userSessions){
                //告诉所有用户,有人上线
                s1.send("/im/user.upline", new StringEntity().metaPut("user_id"), s.attr("userId"));
            }
        });
        
        //启动服务
        SocketD.createServer("sd:ws")
                .config(c -> c.port(8602))
                .listen(listener)
                .start();
    }
}

3、Socket.D 是什么东东?

Socket.D 是一个基于“事件”和“语义消息”“流”的网络应用层协议(听起来好像很 ao 口)。支持 tcp, udp, ws, kcp 传输(有各种不同语言的实现)。有用户说,“Socket.D 之于 Socket,尤如 Vue 之于 Js、Mvc 之于 Http”。

协议之所有强大,有三个关键基础因素:

  • 事件
  • 语义消息

它的帧码结构:

[len:int][flag:int][sid:str(<64)][\n][event:str(<512)][\n][metaString:str(<4k)][\n][data:byte(<16m)]

因为是应用层协议,所以可以建立在任意传输层协议之上。比如 websocket。

4、开源仓库

前言:

在之前的项目中,我们已经使用 OpenVINO
TM
CSharp API 部署 PaddleOCR 全系列模型,但随着PaddleOCRv4版本发布以及OpenVINO CSharp API版本迭代,上一版本的项目已经不再适用。因此在推出的最新项目中,已经完成了对PaddleOCRv4的匹配,并且采用了最新版本的 OpenVINO
TM
CSharp API,可以更快的实现在不同平台进行部署,减少使用者在使用时的步骤以及问题。

1. 项目介绍

该项目主要基于开发的[OpenVINO
TM
C# API](OpenVINO
TM
C# API)项目,基于 C# 编程语言在.NET框架下使用
OpenVINO
TM

部署工具部署百度飞桨下的
PaddleOCR
系列模型,实现图片文字识别、版面分析以及表格识别等功能。

项目提供了简单的案例以及二次开发的API接口,大家可以根据自己需求进行再次开发与使用。

项目
PaddleOCR-OpenVINO-CSharp
链接为:

https://github.com/guojin-yan/PaddleOCR-OpenVINO-CSharp

2. 项目环境

在本项目中主要使用的是自己开发的
OpenVINO
TM
C# API

项目以及
OpenCvSharp4
项目,所使用
NuGet Package
程序包以及安装方式如下所示

2.1 NuGet Package

  • OpenVINO.CSharp.API >= 2023.2.0.2
  • OpenVINO.runtime.win >= 2023.2.0.1
  • OpenCvSharp4.Windows >= 4.8.0.20230708
  • OpenCvSharp4.Extensions >= 4.8.0.20230708

2.2 安装方式

NuGet Package 可以通过Visual Studio 安装或者通过
dotnet
命令安装,安装方式如下:

dotnet add package OpenVINO.CSharp.API
dotnet add package OpenVINO.runtime.win
dotnet add package OpenCvSharp4.Windows
dotnet add package OpenCvSharp4.Extensions

3. 快速开始

3.1 获取项目源码

git clone https://github.com/guojin-yan/PaddleOCR-OpenVINO-CSharp.git
cd PaddleOCR-OpenVINO-CSharp

3.2 获取预测模型

项目中所使用的模型均来自于
PaddleOCR
,模型目录可以参考

注意:

经过测试,OpenVINO目前已经支持
PP-OCR 系列模型列表、PP-Structure 系列模型列表
中的所有模型,并且支持Paddlepaddle格式的模型,用户在下载后可以直接使用,但是表格识别模型
ppstructure_mobile_v2.0_SLANet
需要进行转换才可以使用,需要固定模行输入形状为[1, 3, 488, 488],转换方式keyi 参考该文章:
Paddle2ONNX
.

为了方便大家快速使用,此处提供了模型的快速下载方式:

cd model
./ocr_model_download.sh
./stru_model_download.sh

下载后模型文件目录结构为:

model
   ├──── paddle
            ├──── ch_ppocr_mobile_v2.0_cls_infer
            ├──── ch_PP-OCRv4_det_infer
            ├──── ch_PP-OCRv4_rec_infer
            ├──── ch_ppstructure_mobile_v2.0_SLANet_infer
            ├──── en_ppstructure_mobile_v2.0_SLANet_infer
            ├──── picodet_lcnet_x1_0_fgd_layout_cdla_infer

image

3.3 OCR识别

可以直接通过
Visual Studio
直接运行该项目或者通过
dotnet run
指令运行该项目,
dotnet run
命令如下:

cd PaddleOCR-OpenVINO-CSharp/sample
dotnet run ./../../

程序运行后输出如下图所示:

image
image

4. Contact

如果您准备使用OpenVINO部署PaddleOCR模型,欢迎参考本案例。在使用中有任何问题,可以通过以下方式与我联系。

image

前言

今天给大家分享一个小巧、快速、轻量级的 .NET NoSQL 嵌入式数据库:LiteDB。本篇文章主要是介绍LiteDB和在.NET中如何使用。

LiteDB介绍

LiteDB 是一个小巧、快速和轻量级的 .NET NoSQL 嵌入式数据库。

  • 无服务器的 NoSQL 文档存储
  • 简单的 API,类似于 MongoDB
  • 100% 的 C# 代码支持 .NET 4.5 / NETStandard 1.3/2.0,以单个 DLL(不到 450KB)形式提供
  • 线程安全
  • 支持 ACID,完整的事务支持
  • 写入失败后的数据恢复(WAL 日志文件)
  • 使用 DES(AES)加密算法对数据文件进行加密
  • 使用属性或流畅的映射器 API 将 POCO 类映射为 BsonDocument
  • 存储文件和流数据(类似于 MongoDB 的 GridFS)
  • 单一数据文件存储(类似于 SQLite)
  • 对文档字段建立索引以实现快速搜索
  • 支持 LINQ 查询
  • 提供类似于 SQL 的命令来访问/转换数据
  • LiteDB Studio - 数据访问的精美用户界面
  • 开源且免费供所有人使用,包括商业用途

LiteDB应用场景

可以在以下场景中使用 LiteDB:

  • 桌面/本地小型应用程序
  • 应用程序文件格式
  • 小型网站/应用程序
  • 每个账户/用户数据存储一个数据库的情况

LiteDB项目源代码

创建一个LiteDBCwTest控制台

安装LiteDB包

搜索
LiteDB
包,点击安装。

定义Customer数据模型

    public class Customer
    {
        /// <summary>
        /// Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// Name
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Age
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// Email
        /// </summary>
        public string Email { get; set; }
    }

LiteDB数据创建、插入、查询和删除

namespace LiteDBCwTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //创建或打开数据库文件
            using (var db = new LiteDatabase(@"MyCustomerData.db"))
            {
                // 获取集合(相当于表)
                var collection = db.GetCollection<Customer>("customers");

                var customers = new List<Customer>()
                {
                    new Customer
                    {
                        Name = "追逐时光者",
                        Age = 18,
                        Email = "17854545@gmail.com"
                    },
                    new Customer
                    {
                        Name = "大姚",
                        Age = 30,
                        Email = "16556545@gmail.com"
                    }
                };

                // 批量插入数据
                collection.Insert(customers);

                // 查询数据
                var result = collection.FindAll();

                foreach (var c in result)
                {
                    Console.WriteLine($"Name: {c.Name}, Age: {c.Age}, Email: {c.Email}");
                }

                // 根据条件查询数据
                var query = Query.EQ("Age", 30);
                var resultByAge = collection.Find(query);

                foreach (var c in resultByAge)
                {
                    Console.WriteLine($"Name: {c.Name}, Age: {c.Age}, Email: {c.Email}");
                }

                // 删除数据
                var deletedResult = collection.Delete(resultByAge.FirstOrDefault().Id);
            }
        }
    }
}

创建成功的数据库文件

LiteDB.Studio管理工具下载

用于查看和编辑 LiteDB v5 文档的图形用户界面工具。

LiteDB.Studio管理数据

连接MyCustomerData数据库

查看customers表数据

项目源码地址



更多项目实用功能和特性欢迎前往项目开源地址查看


微服务系列18篇

1 背景

在互联网高可用架构设计中,应该避免将所有的控制权都集中到一个中心服务,即便这个中心服务是多副本模式。
对某个中心服务(组件)的过渡强依赖,那等同于把命脉掌握在依赖方手里,依赖方的任何问题都可能成为你不稳定的因素。

弱化强依赖,实现可降级交互,是一种设计理念和架构模式,目的是将系统的控制权分散到各个节点,避免出现单点故障或中心化控制的问题。
这一点,我们称之为『去中心化』

image

具体来说,
去中心化架构中的每个节点都具有自主性,可以独立地处理和存储数据,并且节点之间通过特定的协议或机制进行通信和协作。这种架构可以提高系统的可用性和可扩展性,降低对单个节点的依赖性,增强系统的可靠性和容错能力。

2 经典去中心化架构设计

我们去分析业内的很多经典的软件设计,都可以看到他们为了实现降低对中心服务(组件)的依赖,做了很多方案优化。

2.1 微服务注册中心

image
如上图所示:
1、Provider 服务提供者:服务向注册中心注册服务信息,即 服务 -> 服务实例 数据模型, 同时定时向注册中心汇报健康检查,如果一定时间内(一般90s)没有进行心跳汇报,则会被注册中心剔除。
所以这边注意,注册中心感知到应用下线并进行剔除这个过程可能比较长。
2、Consumer 服务消费者:服务向注册中心获取所需服务对应的服务实例信息。这边需要注意,在Spring Cloud生态中,一般通过实时订阅或者定时拉取方式从注册中心中获取所需的服务实例信息。
3、Remote Call 远程调用:Consumer从注册中心获取的Provider的实例信息,通过 Load Balance的策略,确定一个实际的实例,发起远程调用。

去中心化分析:很明显,我们的注册和订阅都依赖注册中心(Eureka、ZK、Etcd或者其他...),如果这个注册中心挂了,我们连对服务的访问路由地址都无法匹配,请求都没办法发出去。
所以现在一般Client端会缓存依赖服务的地址列表到本地,即便注册中心挂了,在短时间内也会正常运行,只是新增或者更新的服务实例无法获取到。

2.2 分布式存储系统

分布式存储系统是实现去中心化的一种重要实现方式。通过将数据分散存储在多个节点上,而不是集中存储在中心服务器上,分布式存储系统可以避免单点故障和中心化控制的问题,提高系统的可用性和可扩展性。

在分布式存储系统中,每个节点都有自己的存储设备和计算能力,可以独立地存储和检索数据。节点之间通过特定的协议或机制进行通信和协作,共同维护系统的数据和功能。这种架构可以降低对单个节点的依赖性,增强系统的可靠性和容错能力。
image
如图,B Region 如果挂了,流量会调度到A Region中,如果A、B均挂了,则会启动Backups Region,当然,数据可能会有一些延迟,但依然能保证系统正常提供服务。

3 常用的架构设计方案

业内有一些优秀的设计经验,用于规避中心故障导致的服务雪崩。

3.1 多副本模式+重试

image
比如你的中心服务有20个副本(实例),其中一个副本(实例)出故障,导致执行返回5xx,那么第二次请求的时候大概会有 19/20 的成功概率。
负载均衡模式默认是RR,所以实例越多,实际上重试成功的概率会越高。

3.2 多副本模式+异常隔离

image
如果依赖的中心服务存在多副本,那么即使存在不健康副本(实例),只要是被自动驱逐之后,服务依旧是健康的。
但是驱逐需要保障剩余的副本能够支撑峰值流量的冲击。

3.3 强大的主备模式

标准两地三中心建设(同城主、同城备、异地备),避免单机房故障,甚至区域自然灾害导致系统无法提供正常服务。
image

3.4 极限兜底:如缓存保证依赖可降级

image
类似微服务注册中心的做法,用一层缓存做兜底,一般来说数据库跟缓存同时出故障的概率不高。
笔者的团队就有一个案例:依赖的Etcd服务,用于路由分发的配置信息存储,失联了4小时,靠着缓存保证了大部分流量的正常运行。

4 总结

在互联网高可用架构建设中,去中心化设计,可以降低对单个节点的依赖性,增强系统的可靠性和容错能力。

我们是
袋鼠云数栈 UED 团队
,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。

本文作者:大喜

相关文章:
袋鼠云出品!数栈UI 5.0全新体验升级,设计背后的故事

前言

表单是B端产品中最常见的组件之一,主要⽤于数据收集、校验和提交。比如登陆流程的账号密码填写,注册流程的邮箱、用户名等信息填写,都是表单应用的常见案例,在数栈产品中也是出现频率⾮常⾼的组件。

尽管表单应用十分普遍,但在我们对旧版数栈产品进行调研时,发现许多产品同学都反馈了关于表单的问题。所以在实际设计时关于「表单」会有很多需要去思考的问题:

  • 标签是使⽤左右布局还是上下布局更合适?
  • 标签⽂本过⻓要怎么解决?
  • 提示信息怎么显示不会形成⼲扰?
  • 操作按钮居左还是居右?
  • 控件⻓度整体排列还是按输⼊预期错落有致?
  • ……

本文就根据数栈UI 5.0的设计逻辑,从表单构成、表单布局,以及表单的交互形式等多⻆度梳理了这篇文章,希望能给大家带来B端产品设计不一样的启示,这些干货知识相信你一定用的上。

表单的构成

尽管我们都对表单很熟悉,但为了确保清晰,我们还是先介绍一下它的构成。一个基础的表单通常由标签、表单域、提示信息、校验信息和操作按钮等基础组件构成。

file

标签

标签主要⽤于告知⽤户要录⼊的内容,通常需要简明扼要便于⽤户理解。

标签的放置分三种形式⽔平排列(右标签),上下排列(顶标签),显示输⼊框内(⾏内标签)。

数栈⽬前的表单⻚以上下排列的表单样式为主,⽔平排列的表单为辅。数栈UI5.0使⽤上下表单形式⽬的也是为了解决UI4.0中⽔平表单所存在的问题,⽐如标题过⻓、对⻬、备注提示信息位置不统⼀、视觉的整体性等。但不管标签是上下排列还是左右排列都有各⾃的优劣势,具体运⽤到⻚⾯中还是需要考虑实际的使⽤场景。还有⼀类⾏内标签应⽤较少,主要⽤于搜索框组件的使⽤。

上下排列-顶标签

file

应用场景:
适⽤基础表单、分布表单、抽屉、弹窗等表单交互形式。

优势:

  • 相⽐于左右对⻬标签可容纳更多字数
  • 标签与表单域联系更加紧密,视觉横向移动距离⼩,最适合快速浏览操作(上下表单:单个标签到输⼊区平均耗时50毫秒;⽔平表单:单个标签到输⼊区平均耗时 240 毫秒)
  • 信息扩展性更强,可容纳更多提示信息来帮助⽤户更具象的理解以及预防错误发⽣
  • 表单整体布局更加规则且有秩序

劣势:
⼀定程度上占⽤⼤量的纵向空间,纵向空间利⽤率不⾼。

file

file

左右排列-右标签

file

应用场景:
⽤于表格筛选等纵向空间有限时,使⽤横向排列减少⻚⾯⾼度占⽐,⽐如:表格筛选可使⽤横向表单来减少占⽤⾼度,对⻬⽅式按照输⼊框对⻬。

file

file

表单域

表单域包含文本框、多行文本框、单选框、复选框和下拉选择框等,用于采集用户输入或选择的数据。根据不同类型的数据,选择与之对应的录入方式能够提高表单操作的效率和用户体验。

文本录入

⽂本录⼊是最基础的信息输⼊⽅式。按照输⼊的内容分为单⾏输⼊框、多⾏输⼊框和数值输⼊框。但需要注意的是输⼊项过多,操作就会变得繁琐,在之前发布的⽂章可⽤性原则中有提到过系统识别胜过记忆原则,⽤选择代替输⼊可以减少⽤户的记忆负担,也能减少输⼊错误等问题,可以有效的提升操作效率。

file

应用场景:
当用户输入的内容不可预测或自由度程度高时使用。使用单行文本框适用于输入文本字符数较少的场景;多行文本框适用于输入文本字符数较多时,可以选择使用拖拽文本框样式或⽂本⾃动撑⾼的功能。

file

复合输入框

输⼊的内容带单位/符号,使⽤复合输⼊框让输⼊信息更具整体性。

file

file

file

选择录入

选择录⼊是为⽤户预先提供了⼀定的选择范围,在指定范围中选择⽬标选项进⾏录⼊,在数栈的产品中⽐较常⽤的组件有单选、多选、选择器、开关、时间选择器等。

Radio单选

在⼀组相关且互斥的数据中,⽤户仅能选择⼀个选项。

file

应用场景:

  • 当选项数量少于5个时,使⽤平铺可以减少⽤户的操作步⻓,当选项过多时建议使⽤下拉选择器
  • 在⼀组单选框中,可以设置⼀个最有可能被选择或者最安全的选项作为默认选项

file

file

Checkbox复选

允许⽤户选择⼀个或多个独⽴选项。

file

应用场景:

  • ⽤于筛选或批量处理的操作:⽤于过滤⻚⾯、菜单中的数据,表格批量操作等
  • ⽤于条款或条件级:选中复选框表明⽤户同意这些条款或条件
  • 当选项内容较少时(满⾜(7±2 )法则),平铺的交互效果更友好,⽅便⽤户点选取消

file

file

Switch开关

互斥性的操作控件,⽤户可打开或关闭某个功能。

file

应用场景:
对于⽤户更改后⽴即⽣效的设置,使⽤开关。

file

file

Select选择器

当⽤户需要从⼀组同类数据中选择⼀个或多个时,可以使⽤下拉选择器,点击后选择对应项。

file

应用场景:

  • 主要⽤于表单填写(录⼊)和属性选择(筛选)场景
  • 当选项⼤于5个以上时,使⽤选择器,保持洁⾯简洁,避免混乱

file

⽇期/时间选择器

这个⽐较明确,仅⽤于时间/⽇期的选择或筛选。

file

应用场景:
当⽤户需要输⼊⽇期、时间信息时,提供基础的时间、⽇期筛选功能。

file

file

穿梭框

左右两侧布局的多选组件,分为候选区和已选区,两侧数据平铺在⻚⾯上,⽤户可以以直观的⽅式将数据从⼀侧即时移到另⼀侧,完成选择或移除数据的交互⾏为。

应用场景:
需要更清晰的展示选择内容时,穿梭框⽤直观的⽅式展示出了更多的选项信息,能够减少因信息隐藏造成的错误,⽅便⽤户实时了解选择的内容,增加⽤户的确定感。

file

file

上传录⼊

⽤于传输⽂件或者提交相应的内容,⽬前数栈多数场景都是使⽤单个上传样式。

file

提示与反馈


之前的文章
中,我们提到了尼尔森十大可用性原则中的“系统可见性原则”和“帮助用户发现、判断和修复错误”,这些都强调了提示与反馈的重要性。在用户进行任务操作的过程中,适当的反馈能够让用户了解当前的状态,并引导用户进行正确的交互行为。

为了提供更好的用户体验,数栈UI5.0提供了多种组件类型,来应对不同场景下的提示与反馈交互,例如警告提示、文本提示、必填项提示、Tooltips文字气泡提示、Popover气泡卡片提示等。此外,对于操作结果的反馈方式,我们也可以采用校验反馈、全局提示、通知提醒框、Modal对话框、Popconfirm气泡确认框、页面反馈等。在整个表单填写过程中,及时给予用户相应的提示与反馈,可以显著提高填写的效率。

文本提示

提升⽤户输⼊内容的准确性和效率,使⽤提示性⽂案的⽅式显示在操作区域。

file

应用场景:

  • 在输⼊框内显示提示⽂案,告知⽤户输⼊规则,在⽤户还未输⼊任何字符时显示
  • 在表单域上⽅提示,对业务规则或输⼊⽬的等信息进⾏说明

file

必填项提示

当⻚⾯需要填写的表单过多时,多数⽤户都会表现出排斥,如果能明确告知⽤户必填的表单,能够极⼤简化⽤户录⼊的流程,减少不必要的信息⼲扰。
数栈UI5.0沿⽤了之前的“*”星号作为必填提示,也是⽬前⽤户普遍⽐较习惯的⼀种形式。

file

应用场景:

  • 任务中必须完成的操作需要标记星号
  • ⼀个表单所有都是必填项时,为了避免产⽣理解性的错误,我们还是建议标记星号,因为部分⽤户会习惯判断⽆星号的表单不是必填内容

file

Tooltips⽂字⽓泡提示

常⽤于解释说明,仅承载简单的⽂案信息。

file

应用场景:

  • 展示帮助性信息:解释说明、帮助信息这类提示更偏向于业务属性,随着⽤户深⼊使⽤产品,这些信息会变得不再重要,⽤户查看的频率也会越来越低。所以我们通常会将这类信息收起,当⽤户不理解某个功能,或想要获得更多信息时,通过访问“?”问号 icon 查看相关联的更多帮助性信息。
  • 增强交互的确定感:当⽤户与界⾯进⾏交互时,⽂字提示能够帮助⽤户增强对所交互元素效果的确定感(如按钮的操作提示)
  • ⻚⾯位置有限时:当⻚⾯位置有限时,⼀些UI元素需要以简化的形式出现(如单独的图标),或者⽂字省略,使⽤⽂字提示能够更好的帮助⽤户理解信息

file

Popover⽓泡卡⽚提示

常⽤于承载信息和操作,承载的内容和形式更为多样。

file

应用场景:
在使⽤场景上,⽓泡弹窗(Popover)可以像⽂字提示(Tooltip)⼀样为⽤户提供帮助,但整体来说扩展性更强。⼀⽅⾯,Popover 可以承载更多的图⽂信息,提供详情预览的功能;另⼀⽅⾯ Popover 允许⽤户在其中进⾏⼀些简单操作,在功能上更接近弹窗。

file

警告提示

向⽤户传递与当前⻚⾯相关的⾏为反馈、公告信息。提示较为醒⽬,通常显示在⻚⾯顶部,或者弹窗顶部,随容器宽度⾃适应。⾮浮层的静态展现形式,始终展现,不会⾃动消失,⽤户可以点击关闭。

file

应用场景:

  • ⽤于向⽤户传递产品或系统的重要提醒,与⽤户的任务或状态⽆关,会⼀直存在,直到被⽤户处理或关闭
  • 仅在必要时使⽤提示,且应将提示限制在与之内容相关的任务界⾯中

file

校验反馈

⽤于表单等控件的结果反馈,显示在对应控件下⽅,在操作后消失。

file

应用场景:
⽤于表单、表格等数据录⼊场景下,当⽤户输⼊的内容不符合字段或表单的要求显示。

file

全局提示

全局展示操作反馈信息,可提供成功、警告和错误等反馈信息,顶部居中显示并⾃动消失,是⼀种不打断⽤户操作的轻量级提示⽅式。

file

应用场景:

  • ⽤于执⾏操作后提供的操作结果反馈,如成功、失败等提示
  • 只提供结果反馈,不提供给操作按钮,如果需要⽤户对结果做出回应,建议使⽤ Modal 对话框

file

通知提醒框

向⽤户反馈重要的警告提示和通知消息,⼀般显示在⻚⾯的右上⻆,可以⼿动关闭,也可以设置时间⾃动关闭,⽬前数栈产品内是在弹出⼏秒后⾃动关闭。

file

应用场景:

  • ⼀般⽤于系统级通知,需要吸引⽤户关注但⼜不强制⽤户去处理的场景
  • 通知提醒框为内容提供的空间有限,因此内容必须简短明了,⽤户应该能够快速浏览通知,了解情况,并知道下⼀步该做什么

file

file

页面反馈

以⻚⾯的形式展示操作结果反馈,或进⼀步引导。

应用场景:

⽤于某个任务流结束后的结果反馈,且⽤户⾮常关注此任务的结果时,建议使⽤落地⻚反馈结果。

file

表单操作按钮布局

在数据录⼊完成后,需要对任务进⾏保存、提交或者取消等操作。除了对表单任务进⾏保存/提交操作外,还需提供⽤户能够随时取消当前执⾏的任务的操作。所以通常表单⻚都应提供两个按钮,确定/保存和取消操作。

按钮之间需要区分主次关系,按钮作为主要的视觉引导,在⼀个焦点任务中最多只使⽤⼀个主按钮。同时存在多个主按钮会让⽤户失去操作焦点,造成信息⼲扰。

按钮居左

当表单内容靠左时,按钮居左边,主次关系从左到右排列。尼尔森团队发表过一份关于《眼睛轨迹的研究》报告,其中提到了“F”型浏览模式。用户的阅读习惯一直以来都是从上到下、从左到右。因此,按照“F”型顺序延伸,当表单布局靠左时,按钮组合的位置也应靠左。

再说到按钮的主次关系布局,我们通常将靠近边缘的按钮视为主要按钮。这是因为菲兹定律中有一条叫做边角利用,边界对于用户的操作来说是“无限可触发”的。当内容置于边缘时,操作失误率会大大降低。

file

按钮居中

当表单内容分步时,步骤条位于⻚⾯中⼼,对应的操作按钮同样居中显示。垂直布局下,⽤户浏览时的眼动路径单纯向下,这种由上⾃下的浏览效率是最⾼的。因此,对应的主次关系布局应该遵循方向性原则,主按钮带有明确⽅向,具有下⼀步性质的按钮。

file

按钮居右

弹窗的布局是按照“Z”型构图法,按钮布局在“Z”的末尾,按照古腾堡原则(对⻆线平衡法则)这个区域是⽤户浏览⾏为的最终落点区域。当⽤户任务进⾏到这个部分时需要采取措施,所以通常在这⾥放置按钮或者⾏动点。主按钮放在边缘最右侧,便于⽤户快速获得⽬标操作。

file

表单的布局

表单的布局形式影响着表单的操作效率,在表单设计时,我们通常会根据信息的容量以及内容的关联性来选择合适的内容组织形式。内容组织形式分为三种基础表单、分布表单、分组表单。

基础表单

基础表单是最简单的布局形式,将所有需填写表单内容项直接罗列在⻚⾯上。

应用场景:

适用于内容较少、结构简单的场景,表单项采用单列纵向排列。较短宽度且具有相关性的表单项可以组合在一行中,形成弱分组的暗示。通常,操作按钮会跟随内容之后,当内容超出一屏幕后,操作按钮会悬浮固定在底部。

file

分组表单

分组表单是按照一定相关性进行分组的表单,是遵循《简约至上-交互设计四策略》中提到的四⼤策略之⼀“组织”的应⽤。在基础平铺的基础上,将表单项中相关联的表单项进行分组,使表单显得更有规律和组织性。即使表单项较多,也不会显得杂乱无章,减轻了用户的心理压力和视觉疲劳,提高了操作体验。

应用场景:

适用于需要填写大量内容的单次任务表单页中,且不同内容之间存在一定的可分类归纳性时。

file

分步表单

分布表单同样应⽤了四⼤策略中的另⼀项策略“转移”——当任务较复杂时,为了更简单易⽤,可以对复杂任务进⾏巧妙拆解转移。将⽤户需要录⼊的复杂信息按照线性流程组织拆解,利⽤步骤条告知⽤户完整流程和进度。分步表单的流程化明显,后⼀步填写的内容常基于前⼀步来填写。

应用场景:

分步表单适⽤于内容较多,并且前后步骤之间存在线性关系的情况。在数栈产品中,⼀般步骤⻚的信息承载量普遍都会较⼤,按照纵向单列布局,导致⼀屏横向空间空⽩过多,纵向路径过⻓。所以为了确保信息的屏效⽐(⼀屏幕的内容曝光率),我们在做分布表单布局时,采⽤多列平铺的样式。

优势:
节省⻚⾯纵向空间,可以承载更多表单项,能够放置更多的控件单元。

劣势:
“Z”字型的视觉动线较为复杂,填写体验会相对差⼀些。

file

file

同样⾼度的屏幕,多列平铺的表单能够显示更多内容

表单的交互形式

⽬前表单常⽤的交互形式有⻚⾯跳转、抽屉、弹窗、⽓泡卡⽚、原位编辑。在什么场景下选择什么样的交互形式,通常会根据内容的承载量以及关联度来判断,从少到多依次为:⽓泡卡⽚ – 原位编辑 – Modal对话框 – 抽屉 – ⻚⾯跳转。

气泡卡片

不会影响原有任务进程,承载内容少。把内容的编辑修改操作及校验放在⽓泡卡⽚上完成,不会打断原有任务进程。

file

原位编辑

其编辑内容也为展示内容,默认展示状态操作,可切换为编辑状态,属于轻量型的信息采集表单。

file

Modal对话框

⽤户在不离开当前⻚的情况下继续操作,是流程步骤中的分⽀⾏为,只能承载简单的表单内容。

file

抽屉

拓展性更强,可承载⽐弹窗更复杂⼀些的表单内容。

file

页面跳转

最常⽤的⽅式,适⽤于绝⼤部分的表单,⽀持构建复杂的表单。

file

总结

表单是产品内操作成本较⾼的组件,操作中很容易引起⽤户抵触⼼理,所以在表单的整体完善度、组件的丰富度、交互的流畅度上还需要更深⼊的去探索。

希望本文能帮助你们优化表单功能,更多地考虑功能实现与体验设计的平衡。

最后

欢迎关注【袋鼠云数栈UED团队】~
袋鼠云数栈 UED 团队持续为广大开发者分享技术成果,相继参与开源了欢迎 star