首頁

如何快速理解客戶設(shè)計(jì)需求?

seo達(dá)人

11.jpeg

作為一個(gè)設(shè)計(jì)者,我們?cè)俳o客戶做設(shè)計(jì)方案的時(shí)候,大家會(huì)發(fā)現(xiàn)客戶的需求點(diǎn),很難去理解。并不是設(shè)計(jì)的技術(shù)水平問題,而是再理解客戶的需求點(diǎn)上出現(xiàn)了問題。就算你設(shè)計(jì)的東西在同行看來已經(jīng)很好了。但是客戶往往不是很滿意??蛻粼僖笪覀冏鲈O(shè)計(jì)的時(shí)候,其實(shí)心里已經(jīng)有了大概的想法,只是自己無法通過設(shè)計(jì)去實(shí)現(xiàn)而已。我們要做的是用自己的專業(yè)知識(shí)全區(qū)完成客戶的想法,已達(dá)到客戶滿意的效果。那么我們?nèi)绾慰焖倮斫饪蛻舻脑O(shè)計(jì)需求呢?

22.jpeg

第一:設(shè)計(jì)的能力加強(qiáng)提升,擁有過硬的技術(shù):

客戶的需求形形色色,運(yùn)用到的技能要全面,這是最為基礎(chǔ)的點(diǎn)。如果連技術(shù)都不過關(guān),就算理解了,也做不到。因此作為一個(gè)設(shè)計(jì)者,我自身就要擁有過硬的技能。而不是濫竽充數(shù),忽悠客戶,以低標(biāo)準(zhǔn)去做設(shè)計(jì)。

第二:換位思考,從客戶的角度去想問題:

換位思考就是要從客戶的角度去思考。只有從客戶的角度看問題,我們才能更好去理解客戶的需求。多做假設(shè)性思考,如果我是客戶,我要注意哪些問題。那些會(huì)對(duì)我有影響,那些會(huì)對(duì)我更有利。這樣才能做出讓客戶滿意的設(shè)計(jì),在這競(jìng)爭(zhēng)激烈的時(shí)代客戶就是上帝。不能把握號(hào)每一個(gè)客戶,對(duì)于我們來說是最大的損失。就算你不是老板,但是你不會(huì)老板想問題,你到哪都不受歡迎干不久,就算你技術(shù)再好,能力再強(qiáng)。

第三:用自己的專業(yè)角度給予意見。

客戶他們站在他們的角度就思考,但是他們并不是專業(yè)的,有可能惠發(fā)生一些致命性的錯(cuò)誤,但是他們不知道,也不覺得這是個(gè)問題。那么我們作為專業(yè)的工作者,我們也要給專業(yè)的意見或者是建議。例如,最新的廣告法,規(guī)定那些用詞是違規(guī)的、那些字體不用商用、設(shè)計(jì)那些顏色搭配是不利于展示的等等。

33.jpeg


 

藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

微信圖片_20210513163802.png

 

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

 

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)

 

vue電商后臺(tái)管理系統(tǒng)保姆級(jí)教程(八)——角色列表結(jié)構(gòu)功能

前端達(dá)人

8、角色列表

8.1 通過路由展示角色列表組件

在power中新建一個(gè)roles.vue(角色列表)初始化基本結(jié)構(gòu):
在這里插入圖片描述

在路由中加載導(dǎo)入:
在這里插入圖片描述
在這里插入圖片描述

8.2 繪制基本布局結(jié)構(gòu)并獲取列表數(shù)據(jù)

效果圖:
在這里插入圖片描述
面包屑導(dǎo)航:
在這里插入圖片描述
卡片視圖:
在這里插入圖片描述
API:
在這里插入圖片描述
渲染數(shù)據(jù):
定義數(shù)據(jù)date:
在這里插入圖片描述
生命周期函數(shù):
在這里插入圖片描述

8.3 渲染角色列表數(shù)據(jù)

先渲染索引列:
在這里插入圖片描述
優(yōu)化樣式:
在這里插入圖片描述

在索列之前加和 展開列:
在這里插入圖片描述

8.4 說明角色列表需要完成的功能模塊

現(xiàn)在還沒有具體的樣式,后面會(huì)寫
角色信息的添加,刪除功能前面做了,所以這里就不寫了

點(diǎn)擊對(duì)應(yīng)按鈕出現(xiàn)對(duì)應(yīng)的彈出層,然后執(zhí)行對(duì)應(yīng)的操作。

8.5 分析角色下權(quán)限渲染的思路

在展開行中拿到渲染的數(shù)據(jù)
在請(qǐng)求數(shù)據(jù)列表中返回了數(shù)據(jù)children,通過作用域插槽來拿
在這里插入圖片描述
實(shí)現(xiàn)效果:
在這里插入圖片描述
拿到數(shù)據(jù)之后通過三層for循環(huán)渲染出對(duì)應(yīng)的ui結(jié)構(gòu)

8.6 通過第一層for循環(huán)渲染一級(jí)權(quán)限

先做一下柵格布局,區(qū)分出三個(gè)區(qū)域用來放三層for循環(huán):

scope.row是當(dāng)前對(duì)象的數(shù)據(jù)。 .children 是一級(jí)權(quán)限的數(shù)據(jù), :key每次循環(huán)綁定一個(gè)唯一的key值,通過插值表達(dá)式渲染出數(shù)據(jù)
在這里插入圖片描述
放在el-tag標(biāo)簽中美化樣式
在這里插入圖片描述

8.7 美化一級(jí)權(quán)限

思路:
每行之間隔開距離,給每行放一個(gè)buttom的邊框,第一行放一個(gè)top邊框(這里使用三元表達(dá)判斷) 加圖標(biāo)
在這里插入圖片描述
每行都放buttom,利用三元表達(dá)式,如果i1===0.則bdtop否則空
在這里插入圖片描述

8.8 通過二層for循環(huán)渲染二級(jí)權(quán)限

使用柵格布局分出2級(jí)權(quán)限和3級(jí)權(quán)限,,方法和之前的一樣。
在這里插入圖片描述
添加邊框 線(上邊框)第一個(gè)不添加,利用三元表達(dá)式判斷:
在這里插入圖片描述
動(dòng)態(tài)綁定class類,然后判斷
在這里插入圖片描述
最終效果:
在這里插入圖片描述

8.9 通過第三層for循環(huán)渲染三級(jí)權(quán)限

柵格布局:
注使用item2的children
在這里插入圖片描述
通過作用域插槽拿到數(shù)據(jù) children 拿到子組件數(shù)據(jù),通過柵格分隔樣式,動(dòng)態(tài)綁定邊框值。

8.10 美化角色權(quán)限下的UI結(jié)構(gòu)

設(shè)置最小寬度:
設(shè)置body的最小寬度為1366px
在這里插入圖片描述

角色列表設(shè)置居中:
定義一個(gè)類:哪里用到往哪里加
在這里插入圖片描述
最后把代碼插槽刪了

8.11 點(diǎn)擊刪除權(quán)限按鈕彈出確認(rèn)提示框

使用element組件中的可移除標(biāo)簽屬性:
在這里插入圖片描述
closable屬性:
在這里插入圖片描述
綁定點(diǎn)擊事件:
removeRightById:
在這里插入圖片描述
定義事件:
在這里插入圖片描述
然后彈框提示用戶是否要?jiǎng)h除,使用的還是element組件L

在這里插入圖片描述
catch捕獲錯(cuò)誤:在這里插入圖片描述
結(jié)果判斷用戶操作:
在這里插入圖片描述
這里只是打印了結(jié)果,沒有向后端發(fā)起請(qǐng)求。

8.12 完成刪除角色下指定權(quán)限的功能

上一節(jié)點(diǎn)擊了刪除按鈕后需要向后端發(fā)起刪除的請(qǐng)求,刪除用戶在數(shù)據(jù)庫中的權(quán)限:
API:
在這里插入圖片描述
發(fā)起delect請(qǐng)求:
先把item3.id傳進(jìn)去:
在這里插入圖片描述
在處理函數(shù)的形參中j接收一下:
在這里插入圖片描述
然后再發(fā)起delect請(qǐng)求的時(shí)候用之前的參數(shù)字符串拼接
然后進(jìn)行判斷:
在這里插入圖片描述
有個(gè)缺點(diǎn):刪除之后展開欄就被關(guān)閉了 解決辦法:
在這里插入圖片描述
把close權(quán)限賦值給一級(jí)標(biāo)簽二級(jí)標(biāo)簽
在這里插入圖片描述



藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png


文章來源:csdn   作者:十九萬里

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)

Jquery選擇器中使用變量實(shí)現(xiàn)動(dòng)態(tài)選擇例子

前端達(dá)人

這篇文章主要介紹了Jquery選擇器中使用變量實(shí)現(xiàn)動(dòng)態(tài)選擇例子,這樣做的好處我們可以動(dòng)態(tài)選擇一些元素,核心思想其實(shí)就是用字符串組合,需要的朋友可以參考下


例子一:

例子二:


<table>
  <tr>
    <th>用戶名</th>
    <th>狀態(tài)</th>
  <tr>
  <tr>
    <td>張三</td>
    <td data-uid="10000">正常</td>
  <tr>
  <tr>
    <td>李四</td>
    <td data-uid="10001">凍結(jié)</td>
  <tr>
  <tr>
    <td>王二麻子</td>
    <td data-uid=10002>凍結(jié)</td>
  <tr>
</table>
 
<script type="text/javascript">
$(document).ready(function(){
  var uid = 1001;
  $("td[data-uid = "+ uid +"]").html('正常');
}
</script>





<script type="text/javascript">
 $(function(){
  alert(123);
  var v=4;
  var test=$("input[type='radio'][value='"+v+"']");//直接拼接字符串就可以了
  console.info(test);
  var testValue=test.attr({"checked":true});
  console.info(testValue);
 });
 </script>
  
 <body>
  This is my JSP page. <br>
  <table>
 <tr>
 <td>性別:</td>
 <td>
  <input name="sex" type="radio" value="0"/>男 0
  <input name="sex" type="radio" value="1"/>女 1
  <input name="sex" type="radio" value="2"/>女 2
  <input name="sex" type="radio" value="3"/>女 3
  <input name="sex" type="radio" value="4"/>女 4
 </td>
 </tr>
  </table>
 </body>




例子三、jQuery中選擇器參數(shù)使用變量應(yīng)該注意的問題

這是原來的代碼


var li_index = $(this).index();
 
var $content_index = li_index + 2;
 
var $content_progress = $(“div.content:eq(” + $content_index + “)”);
 
var $newavalue = $(this).find(“a”).attr(“name”);
 
var $resource = $(this).find(“a”).html().replace(“首頁”,$newavalue);
 
var $afterresource = $resource.replace($newavalue,””);
 
var $afterresource = $newavalue + $afterresource.replace(“首頁”,$newavalue);


實(shí)現(xiàn)的是關(guān)鍵詞替換,不過到第三行時(shí)候不執(zhí)行了,調(diào)試啊,替換啊,都不行。 從早上到剛才一直在各種群里面發(fā)問,終于 …… 俺們大本營(yíng) 的Lomu大神一陣見血:

你的寫法不對(duì)

要連接符

$(“div.content:nth-child($content_index)”);

$(“div.content:nth-child(” + $content_index + “)”);


關(guān)鍵是外面有引號(hào)

有引號(hào)被當(dāng)字符串處理了

說真的現(xiàn)在感覺,有些基礎(chǔ)的東西出錯(cuò),光靠自己調(diào)試根本找不出問題所在。比如剛才那個(gè) + 號(hào),我看書就沒見過。出現(xiàn)這種錯(cuò)誤百度也不知道什么關(guān)鍵詞。真不知道  選擇器 里面用變量 還要用到+號(hào),那個(gè)《鋒利的jQuery 》也沒有明確的說 選擇器 里面用變量 還要用到+號(hào),包括我們的w3cschool。





  藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png


文章來源:腳本之家   作者:junjie  

分享此文一切功德,皆悉回向給文章原作者及眾讀者.

免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)



網(wǎng)站建設(shè)-如何建設(shè)一個(gè)優(yōu)質(zhì)的網(wǎng)站?

seo達(dá)人

 

網(wǎng)站建設(shè)-如何建設(shè)一個(gè)優(yōu)質(zhì)的網(wǎng)站?

1.jpeg網(wǎng)站建設(shè)

互聯(lián)網(wǎng)時(shí)代的到來,作為一個(gè)企業(yè)你如果還沒有屬于自己的網(wǎng)站,那么你就真的“out”了,互聯(lián)網(wǎng)的日流量達(dá)到上億,這些不是簡(jiǎn)單的點(diǎn)擊率,而是一筆真真正正的大錢。如果你還不會(huì)互聯(lián)網(wǎng),不了解互聯(lián)網(wǎng),那么這些都與你毫無關(guān)系。而網(wǎng)站建設(shè)是企業(yè)面向互聯(lián)的主要窗口之一。也是大家公認(rèn)渠道之一。

網(wǎng)站建設(shè)對(duì)于企業(yè)來說意義重大,它不僅是企業(yè)展示的窗口那么簡(jiǎn)單?;ヂ?lián)網(wǎng)時(shí)代下,眾多企業(yè)紛紛進(jìn)行互聯(lián)網(wǎng)轉(zhuǎn)型,那是因?yàn)檫@些企業(yè)的領(lǐng)導(dǎo)者擁有者敏銳的嗅覺,具有洞察時(shí)代大趨勢(shì)的能力。網(wǎng)站建設(shè)使他們首先要做的事情。那么如何建設(shè)一個(gè)優(yōu)質(zhì)的網(wǎng)站呢?

2.jpeg網(wǎng)站建設(shè)

第一:網(wǎng)站建設(shè)平臺(tái)要有強(qiáng)大開發(fā)團(tuán)隊(duì)

網(wǎng)站建設(shè)是一門技術(shù)活,沒有強(qiáng)大的技術(shù)作為支撐,就無法保障網(wǎng)站的安全性和功能的實(shí)現(xiàn)。開發(fā)團(tuán)隊(duì)的強(qiáng)大決定了網(wǎng)站質(zhì)量與品質(zhì)。擁有一穩(wěn)定的后臺(tái),才能確保企業(yè)網(wǎng)站的一系列工作順利進(jìn)行。

第二:網(wǎng)站建設(shè)要有專業(yè)的設(shè)計(jì)團(tuán)隊(duì)

一個(gè)網(wǎng)站就好比一個(gè)門面,設(shè)計(jì)人員就是裝修的師傅。門面不好看給客戶的第一印象就是不專業(yè),第一印象分就大打折扣,不能引起客戶的重視。設(shè)計(jì)的不合理,就會(huì)影響到客戶的體驗(yàn)度。一個(gè)沒有體驗(yàn)度網(wǎng)站,很難留住客戶,進(jìn)行流量的轉(zhuǎn)化。一切設(shè)計(jì)以客戶的體驗(yàn)度為核心。

第三:網(wǎng)站建設(shè)要跟上時(shí)代的步伐

時(shí)代變,網(wǎng)站建設(shè)的功能和需求點(diǎn)也在變,只有去適應(yīng)時(shí)代的打造需求,企業(yè)才能在競(jìng)爭(zhēng)激烈的時(shí)代下生存。功能的更新?lián)Q代也要跟上時(shí)代的步伐,才能滿足客戶的體驗(yàn)需求。客戶才會(huì)為我們買單。

3.jpegSEO優(yōu)化

第四:網(wǎng)站建設(shè)要有利于SEO優(yōu)化

網(wǎng)站建設(shè)只是完成面建設(shè),而我們建設(shè)網(wǎng)站的目的是為了,引來流量,轉(zhuǎn)化流量,實(shí)現(xiàn)利潤(rùn)轉(zhuǎn)化。一個(gè)沒有不利于SEO優(yōu)化的網(wǎng)站,就像埋藏再深山的金山,難以被發(fā)現(xiàn),吸引不到客戶。SEO的意義在于打通前往金山的通道。海、陸、空全方位立體打通,讓客戶絡(luò)繹不絕前往。金山才得以被發(fā)現(xiàn),被開發(fā)。

第五:網(wǎng)站堅(jiān)持維護(hù)更新

這個(gè)時(shí)代不是大魚吃小魚的時(shí)代,而是快魚吃慢魚的時(shí)代。只有不斷的去完善更新,才能適應(yīng)生存。網(wǎng)站也一樣,只有不斷優(yōu)化升級(jí)才能不被淘汰。

第六:網(wǎng)站建設(shè)要符合國(guó)家政策

要及時(shí)了解國(guó)家的相關(guān)法律法規(guī)以及一些相關(guān)的政策,例如最新的廣告法,不能只用不符合要求的字眼。例如分銷系統(tǒng),不能越過法律底線。那些文字可以商業(yè),哪些是有版權(quán)的等。

以上是一些個(gè)人的網(wǎng)站建設(shè)個(gè)人見解,如有更好的意見也歡迎大家一起探討,相互學(xué)習(xí)。

 

 


藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png



文章來源:SEO

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。


 

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)

用戶錯(cuò)了嗎? 防錯(cuò)與容錯(cuò)

資深UI設(shè)計(jì)者

據(jù)說只要可能犯錯(cuò),就一定會(huì)有人犯錯(cuò),用戶犯錯(cuò)的可能性比我們想象中要大得多得多得多
做好防錯(cuò)與容錯(cuò),可以讓用戶更順暢...




據(jù)說只要可能犯錯(cuò),就一定會(huì)有人犯錯(cuò),用戶犯錯(cuò)的可能性比我們想象中要大得多得多得多得多。

做好防錯(cuò)與容錯(cuò),可以讓用戶更順暢的達(dá)成自己的目標(biāo)。


恩,用戶總是那么不可理喻對(duì)吧

都做得那么明顯了,還犯錯(cuò)。該提醒的也提醒了...誒~

打住,打住,當(dāng)用戶犯錯(cuò)時(shí),別急著怪他,我們需要先判斷清楚。


一、用戶真的錯(cuò)了嗎?

用戶委屈的說:“來來來,我就想下載一個(gè)資源,大家都是講道理的設(shè)計(jì)師,來評(píng)評(píng)理,我錯(cuò)在哪里?”

這,這... 每一步的確都好像沒問題,那,問題究竟在哪?

作為設(shè)計(jì)師的你是不是已經(jīng)敏銳的察覺到了什么?

對(duì),關(guān)鍵點(diǎn)在 ' 67bh ' 這里。都是空格惹的禍!

那好,你準(zhǔn)備好方案救用戶了嗎?......(這里理論上應(yīng)該停頓30s以上吧)。

當(dāng)然,現(xiàn)在不會(huì)公布答案,方式有好多種。留著你看完文章中間部分再跟大家一起找方案吧。

這一部分的重點(diǎn)不是方案,而是思維。


很多時(shí)候,用戶并沒有錯(cuò),作為一個(gè)有擔(dān)當(dāng)?shù)脑O(shè)計(jì)師,我們可不能甩鍋。

有了這個(gè)前提,我們就可以去掉心中的那些煩躁和埋怨...開始愿意伸出援手,去拯救用戶了。


二、如何避免用戶“犯錯(cuò)”

對(duì),這個(gè)疑問就已經(jīng)包含了解決方案了。

真的感嘆中文的博大精深,避 (防錯(cuò))、免 (容錯(cuò))。

為了讓大家能更好的理解什么是防錯(cuò)和容錯(cuò),我特意舉一個(gè)例子哈~

(什么,防錯(cuò)容錯(cuò)你都懂?你怎么知道我講的跟你想的一樣呢,既然這么厲害趕緊做下面這道題。)

對(duì),就是圖片里那個(gè)拿滑板的家伙,估計(jì)是第一次來這片海灘,有鯊魚都不知道,還使勁忘海里沖...


從避(防錯(cuò))的角度來看,你有什么方法幫他呢?(先不考慮哪種方法更好也不要考慮成本哈,能達(dá)到目的的都行。)

友情提示:防錯(cuò)的目的是讓用戶在操作之前,盡量減少用戶出錯(cuò)的可能性。


看看的你腦袋是不是真的轉(zhuǎn)得飛起...

我這邊有幾個(gè)想法,看看我們有沒有緣,想到一塊兒去了:

  • 大聲告訴他,這位拿滑板的大哥,海里有鯊魚,別忘海里沖了...

  • 警告這位大哥,嘿兄弟,這里只允許坐輪船和直升機(jī)去海島那邊。

  • 在通往海島的路線全程搭起防鯊網(wǎng)。

恩,目前就想到這些了,還有方案的同學(xué)可以在評(píng)論區(qū)炸沙發(fā)哈。


這些方式,我們?cè)囍橄笠幌拢?

  • 【提前做好引導(dǎo)和提示】大聲告訴他,這位拿滑板的大哥,海里有鯊魚,別忘海里沖了...

  • 【優(yōu)先選擇減少輸入】警告這位大哥,嘿兄弟,這里只允許坐輪船和直升機(jī)去海島那邊。

  • 【限制原操作范圍】在通往海島的路線全程搭起防鯊網(wǎng)。

大家應(yīng)該都發(fā)現(xiàn)了,這種方式雖然能達(dá)到讓用戶安全的目的,但是用戶會(huì)有挫敗感,同時(shí)也會(huì)有被限制的感覺。

我只要說到USB插頭,大家應(yīng)該就開始腦補(bǔ)畫面了吧“為什么我插的進(jìn)去的第一次永遠(yuǎn)是錯(cuò)的方向,OMG!”

那,容錯(cuò)呢?


還是這位拿著滑板的大哥,想要去海上的小島,從免(容錯(cuò))的角度來看,你有什么方法幫他呢?

友情提示:容錯(cuò)的目的是在用戶操作之后,自動(dòng)糾正/化解錯(cuò)誤或提供挽回的方法。


我有幾個(gè)奇怪的方法,來跟大家分享一下:

  • 呃...馴化/殺死鯊魚。

  • 派一直專業(yè)驅(qū)鯊救援隊(duì)跟隨這位大哥(滑板大哥:我何德何能,太感動(dòng)了)。


同樣,我們繼續(xù)抽象一下:

  • 【讓原本的錯(cuò)誤不影響用戶行為和結(jié)果】呃...馴化/殺死鯊魚。

  • 【出現(xiàn)錯(cuò)誤可挽回】派一直專業(yè)驅(qū)鯊救援隊(duì)跟隨這位大哥,出現(xiàn)鯊魚就殺魚。


誒,成本好像非常高哈,但是用戶感覺良好哦~

因?yàn)樗踔炼几兄坏竭@片海還有過危險(xiǎn),按自己喜歡的方式行動(dòng)就行。

我提一提微信消息的撤銷功能,大家可能就會(huì)舒緩一口氣了。

不知道挽回了多少個(gè)尷尬的瞬間,是吧~

可是...我只是一個(gè)有無縛雞之力的設(shè)計(jì)師,我肝不過鯊魚怎么辦?

來來來,前面那個(gè)喊救命的大哥又來了,大家趕緊想想辦法吧~


三、試用一下以上方法

(第一步和第四步就是單純點(diǎn)擊,就先刪掉了)

前面講的方法也列在右側(cè)了,看看你們是不是可以針對(duì)每種方法找到對(duì)應(yīng)方案了呢?

看看是不是可以這樣?


方案一:使用方法-提前做好引導(dǎo)和提示


方案二:使用方法-優(yōu)先選擇減少輸入


方案三:使用方法-限制操作范圍


方案四:使用方法-出現(xiàn)錯(cuò)誤可挽回


方案五:使用方法-讓錯(cuò)誤不影響結(jié)果


在這個(gè)案例中,大家覺得那個(gè)方案更好呢?

好吧,這個(gè)問題的確很蠢。當(dāng)然是 方案二 + 方案五 結(jié)合使用了。因?yàn)槭莾蓚€(gè)平臺(tái)的交互,而對(duì)于各自平臺(tái)而言,一個(gè)控制好輸出,一個(gè)控制好輸入。對(duì)平臺(tái)自身的容錯(cuò)性有很大的幫助。

通過上面的案例,相信大家都已經(jīng)熟練掌握好防錯(cuò)和容錯(cuò)的方法了。

什么,還沒掌握?那你滾回去,(望著你正在慢慢蜷縮的身體)不.........不是你滾,是你的鼠標(biāo)往回滾!

那,我們先不管那幾個(gè)往回滾的同學(xué),開始進(jìn)行強(qiáng)化學(xué)習(xí)啦~


四、帶著思考學(xué)習(xí)

找了一些生活中經(jīng)常用到的產(chǎn)品,讓大家感受一下防錯(cuò)容錯(cuò)的魅力。

如果你根本無法從圖中發(fā)現(xiàn)什么,那我只能說... 你還是需要經(jīng)常用銀杏葉擦擦眼睛了(因?yàn)椴亮酥竽憔透菀装l(fā)現(xiàn)(人性)。

案例先到這里,大家一定以為要結(jié)束了吧~不,不,前面這些都不是最重要的。

方法總會(huì)越來越多,靠“別人”總結(jié)的方法也就能應(yīng)個(gè)急。

來來來,放空~~~~拋棄你的職業(yè)相關(guān)認(rèn)知、拋棄你的設(shè)計(jì)師的身份,你再看我們的設(shè)計(jì)。

你像孩子一樣,好奇又“無知”。

你會(huì)發(fā)現(xiàn),為什么會(huì)有這么多奇怪的看不見的規(guī)則,為什么我這么難完成我的任務(wù)。


五、提前預(yù)知錯(cuò)誤風(fēng)險(xiǎn)(重點(diǎn))

如果當(dāng)客戶遇到問題,你能用合適的方法去解決,那你已經(jīng)是個(gè)不錯(cuò)的設(shè)計(jì)師了,但離優(yōu)秀還很遠(yuǎn),因?yàn)閮?yōu)秀的設(shè)計(jì)師必須具有敏銳的嗅覺,要在產(chǎn)品團(tuán)隊(duì)的前面,感知并規(guī)避風(fēng)險(xiǎn)。

所以,更重要的還是,我們必須學(xué)會(huì)變身。

好了,這一次真的需要大家獨(dú)立思考了,并且沒有標(biāo)準(zhǔn)答案,大家可以交流交流。


在以下場(chǎng)景中,可能會(huì)出現(xiàn)什么“錯(cuò)誤”,如何有效處理用戶“犯錯(cuò)”?

在生活中,其實(shí)會(huì)有很多很多“讓用戶犯錯(cuò)”的產(chǎn)品/場(chǎng)景,多參與其中,去發(fā)現(xiàn)問題,去思考解決方案,慢慢的,你就會(huì)具備非常好的問題發(fā)現(xiàn)能力和解決能力了。

說了這么多,可能有一部分同學(xué)會(huì)想說:

“用戶出錯(cuò)的情況應(yīng)該很少吧,你花這么長(zhǎng)的篇幅”

“你一定低估了用戶的智商”

我告訴你,出來玩玩,誰帶智商做事啊~

不信你看。


六、那些你可能想象不到的用戶錯(cuò)誤

百度一下,你會(huì)發(fā)現(xiàn)用戶犯錯(cuò)的可能性大大超出你的預(yù)期。

只是,你以為與你“無關(guān)”而已。


七、防止用戶犯錯(cuò)的設(shè)計(jì)可能比你想象中更難,更重要

要防止用戶犯錯(cuò),你需要不斷的模擬用戶的操作行為,去捕獲那些可能存在的問題,然后將它一一化解;這個(gè)過程很難,因?yàn)槟阋獟侀_自己以往的經(jīng)驗(yàn)和認(rèn)知,去感受用戶的視角。


想想,用戶體驗(yàn)的改進(jìn)不就是讓產(chǎn)品越來越符合用戶認(rèn)知,從而減少用戶“犯錯(cuò)”嗎?

只是有些錯(cuò)誤,我們只作為圍觀者,將它推向了用戶。

從現(xiàn)在起,將“錯(cuò)誤”留給自己。




 藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png



文章來源:站酷   作者:得勿

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)






移動(dòng)端導(dǎo)航設(shè)計(jì)

資深UI設(shè)計(jì)者

合理的移動(dòng)導(dǎo)航設(shè)計(jì)能夠盡可能地減少摩擦,引導(dǎo)用戶去他們要去的地方。

這篇文章匯總了移動(dòng)端導(dǎo)航設(shè)計(jì)最常見的樣式、要注意的設(shè)計(jì)準(zhǔn)則以及優(yōu)秀的案例分析,一起來系統(tǒng)性地掌握這些知識(shí)~

什么是移動(dòng)端導(dǎo)航?

簡(jiǎn)單來說,導(dǎo)航是用戶從 A 點(diǎn)到 B 點(diǎn)的方式,是他們發(fā)現(xiàn)設(shè)計(jì)點(diǎn)并與產(chǎn)品交互的過程。

可能很多用戶認(rèn)為導(dǎo)航的目標(biāo)是“在盡可能短的時(shí)間內(nèi)讓用戶從 A 到 B”,但時(shí)間短只屬于操作結(jié)果,這個(gè)結(jié)果需要依靠合理且簡(jiǎn)單的設(shè)計(jì)才能實(shí)現(xiàn)。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 一個(gè)頁面中可以存在多種導(dǎo)航。例如在油管首頁,有頂部導(dǎo)航欄、篩選器導(dǎo)航和底部導(dǎo)航,這些導(dǎo)航相互搭配為產(chǎn)品助力。

移動(dòng)端導(dǎo)航常見的設(shè)計(jì)樣式

1. 漢堡菜單

圍繞漢堡菜單有很多爭(zhēng)論,但存在即合理,在合適的場(chǎng)景下漢堡菜單也能發(fā)揮大的作用。

來看一下漢堡菜單具備的優(yōu)勢(shì):

  • 視覺空間:節(jié)省屏幕空間,包含有價(jià)值的信息;
  • 心智模型:大多數(shù)用戶熟悉這種設(shè)計(jì)樣式并知道如何操作;
  • 使用經(jīng)驗(yàn):調(diào)節(jié)學(xué)習(xí)曲線,改善使用體驗(yàn)。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 使用用戶熟悉的設(shè)計(jì)可以事半功倍。例如美團(tuán)和餓了么兩個(gè)產(chǎn)品有著完全不同的主題色,但外賣點(diǎn)餐流程卻是一樣的,仍然是用戶熟悉的操作,并沒有因?yàn)楫a(chǎn)品的不同而改變點(diǎn)餐流程。

2. 底部導(dǎo)航

底部導(dǎo)航欄通常包含產(chǎn)品中最主要的導(dǎo)航鏈接,用戶只需要簡(jiǎn)單的點(diǎn)擊就能直觀地在不同頁面間切換。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 幾乎每款產(chǎn)品都缺少不了底部導(dǎo)航欄,它方便用戶單手操作,不需要太費(fèi)力就能快速訪問產(chǎn)品頁面,提高可用性。

3. 頂部導(dǎo)航

關(guān)于頂部導(dǎo)航,可以看之前分享的文章,里面詳細(xì)介紹了頂部導(dǎo)航的設(shè)計(jì)方法。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 頂部導(dǎo)航通常包含頁面中最重要的信息,與其他輔助導(dǎo)航結(jié)合使用。

4. 卡片式導(dǎo)航

卡片式是一種出色的設(shè)計(jì)樣式,支持改變各種形狀和大小,并且能展示文本、鏈接或照片等各種元素。

隨著網(wǎng)絡(luò)上的內(nèi)容越來越碎片化和個(gè)性化,卡片是在頁面中聚合單個(gè)信息的好方式。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 為了改進(jìn)體驗(yàn),卡片可以個(gè)性化顯示不同的內(nèi)容。另外卡片很容易適應(yīng)不同的屏幕尺寸,配合響應(yīng)性設(shè)計(jì)。

5. 標(biāo)簽

標(biāo)簽往往是在一個(gè)大主題下同時(shí)支持多個(gè)選項(xiàng),每個(gè)選項(xiàng)都轉(zhuǎn)到不同的界面。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 標(biāo)簽通常用于在同一頁面中的幾個(gè)視圖之間切換,展示內(nèi)容上的差異性。而頂部導(dǎo)航欄有主頁、搜索、收藏夾等多個(gè)圖標(biāo),代表不同的功能。

6. 基于手勢(shì)的導(dǎo)航

基于手勢(shì)的導(dǎo)航可以讓用戶在所需方向上快速滑動(dòng),來完成特定的操作。

這種樣式的優(yōu)點(diǎn)在于,即使最沒有經(jīng)驗(yàn)的用戶也很容易掌握,因?yàn)槭謩?shì)通常是直觀的。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 國(guó)外大火的約會(huì)產(chǎn)品Tinder以及國(guó)內(nèi)的探探,都使用了基于手勢(shì)的導(dǎo)航樣式,為用戶帶來滑動(dòng)的樂趣。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 基于手勢(shì)的導(dǎo)航并不是Tinder發(fā)明的,但這款產(chǎn)品無疑將這種流行帶給了大眾。經(jīng)典的向左或向右滑動(dòng)模式保持了事物的動(dòng)態(tài)性、簡(jiǎn)單性和娛樂性。

7. 全屏導(dǎo)航

全屏導(dǎo)航是指將大部分屏幕用于導(dǎo)航操作,能夠很好地將用戶的注意力聚焦到具體的產(chǎn)品細(xì)節(jié)上。這是一種以連貫的方式提供大量導(dǎo)航的方法,可以立即幫助用戶了解產(chǎn)品的功能。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 點(diǎn)擊圖片可以跳轉(zhuǎn)到全屏大圖導(dǎo)航中,能夠更清晰地查看商品的外觀狀態(tài)。

8. 3D touch

最初是由蘋果公司提供給用戶的,這是一種創(chuàng)建導(dǎo)航快捷方式的方法,可以顯示選定的 APP 的一些關(guān)鍵操作。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 蘋果為手機(jī)創(chuàng)造了一種全新的快捷方式,同時(shí)提供了強(qiáng)大的可用性。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 3D touch另一個(gè)用途是內(nèi)容預(yù)覽,在處理內(nèi)容選項(xiàng)時(shí)例如收件箱或文章列表時(shí),這是給用戶提供預(yù)覽的好方法。

移動(dòng)端導(dǎo)航設(shè)計(jì)準(zhǔn)則

1. 導(dǎo)航需要直觀明顯

對(duì)所有類型的導(dǎo)航來說都是如此。在移動(dòng)端中由于屏幕空間的縮小和交互成本的增加,導(dǎo)航體驗(yàn)的好壞會(huì)對(duì)產(chǎn)品產(chǎn)生很大的影響。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 從可用性角度來看,直觀的導(dǎo)航對(duì)目標(biāo)用戶來說至關(guān)重要。這意味著需要進(jìn)行嚴(yán)格的測(cè)試和大量的研究,可以使用卡片分類或樹狀圖等方法來驗(yàn)證導(dǎo)航的可用性。

2. 考慮手指的位置

這點(diǎn)對(duì)于移動(dòng)應(yīng)用來說至關(guān)重要,沒有用戶想反復(fù)點(diǎn)擊圖標(biāo)卻沒有反應(yīng)。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 鏈接和按鈕的尺寸需要足夠大,以便大多數(shù)用戶在第一次點(diǎn)擊時(shí)就能成功點(diǎn)擊。頁面中按鈕的尺寸最小通常保持在10mm。

3. 建立視覺層級(jí)避免混亂

小屏幕意味著更容易陷入混亂。即使頁面中有少量的元素,如果元素沒有平衡,用戶仍然會(huì)有混亂的感覺。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 極簡(jiǎn)主義是UI設(shè)計(jì)的一種特定風(fēng)格,通過必備的頂部導(dǎo)航欄、留白以及由大小、版式、顏色劃分的視覺層級(jí)來規(guī)劃頁面內(nèi)容。

移動(dòng)端導(dǎo)航示例分析

1. Facebook

Facebook 的導(dǎo)航構(gòu)成比較復(fù)雜,融合了多種不同樣式的導(dǎo)航。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ Facebook主頁包括漢堡菜單、頂部導(dǎo)航欄和底部導(dǎo)航欄。通過這種方式,這家社交媒體巨頭明確的將主要內(nèi)容與次要內(nèi)容分隔開。

2. Spotify

Spotif 作為音樂流媒體業(yè)務(wù)的巨頭,即使對(duì)于新用戶來說,頁面的設(shè)計(jì)也容易理解和探索。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 以高度視覺化的形式突出每張卡片背后的關(guān)鍵內(nèi)容,另外底部導(dǎo)航也可以完成繁重的任務(wù)指引。

3. App Store

App Store 是使用標(biāo)簽進(jìn)行導(dǎo)航的好例證,每個(gè)標(biāo)簽代表了同一內(nèi)容的不同方面。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 在排行榜中,用戶可以瀏覽付費(fèi)、免費(fèi)和熱門的標(biāo)簽頁,從而快速建立一致性和對(duì)其他頁面的感知。

4. Telegram

Telegram 可以供任何人使用,漢堡菜單提供了用戶可能需要的所有關(guān)鍵導(dǎo)航選項(xiàng)。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 每個(gè)用戶都能立即找出漢堡菜單,非常容易使用和理解,而且?guī)缀醪徽加媒缑嬷械膶氋F空間。

5. Yelp

yelp 在創(chuàng)建全屏導(dǎo)航體驗(yàn)時(shí)采用了一種稍微不同的方法。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ Yelp將屏幕劃分為兩個(gè)不同的區(qū)域,實(shí)際上并沒有將整個(gè)屏幕專門用于導(dǎo)航選項(xiàng),而是將頂部用于導(dǎo)航選項(xiàng),并在底部留下更多的負(fù)空間。

6. Trello

頁面中的卡片是拉長(zhǎng)的矩形,整齊有序地填滿屏幕空間而不會(huì)讓用戶不知所措。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ 卡片系統(tǒng)很好地代表了Trello簡(jiǎn)化復(fù)雜工作流程的能力,為用戶帶來整潔和方便。

7. Twitter

同樣使用了多種導(dǎo)航混合的設(shè)計(jì)樣式。

你了解移動(dòng)端導(dǎo)航設(shè)計(jì)嗎?收下這篇系統(tǒng)性的總結(jié)!

△ Twitter將導(dǎo)航重點(diǎn)放在底部欄上,涵蓋了整個(gè)平臺(tái)中四個(gè)主要的方面。

最后

沒有高速公路,我們很難便利地在城市間穿梭。同理,如果沒有導(dǎo)航,一款 APP 的使用也會(huì)遇到很多麻煩。導(dǎo)航就像高速,不斷在為用戶提供必要的指引!




 藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png



文章來源:站酷   作者:Clip設(shè)計(jì)夾

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)



SpringBoot + Shiro + Mybatis-plus + Kaptcha + vue實(shí)現(xiàn)權(quán)限管理登錄功能

前端達(dá)人

登錄功能

在這里插入圖片描述

使用到的技術(shù)

  • shiro
  • Mybatis-plus
  • Springboot
  • kaptcha

參考優(yōu)秀博文

一個(gè)博主做的shiro筆記:https://www.guitu18.com/post/2019/07/26/43.html

引入依賴

 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.7.0</version> </dependency> <!--mybatis-plus 持久層--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <!--   整合swagger     --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.8.0</version> </dependency> <!-- kaptcha 驗(yàn)證碼 --> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> </dependencies> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

配置shiro

package com.unclebb.zlgl.config; import com.unclebb.zlgl.utils.CustomRealm; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; /**
 * @program: zlgl
 * @description: Shiro配置類:將SecurityManager以及Realm都注入到Spring容器中
 * @author: LiuZhiliang
 * @create: 2021-05-10 08:56
 **/ @Configuration public class ShiroConfig { /** 
    * @Description: 代理生成器,需要借助SpringAOP來掃描@RequiresRoles和@RequiresPermissions等注解。生成代理類實(shí)現(xiàn)功能增強(qiáng),從而實(shí)現(xiàn)權(quán)限控制。需要配合AuthorizationAttributeSourceAdvisor一起使用,否則權(quán)限注解無效。
    * @Param:
    * @return:
    * @Author: Liuzhiliang
    * @Date:
    */ @Bean public DefaultAdvisorAutoProxyCreator lifecycleBeanProcessor(){ DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } /** 
    * @Description:  上面配置的DefaultAdvisorAutoProxyCreator相當(dāng)于一個(gè)切面,下面這個(gè)類就相當(dāng)于切點(diǎn)了,兩個(gè)一起才能實(shí)現(xiàn)注解權(quán)限控制。
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){ AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } /**
     * @Description: Filter工廠,設(shè)置對(duì)應(yīng)的過濾條件和跳轉(zhuǎn)條件
     * @Param:
     * @return:
     * @Author: Liuzhiliang
     * @Date:
     */ //權(quán)限管理,配置主要是Realm的管理認(rèn)證 @Bean public DefaultWebSecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); ThreadContext.bind(securityManager); return securityManager; } //將自己的驗(yàn)證方式加入容器 @Bean public CustomRealm myShiroRealm() { HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); //加密 matcher.setHashAlgorithmName("md5"); matcher.setHashIterations(1); CustomRealm customRealm = new CustomRealm(); customRealm.setCredentialsMatcher(matcher); return customRealm; } @Bean public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //        Map<String,String> maps = new HashMap<>(); //        maps.put("/logout","logout"); //        maps.put("/**","authc"); //        shiroFilterFactoryBean.setLoginUrl("/login"); //        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html"); //        shiroFilterFactoryBean.setSuccessUrl("/index"); //        shiroFilterFactoryBean.setFilterChainDefinitionMap(maps); return shiroFilterFactoryBean; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

配置swagger

package com.unclebb.zlgl.config; import com.google.common.base.Predicates; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /**
 * @Author unclebb
 * @Description Swagger配置類
 * @Date 2021/5/9
 **/ @Configuration @EnableSwagger2 public class Swagger2Config { @Bean public Docket webApiConfig(){ return new Docket(DocumentationType.SWAGGER_2) .groupName("webApi") .apiInfo(webApiInfo()) .select() //過濾掉admin路徑下的所有頁面 .paths(Predicates.and(PathSelectors.regex("/user/.*"))) //過濾掉所有error或error.*頁面 //.paths(Predicates.not(PathSelectors.regex("/error.*"))) .build(); } private ApiInfo webApiInfo(){ return new ApiInfoBuilder() .title("網(wǎng)站-API文檔") .description("本文檔描述了網(wǎng)站微服務(wù)接口定義") .version("1.0") .contact(new Contact("qy", "http://atguigu.com", "55317332@qq.com")) .build(); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

配置kaptcha

package com.unclebb.zlgl.config; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.util.Properties; /**
 * @program: zlgl
 * @description: Kaptcha配置類
 * @author: LiuZhiliang
 * @create: 2021-05-12 09:03
 **/ @Component public class KaptchaConfig { @Bean public DefaultKaptcha getKaptcha(){ DefaultKaptcha dk = new DefaultKaptcha(); Properties properties = new Properties(); // 圖片邊框 properties.setProperty("kaptcha.border", "yes"); // 邊框顏色 properties.setProperty("kaptcha.border.color", "105,179,90"); // 字體顏色 properties.setProperty("kaptcha.textproducer.font.color", "red"); // 圖片寬 properties.setProperty("kaptcha.image.width", "110"); // 圖片高 properties.setProperty("kaptcha.image.height", "40"); // 字體大小 properties.setProperty("kaptcha.textproducer.font.size", "30"); // session key properties.setProperty("kaptcha.session.key", "code"); // 驗(yàn)證碼長(zhǎng)度 properties.setProperty("kaptcha.textproducer.char.length", "4"); // 字體 properties.setProperty("kaptcha.textproducer.font.names", "宋體,楷體,微軟雅黑"); Config config = new Config(properties); dk.setConfig(config); return dk; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

pojo

User

package com.unclebb.zlgl.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.util.Set; /**
 * @Author unclebb
 * @Description 用戶實(shí)體類
 * @Date 2021/5/9
 **/ @Data @TableName(value = "user") public class User { @TableId(value = "id",type = IdType.AUTO)//指定自增策略 private int id; @TableField(value = "username") private String username; @TableField(value = "password") private String password; @TableField(exist = false) private Set<Role> rolesSet; private String salt; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

Role

package com.unclebb.zlgl.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import lombok.Data; import java.util.Set; /**
 * @Author unclebb
 * @Description 角色實(shí)體類
 * @Date 2021/5/9
 **/ @Data public class Role { @TableId(value = "id",type = IdType.AUTO)//指定自增策略 private int id; @TableField(value = "user_name") private String userName; @TableField(value = "role_name") private String roleName; @TableField(exist = false) private Set<Permission> permissionSet; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

Permission

package com.unclebb.zlgl.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import lombok.Data; /**
 * @Author unclebb
 * @Description 權(quán)限實(shí)體類
 * @Date 2021/5/9
 **/ @Data public class Permission { @TableId(value = "id",type = IdType.AUTO)//指定自增策略 private int id; @TableField(value = "role_name") private String roleName; @TableField(value = "permission_name") private String permissionName; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Mapper

基本格式:

package com.unclebb.zlgl.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.unclebb.zlgl.pojo.User; import org.apache.ibatis.annotations.Mapper; /**
 * @Author unclebb
 * @Description 用戶映射
 * @Date 2021/5/9
 **/ @Mapper public interface UserMapper extends BaseMapper<User> { } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Service

Interface

LoginService

package com.unclebb.zlgl.service; import com.baomidou.mybatisplus.extension.service.IService; import com.unclebb.zlgl.pojo.User; import org.springframework.stereotype.Service; /**
 * @Author unclebb
 * @Description 用戶登錄接口
 * @Date 2021/5/9
 **/ @Service public interface LoginService extends IService<User> { public User getByUsername(String username); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

RoleService

package com.unclebb.zlgl.service; import com.baomidou.mybatisplus.extension.service.IService; import com.unclebb.zlgl.pojo.Role; import org.springframework.stereotype.Service; import java.util.List; @Service public interface RoleService extends IService<Role> { public List<Role> getRole(String userName); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

PermissionService

package com.unclebb.zlgl.service; import com.baomidou.mybatisplus.extension.service.IService; import com.unclebb.zlgl.pojo.Permission; import org.springframework.stereotype.Service; import java.util.List; @Service public interface PermissionService extends IService<Permission> { public List<Permission> getPermissions(String roleName); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ServiceImpl

LoginServiceImpl

package com.unclebb.zlgl.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.unclebb.zlgl.mapper.UserMapper; import com.unclebb.zlgl.pojo.Role; import com.unclebb.zlgl.pojo.User; import com.unclebb.zlgl.service.LoginService; import com.unclebb.zlgl.service.PermissionService; import com.unclebb.zlgl.service.RoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashSet; import java.util.List; import java.util.Set; /**
 * @Author unclebb
 * @Description 登錄實(shí)現(xiàn)類
 * @Date 2021/5/9
 **/ @Service public class LoginServiceImpl extends ServiceImpl<UserMapper, User> implements LoginService { @Autowired RoleService roleService; @Override public User getByUsername(String username) { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("username",username); User user = this.getOne(wrapper); List<Role> roleList = roleService.getRole(user.getUsername()); user.setRolesSet(new HashSet<Role>(roleList)); return user; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

RoleServiceImpl

package com.unclebb.zlgl.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.unclebb.zlgl.mapper.RoleMapper; import com.unclebb.zlgl.pojo.Permission; import com.unclebb.zlgl.pojo.Role; import com.unclebb.zlgl.service.PermissionService; import com.unclebb.zlgl.service.RoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashSet; import java.util.List; import java.util.Set; /**
 * @program: zlgl
 * @description: Role實(shí)現(xiàn)類
 * @author: LiuZhiliang
 * @create: 2021-05-10 16:16
 **/ @Service public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService { @Autowired PermissionService permissionService; @Override public List<Role> getRole(String userName) { QueryWrapper wrapper = new QueryWrapper(); wrapper.eq("user_name",userName); List<Role> roleList = this.list(wrapper); for (Role role:roleList){ List<Permission> permissions = permissionService.getPermissions(role.getRoleName()); role.setPermissionSet(new HashSet<Permission>(permissions)); } return roleList; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

PermissionServiceImpl

package com.unclebb.zlgl.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.unclebb.zlgl.mapper.PermissionMapper; import com.unclebb.zlgl.pojo.Permission; import com.unclebb.zlgl.pojo.User; import com.unclebb.zlgl.service.PermissionService; import org.springframework.stereotype.Service; import java.util.List; import java.util.Set; /**
 * @program: zlgl
 * @description: Permission實(shí)現(xiàn)類
 * @author: LiuZhiliang
 * @create: 2021-05-10 16:18
 **/ @Service public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService { @Override public List<Permission> getPermissions(String roleName) { QueryWrapper<Permission> wrapper = new QueryWrapper<>(); wrapper.eq("role_name",roleName); return this.list(wrapper); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

Controller

package com.unclebb.zlgl.controller; import com.unclebb.zlgl.pojo.Role; import com.unclebb.zlgl.pojo.User; import com.unclebb.zlgl.service.RoleService; import com.unclebb.zlgl.utils.Result; import io.swagger.annotations.ApiOperation; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpSession; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; /**
 * @Author unclebb
 * @Description 登錄控制器
 * @Date 2021/5/9
 **/ @RestController public class LoginController { @Autowired RoleService roleService; /** 
    * @Description: 登錄接口 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @ApiOperation(value = "登錄接口") @RequestMapping("/user/login") public Result login(@RequestBody User user){ System.out.println("進(jìn)入/user/login API接口"); if (StringUtils.isEmpty(user.getUsername())||StringUtils.isEmpty(user.getPassword())){ return Result.fail("請(qǐng)輸入用戶名密碼"); } Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); Object sessionId = session.getId(); Map ret = new HashMap<String,Object>(); ret.put("token",sessionId); UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword()); try { //登錄成功 subject.login(token); return Result.ok(ret); } catch (AuthenticationException e) { e.printStackTrace(); //登錄失敗 return Result.fail("用戶名密碼錯(cuò)誤"); } } /** 
    * @Description: 基本測(cè)試接口 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/noauthority") public Result noauthority(){ return Result.fail("沒有權(quán)限"); } /** 
    * @Description: 測(cè)試session接口 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/demoSession") @ResponseBody public String demoSession(HttpSession session){ System.out.println("測(cè)試session"); Enumeration<String> names = session.getAttributeNames(); while (names.hasMoreElements()){ String name = names.nextElement(); Object value = session.getAttribute(name); System.out.println(name + " -------  "+ value); } return "session 取值"; } /** 
    * @Description: 測(cè)試session接口 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/demoSession2") @ResponseBody public String demoSession2(){ Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); System.out.println(session.getHost()); System.out.println(session.getId()); System.out.println(session.getLastAccessTime().getTime()); System.out.println(session.getTimeout()); System.out.println(session.getAttribute("test")); return "session 取值"; } /** 
    * @Description: 測(cè)試session接口 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/checkPermission") @ResponseBody public Result checkPermission(User user){ if (StringUtils.isEmpty(user.getUsername())||StringUtils.isEmpty(user.getPassword())){ return Result.fail("請(qǐng)輸入用戶名密碼"); } Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); session.setAttribute("test","test"); UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword()); token.setRememberMe(true); try { //登錄成功 subject.login(token); } catch (AuthenticationException e) { e.printStackTrace(); //登錄失敗 return Result.fail("用戶名密碼錯(cuò)誤"); } try { subject.checkRole("admin"); return Result.ok("權(quán)限檢查成功"); } catch (AuthorizationException e) { e.printStackTrace(); return Result.fail("檢查權(quán)限失敗"); } } /** 
    * @Description: 根據(jù)token獲取用戶授權(quán)信息接口 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/checkRole") public Result checkRole(@RequestParam String token){ Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); List<Role> roleList = null; if (token.equals(session.getId().toString())){ String username = session.getAttribute("org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY").toString(); System.out.println(username); roleList = roleService.getRole(username); } return Result.ok(roleList); } /** 
    * @Description: 測(cè)試kaptcha ,獲取驗(yàn)證碼
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/testKaptcha") @ResponseBody public String TestKaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException { byte[] captcha = null; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { // 將生成的驗(yàn)證碼保存在session中 String createText = defaultKaptcha.createText(); request.getSession().setAttribute("rightCode", createText); BufferedImage bi = defaultKaptcha.createImage(createText); ImageIO.write(bi, "jpg", out); } catch (Exception e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); } captcha = out.toByteArray(); response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); ServletOutputStream sout = response.getOutputStream(); sout.write(captcha); sout.flush(); sout.close(); return "測(cè)試Kaptcha"; } /**
     * 校對(duì)驗(yàn)證碼
     *
     * @param request
     * @param response
     * @return
     */ @RequestMapping(value = "/user/verifyKaptcha") public Result imgvrifyControllerDefaultKaptcha(HttpServletRequest request, HttpServletResponse response) { ModelAndView model = new ModelAndView(); String rightCode = (String) request.getSession().getAttribute("rightCode"); String tryCode = request.getParameter("tryCode"); System.out.println("rightCode:" + rightCode + " ———— tryCode:" + tryCode); if (!rightCode.equals(tryCode)) { model.addObject("info", "驗(yàn)證碼錯(cuò)誤,請(qǐng)?jiān)佥斠淮?"); model.setViewName("login"); return Result.fail("驗(yàn)證碼錯(cuò)誤"); } else { model.addObject("info", "登陸成功"); model.setViewName("index"); return Result.ok("驗(yàn)證成功"); } } /** 
    * @Description: 測(cè)試 校驗(yàn)權(quán)限 permission 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/testShiroPermission") @RequiresPermissions("user:add") public Result TestShiroPermissions(){ System.out.println("訪問 TestShiroPermissions API"); Subject subject = SecurityUtils.getSubject(); String username = (String) subject.getPrincipal(); System.out.println(username); return Result.ok(username); } /** 
    * @Description: 登出功能API
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/logout") public Result logout(){ Subject subject = SecurityUtils.getSubject(); String username = (String) subject.getPrincipal(); subject.logout(); return Result.ok(username); } /** 
    * @Description:  測(cè)試校驗(yàn) 角色 role
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @RequestMapping("/user/TestRole") @RequiresRoles("admin") public Result TestRole(){ System.out.println("測(cè)試TestRole"); return Result.ok("測(cè)試Role"); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279

util

Result

package com.unclebb.zlgl.utils; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /**
 * @Author unclebb
 * @Description 統(tǒng)一返回API格式
 * @Date 2021/5/9
 **/ @Data @ApiModel(value = "全局統(tǒng)一返回結(jié)果") public class Result<T> { @ApiModelProperty(value = "返回碼") private Integer code; @ApiModelProperty(value = "返回消息") private String message; @ApiModelProperty(value = "返回?cái)?shù)據(jù)") private T data; public Result(){} public static <T> Result<T> build(T data) { Result<T> result = new Result<T>(); if (data != null) result.setData(data); return result; } public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) { Result<T> result = build(body); result.setCode(resultCodeEnum.getCode()); result.setMessage(resultCodeEnum.getMessage()); return result; } public static<T> Result<T> ok(){ return Result.ok(null); } /**
     * 操作成功
     * @param data
     * @param <T>
     * @return
     */ public static<T> Result<T> ok(T data){ Result<T> result = build(data); return build(data, ResultCodeEnum.SUCCESS); } public static<T> Result<T> fail(){ return Result.fail(null); } /**
     * 操作失敗
     * @param data
     * @param <T>
     * @return
     */ public static<T> Result<T> fail(T data){ Result<T> result = build(data); return build(data, ResultCodeEnum.FAIL); } public Result<T> message(String msg){ this.setMessage(msg); return this; } public Result<T> code(Integer code){ this.setCode(code); return this; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

ResultCode

package com.unclebb.zlgl.utils; import lombok.Getter; /**
 * @Author unclebb
 * @Description API狀態(tài)信息
 * @Date 2021/5/9
 **/ @Getter public enum ResultCodeEnum { SUCCESS(200,"成功"), FAIL(201, "失敗"), SERVICE_ERROR(202, "服務(wù)異常"), DATA_ERROR(204, "數(shù)據(jù)異常"), SIGN_ERROR(300, "簽名錯(cuò)誤"), PAY_PASSWORD_ERROR(401, "支付密碼錯(cuò)誤"), REPEAT_ERROR(402, "重復(fù)提交"), INVEST_AMMOUNT_MORE_ERROR(501, "出借金額已經(jīng)多余標(biāo)的金額"), RETURN_AMMOUNT_MORE_ERROR(502, "還款金額不正確"), PROJECT_AMMOUNT_ERROR(503, "標(biāo)的金額不一致") ; private Integer code; private String message; private ResultCodeEnum(Integer code, String message) { this.code = code; this.message = message; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

CustomRealm

package com.unclebb.zlgl.utils; import com.unclebb.zlgl.pojo.Permission; import com.unclebb.zlgl.pojo.Role; import com.unclebb.zlgl.pojo.User; import com.unclebb.zlgl.service.LoginService; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; /**
 * @program: zlgl
 * @description: 自定義Realm
 * @author: LiuZhiliang
 * @create: 2021-05-10 09:09
 **/ public class CustomRealm extends AuthorizingRealm { @Autowired LoginService loginService; /** 
    * @Description: 授權(quán)配置
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); User user = loginService.getByUsername(username); if (user == null){ return null; }else { SimpleAuthorizationInfo  simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for (Role role : user.getRolesSet()){ simpleAuthorizationInfo.addRole(role.getRoleName()); for (Permission permission : role.getPermissionSet()){ simpleAuthorizationInfo.addStringPermission(permission.getPermissionName()); } } return simpleAuthorizationInfo; } } /** 
    * @Description: 認(rèn)證配置 
    * @Param:  
    * @return:  
    * @Author: Liuzhiliang
    * @Date:  
    */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = token.getPrincipal().toString(); User user = loginService.getByUsername(username); if (user == null){ return null; }else { //匹配密碼 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,user.getPassword(),getName()); simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt())); return simpleAuthenticationInfo; } } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

前端代碼

前端我這里直接用了 開源的管理系統(tǒng)框架
附地址:

https://github.com/PanJiaChen/vue-admin-template

運(yùn)行截圖如下
在這里插入圖片描述
在這里插入圖片描述

完事兒只需要改一下它的 返回狀態(tài)碼校驗(yàn),配置下跨域就可以了
在這里插入圖片描述

整合驗(yàn)證碼

驗(yàn)證碼部分包含兩個(gè)API接口

/user/testKaptcha 獲取驗(yàn)證碼信息
/user/verifyKaptcha 校驗(yàn)

其中獲取驗(yàn)證碼圖片信息相當(dāng)于請(qǐng)求靜態(tài)圖片資源,直接將驗(yàn)證碼圖片的src指向 該接口即可,前端源碼如下:

 <el-image :src="kaptcha" @click="refreshCode()" alt="加載失敗" style="margin-left:10px;height:40px;margin-top:5px"> <div slot="placeholder" class="image-slot"> <i class="el-icon-loading"></i> </div> </el-image> 
  • 1
  • 2
  • 3
  • 4
  • 5

其中路徑定義為:

kaptcha:"http://localhost:8082/user/testKaptcha?t="+ new Date().getTime(), 
  • 1

后面加的時(shí)間參數(shù)是為了刷新url用的
前端的刷新函數(shù)就是將kaptcha重新賦值

 refreshCode(){ console.log("測(cè)試切換驗(yàn)證碼") this.kaptcha = "http://localhost:8082/user/testKaptcha?t="+ new Date().getTime() console.log(this.kaptcha) }, 
  • 1
  • 2
  • 3
  • 4
  • 5

登錄、權(quán)限校驗(yàn)、登出效果如下

登錄

登錄首先會(huì)驗(yàn)證 驗(yàn)證碼的正確性,登陸成功進(jìn)入主界面

驗(yàn)證碼錯(cuò)誤如下:
在這里插入圖片描述
用戶名密碼錯(cuò)誤如下:
在這里插入圖片描述
登陸成功后請(qǐng)求校驗(yàn)角色 校驗(yàn)成功
在這里插入圖片描述請(qǐng)求校驗(yàn)權(quán)限 校驗(yàn)成功
在這里插入圖片描述

退出,執(zhí)行兩次,data為null
在這里插入圖片描述

再次校驗(yàn)權(quán)限,報(bào)出異常

在這里插入圖片描述


 藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png


文章來源:csdn   作者:黑胡子大叔的小屋

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)

SpringBoot + Spring Cloud +Vue 管理系統(tǒng)前端搭建(二、visual studio code開發(fā)前端項(xiàng)目)

前端達(dá)人

我們打開visual studio code , 選擇文件------------->將文件夾添加到工作區(qū),導(dǎo)入我們的項(xiàng)目

 

安裝Element

導(dǎo)入后,我們安裝以下element

官網(wǎng):https://element.eleme.cn/#/zh-CN/component/installation

安裝命令:npm add element-ui或者也可以用yarn

安裝完成后,我們?cè)趍ain.js中引入Element

import Vue from 'vue'

import App from './App'

import router from './router'

import ElementUI from 'element-ui'

import 'element-ui/lib/theme-chalk/index.css'

Vue.config.productionTip = false

 

/* eslint-disable no-new */

Vue.use(ElementUI)

new Vue({

el: '#app',

router,

components: { App },

template: '<App/>'

})

頁面路由

 我們把components改名為views,并在目錄下添加3個(gè)頁面:Login.vue、Home.vue、404.vue。

頁面內(nèi)容類似:

<template>

<div class="page">

<h2>Login Page</h2>

</div>

</template>

 

<script>

export default {

name: 'Login'

}

</script>

配置路由

打開router/index.js,添加3個(gè)路由分別對(duì)應(yīng)主頁、登錄、404頁面

import Vue from 'vue'

import Router from 'vue-router'

import Login from '@/views/Login'

import Home from '@/views/Home'

import NotFound from '@/views/404'

 

Vue.use(Router)

 

export default new Router({

routes: [

{

path: '/',

name: 'Home',

component: Home

}, {

path: '/login',

name: 'Login',

component: Login

}, {

path: '/404',

name: 'notFound',

component: NotFound

}

]

})

配置完后啟動(dòng)項(xiàng)目,在瀏覽器訪問測(cè)試

http://localhost:8080/#/

http://localhost:8080/#/login

 

http://localhost:8080/#/404

說明我們的配置已經(jīng)生效了

安裝scss

安裝依賴:

npm uninstall sass-loader //卸載當(dāng)前版本) 
npm install sass-loader@7.3.1 --save-dev //卸了重新安裝了一個(gè)低版本
npm install node-sass@4.14.1 --save-dev //安裝node-sass 

安裝的時(shí)候注意對(duì)應(yīng)版本,版本不對(duì)應(yīng),啟動(dòng)會(huì)報(bào)錯(cuò)

安裝后修改404頁面

<template>

<div class="site-wrapper site-page--not-found">

<div class="site-content__wrapper">

<div class="site-content">

<h2 class="not-found-title">404</h2>

<p class="not-found-desc">抱歉!您訪問的頁面<em>失聯(lián)</em>啦 ...</p>

<el-button @click="$router.go(-1)">返回上一頁</el-button>

<el-button type="primary" class="not-found-btn-gohome" @click="$router.push('/')">進(jìn)入首頁</el-button>

</div>

</div>

</div>

</template>

 

<script>

export default {

name: '404'

}

</script>

 

<style lang="scss">

.site-wrapper.site-page--not-found {

position: absolute;

top: 60px;

right: 0;

bottom: 0;

left: 0;

overflow: hidden;

.site-content__wrapper {

padding: 0;

margin: 0;

background-color: #fff;

}

.site-content {

position: fixed;

top: 15%;

left: 50%;

z-index: 2;

padding: 30px;

text-align: center;

transform: translate(-50%, 0);

}

.not-found-title {

margin: 20px 0 15px;

font-size: 8em;

font-weight: 500;

color: rgb(55, 71, 79);

}

.not-found-desc {

margin: 0 0 30px;

font-size: 26px;

text-transform: uppercase;

color: rgb(118, 131, 143);

> em {

font-style: normal;

color: #ee8145;

}

}

.not-found-btn-gohome {

margin-left: 30px;

}

}

</style>

再瀏覽器訪問http://localhost:8080/#/404

 

可以看到樣式改變了

安裝axios

命令:npm install axios

安裝完成后修改Home頁面,進(jìn)行一個(gè)簡(jiǎn)單的測(cè)試

<template>

<div class="page">

<h2>Home Page</h2>

<el-button type="primary" @click="testAxios()">測(cè)試Axios調(diào)用</el-button>

</div>

</template>

 

<script>

import axios from 'axios'

import mock from '@/mock/mock.js'

export default {

name: 'Home',

methods: {

testAxios() {

axios.get('http://localhost:8080').then(res => { alert(res.data) })

}

}

}

</script>

可以看到我們的請(qǐng)求已經(jīng)成功了

安裝Mock.js

為了模擬后臺(tái)接口提供頁面需要的數(shù)據(jù),引入mock.js

安裝依賴:npm install mockjs -dev

安裝完成,在src新建一個(gè)mock目錄,創(chuàng)建mock.js,在里面模擬兩個(gè)接口,分別攔截用戶和菜單的請(qǐng)求并返回相應(yīng)數(shù)據(jù)。

import Mock from 'mockjs'

 

Mock.mock('http://localhost:8080/user', {

'name': '@name', // 隨機(jī)生成姓名

'name': '@email', // 隨機(jī)生成郵箱

'age|1-12': 7, // 年齡1-12之間

})

Mock.mock('http://localhost:8080/menu', {

'id': '@increment', // id自增

'name': 'menu', // 名稱為menu

'order|1-10': 6, // 排序1-10之間

})

修改Home.vue,在頁面添加兩個(gè)按鈕,分別觸發(fā)用戶和菜單請(qǐng)求。成功后彈出返回結(jié)果

注意:要在頁面引入mock    import mock from '@/mock/mock.js'

Home.vue

<template>
  <div class="page">
    <h2>Home Page</h2>
    <el-button type="primary" @click="testAxios()">測(cè)試Axios調(diào)用</el-button>
    <el-button type="primary" @click="getUser()">獲取用戶信息</el-button>
    <el-button type="primary" @click="getMenu()">獲取菜單信息</el-button>
  </div>
</template>

<script>
import axios from 'axios'
import mock from '@/mock/mock.js'
export default {
  name: 'Home',
  methods: {
    testAxios() {
      axios.get('http://localhost:8080').then(res => { alert(res.data) })
    },
    getUser() {
      axios.get('http://localhost:8080/user').then(res => { alert(JSON.stringify(res.data)) })
    },
    getMenu() {
      axios.get('http://localhost:8080/menu').then(res => { alert(JSON.stringify(res.data)) })
    }
  }
}
</script>

訪問http://localhost:8080/#/

點(diǎn)擊獲取用戶信息

點(diǎn)擊獲取菜單信息

可以看到我們已經(jīng)得到響應(yīng)數(shù)據(jù),這樣mock就集成進(jìn)來了

看完記得點(diǎn)贊哦

  藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png


文章來源:csdn   作者:Java璐到底

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)


講真,我從這些Dribbble頂尖圖標(biāo)大神的作品中學(xué)到很多,建議你一定要看看

seo達(dá)人

今天彩云就跟大家分享一些Dribbble上,我這些年一直珍藏的10位圖標(biāo)設(shè)計(jì)大佬們,我建議你一定要收藏學(xué)習(xí)。

 

1、Scott Tusk

https://dribbble.com/Tusk

首先推薦的就是這位大佬了,他在Drbbble上堅(jiān)持了365天打卡練習(xí),每天更新一張高質(zhì)量圖標(biāo)或者矢量小插圖設(shè)計(jì),圖形簡(jiǎn)單好看,非常值得借鑒和臨摹練習(xí)。

圖片

圖片

圖片

2、Dmitri Litvinov

https://dribbble.com/dmitrilitvinov

一個(gè)在圖標(biāo)設(shè)計(jì)上非常有造詣的自由設(shè)計(jì)師,他在圖標(biāo)的造型和風(fēng)格一致性上做的非常好,而且能看出來他的作品大部分都是能落地的稿子,值得學(xué)習(xí)。

圖片

圖片

圖片

 

3、Paulius Kairevicius

https://dribbble.com/kairevicius

這位大神在設(shè)計(jì)圖標(biāo)Logo的時(shí)候擅長(zhǎng)用嚴(yán)謹(jǐn)?shù)谋壤?,而且他?huì)把他的作圖過程和輔助線放出來,我覺得從這些作品中可以學(xué)到很多設(shè)計(jì)的思路,推薦給大家。

圖片

圖片

圖片

圖片

 

4、Justas Galaburda

https://dribbble.com/jucha

這些大神的作品喜歡加噪點(diǎn),很有自己的風(fēng)格特點(diǎn),圖標(biāo)都做的比較可愛。如果是做些偏萌系的設(shè)計(jì),包括一些小表情之類的可以參考他的作品了。

圖片

圖片

圖片

 

5、Martin David

https://dribbble.com/srioz

專業(yè)的圖標(biāo)設(shè)計(jì)師,在圖標(biāo)設(shè)計(jì)這個(gè)領(lǐng)域相當(dāng)專注,看他的個(gè)人主頁幾乎全是圖標(biāo)的設(shè)計(jì),以商業(yè)圖標(biāo)設(shè)計(jì)居多。做項(xiàng)目的時(shí)候,非常值得參考了。

圖片

圖片

圖片

 

6、Myicons

https://dribbble.com/lineicons

這位其實(shí)是一個(gè)圖標(biāo)平臺(tái)的賬號(hào),會(huì)定期更新大量的圖標(biāo)資源,把它收藏起來當(dāng)成靈感庫還不錯(cuò)。

圖片

 

7、Eddie Lobanovskiy

https://dribbble.com/lobanovskiy

這位大佬(也可能是一個(gè)團(tuán)隊(duì)賬號(hào))非常的全面,不僅僅只是在圖標(biāo)領(lǐng)域,在3D、插畫、品牌、網(wǎng)頁、UI都頂級(jí)優(yōu)秀。我個(gè)人非常喜歡他在圖標(biāo)這塊的創(chuàng)意,能看到他展示了很多圖形的方案,過程稿,我覺得可以學(xué)習(xí)到很多,比如用到自己的作品集展示中,就很實(shí)用了。

圖片

圖片

圖片

圖片

 

8、Eddy Gann

https://dribbble.com/Ed117

這位大佬非常擅長(zhǎng)動(dòng)態(tài)圖標(biāo)的設(shè)計(jì),他做的圖標(biāo)動(dòng)效并不夸張,但卻是非常容易的落地到實(shí)際項(xiàng)目中。在動(dòng)效創(chuàng)意如此流行的今天,他的這些作品一定可以給你提供靈感,專注在圖標(biāo)動(dòng)效上的作品并不多見,值得收藏。

圖片

圖片

圖片

 

9、Zach Roszczewski

https://dribbble.com/ZachRoszczewski

這位大佬在圖標(biāo)的多種風(fēng)格方面把握的都比較好,想要同時(shí)看多種風(fēng)格搭配的可以收藏了。

圖片

圖片

圖片

 

10、Evgenii Dolgov

https://dribbble.com/numicor

最后推薦一位矢量風(fēng)格圖標(biāo)設(shè)計(jì)大神,他的作品風(fēng)格獨(dú)特,擅長(zhǎng)在圖標(biāo)上疊加很多插畫形式的明暗紋理,形式感比較強(qiáng),值得學(xué)習(xí)。

圖片

圖片

圖片

 

總結(jié)

文章中列出來的這些是我從關(guān)注列表中再三篩選出來的比較有代表性的圖標(biāo)設(shè)計(jì)大神,在我的工作學(xué)習(xí)過程中,他們給了我很多的靈感。當(dāng)然,這份推薦名單只是我自己的個(gè)人喜好,無關(guān)粉絲數(shù)量,排名也不分先后。

這篇分享,一定是值得收藏的,不論是找靈感,還是臨摹學(xué)習(xí),不用到處找,這10位大佬的作品就足夠你研究了。

在看的過程中,要學(xué)會(huì)去分析優(yōu)秀的圖標(biāo),并用到自己的設(shè)計(jì)中。不管是練習(xí)還是實(shí)際項(xiàng)目,好的設(shè)計(jì)一定是有道理的,多想想別人為什么這么做。比如:為什么對(duì)方用這個(gè)顏色?顏色的配比怎樣?輔助圖形用的哪些?一套圖標(biāo)中的輔助圖形如何做到豐富又不失一致性等等問題。不要只是依葫蘆畫瓢,要思考背后的道理,這個(gè)很重要。

最后,對(duì)于圖標(biāo)設(shè)計(jì)本身,最重要的還是要保持練習(xí),多看多做才能真正提升

 

原文地址:彩云譯設(shè)計(jì)(公眾號(hào)) 作者:彩云Sky

轉(zhuǎn)載請(qǐng)注明:學(xué)UI網(wǎng)》講真,我從這些講真,我從這些Dribbble頂尖圖標(biāo)大神的作品中學(xué)到很多,建議你一定要看看

 

藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

微信圖片_20210513163802.png

 

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

 

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)


怎樣讓UI作品集脫穎而出?試試這3種方法!

seo達(dá)人

 

優(yōu)秀的設(shè)計(jì)師不僅要會(huì)設(shè)計(jì),更要會(huì)包裝。經(jīng)過設(shè)計(jì)師精心包裝的設(shè)計(jì)作品,總是更容易被甲方接受,經(jīng)過精心包裝的作品集,自然也更受招聘公司的青睞。通過對(duì)國(guó)外優(yōu)秀UI設(shè)計(jì)作品的歸納,以下總結(jié)出了下面三種UI作品的展示方法,希望能對(duì)大家有些幫助。

 

01.錯(cuò)位平鋪

平鋪展示是最簡(jiǎn)單粗暴的展示方法,很容易讓你的作品顯得枯燥乏味。可以將頁面進(jìn)行簡(jiǎn)單的錯(cuò)位處理,讓版式更靈動(dòng),畫面外的部分也會(huì)給人以想象的空間,讓面試官覺得整個(gè)作品豐富且龐大,是最為穩(wěn)妥的展示方法。

圖片

圖片

圖片

圖片

 

02.模塊分離

將部分模塊分離出頁面,通過陰影效果進(jìn)行前后位置的劃分,有助于表現(xiàn)你對(duì)整個(gè)頁面層級(jí)的理解。UI不僅僅是簡(jiǎn)單的時(shí)間工作,多展示你對(duì)整個(gè)框架和層級(jí)的思考,會(huì)讓作品集更加出彩。

圖片

圖片

圖片

圖片

 

03.組件化展示

UI設(shè)計(jì)師們對(duì)整體風(fēng)格的把控能力越來越重要,這關(guān)乎你能否獨(dú)立負(fù)責(zé)整個(gè)項(xiàng)目,所以在作品集中展示你的組件庫尤為重要。組件是否能方便的復(fù)用,各個(gè)組件是否能保持風(fēng)格的統(tǒng)一,這些都會(huì)對(duì)你面試更高級(jí)的設(shè)計(jì)師有很大幫助。

圖片

圖片

圖片

圖片

 


 藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

截屏2021-05-13 上午11.41.03.png


文章來源:深海公眾號(hào)   作者:深海

分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.yvirxh.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)




日歷

鏈接

個(gè)人資料

存檔