<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          如何快速理解客戶設計需求?

          seo達人

          11.jpeg

          作為一個設計者,我們再給客戶做設計方案的時候,大家會發現客戶的需求點,很難去理解。并不是設計的技術水平問題,而是再理解客戶的需求點上出現了問題。就算你設計的東西在同行看來已經很好了。但是客戶往往不是很滿意??蛻粼僖笪覀冏鲈O計的時候,其實心里已經有了大概的想法,只是自己無法通過設計去實現而已。我們要做的是用自己的專業知識全區完成客戶的想法,已達到客戶滿意的效果。那么我們如何快速理解客戶的設計需求呢?

          22.jpeg

          第一:設計的能力加強提升,擁有過硬的技術:

          客戶的需求形形色色,運用到的技能要全面,這是最為基礎的點。如果連技術都不過關,就算理解了,也做不到。因此作為一個設計者,我自身就要擁有過硬的技能。而不是濫竽充數,忽悠客戶,以低標準去做設計。

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

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

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

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

          33.jpeg


           

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          微信圖片_20210513163802.png

           

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

           

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

           

          vue電商后臺管理系統保姆級教程(八)——角色列表結構功能

          前端達人

          8、角色列表

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

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

          在路由中加載導入:
          在這里插入圖片描述
          在這里插入圖片描述

          8.2 繪制基本布局結構并獲取列表數據

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

          8.3 渲染角色列表數據

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

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

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

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

          點擊對應按鈕出現對應的彈出層,然后執行對應的操作。

          8.5 分析角色下權限渲染的思路

          在展開行中拿到渲染的數據
          在請求數據列表中返回了數據children,通過作用域插槽來拿
          在這里插入圖片描述
          實現效果:
          在這里插入圖片描述
          拿到數據之后通過三層for循環渲染出對應的ui結構

          8.6 通過第一層for循環渲染一級權限

          先做一下柵格布局,區分出三個區域用來放三層for循環:

          scope.row是當前對象的數據。 .children 是一級權限的數據, :key每次循環綁定一個唯一的key值,通過插值表達式渲染出數據
          在這里插入圖片描述
          放在el-tag標簽中美化樣式
          在這里插入圖片描述

          8.7 美化一級權限

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

          8.8 通過二層for循環渲染二級權限

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

          8.9 通過第三層for循環渲染三級權限

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

          8.10 美化角色權限下的UI結構

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

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

          8.11 點擊刪除權限按鈕彈出確認提示框

          使用element組件中的可移除標簽屬性:
          在這里插入圖片描述
          closable屬性:
          在這里插入圖片描述
          綁定點擊事件:
          removeRightById:
          在這里插入圖片描述
          定義事件:
          在這里插入圖片描述
          然后彈框提示用戶是否要刪除,使用的還是element組件L

          在這里插入圖片描述
          catch捕獲錯誤:在這里插入圖片描述
          結果判斷用戶操作:
          在這里插入圖片描述
          這里只是打印了結果,沒有向后端發起請求。

          8.12 完成刪除角色下指定權限的功能

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



          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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


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

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          Jquery選擇器中使用變量實現動態選擇例子

          前端達人

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


          例子一:

          例子二:


          <table>
            <tr>
              <th>用戶名</th>
              <th>狀態</th>
            <tr>
            <tr>
              <td>張三</td>
              <td data-uid="10000">正常</td>
            <tr>
            <tr>
              <td>李四</td>
              <td data-uid="10001">凍結</td>
            <tr>
            <tr>
              <td>王二麻子</td>
              <td data-uid=10002>凍結</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中選擇器參數使用變量應該注意的問題

          這是原來的代碼


          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);


          實現的是關鍵詞替換,不過到第三行時候不執行了,調試啊,替換啊,都不行。 從早上到剛才一直在各種群里面發問,終于 …… 俺們大本營 的Lomu大神一陣見血:

          你的寫法不對

          要連接符

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

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


          關鍵是外面有引號

          有引號被當字符串處理了

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





            藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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


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

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

          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務



          網站建設-如何建設一個優質的網站?

          seo達人

           

          網站建設-如何建設一個優質的網站?

          1.jpeg網站建設

          互聯網時代的到來,作為一個企業你如果還沒有屬于自己的網站,那么你就真的“out”了,互聯網的日流量達到上億,這些不是簡單的點擊率,而是一筆真真正正的大錢。如果你還不會互聯網,不了解互聯網,那么這些都與你毫無關系。而網站建設是企業面向互聯的主要窗口之一。也是大家公認渠道之一。

          網站建設對于企業來說意義重大,它不僅是企業展示的窗口那么簡單?;ヂ摼W時代下,眾多企業紛紛進行互聯網轉型,那是因為這些企業的領導者擁有者敏銳的嗅覺,具有洞察時代大趨勢的能力。網站建設使他們首先要做的事情。那么如何建設一個優質的網站呢?

          2.jpeg網站建設

          第一:網站建設平臺要有強大開發團隊

          網站建設是一門技術活,沒有強大的技術作為支撐,就無法保障網站的安全性和功能的實現。開發團隊的強大決定了網站質量與品質。擁有一穩定的后臺,才能確保企業網站的一系列工作順利進行。

          第二:網站建設要有專業的設計團隊

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

          第三:網站建設要跟上時代的步伐

          時代變,網站建設的功能和需求點也在變,只有去適應時代的打造需求,企業才能在競爭激烈的時代下生存。功能的更新換代也要跟上時代的步伐,才能滿足客戶的體驗需求。客戶才會為我們買單。

          3.jpegSEO優化

          第四:網站建設要有利于SEO優化

          網站建設只是完成面建設,而我們建設網站的目的是為了,引來流量,轉化流量,實現利潤轉化。一個沒有不利于SEO優化的網站,就像埋藏再深山的金山,難以被發現,吸引不到客戶。SEO的意義在于打通前往金山的通道。海、陸、空全方位立體打通,讓客戶絡繹不絕前往。金山才得以被發現,被開發。

          第五:網站堅持維護更新

          這個時代不是大魚吃小魚的時代,而是快魚吃慢魚的時代。只有不斷的去完善更新,才能適應生存。網站也一樣,只有不斷優化升級才能不被淘汰。

          第六:網站建設要符合國家政策

          要及時了解國家的相關法律法規以及一些相關的政策,例如最新的廣告法,不能只用不符合要求的字眼。例如分銷系統,不能越過法律底線。那些文字可以商業,哪些是有版權的等。

          以上是一些個人的網站建設個人見解,如有更好的意見也歡迎大家一起探討,相互學習。

           

           


          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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



          文章來源:SEO

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


           

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          用戶錯了嗎? 防錯與容錯

          資深UI設計者

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




          據說只要可能犯錯,就一定會有人犯錯,用戶犯錯的可能性比我們想象中要大得多得多得多得多。

          做好防錯與容錯,可以讓用戶更順暢的達成自己的目標。


          恩,用戶總是那么不可理喻對吧

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

          打住,打住,當用戶犯錯時,別急著怪他,我們需要先判斷清楚。


          一、用戶真的錯了嗎?

          用戶委屈的說:“來來來,我就想下載一個資源,大家都是講道理的設計師,來評評理,我錯在哪里?”

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

          作為設計師的你是不是已經敏銳的察覺到了什么?

          對,關鍵點在 ' 67bh ' 這里。都是空格惹的禍!

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

          當然,現在不會公布答案,方式有好多種。留著你看完文章中間部分再跟大家一起找方案吧。

          這一部分的重點不是方案,而是思維。


          很多時候,用戶并沒有錯,作為一個有擔當的設計師,我們可不能甩鍋。

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


          二、如何避免用戶“犯錯”

          對,這個疑問就已經包含了解決方案了。

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

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

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

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


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

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


          看看的你腦袋是不是真的轉得飛起...

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

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

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

          • 在通往海島的路線全程搭起防鯊網。

          恩,目前就想到這些了,還有方案的同學可以在評論區炸沙發哈。


          這些方式,我們試著抽象一下:

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

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

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

          大家應該都發現了,這種方式雖然能達到讓用戶安全的目的,但是用戶會有挫敗感,同時也會有被限制的感覺。

          我只要說到USB插頭,大家應該就開始腦補畫面了吧“為什么我插的進去的第一次永遠是錯的方向,OMG!”

          那,容錯呢?


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

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


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

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

          • 派一直專業驅鯊救援隊跟隨這位大哥(滑板大哥:我何德何能,太感動了)。


          同樣,我們繼續抽象一下:

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

          • 【出現錯誤可挽回】派一直專業驅鯊救援隊跟隨這位大哥,出現鯊魚就殺魚。


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

          因為他甚至都感知不到這片海還有過危險,按自己喜歡的方式行動就行。

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

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

          可是...我只是一個有無縛雞之力的設計師,我肝不過鯊魚怎么辦?

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


          三、試用一下以上方法

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

          前面講的方法也列在右側了,看看你們是不是可以針對每種方法找到對應方案了呢?

          看看是不是可以這樣?


          方案一:使用方法-提前做好引導和提示


          方案二:使用方法-優先選擇減少輸入


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


          方案四:使用方法-出現錯誤可挽回


          方案五:使用方法-讓錯誤不影響結果


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

          好吧,這個問題的確很蠢。當然是 方案二 + 方案五 結合使用了。因為是兩個平臺的交互,而對于各自平臺而言,一個控制好輸出,一個控制好輸入。對平臺自身的容錯性有很大的幫助。

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

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

          那,我們先不管那幾個往回滾的同學,開始進行強化學習啦~


          四、帶著思考學習

          找了一些生活中經常用到的產品,讓大家感受一下防錯容錯的魅力。

          如果你根本無法從圖中發現什么,那我只能說... 你還是需要經常用銀杏葉擦擦眼睛了(因為擦了之后你就更容易發現(人性)。

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

          方法總會越來越多,靠“別人”總結的方法也就能應個急。

          來來來,放空~~~~拋棄你的職業相關認知、拋棄你的設計師的身份,你再看我們的設計。

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

          你會發現,為什么會有這么多奇怪的看不見的規則,為什么我這么難完成我的任務。


          五、提前預知錯誤風險(重點)

          如果當客戶遇到問題,你能用合適的方法去解決,那你已經是個不錯的設計師了,但離優秀還很遠,因為優秀的設計師必須具有敏銳的嗅覺,要在產品團隊的前面,感知并規避風險。

          所以,更重要的還是,我們必須學會變身。

          好了,這一次真的需要大家獨立思考了,并且沒有標準答案,大家可以交流交流。


          在以下場景中,可能會出現什么“錯誤”,如何有效處理用戶“犯錯”?

          在生活中,其實會有很多很多“讓用戶犯錯”的產品/場景,多參與其中,去發現問題,去思考解決方案,慢慢的,你就會具備非常好的問題發現能力和解決能力了。

          說了這么多,可能有一部分同學會想說:

          “用戶出錯的情況應該很少吧,你花這么長的篇幅”

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

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

          不信你看。


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

          百度一下,你會發現用戶犯錯的可能性大大超出你的預期。

          只是,你以為與你“無關”而已。


          七、防止用戶犯錯的設計可能比你想象中更難,更重要

          要防止用戶犯錯,你需要不斷的模擬用戶的操作行為,去捕獲那些可能存在的問題,然后將它一一化解;這個過程很難,因為你要拋開自己以往的經驗和認知,去感受用戶的視角。


          想想,用戶體驗的改進不就是讓產品越來越符合用戶認知,從而減少用戶“犯錯”嗎?

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

          從現在起,將“錯誤”留給自己。




           藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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



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

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務






          移動端導航設計

          資深UI設計者

          合理的移動導航設計能夠盡可能地減少摩擦,引導用戶去他們要去的地方。

          這篇文章匯總了移動端導航設計最常見的樣式、要注意的設計準則以及優秀的案例分析,一起來系統性地掌握這些知識~

          什么是移動端導航?

          簡單來說,導航是用戶從 A 點到 B 點的方式,是他們發現設計點并與產品交互的過程。

          可能很多用戶認為導航的目標是“在盡可能短的時間內讓用戶從 A 到 B”,但時間短只屬于操作結果,這個結果需要依靠合理且簡單的設計才能實現。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          移動端導航常見的設計樣式

          1. 漢堡菜單

          圍繞漢堡菜單有很多爭論,但存在即合理,在合適的場景下漢堡菜單也能發揮大的作用。

          來看一下漢堡菜單具備的優勢:

          • 視覺空間:節省屏幕空間,包含有價值的信息;
          • 心智模型:大多數用戶熟悉這種設計樣式并知道如何操作;
          • 使用經驗:調節學習曲線,改善使用體驗。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 使用用戶熟悉的設計可以事半功倍。例如美團和餓了么兩個產品有著完全不同的主題色,但外賣點餐流程卻是一樣的,仍然是用戶熟悉的操作,并沒有因為產品的不同而改變點餐流程。

          2. 底部導航

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

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          3. 頂部導航

          關于頂部導航,可以看之前分享的文章,里面詳細介紹了頂部導航的設計方法。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          4. 卡片式導航

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

          隨著網絡上的內容越來越碎片化和個性化,卡片是在頁面中聚合單個信息的好方式。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 為了改進體驗,卡片可以個性化顯示不同的內容。另外卡片很容易適應不同的屏幕尺寸,配合響應性設計。

          5. 標簽

          標簽往往是在一個大主題下同時支持多個選項,每個選項都轉到不同的界面。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          6. 基于手勢的導航

          基于手勢的導航可以讓用戶在所需方向上快速滑動,來完成特定的操作。

          這種樣式的優點在于,即使最沒有經驗的用戶也很容易掌握,因為手勢通常是直觀的。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 國外大火的約會產品Tinder以及國內的探探,都使用了基于手勢的導航樣式,為用戶帶來滑動的樂趣。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 基于手勢的導航并不是Tinder發明的,但這款產品無疑將這種流行帶給了大眾。經典的向左或向右滑動模式保持了事物的動態性、簡單性和娛樂性。

          7. 全屏導航

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

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 點擊圖片可以跳轉到全屏大圖導航中,能夠更清晰地查看商品的外觀狀態。

          8. 3D touch

          最初是由蘋果公司提供給用戶的,這是一種創建導航快捷方式的方法,可以顯示選定的 APP 的一些關鍵操作。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 蘋果為手機創造了一種全新的快捷方式,同時提供了強大的可用性。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 3D touch另一個用途是內容預覽,在處理內容選項時例如收件箱或文章列表時,這是給用戶提供預覽的好方法。

          移動端導航設計準則

          1. 導航需要直觀明顯

          對所有類型的導航來說都是如此。在移動端中由于屏幕空間的縮小和交互成本的增加,導航體驗的好壞會對產品產生很大的影響。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 從可用性角度來看,直觀的導航對目標用戶來說至關重要。這意味著需要進行嚴格的測試和大量的研究,可以使用卡片分類或樹狀圖等方法來驗證導航的可用性。

          2. 考慮手指的位置

          這點對于移動應用來說至關重要,沒有用戶想反復點擊圖標卻沒有反應。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          3. 建立視覺層級避免混亂

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

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 極簡主義是UI設計的一種特定風格,通過必備的頂部導航欄、留白以及由大小、版式、顏色劃分的視覺層級來規劃頁面內容。

          移動端導航示例分析

          1. Facebook

          Facebook 的導航構成比較復雜,融合了多種不同樣式的導航。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          2. Spotify

          Spotif 作為音樂流媒體業務的巨頭,即使對于新用戶來說,頁面的設計也容易理解和探索。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 以高度視覺化的形式突出每張卡片背后的關鍵內容,另外底部導航也可以完成繁重的任務指引。

          3. App Store

          App Store 是使用標簽進行導航的好例證,每個標簽代表了同一內容的不同方面。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

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

          4. Telegram

          Telegram 可以供任何人使用,漢堡菜單提供了用戶可能需要的所有關鍵導航選項。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 每個用戶都能立即找出漢堡菜單,非常容易使用和理解,而且幾乎不占用界面中的寶貴空間。

          5. Yelp

          yelp 在創建全屏導航體驗時采用了一種稍微不同的方法。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ Yelp將屏幕劃分為兩個不同的區域,實際上并沒有將整個屏幕專門用于導航選項,而是將頂部用于導航選項,并在底部留下更多的負空間。

          6. Trello

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

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ 卡片系統很好地代表了Trello簡化復雜工作流程的能力,為用戶帶來整潔和方便。

          7. Twitter

          同樣使用了多種導航混合的設計樣式。

          你了解移動端導航設計嗎?收下這篇系統性的總結!

          △ Twitter將導航重點放在底部欄上,涵蓋了整個平臺中四個主要的方面。

          最后

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




           藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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



          文章來源:站酷   作者:Clip設計夾

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務



          SpringBoot + Shiro + Mybatis-plus + Kaptcha + vue實現權限管理登錄功能

          前端達人

          登錄功能

          在這里插入圖片描述

          使用到的技術

          • shiro
          • Mybatis-plus
          • Springboot
          • kaptcha

          參考優秀博文

          一個博主做的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 驗證碼 --> <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等注解。生成代理類實現功能增強,從而實現權限控制。需要配合AuthorizationAttributeSourceAdvisor一起使用,否則權限注解無效。
              * @Param:
              * @return:
              * @Author: Liuzhiliang
              * @Date:
              */ @Bean public DefaultAdvisorAutoProxyCreator lifecycleBeanProcessor(){ DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } /** 
              * @Description:  上面配置的DefaultAdvisorAutoProxyCreator相當于一個切面,下面這個類就相當于切點了,兩個一起才能實現注解權限控制。
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){ AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } /**
               * @Description: Filter工廠,設置對應的過濾條件和跳轉條件
               * @Param:
               * @return:
               * @Author: Liuzhiliang
               * @Date:
               */ //權限管理,配置主要是Realm的管理認證 @Bean public DefaultWebSecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); ThreadContext.bind(securityManager); return securityManager; } //將自己的驗證方式加入容器 @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("網站-API文檔") .description("本文檔描述了網站微服務接口定義") .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"); // 驗證碼長度 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 用戶實體類
           * @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 角色實體類
           * @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 權限實體類
           * @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 登錄實現類
           * @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實現類
           * @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實現類
           * @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("進入/user/login API接口"); if (StringUtils.isEmpty(user.getUsername())||StringUtils.isEmpty(user.getPassword())){ return Result.fail("請輸入用戶名密碼"); } 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("用戶名密碼錯誤"); } } /** 
              * @Description: 基本測試接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ @RequestMapping("/user/noauthority") public Result noauthority(){ return Result.fail("沒有權限"); } /** 
              * @Description: 測試session接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ @RequestMapping("/user/demoSession") @ResponseBody public String demoSession(HttpSession session){ System.out.println("測試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: 測試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: 測試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("請輸入用戶名密碼"); } 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("用戶名密碼錯誤"); } try { subject.checkRole("admin"); return Result.ok("權限檢查成功"); } catch (AuthorizationException e) { e.printStackTrace(); return Result.fail("檢查權限失敗"); } } /** 
              * @Description: 根據token獲取用戶授權信息接口 
              * @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: 測試kaptcha ,獲取驗證碼
              * @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 { // 將生成的驗證碼保存在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 "測試Kaptcha"; } /**
               * 校對驗證碼
               *
               * @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", "驗證碼錯誤,請再輸一次!"); model.setViewName("login"); return Result.fail("驗證碼錯誤"); } else { model.addObject("info", "登陸成功"); model.setViewName("index"); return Result.ok("驗證成功"); } } /** 
              * @Description: 測試 校驗權限 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:  測試校驗 角色 role
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ @RequestMapping("/user/TestRole") @RequiresRoles("admin") public Result TestRole(){ System.out.println("測試TestRole"); return Result.ok("測試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 統一返回API格式
           * @Date 2021/5/9
           **/ @Data @ApiModel(value = "全局統一返回結果") public class Result<T> { @ApiModelProperty(value = "返回碼") private Integer code; @ApiModelProperty(value = "返回消息") private String message; @ApiModelProperty(value = "返回數據") 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狀態信息
           * @Date 2021/5/9
           **/ @Getter public enum ResultCodeEnum { SUCCESS(200,"成功"), FAIL(201, "失敗"), SERVICE_ERROR(202, "服務異常"), DATA_ERROR(204, "數據異常"), SIGN_ERROR(300, "簽名錯誤"), PAY_PASSWORD_ERROR(401, "支付密碼錯誤"), REPEAT_ERROR(402, "重復提交"), INVEST_AMMOUNT_MORE_ERROR(501, "出借金額已經多余標的金額"), RETURN_AMMOUNT_MORE_ERROR(502, "還款金額不正確"), PROJECT_AMMOUNT_ERROR(503, "標的金額不一致") ; 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: 授權配置
              * @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: 認證配置 
              * @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

          前端代碼

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

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

          運行截圖如下
          在這里插入圖片描述
          在這里插入圖片描述

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

          整合驗證碼

          驗證碼部分包含兩個API接口

          /user/testKaptcha 獲取驗證碼信息
          /user/verifyKaptcha 校驗

          其中獲取驗證碼圖片信息相當于請求靜態圖片資源,直接將驗證碼圖片的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

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

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

          登錄、權限校驗、登出效果如下

          登錄

          登錄首先會驗證 驗證碼的正確性,登陸成功進入主界面

          驗證碼錯誤如下:
          在這里插入圖片描述
          用戶名密碼錯誤如下:
          在這里插入圖片描述
          登陸成功后請求校驗角色 校驗成功
          在這里插入圖片描述請求校驗權限 校驗成功
          在這里插入圖片描述

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

          再次校驗權限,報出異常

          在這里插入圖片描述


           藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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


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

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          SpringBoot + Spring Cloud +Vue 管理系統前端搭建(二、visual studio code開發前端項目)

          前端達人

          我們打開visual studio code , 選擇文件------------->將文件夾添加到工作區,導入我們的項目

           

          安裝Element

          導入后,我們安裝以下element

          官網:https://element.eleme.cn/#/zh-CN/component/installation

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

          安裝完成后,我們在main.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個頁面:Login.vue、Home.vue、404.vue。

          頁面內容類似:

          <template>

          <div class="page">

          <h2>Login Page</h2>

          </div>

          </template>

           

          <script>

          export default {

          name: 'Login'

          }

          </script>

          配置路由

          打開router/index.js,添加3個路由分別對應主頁、登錄、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

          }

          ]

          })

          配置完后啟動項目,在瀏覽器訪問測試

          http://localhost:8080/#/

          http://localhost:8080/#/login

           

          http://localhost:8080/#/404

          說明我們的配置已經生效了

          安裝scss

          安裝依賴:

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

          安裝的時候注意對應版本,版本不對應,啟動會報錯

          安裝后修改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>失聯</em>啦 ...</p>

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

          <el-button type="primary" class="not-found-btn-gohome" @click="$router.push('/')">進入首頁</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頁面,進行一個簡單的測試

          <template>

          <div class="page">

          <h2>Home Page</h2>

          <el-button type="primary" @click="testAxios()">測試Axios調用</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>

          可以看到我們的請求已經成功了

          安裝Mock.js

          為了模擬后臺接口提供頁面需要的數據,引入mock.js

          安裝依賴:npm install mockjs -dev

          安裝完成,在src新建一個mock目錄,創建mock.js,在里面模擬兩個接口,分別攔截用戶和菜單的請求并返回相應數據。

          import Mock from 'mockjs'

           

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

          'name': '@name', // 隨機生成姓名

          'name': '@email', // 隨機生成郵箱

          '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,在頁面添加兩個按鈕,分別觸發用戶和菜單請求。成功后彈出返回結果

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

          Home.vue

          <template>
            <div class="page">
              <h2>Home Page</h2>
              <el-button type="primary" @click="testAxios()">測試Axios調用</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/#/

          點擊獲取用戶信息

          點擊獲取菜單信息

          可以看到我們已經得到響應數據,這樣mock就集成進來了

          看完記得點贊哦

            藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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


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

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務


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

          seo達人

          今天彩云就跟大家分享一些Dribbble上,我這些年一直珍藏的10位圖標設計大佬們,我建議你一定要收藏學習。

           

          1、Scott Tusk

          https://dribbble.com/Tusk

          首先推薦的就是這位大佬了,他在Drbbble上堅持了365天打卡練習,每天更新一張高質量圖標或者矢量小插圖設計,圖形簡單好看,非常值得借鑒和臨摹練習。

          圖片

          圖片

          圖片

          2、Dmitri Litvinov

          https://dribbble.com/dmitrilitvinov

          一個在圖標設計上非常有造詣的自由設計師,他在圖標的造型和風格一致性上做的非常好,而且能看出來他的作品大部分都是能落地的稿子,值得學習。

          圖片

          圖片

          圖片

           

          3、Paulius Kairevicius

          https://dribbble.com/kairevicius

          這位大神在設計圖標Logo的時候擅長用嚴謹的比例,而且他會把他的作圖過程和輔助線放出來,我覺得從這些作品中可以學到很多設計的思路,推薦給大家。

          圖片

          圖片

          圖片

          圖片

           

          4、Justas Galaburda

          https://dribbble.com/jucha

          這些大神的作品喜歡加噪點,很有自己的風格特點,圖標都做的比較可愛。如果是做些偏萌系的設計,包括一些小表情之類的可以參考他的作品了。

          圖片

          圖片

          圖片

           

          5、Martin David

          https://dribbble.com/srioz

          專業的圖標設計師,在圖標設計這個領域相當專注,看他的個人主頁幾乎全是圖標的設計,以商業圖標設計居多。做項目的時候,非常值得參考了。

          圖片

          圖片

          圖片

           

          6、Myicons

          https://dribbble.com/lineicons

          這位其實是一個圖標平臺的賬號,會定期更新大量的圖標資源,把它收藏起來當成靈感庫還不錯。

          圖片

           

          7、Eddie Lobanovskiy

          https://dribbble.com/lobanovskiy

          這位大佬(也可能是一個團隊賬號)非常的全面,不僅僅只是在圖標領域,在3D、插畫、品牌、網頁、UI都頂級優秀。我個人非常喜歡他在圖標這塊的創意,能看到他展示了很多圖形的方案,過程稿,我覺得可以學習到很多,比如用到自己的作品集展示中,就很實用了。

          圖片

          圖片

          圖片

          圖片

           

          8、Eddy Gann

          https://dribbble.com/Ed117

          這位大佬非常擅長動態圖標的設計,他做的圖標動效并不夸張,但卻是非常容易的落地到實際項目中。在動效創意如此流行的今天,他的這些作品一定可以給你提供靈感,專注在圖標動效上的作品并不多見,值得收藏。

          圖片

          圖片

          圖片

           

          9、Zach Roszczewski

          https://dribbble.com/ZachRoszczewski

          這位大佬在圖標的多種風格方面把握的都比較好,想要同時看多種風格搭配的可以收藏了。

          圖片

          圖片

          圖片

           

          10、Evgenii Dolgov

          https://dribbble.com/numicor

          最后推薦一位矢量風格圖標設計大神,他的作品風格獨特,擅長在圖標上疊加很多插畫形式的明暗紋理,形式感比較強,值得學習。

          圖片

          圖片

          圖片

           

          總結

          文章中列出來的這些是我從關注列表中再三篩選出來的比較有代表性的圖標設計大神,在我的工作學習過程中,他們給了我很多的靈感。當然,這份推薦名單只是我自己的個人喜好,無關粉絲數量,排名也不分先后。

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

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

          最后,對于圖標設計本身,最重要的還是要保持練習,多看多做才能真正提升

           

          原文地址:彩云譯設計(公眾號) 作者:彩云Sky

          轉載請注明:學UI網》講真,我從這些講真,我從這些Dribbble頂尖圖標大神的作品中學到很多,建議你一定要看看

           

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          微信圖片_20210513163802.png

           

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

           

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務


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

          seo達人

           

          優秀的設計師不僅要會設計,更要會包裝。經過設計師精心包裝的設計作品,總是更容易被甲方接受,經過精心包裝的作品集,自然也更受招聘公司的青睞。通過對國外優秀UI設計作品的歸納,以下總結出了下面三種UI作品的展示方法,希望能對大家有些幫助。

           

          01.錯位平鋪

          平鋪展示是最簡單粗暴的展示方法,很容易讓你的作品顯得枯燥乏味??梢詫㈨撁孢M行簡單的錯位處理,讓版式更靈動,畫面外的部分也會給人以想象的空間,讓面試官覺得整個作品豐富且龐大,是最為穩妥的展示方法。

          圖片

          圖片

          圖片

          圖片

           

          02.模塊分離

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

          圖片

          圖片

          圖片

          圖片

           

          03.組件化展示

          UI設計師們對整體風格的把控能力越來越重要,這關乎你能否獨立負責整個項目,所以在作品集中展示你的組件庫尤為重要。組件是否能方便的復用,各個組件是否能保持風格的統一,這些都會對你面試更高級的設計師有很大幫助。

          圖片

          圖片

          圖片

          圖片

           


           藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

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


          文章來源:深海公眾號   作者:深海

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務




          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合