什么是“有驾”
【有驾】是百度旗下的汽车信息与服务平台,累计用户超5.3亿,致力于为用户提供真实、可靠的看选买车服务,以及为车企和经销商提供从品牌到效果的一站式互联网营销解决方案。
现状分析
有驾品牌在孵化初期,重点是在用户词建立品牌感知。所以我们提取“有驾“的字形做为品牌符号,减少歧义,强化用户的感知。
但是随着品牌持续运营进入新的阶段,我们发现现有的设计无法满足后续的运营诉求了,主要体现在:
品牌logo:不能体现汽车的行业属性,缺乏成体系的品牌符号和VI体系,色彩上也不够符合时下潮流的年轻配色体系。
品牌活动:品牌关联度弱,活动维度单一。
项目概述
因此,我们重新梳理有驾的品牌定位与调性,借助本次品牌升级,打造有驾差异化风格,形成独有的视觉印记。
因为用户对于旧的logo已有一定的认知。所以此次改版的目标在保持固有用户认知,在原有基础上进行品牌标识的探索及应用,以强化品牌感知,提升品牌的竞争力,整合业务资源做心智触达。
前期分析
前期我们对汽车垂类的竞品进行了一轮调研,并且结合有驾的用户群里,寻找有驾品牌的差异点。
有驾用户群体年轻化为主,普遍具有高学历,集中在新一线二线城市。
通过以上在用户、行业及行业趋势等多唯独的信息搜集后,我们确定了有驾品牌设计的四个核心关键词:年轻、科技、未来、专业。
建立体系
在明确设计方向后,我们梳理了线上线下的所有品牌触点,结合前期的调研结论,汇总出了有驾设计系统的完整框架,以确保品牌设计的完整性和灵活适用性。
设计落地
基于前期分析洞察结论,我们在继承圆形和车形的基础上,对品牌符号与icon进行了大量的方案探索。从图形、质感等方面切入,简化图形形态,尝试不同的形态呈现的视觉感受和气质。最终确定了全新品牌logo方案。
相对于升级前,新版的logo加入汽车元素,解决升级前logo的行业属性不明确的问题,让产品app的行业属性更加直观。同时增加品牌符号做为底纹,辅以有驾的圆形符号成为品牌核心的一部分。强化有驾的品牌基因。
符号提炼
确定品牌logo后,为了确保品牌能够更好的拓展应用,进行了品牌符号的提炼。并为了延续之前的品牌调性。所以辅助图形延续了之前的圆环造型,造型偏向轮胎;在不破坏原有型的基础上,加入一些折角的质感的变化,使图形变化更加丰富,更有识别度。
设计语言
为了更好的触达到各业务场景,所以我们对视觉风格进行了探索和拓展。分别以浅色与深色作为主要探索方向,以适配不同的落地场景。结合有驾的年轻化,科技感的设计目标,探索出以下三种质感呈现:
符号拓展
在提取的形状基础上进行变形,增加折叠细节。在大事件活动,海报等场景使用,增加品牌关联度。
设计字体
结合全新的品牌定位,我们也优化了有驾的品牌字体,从细节出透出有驾的品牌感知。
品牌手册
新的品牌需要一套更全面的品牌系统来满足不同场景下的业务拓展需求。
目前我们也对现有的品牌手册进行拓展和完善,同步到业务方,以便更好的保证各业务场景触点下品牌的认知和统一,达到提质增效的目的。
品牌落地
除了对品牌对角度的塑造和升级,我们更积极的把品牌渗透到活动、栏目包装、大事件运营、品牌海报等各维度场景中,让有驾品牌形象更加立体多元。
结语
目前有驾品牌升级已经取得阶段性成果,沉淀出更加完善的品牌资产,不仅提升设计效率保证全链路的品牌曝光,也为业务规模化打下基础。之后我们也将不断完善和扩充品牌资产,将设计成果不断落地到业务中,细化业务目标并与设计目标紧密结合,多维度助力业务的高速发展。
从事体验设计这么多年,经历过多款B端和C端产品的体验设计,有了一定的个人感悟。由于两者用户群体、使用场景、产品定位等方面的不同,让两者的体验设计策略也存在较大的差异。但是无论是B端还是C端产品,有一个共同的体验目标就是“提升用户的操作效率”。甚至在一定程度上,C端产品比B端产品要求更高。
为什么这么说呢?
因为C端产品面临激烈的市场竞争,如果效率方面存在明显的不足,用户很容易就转向其他平台了。而B端产品一旦部署上线,不菲的产品价格,平台切换的风险,数据迁移的成本等因素,很容易形成产品的护城河。虽然用户内心已是万马奔腾,但是依旧要自己摸索尝试、查看文档、或者请教别人来完成工作任务。
今天我们了解下C端产品用户行为路径中提升效率的4种方法。
用户行为探知,就是根据用户的操作行为或特定的时间,系统给出相应的推荐操作。
最常见的就是截屏操作产生的行为引导,目前主流的产品应用都会做出分享功能提示。在淘宝中,由于商品链接无法在微信中直接分享,所以淘宝对可能的用户分享行为都进行了设计优化。
例如用户在商品页面截屏时,系统会自动复制淘口令,既方便用户分享给好友,又方便了对方快速获取商品信息,避免了图片分享过程中的复杂操作。同样微信在用户发信息时,会自动提示是否要发送截图内容,减少了用户选择图片等操作流程,提升了用户效率。
(左图:淘宝截屏提示 右图:微信提示截屏信息)
高德地图在特定时间段,开启导航时会默认给出“上班路线”的按钮,方便用户快速导航。此外还在地址中增加了“常搜”标签,根据当前地址优先显示常搜的地址,帮助用户快速完成导航设定。
用户行为引导,就是通过用户行为流程分析,在用户路径中增加相关功能的曝光和引导,让流程更加流畅,从而提高用户的操作效率。
淘宝购物商品详情页中,在最后几张商品图片中植入了评价信息和入口,更加符合用户的心智,引导性也更强。同时用户可以直接选择自己喜欢的款式查看商品评价,操作效率也更高。
而且增加评论引导后,实现了用户在首屏就可以了解商品、价格和用户评价,有利于用户对商品作出初步的购买决策,从而提高用户效率。
相比之下,专门的评价模块进入后默认显示全部商品的评价信息,用户需要手动选择才能查看自己喜欢的商品款式的评价信息,无形中拉长了用户的行为路径,增加了用户操作成本。
在今日头条中,搜索行为与资讯内容绑定。用户在浏览的资讯后,资讯下方会自动显示搜索关键词,可以帮助用户更快捷的进行搜索操作。
同样在热榜资讯下方增加了详情提示,引导用户去查看事件详情。
(左图:搜索关键词推荐 右图:热榜引导)
手机产品屏幕的空间相对较小,展示内容有限。因此需要根据用户行为,将相关功能聚合,让用户在一屏中可以获取更多的信息,从而提高用户效率。
在天猫部分商品详情页中,将商品参数集合在了商品名称右侧,保证了用户在不滑动屏幕的情况下,就可以直接读取商品参数。方便了用户快速了解商品信息,提升了用户的购物效率。
考拉海购则在部分商品首屏中,直接分类展现出了商品的型号和款式分类,并且实现了商品价格联动,提升了用户获取信息的效率。
减少用户的记忆成本,最好的方法就是让系统产生记忆。因此大多数APP都会提供历史浏览记录等功能,方便用户查找相关信息。而内容型产品为了更好的提高用户操作效率,则是将用户行为记忆直接保留在内容层面上。
我们常见的音乐类产品会留存音乐的播放进度,用户点击后就可以直接再次播放。
(左图:喜马拉雅 右图:网易云音乐)
微信公众号文章阅读时,会对用户阅读位置增加锚点。用户再次阅读时,自动定位到上次退出时位置,从而提高用户的阅读效率。
微信“看一看”进入时,内容会自动刷新,提供更多新的内容给用户,为了帮助用户更好地区分新内容,微信增加了浏览位置提醒。
同样对于用户未完成的文章内容,用户再次进入时,今日头条会给出继续阅读的提示信息,方便用户快速操作。
在提升用户效率时,我们需要关注用户场景和行为路径,从而寻找到更多的效率提升突破口,主要包含以下3个注意点:
1、明确用户的行为路径,寻找用户核心关切点,提升用户效率;
2、转移用户操作成本,让系统承担更多的行为判断和用户引导;
3、用户行为聚合时,应当集中关键的行为信息,避免对用户核心行为造成干扰;
以上就是我对提升用户效率方法的分析和总结,欢迎大家留言交流。
作者:子牧先生
转载请注明:站酷
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
1. <!-- 弹出框 --> <el-dialog :title="titleMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-form :model="form" :rules="rules" ref="form"> <el-form-item label="商品名称" prop='goodsName' style="width:40%"> <el-input v-model="form.goodsName" auto-complete="off" placeholder="请输入商品名称" size="medium"></el-input> </el-form-item> <el-form-item label="商品图片" prop='goodsImg'> <el-upload action="uploadAction" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :limit="1" :show-file-list="true" name="img" ref="upload" :data="form" accept="image/png,image/gif,image/jpg,image/jpeg" :headers="headers" :on-exceed="handleExceed" :auto-upload="false" :on-error="uploadError" :before-upload="handleBeforeUpload" :on-change="changeFile"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="50px" :src="dialogImageUrl" alt=""> </el-dialog> </el-form-item> <el-form-item label="商品对应积分" prop='goodsIntegral'> <el-input v-model="form.goodsIntegral" auto-complete="off" placeholder="请输入积分" size="medium" type="number"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="cancel">取 消</el-button> <el-button type="primary" @click="uploadFileFun('form')">确 定</el-button> "注意uploadFileFun('form') 括号内记得带引号不然可能会报validate is not defined" </div> </el-dialog>
2.data部分
data() { return { //新增和编辑弹框标题 titleMap: { addStore: '新增商品', editStore: "修改商品" }, dialogStatus: "", //新增编辑弹出框 dialogFormVisible: false, dialogVisible: false, //表格数据 tableData: [], form: { id: '', goodsName: '', goodsImg: '', goodsIntegral: '', }, rules: { goodsName: [{ required: true, message: '请输入商品名称', trigger: 'blur' }], goodsIntegral: [{ required: true, message: '请输入商品积分', trigger: 'blur' }], }, headers: { Authorization: 'Bearer ' + window.localStorage.getItem("token") }, dialogImageUrl: '', //图片回显 uploadFiles: '', //formData img 文件 goodsId: '', //判断是新增还是编辑 },
// 上传文件之前的钩子 handleBeforeUpload(file) { console.log('按钮', this.titleMap) if (!(file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/jpg' || file.type === 'image/jpeg')) { this.$notify.warning({ title: '警告', message: '请上传格式为image/png, image/gif, image/jpg, image/jpeg的图片' }) } let size = file.size / 1024 / 1024 / 2 if (size > 2) { this.$notify.warning({ title: '警告', message: '图片大小必须小于2M' }) } }, //图片上传超过数量限制 handleExceed(files, fileList) { this.$message.error("上传图片不能超过1张!"); }, handleRemove(file, fileList) { this.$message.error("删除成功!"); }, // 图片上传失败时 uploadError() { this.$message.error("图片上传失败!"); }, //预览图片 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, //文件改变时 on-change方法 ,fileList[0].raw 就是传给后端的值 //filelist这个对象里面有很多属性,我们上传文件时,实际上传的是filelist列表中每一项的raw,只有raw可以正常上传, 获取到文件后,需要定义变量保存文件。所以需要获取filelist中的raw进行保存。 //这里我用的formdata上传多文件,console打印formdata,文件在控制台中显示的格式为binary。 changeFile(file, fileList) { this.uploadFiles = fileList[0].raw }, uploadFileFun(formName) { this.$refs[formName].validate((valid) => { let fd = new FormData(); fd.append('id', this.form.id); fd.append('goodsName', this.form.goodsName); fd.append('goodsIntegral', this.form.goodsIntegral); fd.append('img', this.uploadFiles); let config = { headers: { 'Content-Type': 'multipart/form-data' } } 根据goodsID判断是编辑提交还是新增提交,主要针对新增编辑使用同一个弹框 if (valid && !this.goodsId) { this.$axios.post("接口地址", fd, config).then(res => { if (res.data.success == true) { this.dialogFormVisible = false this.$message({ message: res.data.msg, type: 'success' }); //新增完清空表单内容 setTimeout(() => { this.$refs.form.resetFields(); }, 200) this.reload() } else { this.$message.error(res.data.msg); } }).catch(res => { console.log(res) }) } else { this.$axios.post("接口地址", fd, config).then(res => { if (res.data.success == true) { this.dialogFormVisible = false this.$message({ message: res.data.msg, type: 'success' }); //编辑完清空表单内容 setTimeout(() => { this.$refs.form.resetFields(); }, 200) this.reload() } else { this.$message.error(res.data.msg); } }).catch(res => { console.log(res) }) } }) }, add() { this.dialogStatus = "addStore" this.dialogFormVisible = true this.goodsId = "" //新增商品是商品ID为空 }, // 取消 cancel() { this.dialogFormVisible = false this.$refs[formName].resetFields() }, //编辑 handleEdit(index, row) { this.form = this.tableData[index] this.dialogStatus = "editStore" this.goodsId = row.id this.currentIndex = index this.dialogFormVisible = true },
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
在我上一篇写的Node.js实现简单的POST请求
里面POST请求接受参数需要写两个事件,这难免有些不太方便
如果我们用formidable来接受参数的话,会变得特别方便。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <form class="upload" action="shangchuan" enctype="multipart/form-data" method="post"><!-- 上传接口是/shangchuan --> <p> 请上传一个头像 <input type="file" name="wenjian"> </p> <p> <input type="submit" value="提交"> </p> </form> </body> </html>
![]()
安装依赖,执行下面这三句npm语句
npm install finalhandler --save
npm install serve-static --save
npm install formidable --save
之后会自动生成下面这个package.json文件
{
"dependencies": {
"finalhandler": "^1.1.1",
"formidable": "^1.2.1",
"serve-static": "^1.13.2"
}
}
var finalhandler = require('finalhandler') var http = require('http') var serveStatic = require('serve-static') var url = require('url') var fs = require('fs') var querystring = require('querystring') var formidable = require('formidable') var path = require('path') // Serve up public/ftp folder //配置静态资源服务器,将public文件夹静态化出来 var serve = serveStatic('public', {'index': ['index.html', 'index.htm']}) // Create server var server = http.createServer(function onRequest (req, res) { //路由 var pathname = url.parse(req.url).pathname; if(pathname == '/shangchuan'){ //创建一个表单的实例,formidable var form = new formidable.IncomingForm(); //设置上传的文件存放在哪里 form.uploadDir = './uploads'; //处理表单 form.parse(req,(err,fields,files) => { //fields 表示普通控件 //files 表示文件控件 if(!files.wenjian){ return; } if(!files.wenjian.name){ return; } var extname = path.extname(files.wenjian.name);获取文件的扩展名,便于下面修改上传后的文件名字 //改名 fs.rename(files.wenjian.path, files.wenjian.path + extname,() => { res.end('上传成功') }) // console.log(fields); }) return; } serve(req, res, finalhandler(req, res)) }) // Listen server.listen(3000); console.log('服务已经启动在3000端口');
![]()
会看到这个页面
然后选择任意文件点击提交
会发现在很短的时间内你的文件会提交成功在你的uploads文件夹下。
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
model
: 绑定整个表单model值
rules
: 整个表单校验规则
ref
:获取该表单form组件
prop
: 绑定每个表单的规则,写在el-form-item
上
validate
: 对整个表单进行校验的方法
valid
: 每个必填表单项都提交为true,否则为false
//使用element-ui 页面组件 <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="活动名称" prop="name"> <el-input v-model="ruleForm.name"></el-input> </el-form-item> <el-form-item label="活动区域" prop="region"> <el-select v-model="ruleForm.region" placeholder="请选择活动区域"> <el-option label="区域一" value="shanghai"></el-option> <el-option label="区域二" value="beijing"></el-option> </el-select> </el-form-item> </el-form> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button> </el-form-item> //data中定义form表单中每项表单model值、和每个表单校验的规则 <script> export default { data() { return { ruleForm: { name: '', region: '', }, rules: { name: [ { required: true, message: '请输入活动名称', trigger: 'blur' }, { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' } ], region: [ { required: true, message: '请选择活动区域', trigger: 'change' } ], }; }, //定义表单提交方法 methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); }, } }
<el-form v-if="fromHtmlList.deviceInfo.sitsb.length" :model="fasj" :rules="rules" label-position="left" label-width="125px" ref='sitsb'> <el-form-item label-width="100%" > <div slot="label" class="titleInfo">局端设备</div> </el-form-item> <el-form-item v-for="(item, i) in fromHtmlList.deviceInfo.sitsb" :key="`F_key_${i}`" :label="`${item.label}:`" :class="item.class" :label-width="item.labelWidth" :prop="`${item.rule ? 'deviceInfo.sitsb.'+item.rule : ''}`"> <el-select v-if="item.el === 'slt'" v-model="fasj.deviceInfo.sitsb[item.model]" placeholder="请选择" style="width:200px;" clearable> <el-option v-for="(op, n) in options[item.option]" :key="`vop_key_${n}`" :label="op.label" :value="op.value"> </el-option> </el-select> <el-input v-if="item.el === 'ipt'" v-model="fasj.deviceInfo.sitsb[item.model]" @focus="()=>{ item.focus && handleFocus('sitsb', item.model)}" :placeholder="`${item.placeholder ? item.placeholder : '请输入'}`" style="width:200px;"></el-input> <span v-if="item.el === 'txt'">{{fasj.base[item.model]}}</span> </el-form-item> </el-form> <div class="btn-list"> <el-button type="primary" @click="checkRequired">提 交</el-button> </div> <script> export default { data() { return { fasj: { base: {}, // 基本信息 deviceInfo: {}, }, //定义 页面表单结构 fromHtmlList: { baseInfo: [], deviceInfo: { ywzsb: [], sitsb: [] } }, //定义 表单校验规则 rules: { 'deviceInfo.sitsb.IPType': [ { required: true, message: '请输入', trigger: 'blur' } ], 'deviceInfo.sitsb.IPAddr': [ { required: true, message: '请输入', trigger: 'blur' } ], 'deviceInfo.sitsb.netmask': [ { required: true, message: '请输入', trigger: 'blur' } ], 'deviceInfo.sitsb.vlanId': [ { required: true, message: '请输入', trigger: 'blur' } ], }, options: { IPType: [ {label: 'ipv4', value: 'ipv4'}, {label: 'ipv6', value: 'ipv6'} ], rmSite: [], room: [], }, } }, created(){ const orderType = '业务开通' ;//页面初始加载用到的变量值,可通过组件传值获取 //created中初始定义页面表单结构 this.fromHtmlList = { baseInfo: orderType === '业务开通' ? [ {label: '接入方式', labelWidth: '100px', rule: '' , model: 'serviceType', option: '', el: 'txt', class: 'w2'}, {label: '标准九级地址', labelWidth: '120px', rule: '', model: 'aendAdreesName', option: '', el: 'txt', class: 'w2'}, {label: '城乡类型', labelWidth: '100px', rule: 'cityType', model: 'cityType', option: 'cityType', el: 'slt', class: 'w2'}, {label: '方案设计附件', labelWidth: '120px', rule: '', model: 'fileId', option: '', el: 'btn', class: 'w2'}, ] : orderType === '移机' ? [ {label: '接入方式', labelWidth: '100px', rule: '' , model: 'serviceType', option: '', el: 'txt', class: 'w2'}, {label: '标准九级地址', labelWidth: '120px', rule: '', model: 'aendAdreesName', option: '', el: 'txt', class: 'w2'}, {label: '城乡类型', labelWidth: '100px', rule: 'cityType', model: 'cityType', option: 'cityType', el: 'slt', class: 'w2'}, {label: '方案设计附件', labelWidth: '120px', rule: '', model: 'fileId', option: '', el: 'btn', class: 'w2'}, {label: '移机场景', labelWidth: '100px', rule: 'moveScene', model: 'moveScene', option: 'moveScene', el: 'slt', class: 'w2'}, {label: '是否需要网络调整', labelWidth: '', rule: 'netChange', model: 'netChange', option: 'netChange', el: 'slt', class: 'w2'} ] : [ {label: '接入方式', labelWidth: '100px', rule: '' , model: 'serviceType', option: '', el: 'txt', class: 'w2'}, {label: '标准九级地址', labelWidth: '120px', rule: '', model: 'aendAdreesName', option: '', el: 'txt', class: 'w2'}, {label: '城乡类型', labelWidth: '100px', rule: 'cityType', model: 'cityType', option: 'cityType', el: 'slt', class: 'w2'}, {label: '方案设计附件', labelWidth: '120px', rule: '', model: 'fileId', option: '', el: 'btn', class: 'w2'}, {label: '是否需要网络调整', labelWidth: '', rule: 'netChange', model: 'netChange', option: 'netChange', el: 'slt', class: 'w2'}, {label: '是否更换末端设备', labelWidth: '', rule: 'devChange', model: 'devChange', option: 'devChange', el: 'slt', class: 'w2'} ], deviceInfo: { ywzsb: serviceType === 'PON' ? [ // 默认PON {label: '机房', labelWidth: '90px', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: '设备名称', labelWidth: '90px', rule: '', model: 'deviceName', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: '设备端口', labelWidth: '90px', rule: '', model: 'devicePort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: '延伸设备', labelWidth: '90px', rule: '', model: 'deviceExtend', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'} ] : [ // 裸光纤、传输下沉、传输延伸(ywzsb) {label: '机房', labelWidth: '', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: '站点', labelWidth: '', rule: '', model: 'site', option: '', el: 'ipt', class: 'w2'}, {label: '设备名称', labelWidth: '', rule: '', model: 'deviceName', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: '设备端口', labelWidth: '', rule: '', model: 'devicePort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, ], sitsb: serviceType === 'PON' ? [ {label: '机房名称', labelWidth: '', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2'}, {label: '站点名称', labelWidth: '', rule: '', model: 'site', option: '', el: 'ipt', class: 'w2'}, {label: '汇聚交换机', labelWidth: '', rule: '', model: 'switch', option: '', el: 'ipt', class: 'w2'}, {label: '汇聚交换机端口', labelWidth: '', rule: '', model: 'switchPort', option: '', el: 'ipt', class: 'w2'}, {label: 'SR/BARS', labelWidth: '', rule: '' , model: 'srbars', option: '', el: 'ipt', class: 'w2'}, {label: 'SR/BARS端口', labelWidth: '', rule: '', model: 'srbarsPort', option: '', el: 'ipt', class: 'w2'}, {label: 'IP地址类型', labelWidth: '', rule: 'IPType', model: 'IPType', option: 'IPType', el: 'slt', class: 'w2'}, {label: 'IP地址', labelWidth: '', rule: 'IPAddr', model: 'IPAddr', option: '', el: 'ipt', class: 'w2'}, {label: '子网掩码', labelWidth: '', rule: 'netmask', model: 'netmask', option: '', el: 'ipt', class: 'w2'}, {label: 'VLAN ID', labelWidth: '', rule: 'vlanId', model: 'vlanId', option: '', el: 'ipt', class: 'w2'} ] : serviceType === '裸光纤' ? [ // 裸光纤 {label: '机房名称', labelWidth: '', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: '站点名称', labelWidth: '', rule: '', model: 'site', option: '', el: 'ipt', class: 'w2'}, {label: 'SR', labelWidth: '', rule: '', model: 'SR', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: 'SR端口', labelWidth: '', rule: '', model: 'SRPort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: 'BARS', labelWidth: '', rule: '' , model: 'BARS', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, {label: 'BARS端口', labelWidth: '', rule: '', model: 'BARSPort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '点击查询'}, ] : [ // 传输下沉、传输延伸 ] } } }, methods:{ async checkRequired() { let checkName = ['base','sitsb'];//表单校验定义ref let text; for(let key of checkName){ if(this.$refs[key]){ this.$refs[key].validate((valid) => { if(!valid){ text = '请检查必填项'; }else { return false; } }); } } if(text){ this.$message.warning(text); return false; } let _res_ = await this.saveFasjData('', true);//页面表单要保存后才能提交 if(!!_res_ && _res_.code === 200){ this.commit(_param, _url);//保存表单再提交 }else{ this.$message.error(_res_.msg) } }, async commit(param, url) { this.loadings.body = true; let _res = await postDataRequest(url, param); this.loadings.body = false; if (_res && _res.code === 200) { this.$message.success("提交成功"); this.$router.go(-1); } } } } </script>
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
Vite 是 vue 的作者尤雨溪在开发 vue3.0 的时候开发的一个 web 开发构建工具。由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。
Vite 优势:
Vite 劣势:
其他区别:
1. 打包原理的区别
2. 项目入口文件的区别
项目根目录的 index.html 是 Vite 项目的入口文件,而 webpack 的入口文件是 webpack 配置 entry 中指定的 js 文件。
Esbuild
是一款基于 Go
语言开发的 javascript
打包工具,最大的一个特征就是快。
通过官网提供的一张图,我们可以清晰的看到 Esbuild
的表现是多么优秀:
Esbuild
之所以能这么快,主要原因有两个:
Go
语言开发,可以多线程打包,代码直接编译成机器码;
Webpack
一直被人诟病构建速度慢,主要原因是在打包构建过程中,存在大量的 resolve
、load
、transform
、parse
操作(详见 为什么有人说 vite 快,有人却说 vite 慢?- 快速的冷启动 ),而这些操作通常是通过 javascript
代码来执行的。要知道,javascript
并不是什么高效的语言,在执行过程中要先编译后执行,还是单线程并且不能利用多核 cpu
优势,和 Go
语言相比,效率很低。
可充分利用多核 cpu
优势;
关键 API - transfrom & build
Esbuild
并不复杂,它对外提供了两个 API:
transform
和 build
,使用起来非常简单。
transfrom
,转换的意思,将 ts
、jsx
、tsx
等格式的内容转化为 js
。 transfrom
只负责文件内容转换,并不会生成一个新的文件。
build
,构建的意思,根据指定的单个或者多个入口,分析依赖,并使用 loader
将不同格式的内容转化为 js 内容,生成一个或多个 bundle
文件。
我们来看看Vite
是怎么利用 Esbuild
来做预构建和内容转换的。
预构建
为什么要做预构建?原因有两点:
将非 ESM
规范的代码转换为符合 ESM
规范的代码;
将第三方依赖内部的多个文件合并为一个,减少 http
请求数量;
middlewares 中内容转换
Vite
中源文件的转换是在 dev server
启动以后通过 middlewares
实现的。
当浏览器发起请求以后,dev sever
会通过相应的 middlewares
对请求做处理,然后将处理以后的内容返回给浏览器。
middlewares
对源文件的处理,分为 resolve
、load
、transform
、parser
四个过程:
resolve
- 解析 url
,找到源文件的绝对路径;
load
- 加载源文件。如果是第三方依赖,直接将预构建内容返回给浏览器;如果是业务代码,继续 transform
、parser
。
transfrom
- 对源文件内容做转换,即 ts
-> js
, less
-> css
等。转换完成的内容可以直接返回给浏览器了。
parser
- 对转换以后的内容做分析,找到依赖模块,对依赖模块做预转换 - pre transform
操作,即重复 1
- 4
。
pre transform
是 Vite
做的一个优化点。预转换的内容会先做缓存,等浏览器发起请求以后,如果已经完成转换,直接将缓存的内容返回给浏览器。
Vite
在处理步骤 3
时,是通过 esbuild.transform
实现的,对比 Webpack
使用各个 loader
处理源文件,那是非常简单、快捷的。
经验法则:对于应用使用 webpack,对于类库使用 Rollup。
如果你需要代码拆分(Code Splitting),或者你有很多静态资源需要处理,再或者你构建的项目需要引入很多CommonJS模块的依赖,那么 webpack 是个很不错的选择。
如果您的代码库是基于 ES2015 模块的,而且希望你写的代码能够被其他人直接使用,你需要的打包工具可能是 Rollup 。
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
-
<div class="add">
-
<p>商品名称: <input type="text" class="productName"></p>
-
<p>商品价格: <input type="number" class="price" ></p>
-
<!-- multiple: 允许同时上传多张图片 -->
-
<!-- <p>商品图片: <input type="file" class="file" multiple="multiple"></p> -->
-
<p>商品图片: <input type="file" class="file"></p>
-
<p><button class="add-btn">添加商品</button></p>
-
</div>
-
<script src="js/axios.js"></script>
-
<script src="js/util.js"></script>
-
<script src="js/upload.js"></script>
-
// 新建表单数据对象,用来存储上传的文件及上传的其它数据
-
let param = new FormData()
-
-
$(".file").onchange = function(){
-
//获取图片信息
-
let file = this.files[0]
-
//"file"为前后端约定vb的属性名
-
param.append("file",file)
-
}
-
$(".add-btn").onclick = function(){
-
let productName = $(".productName").value;
-
let price = $(".price").value;
-
param.append("productName",productName)
-
param.append("price",price)
-
-
axios.post("/product",param,{
-
headers: {
-
// 默认提交的类型
-
// "content-type": "application/json"
-
// 复杂的表单数据(只要上传文件,就必须是下面的类型)
-
"content-type": "multipart/form-data"
-
}
-
})
-
.then((res)=>{
-
console.log(res.data);
-
})
-
}
下载
npm i multer -S
引入
-
const multer = require("multer")
-
const path = require("path")
配置
注意: 该文件在/router文件夹中,而uploads存放上传图片文件夹在根目录
-
var storage = multer.diskStorage({
-
// 配置文件上传后存储的路径
-
destination: function (req, file, cb) {
-
// NodeJS的两个全局变量
-
// console.log(__dirname); //获取当前文件在服务器上的完整目录
-
// console.log(__filename); //获取当前文件在服务器上的完整路径
-
cb(null, path.join(__dirname,'../uploads'))
-
},
-
// 配置文件上传后存储的路径和文件名
-
filename: function (req, file, cb) {
-
console.log('file',file);
-
cb(null, Date.now() + path.extname(file.originalname))
-
}
-
})
-
var upload = multer({ storage: storage })
在路由中使用
-
//添加商品
-
router.post("/product",upload.single("file1"),(req,res)=>{
-
//接收普通文本参数
-
let {productName,price} = req.body;
-
、接收上传文件数据 -->
-
let imgUrl = req.file.filename;
-
let sql = "insert into product (productName,price,imgUrl) values (?,?,?)"
-
conn.query(sql,[productName, price , imgUrl],(err,result)=>{
-
if (err){
-
console.log('增加失败');
-
return;
-
}
-
let data;
-
if (result.affectedRows === 1){
-
data = {
-
code: 0,
-
msg: '添加成功'
-
}
-
}else{
-
data = {
-
code: 1,
-
msg: '添加失败'
-
}
-
}
-
res.send(data)
-
})
-
})
如果抽离路由模块中的处理函数upload.single("file1")写在Router模块
实现写在抽取的模块
如果req.body为空,可以用nodejs后台文件上传模块connect-multiparty
使用方法如下:
1. 安装模块
npm install connect-multiparty --save
2. 引入模块
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
3. 使用模块
const express = require('express')
const router = express.Router()
router.post('/formdata',multipartMiddleware, function (req,res) {
console.log(req.query)
//分别返回body,文件属性,以及文件存放地址
});
————————————————
原文链接:https://blog.csdn.net/zjwengyidong/article/details/51407903
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
在HappyBirthday/HappyBirthday.html中的title换成相应人的名字
-
<head>
-
<meta charset="utf-8">
-
<title>XXX生日快乐</title>
-
-
<style>
-
html,body{
-
margin:0px;
-
width:100%;
-
height:100%;
-
overflow:hidden;
-
background:linear-gradient(to left top,blue, #ffc0cb);
-
}
-
</style>
-
<link href="favicon.ico" rel="shortcut icon">
-
</head>
在粒子展示祝福的名字进行更换
在HappyBirthday/js/index.js#44行处修改
-
if (i !== -1) {
-
S.UI.simulate(decodeURI(action).substring(i + 3));
-
} else {
-
S.UI.simulate('|#countdown 3||祝|XXX|生日快乐|祝你|生日快乐|祝你幸福|祝你健康|前途光明|祝你|生日快乐!|#icon heart|#icon heart-empty|#icon heart');
-
}
修改粒子动画展示的颜色,视频中使用了粉色(255,192,203)
HappyBirthday/js/index.js#417行处修改
-
S.Dot = function (x, y) {
-
this.p = new S.Point({
-
x: x,
-
y: y,
-
z: 5,
-
a: 1,
-
h: 0
-
});
-
-
this.e = 0.07;
-
this.s = true;
-
-
this.c = new S.Color(255, 192, 203, this.p.a);
-
-
this.t = this.clone();
-
this.q = [];
-
};
在原版代码中,仅仅在电脑浏览器有一个较为好的展示效果,在手机浏览器上字显示效果不佳以及延时不足,但是无法正常显示,主要调整了粒子间距和延时时间
粒子间距:先设置默认间距为8(手机较好显示),然后判断屏幕是否大于手机一般尺寸,调整大一点13(平板和电脑较好显示)。
粒子间距变小,数量变多,加载起来就慢。
HappyBirthday/js/index.js#525行处修改
-
if ((window.innerWidth>500 && window.innerHeight>500)){
-
gap = 13;
-
}
延时时间:当粒子数量变多,加载慢, 按照原作者设置的时间来展示,可能上一个字没展示完就要去展示下一个字,导致变成一坨。
HappyBirthday/js/index.js#119行处修改
HappyBirthday/js/index.js#177行处修改
-
// 118行
-
var delay1,delay2;
-
delay1 = 3000;
-
delay2 = 5000;
-
-
-
// 177行
-
if (window.innerWidth>500 && window.innerHeight>500){
-
delay1 = 1000;
-
delay2 = 2000;
-
}
由于在某些设备上,无法自动播放音乐,需要通过点击触发,增加点击爱心,开始播放。
通过部署在阿里云,可以通过网址进行访问。
我租了一个阿里云,通过简单部署静态页面就可以访问。
(如果有兄弟紧急使用,也可以叫我帮忙部署一下,哈
找到自己的实例,点击完全组,配置开放一个80端口
开放80端口
yum -y install httpd
-
service httpd start
-
service httpd status
启动之后可以看到如下画面
默认会发布var/www/html下面的网页
cp /etc/httpd/conf/httpd.conf /var/www/html
# 解压压缩包 unzip HappyBirthday.zip # 删除压缩包 rm -rf HappyBirthday.zip
service httpd restart
http://8.130.106.21/HappyBirthday/HappyBirthday.html
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
B 端设计离不开设计规范这个话题,而做好设计规范是一个庞大复杂工程,很多人对这些处于一知半解状态,在这个系列文章里我通过结合自己平时的项目案例来谈谈自己对 B 端设计规范的一些理解,希望可以带来一些启发。
本篇先谈谈设计规范制作的指导思想--设计原则,后续文章再展开讲一下常见各种组件的设计规范。
设计规范作为 B 端设计中非常重要的一环,它的作用主要体现在以下三个方面:
在日常工作中,当项目组收到一个新的需求时,如果已经具备了成熟的设计规范体系,其工作效率往往会得到很好的提升。最后上线的页面不用走查还原度。以下是具体工作流程:
通过前面内容我们知道了设计规范对于产品设计意义重大,那么制定设计规范制定依据又是什么呢?这里就要引出设计原则这个话题,设计原则是设计规范的总的纲领,所有的设计规范都应当以设计原则为基准。设计原则主要包含以下内容:
接下来就围绕设计原则清晰、高效、友好、可控这四个方面展开讲解。
清晰原则主要从视觉角度让界面信息传达合理,提高用户信息获取效率。主要包含对比,亲密,对齐,重复四个方面。
① 对比:
对比是指界面中为了区分信息层级,强化元素对比度,使用的很常见的一种手段,例如下图中利用大色块按钮与线框按钮形成对比来凸显关键按钮;又比如通过对文字字号加大,字体加粗,颜色加深来与弱文案形成对比,凸显关键文字信息。
② 亲密:
如果信息之间关联性越高,它们之间的距离就应该越接近,也越像一个视觉单元;反之,则它们的距离就应该越远,也越像多个视觉单元。亲密性的根本目的是实现组织性,让用户对页面结构和信息层次一目了然。
③ 对齐:
在界面设计中,将元素进行对齐,既符合了用户的认知特点(我们往往倾向使知觉对象的直线延续还是直线,曲线延续还是曲线),也能引导视用户视觉流,让用户更流畅地接收信息。
④ 重复:
重复是指相同的元素在项目中重复引用,作用是可以有效降低用户的学习成本,同时提高这些元素之间的关联性。
高效原则体现在便捷、轻量、简化、一致几个方面,目的是通过合理的方式让产品操作更加便捷;交互体验与内容更加轻量和简化;以及产品风格保持一致。下面结合几个常见案例说明如何应用这一原则。
① 合理利用拖拽--便捷、轻量:
在涉及到诸如上传文件,排序,滑动输入,搭建等需求时,合理采用拖拽交互往往可以打造更加便捷用户体验。
② 尽量减少不必要的跳转--便捷、轻量:
用户操作过程尽量减少跳转,以实现交互减步长,从而使用户操作更高效轻量。例如能用原位操作就不考虑展开收起;能用展开收起就不用气泡...依次类推(优先级从高到低:原位 > 展开收起 > 气泡 > 弹窗 > 抽屉 > 新页面)
③ 放大点击热区--便捷:
放大可点击按钮热区,相对于较小点击热区,具备更丝滑操作体验。
④ 悬停即现--轻量:
利用悬停即现,避免信息过于重复啰嗦,简化页面提高阅读体验。
⑤ 折叠次要功能--简化:
页面功能按钮过多时,可将次要按钮收纳到一起,点击时再展开,外面只展示高频操作或重要按钮,保证页面内容简洁。
⑥ 统一样式--一致:
一致性是指在不同页面中相同操作应保持一致视觉与交互样式,可有降低用户学习成本与企业开发成本。
友好原则应贯穿用户操作前,操作中以及操作后三个阶段,给予用户及时反馈与帮助。
① 操作前:
在用户操作前给到合适的引导与帮助,有效减少用户迷茫感。
② 操作中:
通过交互效果以及页面样式让用户可以清晰感知到自己当前操作。
③ 操作后:
利用界面中元素变化清晰直观展示当前的状态
可控主要体现在自由和导航两个方面。
① 自由:
自由即指用户可以自由完成一些操作,例如回退,撤销,终止等。
② 导航:
导航是指用户随时知晓当前所在位置,而且可以利用导航随意到达目标页面。
通过本篇内容我们大概知道了制作设计规范主要方向,那么具体到每个组件上,我们该如何去设计呢?后续篇章将细分聊聊如何去设计 B 端常见组件的一些内容。
部分参考资料:
作者:huang。亮 来源:优设网
蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请加微信ban_lanlan,报下信息,蓝小助会请您入群。欢迎您加入噢~~
希望得到建议咨询、商务合作,也请与我们联系01063334945。
分享此文一切功德,皆悉回向给文章原作者及众读者. 免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
蓝蓝设计的小编 http://www.lanlanwork.com