
很久以前我写过一篇讲「用户体验」的文章,文中提到电影的观影体验是可以通过灯光、镜头、脚本、台词、道具、特效等等手段去塑造出来的。比如,《教父》中对灯光塑造角色形象的首次运用,营造出阴暗、冷酷、深不可测的角色形象,帮助观众去建立更立体的角色印象。
所以许多学习电影的同学会去分析电影里的某个镜头或某个片段的细节,聊这个镜头的拍摄用了什么样的手法,演员的表演传递出了一种什么样的信息,以值得我们去学习。于是许多学电影的新人就会以为,学好这些东西,就能拍出一部好电影。
但是作为一名导演,如果只关注这些细节去学习所谓的理论知识,而不知道这部电影背后的宗旨,支撑起整个故事脉络的重要信息,众多人物角色的复杂情感关系,以及剧本背景所表达的时代现象等等,那么就不可能在自己的电影里代入那些细节理论。甚至连如何推进到这样的场景都做不到,试问又怎么可能去聊某个镜头下的细节呢?
这叫缺乏上下文联系,也是任何行业的从业人员在学习该行业所需要具备的理论知识时,都会忽略掉的重要条件。
说一个真实故事。设计师 Teisanu Tudor 前阵子在 Instagram 上做了个实验。他扮演成一位资深 UX,每天通过网上找来的几张图片组成各种设计案例、教程、原则等帖子,分享在上面。受欢迎程度远超他的预期,而其中热度最高的帖子,是案例改版对比图,以及两个方案比较图,再加几句简单的总结。比如:
通过这样的说法,难道就能认为现在所有 App 或网页上的 banner 设计都是错误的?当然不能这么随意下定论。
许多人都以为通过这种简单的几个步骤就可以学会设计,且认为这个学习过程是有趣且轻松,可以速成的。
Teisanu Tudor 说:这种速成贴如此火爆,不免让人有些担忧。这些帖子里的案例几乎都是脱离改版目标的上下文背景去探讨体验的,可许多人都忘了目标才能决定设计改版后的效果,而不是单独看起来如何。
或者这类:
A 与 B,真的是 B 更好么?在不同设备与不同用户的条件下,仅仅通过视觉理论得出这样的结论,未免也过于仓促。
我们都知道,一个设计方案不可能适用于所有场景,设计师的主要能力之一就是在具体限制条件下,平衡好不同利益相关者,以及多个变量,产出合理方案。而类似这种帖子的火爆似乎在传递出一种信息,就是设计是不需要具体问题具体分析的,甚至通过这种细节的通用解法就能解决绝大多数设计问题。这就属于误人子弟了。
我经常会在一些地方看到有人在整理某个页面当中的设计细节,然后有模有样总结一遍,试图将其当做产品设计的某种理论或准则。比如截一张某款产品中的界面,说它的按钮摆放有问题,会导致用户如何如何,而依据就是之前得出的设计准则。其中最有趣的一次是,有个人拿着一款产品的设计方案去吐槽另一个产品的方案,说没对上…
在前面两篇理论文章里,我反复说过理论知识的重要性,它可以帮助我们产出设计方案。但是有一个点是没有被提及的,就是「理论知识的连接性」。
许多人会把自己看到或学到的东西看作是一个独立的知识模块,且希望在工作时能运用上,然而却事与愿违。于是渐渐排斥理论,觉得理论无用,形成一种认知,就是理论无用论。再也不去读书,不去学习理论知识,以至于在知识体系层面停滞不前,无法说明白自己产出的方案,只能说感觉:我感觉可以。
这些人再也不会去思考自己为什么做这个需求,以及这个需求的利益相关者是谁,用户的目标,企业的目标,甚至是这次需求的指标,而只是看界面从某个原则上来说是否合理……而这所谓的原则,只是一些无关紧要的东西,却被人当做设计圣经。
这就是理论知识逐渐被人轻视的原因,许多人本末倒置,再也回不到正确的那条路上。
比如,前阵子有位读者问我:呆总,你看 QQ 这里把一些未开通的特权放出来,吸引用户去开通,但是绝大多数直播产品的勋章体系也挺丰富的,却很少看见会这么做的,是为什么呢?
类似这样的问题,在缺乏业务背景,商业目的,需求指标等前提下,是不可能得出一个绝对结论去证明其他产品为什么不这么做的。这是现在大多数人面临的问题,但却不自知。
就像我这个系列文章里说的一样,理论知识当然重要,但是破碎的理论,是有反作用的,所以需要串联,从全局角度出发,再深挖到细节。而不是只聊大方向,或只聊细节。
举个例子。当我们拿到一个需求,说要从 0-1 做一个长视频产品的弹幕体系。可能很多人就会无从下手,第一直觉想的是去找所谓的竞品抄一下。可能还会像上面那种对比图一样,把几个产品的弹幕界面截图下来比较下,试图从界面元素角度判断哪个设计得更合理。但是会发现,即使是抄,也会抄不到位,甚至会被老板质疑这个方案的合理性。而你能反驳的只是:别人也是这么做的。
而关于不同用户发布弹幕的权限,比如次数、时间限制、字符差异等重要信息,就被忽视掉了。包括各种违规弹幕,以及如何判断违规的弹幕,甚至是弹幕在屏幕上出现的密度、形式、速度等信息可能都无法考虑到。这就是现在许多设计师存在的问题 —— 过分专注界面元素,忽视其背后的信息。
虽然我在之前一篇文章里提到,注重细节的重要性,但是理论知识,从来都不是相互独立的,尤其是与项目相关的,更不可能从某个单点出发得出全面的设计方案理论。
如果你是刚入行的设计师,这么做无可厚非,就像学习电影的学生一样,它确实是学习理论的一种途径,只不过缺乏连接。但如果你已经入行一些日子,觉得自己进步缓慢,甚至感到迷茫,且读完我写的文章也意识到了这个问题,那你就要开始反思,自己对于理论知识的学习是否有主动去将它们串联起来。
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:优设 作者:呆呆U理
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
人的时间精力都是有限的,建立良好的信息架构和层级,能让用户在有限的时间里快速获取和理解有用的信息,并进行下一步操作。
一张图上有四句话,读者根据 字号 判断先读哪一句。在从测试和调研中收集来的用户需求和期望的基础上,首先明确内容和交互的优先级,确认信息的先后顺序和关联性后,才能够设计出有重点的交互界面。这些行为是为了引导用户在阅读过程中 一眼获取重要信息。
用视觉语言来说,上面的例子只是通过调整 文案的尺寸 去探索如何设计页面层级。同时,通过调整其他平面设计元素例如 字重、颜色、透明度 等等也可以达成同样的效果。当然,这种行为同时适用于 按钮、菜单栏、表单 等其他控件。
通过距离划分视觉元素展示它们之间联系的基础前提是 格式塔心理学 组织原则,这是在构建数字界面时所考虑的设计系统的基础指导理论。因为用户一般通过 视觉元素的位置 来判断阅读顺序,设计视觉元素和控件的位置是为了促使用户完成任务,同时在某些情况下,也会引导用户去做他们所期望的事。在很多情况下,用户会自己选择想看的信息。
“在网络上,人们会一目十行而不是逐字逐句的阅读内容。他们一般倾向于付出更少的精力,以高效的方式达成目标。”
这意味着在一个拥有很多功能的页面上,用户会一目十行的迅速寻找他们的目标,因此 大部分的视觉信息会被屏蔽。
用户在网络上的阅读方式高度取决于:
用户的任务目标
用户习惯
页面层级
页面内容形式
这就非常明显了:最后两个因素是设计师可以控制的,并且考虑到网络设计越来越先进,运用知识和技术推动用户行为,而不是使电子产品成为用户的阻碍。基于这个原因,我提出一个设计原则。
有一些人说如果需要在图标旁边放一个文字说明,图标就没有存在意义了,因为它的认知优先级被降低了,成为了识别序列里的一个负担。因为图标视觉系统是建立在 逻辑原则 上的(和文字表达的意思相同),所以无论是对于有没有相关交互经验的用户而言,图标被认为是可以帮助用户迅速理解功能的。
一个只有文字说明的软件菜单和同时拥有图标和文字的菜单相比,图标可以帮助用户更快的理解。在上图中,根据用户所期望的功能,可以看到菜单中的图标带有要访问页面的标题名。接下来,当用户习惯图标后,图标将会更加简单的引导用户快速的在界面中寻找到所需要的内容。
当设计一个新界面时设计师需要知道,页面必定会被有不同阅读习惯的人使用。为了促进理解,我会把用户分成三种人并且定义为:新手用户、中间用户、专家用户。
新手用户 — 就像你所想象的那样,这是一个 第一次接触 这个界面的用户。如果这个界面是某个系统中的一部分,那意味着始终有某些功能点是他第一次接触到的。这个趋势是说,这个等级的用户 理解页面的速度会低于用户理解页面的平均值,并且花费更多的时间去理解语句直到找到所需的内容为止。
中间用户 — 比新手用户多一些数字产品的使用经验,但并不是一个界面使用专家,理解界面的时间大概是处于平均值左右。
专家用户 — 他们已经使用这个平台很多次了,所以可以较快的阅读,而且并不需要通过阅读所有的内容去理解界面,可以 快速识别元素、布局和交互的视觉呈现。也许正因为这些原因,很多用户 对产品界面的突然改变抱有抵触心理。
现在,想想看如果一个投资 APP 每周通过 Email 将以下这个界面发送给用户。用户会不会阅读上面所有的内容呢?每次打开都会阅读吗?或者只是阅读对他比较重要的内容?
这个来自金融 APP 的卡片信息展示了用户的收入。看看这个例子,你的阅读顺序是怎么样的?我可以通过元素的摆放位置、比重、尺寸大小…所形成的视觉层级逻辑来理解它。由于缺乏明确的层级关系,有一些内容无法被精准获知,必须在事后实际运营的过程中调试,通过用户使用数据反馈来决定内容的优先级和必要性,并进行修改(使用 Hotjar,Crazy Egg 之类的热点地图可以收集数据)。
请注意在这些内容中:唯一的 动态信息 就是整个【 3 】模块中的重要信息【 4 】中的内容。所有的邮件页面中位于【 1 】的内容都是一样的。【 2 】中的信息是不变的,并且重复出现在每一封这类型的邮件中,它们都是其认知标识的一部分。
第一次看到的用户需要理解这是关于什么内容的信息,所以信息全面是非常重要的,但是 并不需要把所有信息都放在突出的位置上。考虑到这点,通过 减少色彩饱和度、改变字号大小 等降低视觉重量的方式,是不打断用户阅读过程的选择。
一张展示了用户收入的来自金融 APP 的 Email 卡片,它应用合理排版促进用户更好的理解信息。
在上面这张卡片里,简单的改变了内容排布,突出了最重要的内容。他们展示了 层级关系 对用户体验的影响。一味格式化的信息传递被更具个性化、同理心的方法所取代。头部和底部信息与主体信息相合并,通过这种隔离降低了被突出的可能性。最后,将主按钮更改为次级按钮(具体情况要根据点击率来决定,主按钮可能是最好的方式,有背景色的主按钮更能激起用户点击欲望)
在商业软件环境中,确切的说是在大量的表格中,更多见的是列表标题比每一行的内容更加突出。因为标题是固定信息,而且用户可能每天都会看到,而不是将重要等级修改为 主要和可变内容(列表内的内容信息)。
认识到设计界面时成本和实现功能之间的复杂性,遵循这一思路可以帮助设计师确定元素优先级,并且创建层级关系以提升用户的使用体验。同时,因为引导对新用户来说是必须的,所以在设计产品的时候,重要功能需要结合良好的入门教程、功能提示和及时反馈。这样便建立了可以提升用户日活及留存的高效、友好的用户体验。
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:站酷 作者:ZZiUP
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
“文中示例相关数据都为假的模拟数据,而非真正的商业数据,以此声明”
【度量Measure】是一种测量评定对象的方式,它帮助我们结构化的获取对象的状态与变化,我们运用这些数据进行洞察,转化为有用的信息,帮助决策和优化,这个过程也是分析诊断的过程。
那日常会有怎样的一些信息获取呢?(这里面包含了数据也包含了一些正负性的反馈)
我们对一个功能上线进行一组完整的项目结果质量数据模拟:
净交易收入额比去年同期上升2.0%,达到2千万
订单量为222,比上周上升了2.0%(对交易产生直接正向作用)
方案产出数共222件,比上周上升了22.2% (对内容产出有直接的提升)
用户的满意度为2.2 ,上升了2% (之前是2.0)
用户使用表现出沉静,轻松的情绪(比之前挫折,晦涩要好很多)
功能点击,周活跃2200,点击率22%,周留存22.2%(0-1)
功能渲染和可交互时长为0.2秒加载完成。用户在使用时交互顺畅无卡顿(符合业界前端质量交付标准)
这段描述符合整个产品使用的过程,它似乎是一个多面体,帮助我们了解整个产品黑盒。这个描述越精细越多维,我们得到的信息就越清晰越客观。(包含多元数据内容,并对数据已进行比对和使用,得到一定的有效信息)反之,假如哪个环节出现问题。我们能清晰看到问题出现的环节,并且通过其表征的信息进行问题的深挖(再细化相关数据或者关联的层次)。
我们可以拆解到这几个层次的数据
业务结果、用户反馈(态度与情绪)、行为点击、系统性能
可理解为:良好的产品运行-》用户流畅使用-》良好的用户反馈-》预期的产品转化结果
从获取方式来说,大致可以从两个大角度(这里从广义的范畴去分)
【qualitative research定性研究】:快速从样本中判断问题的性质和方向
【quantitative research定量研究】:数据的验证性,全面性、追踪性
系统承载业务内容的运作,可以记录各种各样的明细数据表,在海量数据中,进行科学的关联与细分。以大数据驱动为最终目标,其特点是:数据的全面性和自动追踪获取。
追踪问题:产品是否符合市场需求?产品是否良性发展?
业务型数据是围绕着整个商业建设和运作阶段而产生的数据。是最能体现产品、商业价值的部分。可以归纳为三类:内容建设->流量访问->商业交易。是商业链路中产生的具有直接商业结果的数据。
内容建设 是指经过人为输入,系统流转产生的比如商品、文章、方案等等具有实质内容价值的数据。是具有生产过程的(一般是经过一系列的操作完成的)。
流量访问/分发 则是针对商业内容的使用/运作,比如某个商品的浏览,某个内容的传播等等。这些和营销相关具备人群效应的数据也属于业务数据。最常见的就是曝光量点击量,而在中后台系统中则是以访问浏览为主。
商业交易 则是最直接的商业结果型数据,最常见的就是网站的GMV(成交金额:包括:付款金额和未付款。)
订单交易额、注册会员数等等。
以某平台中相关的业务数据为示例
业务结果的分析,是根据不同业务发展,确定核心业务指标,以及建立对核心指标的拆解逻辑。
它或许是个计算公式。或者是个一级指标到二级关联指标。例如以下,这里暂时不展开来讲。
对于业务数据的获取,我们大部分是直接通过后端的数据库沉淀下来的。但如果涉及到商业数据的细分(按照商业目标进行阶段性或者类别型的追踪监测)。比如想知道会员的vip的分层情况。或者知道某行业商品的生产细分情况等等。这些虽然可以通过后端拉数据,让数据分析师或者运营整理出来,但是每次都有加工成本,也没有办法看到实时数据,这时候就会要考虑去做细分埋点,下文会提及到埋点方式。
追踪问题:产品使用情况如何?用户浏览习惯如何?
用户行为数据,是围绕用户访问某产品过程的用户行为轨迹数据。其中大体包含了用户量、曝光量、点击量、浏览量、访问时长、停留时长等等观测用户使用情况的表征数据。
这里是一组典型的平台用户使用行为的描述,而这些行为的最终,是产出了上面的业务数据(订单与成交金额)
访问首页->点击并浏览商品详情->点击客户咨询进行咨询->点击购买提交订单->点击支付,支付完成
由此我们可以解释,行为数据与业务结果之间的关系,并且两者的关注点也是有差异的,在行为链路中,我们更注重每一层的转化关系以及用户为什么没有向下转化的障碍点。
再以B端管理系统为例
B端的管理系统具有典型性,可以用点线面来归纳,点指的是诸如事件曝光点击等。线指的是用户使用路径,面则是广义的综合性观察,比如流量分布,比如区域热图等。通过观察这些,可以观察到用户的使用率和使用路径。并且得知用户使用产品是否真的贴合需求,设计的是否合理高效。
行为数据要结合具体的场景或者维度去观察,才能产生更有用的信息。
运用行为数据,我们可以去做很多分析:漏斗分析、留存分析、流量分布分析、路径分析 、单页热力分析、点击分析、 人群分析等等,这些都是分析方式,在后续关联篇章中会去探讨。
行为数据的获取是依赖于埋点的,在业界有两大类埋点方式:全埋点、手动埋点。
行为数据的三大事件类型基本可以归类为:曝光事件、点击事件、停留事件
对于C端侧重于曝光、点击。对于B端侧重点击、停留 (从流量转化与访问效能两个角度来说)
以上介绍了业务结果和行为点击两种数据,而这两种内容,都会涉及到埋点采集这件事,这里我们介绍下关于埋点采集数据这件事情。
追踪问题:如何根据人物、场景、动作制定精准的采集方案?
埋点,是对特定数据的采集,由前端埋点和上报、进行数据处理和数据分析。一般数据埋点分以下三种:
全埋点虽然是所有数据可按需可查,但是因为它的数据量极大,且需要2次定义和清洗,所以只能对通用性质的数据进行采集。而针对性的内容,由数据采集定义后,由前端上报后,可能做到定点,定期精细具体的统计。
两者大致能产出什么数据分析呢?主要以平台/系统这个角度看:
整体分析-通用全埋点
用户活跃、用户留存、用户跳出率、用户停留时长、用户流量分布...
局部与特定分析-手动埋点
关键事件点击率、关键入口渠道流量总计与分布、关键链路漏斗、关键具体区域曝光与停留时长...
为了获取更精准的业务/行为数据,我们一般会采用手动埋点的方式,所以前期 第一阶段会在场景中确定分析目标,然后梳理相应需要的指标,书写明确的埋点需求是很重要的一个环节,书写的足够明确,才能和业务、前端、数据分析师进行准确的沟通,分析目标一致,然后上线后建立相应的数据看板。
注意点:采集方式|统计口径|数据精准度校验
那怎么定义数据分析时的埋点需求呢?可以用以下方式去描述:
什么用户=用户定义
什么时间=时间戳
什么环境=地理位置+网络环境+硬件环境+软件环境+哪个页面(来源页面)+什么位置
什么行为=事件ID+命名
什么条件=可以以某个行为或者业务交易为条件
结果如何=用户操作的结果
示例:
一个后台系统悬浮帮助功能使用的情况需求
一个搜索使用的情况需求
这2个是比较细致的数据采集的描述。规则了统计的对象,范畴,以及条件,结果观测等等的需求,大家可以在业务和行为数据相关采集中,试着撰写下这样明确的需求。这样的数据采集才具有精准的分析价值。
追踪问题:用户都是哪些人,谁使用了这些功能 ?
人群标签可以理解为数据型用户画像。为什么在这里提及,因为大量数据(特别是具体的采集数据)都会涉及到人群这个角度。人群也是定量数据中最具有独立观察价值的数据。
人群标签就是根据人群特点,进行描述分类,对人群打标签。我们根据不同的获取路径,可以大致分两类。
一类是利用基本数据进行定义,比较简单直接
从不同的端,可以获取用户的基本来源,如访问端的类型,或地理位置等,可以定义为“客户端用户”、“江浙沪用户”等。
通过唯一用户ID所匹配的一系列用户注册时的基本信息内容,如性别、职业、行业、兴趣等。可以定义为“女性用户”、“定制类用户”等。
还有一类就是复合型自定义,一般是根据用户的业务、行为数据或者类别属性来定义的,它非常的灵活聚焦。
使用某类条件公式来定义某一波用户
如我们将购买能力从高低来分层用户:月购买小于5000的为中购买力用户,大于5000的为高购买力用户,周活跃大于2但无购买记录为潜力用户。
另外一种构建用户范畴的方式:通过“时间、地点、事件”等一系列复杂描述来勾勒圈选用户
如我们定义“第一次访问站点时,在首页有关注过每日推荐“的用户。
这里的复合定义很多时候都会用到多指标多维度。是一种深度结合业务场景来圈选人群,定义用户的方式。
人群标签,不仅帮助我们细分数据,知道“到底是什么人做了什么事”,聚焦使用人群的各项指标健康情况。最终,还可以定位产品,定位人群,精细化运营产品:现在的用户大致都集中在哪些人群中?哪些功能是头部用户需要的?哪些功能最受基础版用户的欢迎等等。在探索商业需求的时候,更容易找到抓钩,去深挖商业价值。
常用画像的场景
2.定量用户画像:用定量的数据做某些值的规则,来圈定用户人群
某产品生命周期使用示例:
性能数据一般指由产品进行页面渲染及前后端交互时,监测到的时长数据。观测系统性能,是因为系统数据量很大时,在产品渲染交互环节中,容易产生卡顿,造成用户体验的下降,导致流失率。而系统性能,一般是由性能监控等产品产出质量报告。在一些浏览器中,也有嵌入的插件统计报告。
这里大致介绍下业界google最新的关于7大性能指标的定义
这其中,最重要的3大核心指标是:
可以通过官方出品,安装 web-vitals-extension 插件来获取三大核心指标,也可以通过通过安装 Lighthouse 插件来获取如下指标,现在已经内置在浏览器中
即选择典型用户角色,针对问题或者内容进行集中测试或者访谈:用户访谈、焦点问题调研、可用性测试等。
比较常用的是:系统可用性量表(SUS)、有效性、满意度和易用性的问卷(USE)
不管哪种方式,我们都是围绕“可用性”这个角度去进行评估和研究的。业内可用性这个词称为:“Usability”「ISO9241/11」中有明确的相关定义:一个产品可以被特定的用户在特定的境况中,有效、高效并且满意得达成特定目标的程度。可用性关注的是用户与对象在互动过程中的有效性(effectiveness)、效率(efficiency)和满意度(satisfaction)。
用户反馈中我们获取到什么样的信息,我们第一:明确用户对此内容的态度,观察用户行径中的顺畅度,感受用户认知反馈。第二:询问其严重程度和影响程度,正面负面情绪。这两层是由表及里的,互相关联。但侧重有所不一样。
通常用到以下几种度量
而这些内容中一般包含数据是
而从场景分我们如何使用这几种度量呢?
不难发现,我们最常用到的是「自我报告式的度量」
它比较宽泛的反应了产品综合情况。这里举一个自我报告度量涵盖的范畴
追踪问题:用户使用后,在情感上反应如何?
初步知晓用户反馈情况后,可以深入用户情绪感受,进行点状问题的挖掘。进而对问题进行定性分析追踪和程度评级。用户在一定严重情绪影响下,是对产品会产生排斥的,所以有时候对情绪的收集,能让我们对内容具备敏感度。且在设计过程中,充分建立共情和同理心。
连续型描述模型往往认为人类的情感状态是分布在若干个维度组成的某一个空间中,不同情感状态之间不是独立的,而是连续的,可以转化的。
当度量情绪变化阶梯时,可以试着使用连续情绪。比如:挫折——》生气、沮丧——》厌烦等。而有些程度词是和时间长度有直接关系的,比如说疲惫。我们需要关注场景特点,用户可能会长时间沉浸式体验时,它是否能接受打扰,是否会因为一些内容受挫。这些都会导致他最终直观感受的好与坏。
举例子来陈述:
情绪评分卡:
在各种用户态度反馈中,我们也可以直接去获取针对性的情绪化度量表进行5分表计量评分。
具体方式:
以下为目标设定的取词示例:
常用评估:
高中低评估
低
-会让参加者心烦或沮丧,但不会导致任务失败的问题。
中
-这类问题会显著提高任务的难度,但不会直接导致任务的失败。
高
-所有直接导致任务失败的问题。遇到这类问题后基本没有可能再完成任务。
综合因素评估
多维度的评估
前两个较常用,后两个看产品及技术配合
对用户体验的影响
预期的发生频率
对商业目标的影响
技术/实现成本评分(0=低,1=中,2=高)
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:站酷 作者:酷家乐UED
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如何确定方法?我们需要的是一个完整的度量框架,以及能够聚焦用户体验层为驱动,分解并有力的去解决问题。经过大量的实践和验证得到,抓住一个击破点作为产品体验提升的目标,并一种合理的方式进行推导和验证,这是一种最直接度量体验的标准流程性方式,这里的目标必须是:
体现用户主观感受或者具有行为驱动的目标。
基于业务目标定义+用户诉求了解后,得到的以用户为中心驱动的用户行为。
面对设计圈内已经存在的和部分大厂创造的度量模型,评估优劣后最终我们选取了HEART模型。因为HEART是个比较全面和具备更多扩展性的分析框架,同时足够的权威和标准,而且市面上的模型基本都被HEART的五维囊括。除了这些考虑因素外,再给出以下几个明显的优势点:
1、HEART同时涵盖了定性和定量的不同数据维度。
2、HEART框架同时包含了:宏观和微观的层面
3、HEART模型并不单纯的再定义体验质量,同时也链接了商业价值。把用户体验的原则和收益驱动的指标关联在了一起。
整体的思路是:首先分析业务目标,并就业务目标所落地的产品服务的链路进行拆解,分析链路后,找到其中对体验有决定性影响的因素,提取其因素后,即形成体验目标。
➢示例:商品素材搜索链路
需要注意的是,决定性因素的选取必须在具体的触点中才有意义,脱离后无法判断是否有阻塞性影响。另外,某些设计因素是否是决定性可能在跨触点中体现出来,需要联系整个链路进行交叉分析确定。
决定性因素“搜索结果的分类”,引申出的设计目标为“更清晰的信息层级”、“更完整的信息”。
通过链路触点的分析,决定性因素的提取,设计目标的匹配,我们已对设计优化方向有了准确的了解。这个时候需要从设计师视角做一个完善而精准的”体验目标“的表述。
需要注意的是,HEART模型因其维度的广泛定义,不仅仅可用于体验目标的度量,也可以对产品目标、业务结果进行度量,对体验目标的度量因要从产品因素中剥离出体验问题,相对来说较为复杂,是本次叙述的重点。
通过逐一对度量维度进行体验变量提取,有基础值则进行对比的方式,无基础值则使用趋势的表述方式,结合业务目标的情况下,去概念性假设体验目标的正向或反向结果,最终通过标准的格式提炼出信号,信号的提炼的可以用固定的格式进行书写: 格式:用户 用什么 做什么 体验变量 趋势&数值
体验变量所直接产生的属于原生数据,而一组数据通过某种分析加工后,可以成为一个更有价值的信息,如均值、中位值。选择对数据进行哪种方式处理,受目标的影响较大,每一种数据处理方式,都有指向特征,通过与目标的匹配,可以选取出合适的数据处理方式。
确定指标的注意事项
案例A
度量维度:愉悦度
信号:家装设计师 使用搜索功能 搜索素材时 易操作性达到4.0
体验变量:易操作度
数据:易操作度评分
指标:易操作度评分的均值
4.另外,除了准确的定位、度量、转化的逻辑推导外,参考业务目标进行范围收敛,也是非常重要的工作,它影响着每一个推导环节,以避免偏离产品方向,有效的过滤弱关联或无关联的因素。
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:站酷 作者:酷家乐UED
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
1、了解你的用户
因为你的用户是最终评判用户界面好坏的人,所以用户即是你的终极目标,不了解用户需求,即使你的界面做得再好,也不是用户想要的产品。了解用户的需求是你开始做界面的前提,试着沉下心来仔细观察用户的喜好,并了解他们的技能水平和体验观察他们在界面中如何操作。不要迷恋于追逐设计趋势的更新,或是不断添加新的功能,始终记住,首要的任务是关注你的用户,这样才能创造出一个能让用户达成目标的界面。
2、重视UI模型
在软件中,用户的大部分时间都消耗在界面操作中,比如数据录入、数据修改、数据查阅等等,这点与浏览为主的网站类页面的用户操作是完全不同的,所以我们无需画蛇添足。用户希望在新创造的界面中看到那些已有的、相似功能的或遵循基本操作方式的软件界面,即可利用已成惯例的UI模型,使用户产生亲切感。
3、保持一致
用户需要知道一旦他们学会做某项操作,那么下次也同样可行。语言、布局和设计是需要保持一致性的几个界面元素。一致性的界面可以让用户对于如何操作有更好的理解,从而提升效率。
4、清晰的视觉层次
设计时,要让用户把注意力放在最重要的地方。每一个元素的尺寸、颜色还有位置,它们为理解界面共同指明了道路。清晰的层级关系将对降低外观的复杂性起到重要作用。
5、提供反馈
界面要始终保持和用户的沟通,不管是他们的行为对错与否。随时提示用户的行为:状态更改、出现错误或者异常信息。视觉提示或是简单文字提醒都能告诉用户,他们的行为是否能够达到预期的结果。
6、容错机制
无论你的设计多么的清晰明了,用户都会犯错。你的界面应当允许并要为用户提供可以撤销行为的方式,并且对五花八门的输入数据尽量宽容(没人愿意只是因为填错了生日的格式而重头再来)。同样,如果用户的行为引起了一个错误,在恰当的时机运用信息显示什么行为是错误的,并确保用户明白如何防止这种错误的再次发生。
7、鼓励用户
一旦用户在完成了关键操作,可以通过弹出对话框等方式及时告知用户。值得注意的是,把一个复杂的流程任务分解为若干简单步骤,将会更显繁复和让人精力分散。所以无论正在执行的任务有多么复杂和漫长,在界面上要保持流程的不间断性。
8、语言有亲和力
所有的界面或多或少都有文字在其上,让文稿尽量口语化,而不是华美辞藻的堆砌。为行为提供清晰、简明的标签,保持简朴的文字叙述。。
9、保持简洁
最好的用户界面就是没有界面。优秀的软件界面中,你看不到华而不实的UI修饰,更看不到那些用不到的设计元素。所以当想着是否要在界面上加一个新功能或是新元素的时候,再思考一下:用户或者界面中真的需要这些么?为什么用户想要在这里当这个小巧的动态图标?是否只是因为出于自我喜好和页面的漂亮而去添加这些元素?优秀的UI工程师做出来的软件界面不会十分华丽,界面中没有任何分散用户注意力打搅用户操作的元素。甚至应该达到在用户使用系统的时候完全注意不到页面和操作复杂的问题,一切都应该是顺理成章的。
(图片来源于图虫创意)
文章来源:快资讯 作者:德方科技
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
第一步:
-
//安装
-
npm install crypto-js --save-dev
第二步:在src目录下新建个放公用js文件夹(common),再建一个AES.js文件,例如:
第三步:在AES.js中填写如下代码,key密钥长度则可以是128,192或256位(默认情况下是128位),正常情况下固定16位数即可
-
import CryptoJS from 'crypto-js';
-
-
export default {
-
//随机生成指定数量的16进制key
-
generatekey(num) {
-
let library = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-
let key = "";
-
for (var i = 0; i < num; i++) {
-
let randomPoz = Math.floor(Math.random() * library.length);
-
key += library.substring(randomPoz, randomPoz + 1);
-
}
-
return key;
-
},
-
-
//加密
-
encrypt(word, keyStr) {
-
keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345'; //判断是否存在ksy,不存在就用定义好的key
-
var key = CryptoJS.enc.Utf8.parse(keyStr);
-
var srcs = CryptoJS.enc.Utf8.parse(word);
-
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
-
return encrypted.toString();
-
},
-
//解密
-
decrypt(word, keyStr) {
-
keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345';
-
var key = CryptoJS.enc.Utf8.parse(keyStr);
-
var decrypt = CryptoJS.AES.decrypt(word, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
-
return CryptoJS.enc.Utf8.stringify(decrypt).toString();
-
}
-
-
}
第四步:在需要的地方引入
import AES from "@/common/AES.js";
第五步:调用
-
// var keys = AES.generatekey(16);
-
-
//如果是对象/数组的话,需要先JSON.stringify转换成字符串
-
// 不传key值,就默认使用上述定义好的key值
-
-
var encrypts = AES.encrypt(JSON.stringify(cars));
-
var dess = JSON.parse(AES.decrypt(encrypts));
-
-
// var encrypts = AES.encrypt('1234asdasd');
-
// var dess = AES.decrypt(encrypts);
-
-
console.log(encrypts)
-
console.log(encrypts.length)
-
console.log(dess)
特别提示:当解密的时候是为空的时候(也没有报错),那么就一定是你的key长度不符合规范, 可以调整为key长度为16位。
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:csdn
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
首先项目是基于vue开发的项目
需要引入js
import cryptoJs from 'crypto-js'
// DES加密
export const encryptDes = (message, key) => {
return cryptoJs.DES.encrypt(message, cryptoJs.enc.Utf8.parse(key), {
mode: cryptoJs.mode.ECB,
padding: cryptoJs.pad.Pkcs7
}).toString()
}
package com.huihui.until;
import java.security.SecureRandom;
import java.util.Scanner;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* <b>类说明:DES</b>
* <p>
* <b>详细描述:</b>
* @since 2019年3月31日 下午17:00:16
*/
public class DESCryptUtil {
private static final String DES = "DES";
public static final String desKey = "ba54ee44";
public static String doEncrypt(String plainMessage, String hexDesKey) throws Exception {
byte desKey[] = hexDesKey.getBytes();
byte desPlainMsg[] = plainMessage.getBytes();
return Base64.encodeBase64URLSafeString(desCrypt(desKey, desPlainMsg, Cipher.ENCRYPT_MODE));
}
/**
* 获取解密后的字符串
* @param hexEncryptMessage
* @param hexDesKey
* @return
* @throws Exception
*/
public static String doDecrypt(String hexEncryptMessage, String hexDesKey) throws Exception{
if (hexEncryptMessage == null) {
return null;
}
byte desKey[] = hexDesKey.getBytes();
byte desPlainMsg[] = Base64.decodeBase64(hexEncryptMessage);
return new String(desCrypt(desKey, desPlainMsg, Cipher.DECRYPT_MODE));
}
/**
* 获取解密后的数组
* @param desPlainMsg
* @param hexDesKey
* @return
* @throws Exception
*/
public static byte[] doDecryptByte(byte[] desPlainMsg, String hexDesKey) throws Exception{
if (desPlainMsg == null) {
return null;
}
byte desKey[] = hexDesKey.getBytes();
return desCrypt(desKey, desPlainMsg, Cipher.DECRYPT_MODE);
}
private static byte[] desCrypt(byte[] desKey, byte[] desPlainMsg, int CipherMode) throws Exception{
try {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(desKey);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
javax.crypto.SecretKey key = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(DES);
cipher.init(CipherMode, key, sr);
return cipher.doFinal(desPlainMsg);
} catch (Exception e) {
String message = "";
if (CipherMode == Cipher.ENCRYPT_MODE) {
message = "DES\u52A0\u5BC6\u5931\u8D25";
} else {
message = "DES\u89E3\u5BC6\u5931\u8D25";
}
throw new Exception(message, e);
}
}
/**
* 获取8位的key
* @param str
* @return
*/
public static String processString(String str) {
if(str==null||"".equals(str)) {
return "";
}
StringBuilder sb = new StringBuilder();
for(int i=0;i<8;i++) {
int index = i<<2&(32-i);
sb.append(str.charAt(index));
}
return sb.toString();
}
public static void main(String[] args) throws Exception{
DESCryptUtil se=new DESCryptUtil();
for (int i = 0; i < 5; i++) {
Scanner scanner=new Scanner(System.in);
/*
* 加密
*/
System.out.println("请输入要加密的内容:");
String content = scanner.next();
System.out.println("加密后的密文是:"+se.doEncrypt(content, desKey));
/*
* 解密
*/
System.out.println("请输入要解密的内容:");
content = scanner.next();
System.out.println("解密后的明文是:"+se.doDecrypt(content, desKey));
}
}
}
这是我是在在线生成公钥私钥的网站中生成了自己的公钥私钥用来测试
前台
import JsEncrypt from 'jsencrypt'
// RSA加密
export function encryptRsa(publickey, message) {
const rsa = new JsEncrypt()
rsa.setPublicKey(publickey)
return rsa.encrypt(message)
}
后台
package com.huihui.until;
import org.apache.commons.codec.binary.Base64;
import com.googosoft.config.GlobalConstants;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RSAUtil {
private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); //用于封装随机产生的公钥与私钥
public static void main(String[] args) throws Exception {
//生成公钥和私钥
genKeyPair();
//加密字符串
String message = "df723820";
//GlobalConstants.PUBLICKEY 公钥加密
String messageEn = encrypt(message,GlobalConstants.PUBLICKEY);
System.out.println(message + "\t加密后的字符串为:" + messageEn);
//GlobalConstants.PRIVATEKEY 私钥解密
String messageDe = decrypt(messageEn,GlobalConstants.PRIVATEKEY);
System.out.println("还原后的字符串为:" + messageDe);
}
/**
* 随机生成密钥对
* @throws NoSuchAlgorithmException
*/
public static void genKeyPair() throws NoSuchAlgorithmException {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小为96-1024位
keyPairGen.initialize(1024,new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
keyMap.put(0,publicKeyString); //0表示公钥
keyMap.put(1,privateKeyString); //1表示私钥
}
/**
* RSA公钥加密
*
* @param str
* 加密字符串
* @param publicKey
* 公钥
* @return 密文
* @throws Exception
* 加密过程中的异常信息
*/
public static String encrypt( String str, String publicKey ) throws Exception{
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
}
/**
* RSA私钥解密
*
* @param str
* 加密字符串
* @param privateKey
* 私钥
* @return 铭文
* @throws Exception
* 解密过程中的异常信息
*/
public static String decrypt(String str, String privateKey) throws Exception{
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
}
}
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:csdn
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
一个前端小菜鸡。若下边的内容有瑕希望告诉我,如果有更好的方法希望告诉我,感谢万分。
这篇文章主要介绍的对el-upload放在表单中提交之前rules的验证。这里的图片是必须提交项如果可以不提交可用常用方法直接提交就可以。
<el-form ref="personform" label-position="right" label-width="120px" :model="formLabelAlign" status-icon :rules="rules"> <el-row> <el-form-item label="简述"> <el-input type="textarea" v-model="formLabelAlign.paper" autocomplete="off"></el-input> </el-form-item> </el-row> <el-row> <el-form-item prop="file" ref="uploadpic"> <el-upload
style="display:inline-block" :limit="2" class="upload-demo" ref="upload" action="/hqx/knowledge/importKnowledge" :before-upload="beforeAvatarUpload" :auto-upload="false" :on-change="imageChange" :on-remove="imageRemove" > <el-button slot="trigger" size="small" type="primary" plain>上传</el-button> </el-upload> </el-form-item> </el-row> </el-form> <script> import _ from "lodash"; export default { data() { return { xiugai: false, formLabelAlign: { paper: "" }, images: [],// 图片存储 rules: { file: [{ required: true, message: "请上传图片", trigger: "change" }] }, haspic: false // 默认没有传图片 }; }, methods: { beforeAvatarUpload(file) { // 文件类型进行判断 const isJPG = /^image\/(jpeg|png|jpg)$/.test(file.type); const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error("上传图片只能是 image/jpeg/png 格式!"); } if (!isLt2M) { this.$message.error("上传图片大小不能超过 2MB!"); } return isJPG && isLt2M; }, imageChange(file, fileList, name) {//on-change触发 this.images["file"] = fileList; this.haspic = true; // 如果上传了就不显示提示图片警告 if (typeof this.images.file != "undefined") { if (this.images.file.length > 0) { this.$refs["uploadpic"].clearValidate(); } } }, imageRemove(file, fileList, name) { //on-remove触发 //如果images为空了说明并没有提交图片所以需要显示警告 if (typeof this.images.file != "undefined") { if (this.images.file.length > 0) { this.$refs["uploadpic"].clearValidate(); } else { this.$refs["uploadpic"].validate(); this.haspic = false; } } }, confirm() {// 提交绑定的事件 if (this.haspic) { // 去掉rules中对图片的验证 _.unset(this.rules, ["file"]); this.$refs["personform"].validate(valid => { if (valid) { console.log("说明已经添加了图片直接提交就行了"); const wfForm = new FormData(); wfForm.append( 'dsc',this.formLabelAlign.paper) Object.entries(this.images).forEach(file => { file[1].forEach(item => { wfForm.append('files', item.raw) wfForm.append(item.name, file[0]) }) }) // 直接提交 } else { console.log("error submit!!"); return false; } }); } else { // 向rules提价一条对图片的验证。 _.set(this.rules, "file", { required: true, message: "请上传图片", trigger: "change"}); this.$refs["personform"].validate(valid => { if (valid) { console.log("说明图片没有提交"); } else { console.log("error submit!!"); return false; } }); } } } }; </script>
下边解释一下每段代码的含义:
1.
imageChange(file, fileList, name) {//on-change触发 this.images["file"] = fileList; this.haspic = true; // 如果上传了就不显示提示图片警告 if (typeof this.images.file != "undefined") { if (this.images.file.length > 0) { this.$refs["uploadpic"].clearValidate(); } } }
if (typeof this.images.file != “undefined”) 这个可加可不加
其中的一个原因是因为要频繁对rules进行操作因为element的el-upload的提示功能在选择了图片的时候并不会对图片的提示进行更改所以只能自己进行操作更改他显示或者隐藏
haspic是用来记录他是否上传了图片 如果上传为true否则为false 在后面提交的时候有用。
2.考虑到用户可能会选择了图片又删除了所以加上了一个判断
如果在提交的时候进行验证或者不考虑用户全部删除显示提示可不加
imageRemove(file, fileList, name) { //on-remove触发 //如果images为空了说明并没有提交图片所以需要显示警告 if (typeof this.images.file != "undefined") { if (this.images.file.length > 0) { this.$refs["uploadpic"].clearValidate(); } else { this.$refs["uploadpic"].validate(); this.haspic = false; } } },
confirm() {// 提交绑定的事件 if (this.haspic) { // 去掉rules中对图片的验证 _.unset(this.rules, ["file"]); this.$refs["personform"].validate(valid => { if (valid) { console.log("说明已经添加了图片直接提交就行了"); const wfForm = new FormData(); wfForm.append( 'dsc',this.formLabelAlign.paper) Object.entries(this.images).forEach(file => { file[1].forEach(item => { wfForm.append('files', item.raw) wfForm.append(item.name, file[0]) }) }) // 直接提交 } else { console.log("error submit!!"); return false; } }); } else { // 向rules提价一条对图片的验证。 _.set(this.rules, "file", { required: true, message: "请上传图片", trigger: "change"}); this.$refs["personform"].validate(valid => { if (valid) { console.log("说明图片没有提交"); } else { console.log("error submit!!"); return false; } }); } } } };
提交的时候进行判断。因为没有想到其他的方法所以写了一个变量判断是否在rules加上对图片的判断。因为如果存在对图片的判断。form验证的时候就总是throw error 不能进行提交操作this.$refs[“personform”].validate(valid){}是提交form表单的时的验证
(1)在有图片的时候去掉对图片的验证
(2)在有图片的时候加上对图片的验证
<template> <div> <el-form ref="personform" label-position="right" label-width="120px" :model="formLabelAlign" status-icon :rules="rules"> <el-row> <el-col :span="12"> <el-form-item label="发布人"> <el-input size="mini" v-model="formLabelAlign.person" autocomplete="off" clearable :disabled="xiugai" ></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-form-item label="简述"> <el-input type="textarea" v-model="formLabelAlign.paper" autocomplete="off"></el-input> </el-form-item> </el-row> <el-row> <el-form-item prop="file" ref="uploadpic"> <el-upload
style="display:inline-block" :limit="2" class="upload-demo" ref="upload" action="/hqx/knowledge/importKnowledge" :before-upload="beforeAvatarUpload" :auto-upload="false" :on-change="imageChange" :on-remove="imageRemove" :on-success="onsuccess" > <el-button slot="trigger" size="small" type="primary" plain>上传</el-button> </el-upload> </el-form-item> </el-row> </el-form> </div> </template> <script> import _ from "lodash"; export default { data() { return { xiugai: false, formLabelAlign: { paper: "" }, images: [], rules: { file: [{ required: true, message: "请上传图片", trigger: "change" }] }, haspic: false // 默认没有传图片 }; }, methods: { beforeAvatarUpload(file) { // 文件类型进行判断 const isJPG = /^image\/(jpeg|png|jpg)$/.test(file.type); const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error("上传图片只能是 image/jpeg/png 格式!"); } if (!isLt2M) { this.$message.error("上传图片大小不能超过 2MB!"); } return isJPG && isLt2M; }, imageChange(file, fileList, name) { this.images["file"] = fileList; this.haspic = true; // 如果上传了就不显示提示 if (typeof this.images.file != "undefined") { if (this.images.file.length > 0) { this.$refs["uploadpic"].clearValidate(); } } }, imageRemove(file, fileList, name) { if (typeof this.images.file != "undefined") { if (this.images.file.length > 0) { this.$refs["uploadpic"].clearValidate(); } else { this.$refs["uploadpic"].validate(); this.haspic = false; } } }, onsuccess(response, file, fileList){ // 如果提交失败将haspic改为false后边的数据就不让他提交 }, confirm() { if (this.haspic) { // 去掉rules中对图片的验证 _.unset(this.rules, ["file"]); this.$refs["personform"].validate(valid => { if (valid) { console.log("说明已经添加了图片直接提交就行了"); const wfForm = new FormData(); wfForm.append( 'dsc',this.formLabelAlign.paper) //直接将wfForm提交就可以 } else { console.log("error submit!!"); return false; } }); } else { alert('请添加图片之后在提交') } } } }; </script>
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:csdn
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
1.nodejs接收上传的图片主要是使用formidable模块,服务器是使用的express搭建。
引入formidable
var formidable = require('./node_modules/formidable');
拦截请求,设置formidable的常规项
app.post("/image",function (req,res) { var form = new formidable.IncomingForm(); form.encoding = 'utf-8'; form.uploadDir = path.join(__dirname + "/../page/upload"); form.keepExtensions = true;//保留后缀 form.maxFieldsSize = 2 * 1024 * 1024; });
解析图片,重命名图片名称,返回给前端
//处理图片 form.parse(req, function (err, fields, files){ console.log(files.the_file); var filename = files.the_file.name var nameArray = filename.split('.'); var type = nameArray[nameArray.length - 1]; var name = ''; for (var i = 0; i < nameArray.length - 1; i++) { name = name + nameArray[i]; } var date = new Date(); var time = '_' + date.getFullYear() + "_" + date.getMonth() + "_" + date.getDay() + "_" + date.getHours() + "_" + date.getMinutes(); var avatarName = name + time + '.' + type; var newPath = form.uploadDir + "/" + avatarName; fs.renameSync(files.the_file.path, newPath); //重命名 res.send({data:"/upload/"+avatarName}) })
完整代码如下
var path = require("path"); var fs = require("fs"); var express =require("./node_modules/express"); var app=express(); var bodyParser = require('./node_modules/body-parser'); var formidable = require('./node_modules/formidable'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(express.static(__dirname + "./../page")); app.listen("8083",function () { console.log("服务启动") }); //拦截请求 app.post("/image",function (req,res) { var form = new formidable.IncomingForm(); form.encoding = 'utf-8'; form.uploadDir = path.join(__dirname + "/../page/upload"); form.keepExtensions = true;//保留后缀 form.maxFieldsSize = 2 * 1024 * 1024; //处理图片 form.parse(req, function (err, fields, files){ console.log(files.the_file); var filename = files.the_file.name var nameArray = filename.split('.'); var type = nameArray[nameArray.length - 1]; var name = ''; for (var i = 0; i < nameArray.length - 1; i++) { name = name + nameArray[i]; } var date = new Date(); var time = '_' + date.getFullYear() + "_" + date.getMonth() + "_" + date.getDay() + "_" + date.getHours() + "_" + date.getMinutes(); var avatarName = name + time + '.' + type; var newPath = form.uploadDir + "/" + avatarName; fs.renameSync(files.the_file.path, newPath); //重命名 res.send({data:"/upload/"+avatarName}) }) });
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:博客园
分享此文一切功德,皆悉回向给文章原作者及众读者.免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
唐·诺曼提出了情感化设计的3个方向:本能层、行为层、反思层。但如何在一个项目中,通过情感化设计,让用户切实感受到这样的情绪,一直没有很系统的理论。恰逢58同城交友业务中有这样的项目,可以实践一下这方面的思考。本次活动中,嘉宾分享了直播礼物的价值与意义、直播情境情绪,并以此为基础,探讨了理性化搭建情感化礼物的设计体系。
礼物的价值是什么?有什么意义,为什么不直接用钱?礼物和金钱的不等价感受,决定了礼物是很好的消费载体;不同场景需要不同载体,礼物的多样性满足了不同场景的需求;直接送钱可能会让用户不爽。
礼物要匹配情境情绪出现,送钱也不太合适,而当前平台已存在30多款礼物,但是用户的使用次数较少,期望通过本次项目更新直播间的礼物,并提升ROI。因此需要重新探索直播间会出现的情境情绪,并设计与之匹配的礼物。
这款产品面向下沉市场、25~40岁、单身/离异的用户群体。
设计情感化礼物的灵感来自于彼得·MA·德斯梅特的理论模式。
情感产生的过程:用户对产品的关注点和产品所呈现的信息相结合会引发用户对产品的评估,而评估的结果会最终决定用户对产品的情感是什么样子的。由于个体的动机、价值观、态度的不同,情感产生的差异是不可控的,导致设计师在设计的时候处于一个相对被动的位置。因此期望可以为设计师提供一些方向性的指引,帮助他们更好地完成产品的设计。因此通过模型推导,了解用户对产品的情感和关注点,从而推导出产品应该呈现什么样的信息,从而帮助设计师做出更好的设计。
2.1 规划思路:
2.2 实施步骤:
基于上述结论,给到设计师合理的方向性指引,快速上线了一部分礼物。在产品逐渐趋于成熟之后,需要对最初建立的情感指标进行核准,了解真正用户在使用过程中对产品的情感诉求和关注点,进一步调整情感。
通过1V1电话访谈,对11名真实用户进行了深访。
在阶段二中,主要探讨了以下四点:
结合上述分析,提炼出了情感诉求和产品关注点两个层面的信息。情感诉求层面,通过送礼场景和送礼动机的分析,将原来的5个情感指标重新定义为3个情感指标:自豪、爱慕、情欲。这3个情感指标将成为后续建立礼物库的基础。
产品关注点层面,从功能、体验层面为设计师提供了方向性的引导。
用研通过上述一系列的研究和分析,仅仅可以给设计师一些方向性的引导,设计师在设计层面需要进一步结合分析结论进行拆解和设计。
情绪与意象具有一定的关联性,它可能是生活习得的。例如:秋雨、孤独的老人、掩面哭泣等都可以表达悲伤;又或者是被竞品教育的,例如:火箭、跑车等,用于表达自豪,均是来自竞品的教育。
我们可以从情绪诞生的场景来剥离构成意象的维度:
基于上述维度及元素,设计、产品、运营团队内收集意象,主要方式包括以下两类:
另一方面,也要收集竞品的意象,同时需要将前面头脑风暴产生的意象以及竞品的意象进行形象类型、礼物形态、价格定位的分析和提取。
以此为基础,可以构建情绪意象库。某一种形象,在不同的场景和不同的关系下,可以表达不同的情绪。例如同样是烟花,小仙女棒式的烟花和宏伟的漫天绽放的烟花所表达的情绪是截然不同的。因此我们根据所要表达的情绪,将所对应的形象、场景、关系收纳到对应的意象库中,这可以帮助一些视觉设计师快速给出设计方向。
下一步,即可为意象进行设计形态的处理。我们将需要处理的意象,以单一-复合 和 具体-抽象 为坐标进行了分类,从而划分小礼物、中礼物、大礼物,以提供定价参考。
由于直播间涉及的礼物品类繁多,同时参与设计的视觉同学也较多,为了使得最终的产出有视觉风格上的一致性,针对每一种情绪进行了配色、光效、样式、质感上的定义。
礼物定价趋势方面,对竞品的礼物进行了分析,将竞品的礼物按表达的情绪聚合,并分析在这种情绪上,礼物价格的分布,来帮助我们了解竞品针对不同情绪表达的礼物的定价规则,以指导自己产品的定价。
最后,礼物上线后,销售量top10的礼物中,新礼物占比达到60%。同时同档位中效益最好的一款,收益提升了1035.4%。
以上是关于理性思维搭建情感化设计体系的分享。
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。
文章来源:UXRen 作者:宝珠
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com