




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
在線音樂(lè)網(wǎng)站的設(shè)計(jì)與實(shí)現(xiàn) 摘要平臺(tái)的困難,Web網(wǎng)站作為運(yùn)行的軟件,通過(guò)它諸多新特性實(shí)現(xiàn)了跨平臺(tái)的運(yùn)行使得開(kāi)發(fā)成本大大降低,而web更加隨心所欲地獲取自己的音樂(lè)信息。本次設(shè)計(jì)是基于Vue的在線音樂(lè)網(wǎng)站。
本次設(shè)計(jì)采用了Vue以s發(fā)模式,使用了MVVM架構(gòu)的Vue實(shí)現(xiàn)前端的數(shù)據(jù)綁定以及展示,在網(wǎng)絡(luò)交互的方面上充分使用x的技術(shù)來(lái)實(shí)現(xiàn)與后端Node服務(wù)端交互,而本地?cái)?shù)據(jù)庫(kù)采用了MongoDB非關(guān)系數(shù)據(jù)庫(kù),在最終完成的作品中實(shí)現(xiàn)流行的n認(rèn)證登錄,以及歌單的收藏和取,高性能的網(wǎng)站響應(yīng),以及歌曲播放歷史,歌曲播放,歌曲排行榜,新歌專輯推薦歌手信息獲取,和用戶管理的前后端分離Web系統(tǒng)。本次設(shè)計(jì)Web在音樂(lè)網(wǎng)站雖然功能并不太完善,但是使用到的諸多技術(shù)包括Web網(wǎng)絡(luò)編程,數(shù)據(jù)庫(kù)編程,以及前端架構(gòu)使用和前后端分離的開(kāi)發(fā)思想是具有一價(jià)值的。關(guān)鍵詞:Web;音樂(lè)網(wǎng)站;前后端分離;數(shù)據(jù)庫(kù)編程;Vue框架;
Abstract,moremoreby,,web
,manynewmmakes,web
o,moreVue
n,mode,MVVMVue,ANode,MongoDB,,,and,,,newalbum,,managementWeb,,,Keywords:
目錄1緒論61.1WEB1.2在線音樂(lè)網(wǎng)站的特點(diǎn)及研究意義62總體設(shè)計(jì)7.1首頁(yè)模塊72.2.2詳細(xì)信息模塊72.2.3播放模塊82.2.4用戶模塊82.3系統(tǒng)框圖93VSCODE3.1.2POSTMEN3.2開(kāi)發(fā)技術(shù)介紹103.2.1VUE3.2.2JSON3.2.3MONGODB3.2.4MVVM44.2最新專輯模塊的實(shí)現(xiàn)134.2.1最新專輯的展示頁(yè)14
播放列表傳值的實(shí)現(xiàn)194.4熱門歌手模塊的實(shí)現(xiàn)204.4.2歌手詳細(xì)頁(yè)的實(shí)現(xiàn)214.5用戶中心模塊的實(shí)現(xiàn)234.5.1用戶注冊(cè)功能的實(shí)現(xiàn)234.5.2用戶登錄功能的實(shí)現(xiàn)2.45軟件測(cè)試325.1用戶注冊(cè)功能測(cè)試325.2用戶登錄功能測(cè)試325.3用戶個(gè)人信息功能測(cè)試335.4首頁(yè)模塊測(cè)試335.5搜索功能模塊測(cè)試345.6詳細(xì)頁(yè)模塊測(cè)試355.7播放功能模塊測(cè)試366參考文獻(xiàn)38謝辭39附錄40
b1990年Tim以HTML為開(kāi)發(fā)基礎(chǔ)完成了最初的Web服務(wù)器,其后他在1991了Web的概念,直到1994年萬(wàn)維網(wǎng)聯(lián)盟(WorldWideWebConsortium)即W3C立標(biāo)志了萬(wàn)維網(wǎng)的面世。目前實(shí)現(xiàn)前后端分離的關(guān)鍵即是異步數(shù)據(jù)交互技術(shù)Ajax即“JavascriptAndXML”和重要的基礎(chǔ)框JavaScrip為后續(xù)Jquery,YU實(shí)現(xiàn)提供了基礎(chǔ),這兩項(xiàng)技術(shù)正We系統(tǒng)發(fā)展的“鐵器時(shí)代”,到了應(yīng)用。但是由于標(biāo)準(zhǔn)的不統(tǒng)一使得發(fā)生了兩次瀏覽器大戰(zhàn),于是W3C組織在10月28日,W3C正式發(fā)布HTML5.0推薦標(biāo)準(zhǔn),即H5。而例如Node.js、JSON端MVVM框架、、移動(dòng)Web、混App、則web“現(xiàn)代化時(shí)代”。2在線音樂(lè)網(wǎng)站的特點(diǎn)及研究意義隨著互聯(lián)網(wǎng)的發(fā)展,人們?cè)缫褵o(wú)法離開(kāi)網(wǎng)絡(luò),而在年輕人中有著不少熱愛(ài)群體,他們熱愛(ài)與人分享自己喜愛(ài)的音樂(lè),分享自己對(duì)音樂(lè)的感受和想法,而現(xiàn)在大的音樂(lè)網(wǎng)站想要使用完全的云服務(wù)都要下載客戶端,并且由于在版權(quán)競(jìng)爭(zhēng)的作用下,多的廠商花費(fèi)資金去購(gòu)買版權(quán)而忽視了一些云服務(wù),以及前端排版的更新問(wèn)題,且傳的頁(yè)面相對(duì)于Vue的單頁(yè)面富應(yīng)用的特性有著先天的弱勢(shì),導(dǎo)致了挺多存在的操作不便,繁瑣,加載時(shí)間長(zhǎng)等諸多不利因素,為了避免這種問(wèn)題應(yīng)運(yùn)而生。目前國(guó)內(nèi)擁有最大的手機(jī)用戶群體,且作為比較新興的前端技Vue的單頁(yè)富程序十分多,它不僅可以對(duì)移動(dòng)端進(jìn)行開(kāi)發(fā),以往人們想在別人的電腦上的歌需要一首一首搜索,這樣做十分耗時(shí),于是本項(xiàng)目就在于實(shí)現(xiàn)云端記錄用戶歌單歷史和歌曲資源以及用戶評(píng)論,讓音樂(lè)更加貼近我們。本項(xiàng)目是基于Node.js前端:Vue,Vuex,VueRouter,開(kāi)發(fā)的在線音樂(lè)網(wǎng)站讓用戶能夠輕松快速的聽(tīng)上的音樂(lè)。P端更是有著眾多大廠使用它。這是使得本身就需要把資源放在音樂(lè)上的在線音樂(lè)應(yīng)用可以有更高的效率去運(yùn)行。最大程度地復(fù)用可以讓它有更多的實(shí)現(xiàn)高品質(zhì)音樂(lè)的傳輸,并且音樂(lè)網(wǎng)站的交互可以使小范圍的用戶更多的交流,可以變?nèi)藗冊(cè)谛畔鞑ド系谋粍?dòng)。
22.1并且支持對(duì)收聽(tīng)歷史,歌曲,歌單收藏并對(duì)自己的信息進(jìn)行管理。1)獲取音樂(lè)信息(包括推薦歌單、推薦榜單、推薦歌手)的瀏覽;2)用戶能夠收藏自己喜歡的歌單以及音樂(lè);3)用戶可以在自己的收藏界面中獲取已經(jīng)收藏的歌單,并可以進(jìn)行瀏覽收藏的歌單。4)用戶可以在系統(tǒng)中注冊(cè)并上傳個(gè)人頭像,注冊(cè)完成后可使用賬號(hào)登錄。5)用戶登錄后開(kāi)放收藏,收聽(tīng)歷史等使用權(quán)限。2.2方案論證首頁(yè)分為三個(gè)部分,頭部導(dǎo)航欄,中部?jī)?nèi)容,以及尾部。.本次設(shè)計(jì)的音樂(lè)網(wǎng)站首頁(yè)為響應(yīng)式主頁(yè),頭部導(dǎo)航欄以及中部?jī)?nèi)容顯示都使用了CSS3媒體查詢(@mediaMediaQueries)方式實(shí)現(xiàn)響應(yīng)式的展示。頭部導(dǎo)航欄期的路由位置,選擇對(duì)應(yīng)的標(biāo)簽給予高亮,但是在低分辨率下即手機(jī)等設(shè)備下瀏覽的話高亮路由標(biāo)簽列表以及搜索欄將隱藏,轉(zhuǎn)而顯示一個(gè)下拉按鈕,變?yōu)轭愃葡吕藛蔚娘@示模式以適應(yīng)低分辨率下的展示。中部推薦內(nèi)容部分采用Vue組件封裝好,一共有四種類型,首先是首頁(yè)輪播圖,播圖也采用響應(yīng)式實(shí)現(xiàn),信息皆是由進(jìn)入首頁(yè)時(shí)候Vue的create生命周期通過(guò)請(qǐng)求并發(fā)從后端獲取的信息若網(wǎng)絡(luò)請(qǐng)求有誤將隱藏信息內(nèi)容,首先展示的是每日隨機(jī)推薦,最新的專輯,再是流行歌手,最后是熱門榜單的推薦,點(diǎn)擊分別能進(jìn)入隨機(jī)面,專輯的詳細(xì)頁(yè),歌手的詳細(xì)頁(yè),榜單的詳細(xì)頁(yè)或是直接播放。詳細(xì)信息模塊詳細(xì)信息模塊由歌曲詳細(xì),歌手詳細(xì),榜單詳細(xì),專輯詳細(xì)構(gòu)成。
詳細(xì)頁(yè)都有頭部和尾部組成,頭部采fle布局,自適應(yīng)寬度,由信息頁(yè)的決定頭部圖片的內(nèi)容,進(jìn)入頭部也時(shí)會(huì)在created生命周期中后去Vue的$routeparam參數(shù),部分的頁(yè)面需要有分頁(yè)操作所以會(huì)在創(chuàng)建時(shí)初始化并且通過(guò)aiox問(wèn)對(duì)應(yīng)的后端API去獲取信息并展示數(shù)據(jù),由于有部分頁(yè)是分頁(yè)的,而Vue虛擬Dom特性必須要im標(biāo)簽ke提dif算法的性能,否則會(huì)出現(xiàn)圖片閃回的情況,為
了避免這種情況的發(fā)生,大部分是圖片都是采用的懶加載并且會(huì)將url地址綁定為出版日期,類型,以及歌曲列表,并且會(huì)添加路由跳轉(zhuǎn)形成回環(huán)。播放模塊播放模塊由播放器以及播放列表構(gòu)成播放頁(yè)面包括有歌詞的滾動(dòng)顯示,用戶可以通過(guò)點(diǎn)擊播放按鈕實(shí)現(xiàn)暫停和繼續(xù)播鈕控制播放的音量大小,還能通過(guò)隨機(jī)播放按鈕以及單曲循環(huán)等選擇自己想要的播放模式。進(jìn)度條提供拖動(dòng)改變以及點(diǎn)擊改變,通過(guò)監(jiān)audi標(biāo)簽ontimeupdat行監(jiān)聽(tīng)實(shí)現(xiàn)播放時(shí)間的實(shí)時(shí)更改以及歌曲的長(zhǎng)度時(shí)間。移動(dòng)端播放模塊實(shí)現(xiàn)圖如下:4用戶模塊系統(tǒng)用戶模塊的主要功能有用戶的注冊(cè)和登錄、對(duì)個(gè)人信息的管理、用戶對(duì)收藏信息的管理。注冊(cè)登錄是用戶信息記錄的基礎(chǔ)功能,收藏音樂(lè),收藏歌單,必須在用戶在登錄狀態(tài)下才能使用,否則將跳轉(zhuǎn)至登錄頁(yè)面進(jìn)行登錄。注冊(cè)功能可以自行上傳圖片作為頭像并且可以設(shè)置自己的昵稱,等。
登錄后用戶可以進(jìn)入個(gè)人中心查看到收藏以及歷史信息,以實(shí)現(xiàn)多平臺(tái)都能夠共享播放過(guò)的數(shù)據(jù),并且登錄狀態(tài)會(huì)將服務(wù)端返回的Token暫時(shí)放存放在本地,以至于使其維持登錄狀態(tài)。
信息等功能。歌單,以實(shí)現(xiàn)多平臺(tái)的數(shù)據(jù)共享。下圖為本設(shè)計(jì)的在線音樂(lè)網(wǎng)站的功能模塊圖:圖VscodeVsCode的全稱是VisualStudioCode,是微軟于2015代化輕量級(jí)代碼編輯器。VsCode很多的插件可以使用和開(kāi)發(fā),而有由于前端技術(shù)迭代十分的快速,使得開(kāi)發(fā)者的使用各種框架和工具,VsCode的插件生態(tài)就使得這一個(gè)程序就可以完成各種各樣的開(kāi)
發(fā)任務(wù),插件由開(kāi)發(fā)者發(fā)布也是因?yàn)槿绱税l(fā)布的插件可以讓開(kāi)發(fā)者提高開(kāi)發(fā)效率。3.1.2Postmann是款強(qiáng)大網(wǎng)頁(yè)調(diào)試工具的客戶端,n為用戶提供強(qiáng)大的WebAPI&HTTP請(qǐng)求調(diào)試功能。它能夠修改p頭部,帶自定義的,修改,使用、、、等p請(qǐng)求并且能夠?qū)y(cè)試集合保存,并提供JSON數(shù)據(jù)的高亮解析以方便開(kāi)發(fā)者了解數(shù)據(jù)結(jié)構(gòu)。在本次設(shè)計(jì)中,各類接口的調(diào)試都是通過(guò)n進(jìn)行的。3.2開(kāi)發(fā)技術(shù)介紹3.2.1VueVue框架是一個(gè)用于構(gòu)建前端的漸進(jìn)式框架,它和很多大型開(kāi)發(fā)框架不同,它可以讓你的項(xiàng)目一部分使用Vue并且它使得原來(lái)前端開(kāi)發(fā)的既要關(guān)注視圖又要關(guān)注DOM操作的開(kāi)發(fā)模式轉(zhuǎn)變成了關(guān)注數(shù)據(jù)的開(kāi)發(fā)模式,使得上手更加的輕松以及開(kāi)發(fā)時(shí)間的大大減。還十分有利于第三方庫(kù)的整合和混入,Vue完全能夠?qū)崿F(xiàn)復(fù)雜SPA(singlepagewebapplication)的運(yùn)作,它提供了數(shù)據(jù)的雙向綁定,前端路由配置,項(xiàng)目的編譯壓縮等一系列功能。Vue十分出名的所謂“全家桶”即開(kāi)發(fā)者十分快速的完成項(xiàng)目,總結(jié)起來(lái)就是:1.項(xiàng)目構(gòu)建工具、2.路由配置、3.息管理、4.http請(qǐng)求庫(kù)。3.2.2JSON簡(jiǎn)介JSON是一種數(shù)據(jù)交換格式。與XML用途相似但比起XML,使用JSON來(lái)書(shū)寫數(shù)據(jù)儲(chǔ)和傳輸有著明顯的優(yōu)勢(shì)。JSON的可讀性和編寫的特性都要優(yōu)于XML,并且由于其形式JavaScrip中的對(duì)象十分相似,并JavaScrip中也封裝JSO方法可以進(jìn)和對(duì)象的輕松轉(zhuǎn)換。使得如今各種后端接口基本都是以jso形式傳播數(shù)據(jù),這些都是讓JSON成為更加優(yōu)先的數(shù)據(jù)交換語(yǔ)言格式。總而言之,JSO的可讀性和編碼解碼程度以及網(wǎng)絡(luò)資源占用方面,并且使用起來(lái)非
常方便使得如今的開(kāi)發(fā)中前后端分離項(xiàng)目數(shù)據(jù)交互基本都是使用JSON的。3.2.3MongoDB簡(jiǎn)介MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù),它多大用Web應(yīng)用中,它最
的特點(diǎn)就是非關(guān)系型,且部署十分快速方便,mongoos插件就是異步環(huán)境下對(duì)MongoDB以JSON對(duì)象形式儲(chǔ)存工具使得MongoDB在Web應(yīng)用中十分常見(jiàn)。3.2.4MVVM設(shè)計(jì)模式簡(jiǎn)介MVVM是Model-View-ViewModelM即Model是指數(shù)據(jù)模型,數(shù)據(jù)模型是程序設(shè)計(jì)時(shí)的數(shù)據(jù)結(jié)構(gòu);V指的是View,它是指頁(yè)面布局正是我們通俗的網(wǎng)頁(yè),它負(fù)責(zé)將數(shù)據(jù)展示給用戶并且處理數(shù)據(jù)交互的層面;V指的是ViewModel,負(fù)責(zé)w與Modl的數(shù)據(jù)連接,與更新。
自從MVVM出現(xiàn)VM就更多的抽離了原本屬C中的業(yè)務(wù)邏輯,MVVM主要解決了MVC中大量的DOM操作使頁(yè)面渲染性能降低,加載速度變慢,影響用戶體驗(yàn)當(dāng)和Model頻繁發(fā)生變化,開(kāi)發(fā)者需要主動(dòng)更新到View。
4系統(tǒng)具體設(shè)計(jì)與實(shí)現(xiàn)1首頁(yè)的響應(yīng)式布局的實(shí)網(wǎng)站首頁(yè)作為了解一個(gè)網(wǎng)站內(nèi)容的初始是十分關(guān)鍵的一個(gè)頁(yè)面,并且由于此次在音樂(lè)網(wǎng)站的多平臺(tái)特性,需要使得首頁(yè)在各個(gè)設(shè)備下都能夠正常的瀏覽,通常有幾個(gè)現(xiàn)的方式。1:運(yùn)Nginx(一個(gè)高性能HTT和反向代we服務(wù)器)識(shí)Htt請(qǐng)求useragent獲取用戶的設(shè)備類型從而重定向到移動(dòng)端web地址去,或者到Pc端的地址上。2:寫兩套Css樣式文件和兩套Dom界面加載在同一個(gè)頁(yè)面里并用onresize方監(jiān)聽(tīng)頁(yè)面的實(shí)時(shí)變化,并且使用CSS3中的媒體查詢判斷不同屏幕尺寸下顯示哪一套dom,不顯示的Dom會(huì)使用display:none去隱藏。3:寫兩套CSS文件,但是只些一套Dom,在Vue的created的函數(shù)中添加對(duì)進(jìn)行監(jiān)聽(tīng),并通CSS的媒體查詢將不同屏幕尺寸下的樣式導(dǎo)入Do中,可以減少Dom元素的渲染也可以增加開(kāi)發(fā)效率,但是這樣也使得樣式文件分類要的控制,否則后續(xù)修改會(huì)后比較麻煩的地方,所以通用的媒體查詢樣式類似版心等就單獨(dú)抽離成一個(gè)common.css文件以便后續(xù)更新改動(dòng)。首頁(yè)輪播圖由于也采用響應(yīng)式變化,要使用過(guò)Ref獲取圖片的高度然后賦給輪播圖window.onresize=()=>{ this.imgHeight=this.$refs.imgHeight[0].offsetHeight+"px";
};
setBannerHeight(){ if(document.body.clientWidth<768){
this.imgHeight="350px"; }elseif(document.body.clientWidth<1200){
this.imgHeight="500px"; }else{ this.imgHeight="720px"; } }
圖4.1PC
圖4.2移動(dòng)端首頁(yè)最新專輯模塊的實(shí)現(xiàn)最新專輯的展示頁(yè)由兩個(gè)部分組成:專輯列表,以及底部的分頁(yè)按鈕。專輯列表使用與bootstrap類似的柵格布局實(shí)現(xiàn)的響應(yīng)式布局,首先在大于屏幕寬度的情況下,一行列表會(huì)顯示4個(gè)專輯,大于992px小于1200px顯示3于767px小于992px會(huì)顯示2個(gè)專輯,而小于767p且專輯的圖片因?yàn)橹挥袌D片會(huì)顯得比較單薄,所以img-bo下使用了定位relative;然后再子元素中使用自然。實(shí)現(xiàn)的效果如圖所示:
圖4.3專輯列表實(shí)現(xiàn)圖最新專輯的顯示頁(yè)面數(shù)據(jù)獲取的途徑是在其頁(yè)面生成式發(fā)起Http并且這個(gè)異步請(qǐng)求我使用asynawai進(jìn)行封裝,AP接口封裝到統(tǒng)一的文件API.js中進(jìn)行統(tǒng)一管理,并采用注入式baseurl的方式進(jìn)行管理,以方便或許會(huì)發(fā)生的
Api地址改變,并且在獲取到后端返回的JSON數(shù)據(jù)時(shí)會(huì)提前進(jìn)行數(shù)據(jù)的篩選,并將有用的數(shù)據(jù)進(jìn)行返回,無(wú)用的不返回,這樣可以大大的節(jié)省需要保存的數(shù)據(jù),近一步的提高
SPA的性能。封裝并且數(shù)據(jù)篩選的方法:exportasyncfunctiongetNewAlbums(offset,limit){
constresult=awaitaxios({url:HOST+"/top/album",method:"GET",params:{offset,limit},});if(result.status===200){letalbums=result.data.albums.map((item)=>{
letalbum={}; album.id=item.id; =; album.picUrl=item.blurPicUrl; album.singer=item.artists.map((item)=>).join("/");
album.alias=item.alias; returnalbum;});returnresponse(result.status,albums);}
returnresponse(result.status,[]);
}分頁(yè)功能使用了elementUi中的el-pagination其中current所在的分頁(yè),在頁(yè)面初始化時(shí)候會(huì)使用獲取URL的頁(yè)面值,并且再通aja請(qǐng)求去獲取當(dāng)頁(yè)的數(shù)據(jù),并且保存在一個(gè)數(shù)組中,而在下內(nèi)引用而不需要再次通aja請(qǐng)求獲取使得服務(wù)器壓力大大減小,而且也優(yōu)化了前端的用戶體驗(yàn)不需要頻繁的發(fā)出網(wǎng)絡(luò)請(qǐng)求。由于Vue的虛擬dom比對(duì)算法Diff算法的性能問(wèn)題,會(huì)使得頁(yè)面切換后img的Src沿用此前的Src會(huì)使得頁(yè)面的圖片切換不統(tǒng)一或者說(shuō)切換混亂,所以頁(yè)面的img會(huì)key屬性,以提高Diff算法的能力,并且在全局使用懶加載的形式加強(qiáng)前端的新有瀏覽到的圖片不加載以實(shí)現(xiàn)更好的用戶體驗(yàn)。4.2.2最新專輯詳情頁(yè)的實(shí)現(xiàn)最新專輯詳情頁(yè)由頭部的專輯信息、播放全部按鈕、列表信息,右側(cè)的簡(jiǎn)介顯示欄,
以及底部的云音樂(lè)的評(píng)論信息。最新專輯詳細(xì)頁(yè)的信息由路由開(kāi)始,首先采用動(dòng)態(tài)路由實(shí)現(xiàn)詳細(xì)詳細(xì)頁(yè)create生命周期中獲取路由param信息即在其他頁(yè)面跳轉(zhuǎn)到詳細(xì)候會(huì)將專輯的ID當(dāng)做params的一部分,然后到了最新專輯詳細(xì)頁(yè)的created周期候就會(huì)獲取這個(gè)ID再通過(guò)已經(jīng)封裝好的內(nèi)容去調(diào)用獲取信息的方法。由于Vue虛擬dom渲染的機(jī)制問(wèn)題,如果data中沒(méi)有對(duì)應(yīng)的信息就會(huì)報(bào)錯(cuò)模板渲染的dom前加上了v-if判斷,當(dāng)dat中的數(shù)據(jù)部位空時(shí)才會(huì)進(jìn)行渲染于部分專輯的歌曲可能會(huì)有首的原因我采取的是超過(guò)1首以上的默認(rèn)為隱藏ShowMore=false作為控制顯示與否的控制,默認(rèn)為不顯示點(diǎn)擊更多按鈕則會(huì)顯示。并且渲染列表會(huì)通過(guò)使用v-if去判斷v-for中index的數(shù)值是單數(shù)還是雙數(shù)去定單雙行的樣式形式即:class="(index%2==0?'even':'odd'),并且為了使得列表的顯示風(fēng)格更為固定所以列表采用的fle布局,并且為其設(shè)置了固定的百分比寬度并且超出影藏顯示省略號(hào),使得顯示更加的復(fù)合我們的日常使用。并且對(duì)原本數(shù)據(jù)中歌曲長(zhǎng)度僅返回時(shí)間戳形式的轉(zhuǎn)換,并且將其算法封裝成函數(shù)集成到too目moment.j函數(shù)中使得之后的時(shí)間戳格式化有了一個(gè)更方便的轉(zhuǎn)化方式,直接引入該文件調(diào)用方法即可。轉(zhuǎn)換函數(shù):
clock(timeStamp){ letresult=parseInt(timeStamp);
leth= Math.floor(result/3600)<10?"0"+Math.floor(result/3600):Math.floor(result/3600);letm= Math.floor((result/60)%60)<10 ?"0"+Math.floor((result/60)%60) :Math.floor((result/60)%60);lets=Math.floor(result%60)<10?"0"+Math.floor(result%60):Math.floor(result%60);result=`${h}:${m}:${s}`;returnresult;
針對(duì)音樂(lè)資源可能存在的無(wú)版權(quán)的情況,我采取的是在API是否有資源的情況即在訪問(wèn)接口的信息后在data.playlist.tracks.st循環(huán)篩選數(shù)據(jù)并判斷其長(zhǎng)度,如果其長(zhǎng)度不大于0則在返回的數(shù)據(jù)中設(shè)置字段為true,name在template字段中會(huì)對(duì)渲染列表的song.bannertru夠解決不必要的錯(cuò)誤,并且也優(yōu)化了用戶體驗(yàn)。對(duì)于簡(jiǎn)介欄我使用的是element的el-collapse效果使得較長(zhǎng)的簡(jiǎn)介頁(yè)能優(yōu)雅的顯示出來(lái)。并且其還提供了slot(插槽)讓我能夠義的設(shè)置其中的樣式使得展現(xiàn)的效果更加的舒適。實(shí)現(xiàn)的效果如圖所示:
圖34.3.1熱門榜單詳細(xì)頁(yè)的實(shí)現(xiàn)熱門榜單詳細(xì)頁(yè)由榜單選項(xiàng)和榜單內(nèi)容模塊組成。的歌曲列表。
榜單左側(cè)的榜單類型是固定的2的話會(huì)使其高亮,并且將ID存于頁(yè)面的data頁(yè)面時(shí)會(huì)默認(rèn)選擇第一項(xiàng)為選擇狀態(tài)。展示,其中簡(jiǎn)介顯示不超2當(dāng)鼠標(biāo)移入后會(huì)顯示完整的信息,展示歌曲的列表頁(yè)會(huì)分1行顯示,如果榜單的歌曲數(shù)量超過(guò)15行則榜單最下方會(huì)出現(xiàn)一個(gè)更多的按鈕以便添加接下來(lái)15行,這樣減少分頁(yè)造成的白頁(yè)問(wèn)題提高用戶體驗(yàn)。頁(yè)面初始化時(shí)會(huì)先加載
并保存在data的currentRankData中,并且data中還有儲(chǔ)存finished字段以用來(lái)識(shí)別榜單是否已經(jīng)加載完了,而真正顯示在dom的內(nèi)容是從ShowDate每次點(diǎn)擊更多按鈕就會(huì)將currentRankData接下來(lái)的15個(gè)concat到ShowDate由于Vu的數(shù)據(jù)綁定特性,必須使用變異方法才能使得數(shù)組數(shù)據(jù)類型改變的時(shí)候觸發(fā)Vue視圖的更新,所以這里選擇用concat方法使得數(shù)組改變就觸發(fā)Vue視圖更新做到類似分頁(yè)的效果。并且只要頁(yè)面不在頂部就有會(huì)展示一個(gè)返回頂部的按鈕在右下角以便快速的返回頂部。實(shí)現(xiàn)的效果如圖所示:圖4.3.2播放列表傳值的實(shí)現(xiàn)由于播放列表是在不同的頁(yè)面中都需要的共同數(shù)據(jù),所以需要在不同的頁(yè)面中都能修改和獲取,實(shí)現(xiàn)方式有幾種,
1:使用localstorage儲(chǔ)存,并且在需要的頁(yè)面中獲取來(lái)使用,但是由于localstorage沒(méi)有過(guò)期的限制所以出現(xiàn)了個(gè)問(wèn)題就是數(shù)據(jù)的持久化控制變得不那么方便了。
2:使用sessionstorege存儲(chǔ),相比localstorage而言,sessionstorege存在會(huì)話局限性,雖說(shuō)都是可行但是相對(duì)于Vuex存儲(chǔ)也存在著劣勢(shì)。所以最終決定使用Vuex的方式存儲(chǔ)和傳值,使得Vue單頁(yè)應(yīng)用中各種頁(yè)面都能夠很輕松的獲取到列表,并且還可以在列commi方法中引用儲(chǔ)存歷史的方法,使得每次更改播放列表的時(shí)候都能講播放歷史提交到服務(wù)端實(shí)現(xiàn)這個(gè)播放歷史存儲(chǔ)的功能。具體commit代碼如下:setPlaylist(state,{data}){
state.playList=data; if(state.User_info!==null){
updateHistory(data,state.User_info.id);
}}移動(dòng)端播放模塊實(shí)現(xiàn)如下:圖4.4.1熱門歌手列表頁(yè)的實(shí)現(xiàn)熱門歌手列表頁(yè)由歌手類型的選擇列表和熱門歌手展示列表組成。頭部為熱門歌手的類型選擇列表,fle的橫向布局形成,可換行,并且有高亮顯示,它們是由固定的長(zhǎng)度1的數(shù)組組成的數(shù)據(jù),在頁(yè)面初始化時(shí)默認(rèn)選擇華語(yǔ)男
歌手,并且該頁(yè)面才用seesionstorag選的熱門歌手類型以及分頁(yè)的頁(yè)數(shù),因?yàn)樗鼈兌纪ㄟ^(guò)seesionstorag了起來(lái),在created函數(shù)內(nèi)會(huì)進(jìn)行初始化。頁(yè)面的頭部是一張眾多歌手的背景圖,標(biāo)題和副標(biāo)題都采fle中,沒(méi)有采im標(biāo)簽的形式去展示背景圖,而是采用backgroun圖的大小以及鋪張類型以達(dá)到最佳的展示效果。并且列表與此前的諸多列表類似都采用了懶加載+柵格布局+key換沒(méi)有閃屏的情況,考慮標(biāo)簽內(nèi)的圖片寬度問(wèn)題,也采用了padding使得內(nèi)容不據(jù)整ite而外部添加margi使ite間的距離不至于過(guò)近使得視覺(jué)效果更加舒適而歌手的名字和圖片都添加了歌手詳細(xì)頁(yè)的路由跳轉(zhuǎn)以保證操作的流程。底部默認(rèn)的是分頁(yè)欄,默認(rèn)的是每個(gè)類型的歌手共10名,每2名為5頁(yè),分頁(yè)到了1或5時(shí)都會(huì)有禁止點(diǎn)擊上一頁(yè)和下一頁(yè)的提示。實(shí)現(xiàn)的效果如圖所示:圖74.4.2歌手詳細(xì)頁(yè)的歌手詳細(xì)頁(yè)由歌手的信息展示,以及歌手的熱門歌曲Top50組成。
頁(yè)面使用組件化,將頁(yè)面終端的內(nèi)容抽取成一個(gè)組件當(dāng)父頁(yè)面初始化時(shí)候會(huì)在中獲取到歌手的id再將id傳到組件上,在歌手顯示組件內(nèi)有使用一個(gè)ID執(zhí)行一個(gè)的并發(fā)請(qǐng)求同時(shí)獲取歌手信息和歌手熱門歌曲Top50的歌曲信息并且在回。使得原本需要在Vue頁(yè)面寫的數(shù)據(jù)整合操作都可以在API文件中集中處理對(duì)
統(tǒng)的維護(hù)十分友好,也更好的貫徹前后端分離的思想。Api封裝的代碼如下:exportasyncfunctiongetSingerByid(id){constresult=awaitaxios({ url:HOST+"/artists", method:"GET", params:{id},});if(result.status===200){ letartist={ id:result.data.artist.id, picUrl:result.data.artist.picUrl, name:, desc:result.data.artist.briefDesc,
albumSize:result.data.artist.albumSize,
musicSize:result.data.artist.musicSize,
mvSize:result.data.artist.mvSize, }; letsonglist=result.data.hotSongs.map((item)=>{
letsong={}; song.id=item.id; song.title=; song.picUrl=item.al.picUrl; song.album=; song.alias=item.alias; song.playTime=moment.clock(item.dt/1000); song.artist=item.ar.map((item)=>).join("/");
song.lrc=`${HOST}/lyric?id=${item.id}`;
.mp3`; song.banned=!!(item.st<=0&&item.fee<=0); returnsong; });
letsinger={artist,songlist};
returnresponse(result.status,singer);}returnresponse(result.status,[]);}圖854.5.1用戶注冊(cè)功能的實(shí)現(xiàn)由于前后端分離的原因,很多實(shí)際開(kāi)發(fā)中已經(jīng)不適用session而更多的使用了Toke的方式去認(rèn)證,并且登錄注冊(cè)信息都通過(guò)aja異步請(qǐng)求發(fā)送。與cookie相比Token有著諸多優(yōu)勢(shì)這也是我選擇使用token一就是支持跨域訪問(wèn),token可作為參數(shù)存在body證,若能通過(guò)則回復(fù)用戶信息,如果過(guò)期則重新從服務(wù)端生成token二就是由于(Android,iOS,小程序等等)類似的常用平臺(tái)不支持cooki所以使得我
們此次多平臺(tái)的web應(yīng)用登錄系統(tǒng)使用的是Token登錄。其三則是非常適用于API使得我們可以和各種后端語(yǔ)言耦合,近一步貫徹前后端分離的思想。forinput的信息進(jìn)行處理,若成功則返回注冊(cè)成功并且轉(zhuǎn)換到頁(yè)面的登錄模式,若已存在就提用戶名已注冊(cè)。注冊(cè)頁(yè)面實(shí)現(xiàn)如下:圖9用戶注冊(cè)頁(yè)實(shí)現(xiàn)
圖0
4.5.2用戶登錄功能的實(shí)現(xiàn)這個(gè)功能是實(shí)現(xiàn)用戶的登錄。登錄頁(yè)面和注冊(cè)頁(yè)面設(shè)計(jì)在同一個(gè)頁(yè)面,但是由一個(gè)狀態(tài)值去控制是登錄模式還是注冊(cè)模式,并且會(huì)對(duì)輸入框進(jìn)行驗(yàn)證,如果輸入的密碼或者同戶名為空都無(wú)法登錄,并且出提示窗顯示登錄失敗,若后端服務(wù)器離線的情況下則提示服務(wù)器連接失敗。并且也是由于前后端分離的緣故,我們使用的依舊是插件進(jìn)行異步提交,若驗(yàn)證正常則服務(wù)端會(huì)返回用戶的信息,通過(guò)判斷用戶的類型字段去選擇跳轉(zhuǎn)到個(gè)人中心還是后臺(tái)的管理中心,管理中心路由僅由此頁(yè)面跳轉(zhuǎn),其他頁(yè)面無(wú)法跳轉(zhuǎn),首次登陸的洪湖后端會(huì)確認(rèn)是否如果會(huì)在本地存儲(chǔ)一
個(gè)n當(dāng)下次進(jìn)入主頁(yè)的時(shí)候就會(huì)直接認(rèn)證,實(shí)現(xiàn)的過(guò)程是在下,這個(gè)n則是調(diào)用了后端的檢測(cè)是否登陸的路由,此路由的作用是檢測(cè)用戶本地是否存在n如果有則調(diào)用后端的檢測(cè)n接口,檢測(cè)n接口會(huì)對(duì)傳來(lái)的接口n使用y方法進(jìn)行解密并且對(duì)比其中的有效期,如果與超出當(dāng)前服務(wù)器的時(shí)間則會(huì)返回一個(gè)0作為狀態(tài)值,那么此時(shí)的前端則會(huì)清除本地存儲(chǔ)的若是n沒(méi)過(guò)期則服務(wù)器會(huì)返回用戶信息表示登錄成功,n方法會(huì)將用戶信息存儲(chǔ)在本地,并且同步到VueX中,使得用戶不需要反復(fù)登錄很大程度上提高了用戶體驗(yàn)。
圖1獲取用戶的收藏列表,獲取用戶的聽(tīng)歌歷史,它們兩個(gè)的數(shù)據(jù)都是在登錄后即通過(guò)異步請(qǐng)求通過(guò)登錄后返回的用戶d信息頁(yè)可以點(diǎn)擊頭像然后重新上傳一個(gè)頭像,前端頁(yè)面會(huì)使用s對(duì)其進(jìn)行壓縮使其大小夠小,然后通過(guò)點(diǎn)按鈕提交,后端會(huì)將文件寫入到本地夾并且將頭像文件的名稱保存在數(shù)據(jù)庫(kù)中,以同步信息。
圖2檢測(cè)用戶登錄并拉取用戶信息的代碼如下:exportconstcheckSign={beforeCreate:function(){ letuser_name=localStorage.getItem("user_name"); lettoken=localStorage.getItem("token"); CheckUser({user_name:user_name,token:token}).then(response=>window.console.log('response===>',response)
if(response.data.status==0){
this.$mit("changeIsSignIn",0);
localStorage.setItem("avatar",'avatar.png');
localStorage.clear();}else{//設(shè)置頭像if(response.data.avatar!=null){
localStorage.setItem("avatar",response.data.avatar);
}else{localStorage.setItem("avatar",'avatar.png');
} //收藏和歷史信息獲取 getPortaldata({token}).then(res=>{
window.console.log(res); if(res.data.status==1){ this.$mit("setUserCollect",res.data.data)
} }) this.$mit("setUserinfo",response.data)
this.$mit("setUsertoken",token)
if(response.data.type==1){
this.$mit("changeIsSignIn",1);//admin
}elseif(response.data.type==2){
this.$mit("changeIsSignIn",2);//游客 } } }) .catch(reject=>{
console.log(reject); });}
};4.5.4用戶收藏列表以及歷史列表的實(shí)現(xiàn)用戶收藏列表這個(gè)功能由兩個(gè)多鐘情況的收藏組成,收藏信息只儲(chǔ)存收藏的類型,和收藏類型i以及時(shí)間,用戶通過(guò)在熱門榜單,最新專輯,熱門歌手頁(yè)面等可以存在收藏按鈕的頁(yè)面點(diǎn)擊收藏后,會(huì)執(zhí)行收藏方法,若是沒(méi)有登錄的用戶會(huì)彈出對(duì)話框提示沒(méi)有登錄,若用戶已經(jīng)成功登錄并且有星湖信息的情況就會(huì)調(diào)用收藏添加接口將信息傳入數(shù)據(jù)庫(kù),而歷史信息的實(shí)現(xiàn)就是當(dāng)歌曲進(jìn)入播放列表后才會(huì)調(diào)用儲(chǔ)存方法,即在歌曲也或者其他播放頁(yè)中將播放列表加Vuex中,經(jīng)過(guò)Vuex儲(chǔ)存的歌曲信息都會(huì)存入歷史數(shù)據(jù)中,并且當(dāng)用戶沒(méi)有登錄的時(shí)候不會(huì)進(jìn)行保存。當(dāng)用戶進(jìn)入個(gè)人中心頁(yè)的時(shí)候會(huì)統(tǒng)一調(diào)用信息獲取接口,獲取用戶的收藏以及歷史的信息統(tǒng)一保存并渲染在個(gè)人中心的選項(xiàng)卡中并完成展示。數(shù)據(jù)庫(kù)用MongoDB的popular聚合展示信息,并且用ref關(guān)聯(lián)
圖3
圖4圖5
5統(tǒng)提示的信息填寫規(guī)范。在本次設(shè)計(jì)中,用戶名長(zhǎng)度在3位以上密碼長(zhǎng)度必須8上。表5.1用戶注冊(cè)模塊測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 成功,跳轉(zhuǎn)登錄通過(guò)用戶名測(cè)試 打開(kāi)注冊(cè)頁(yè) 成功,跳轉(zhuǎn)登錄通過(guò)用戶名用戶名長(zhǎng)度試打開(kāi)注冊(cè)頁(yè) 用戶輸入錯(cuò)誤用戶名格式系統(tǒng)提示“注冊(cè)失敗”不輸入密碼 打開(kāi)注冊(cè)頁(yè) 用戶輸入正常的用戶名和昵稱密碼輸入 打開(kāi)注冊(cè)頁(yè) 用戶輸入正確密碼彈出“有未填寫項(xiàng)”注冊(cè)成功并彈出登錄頁(yè)面登錄成功,登錄成功,并跳轉(zhuǎn)
人中心頁(yè)通過(guò)測(cè)試結(jié)果:100%通過(guò)。
用戶登錄功能測(cè)試表5.2用戶登錄模塊測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 登錄測(cè)試 進(jìn)入登陸界面 用戶輸入正確的用戶名和密碼用戶名驗(yàn)證進(jìn)入登陸界面 輸入錯(cuò)誤的用名,正確的密碼密碼驗(yàn)證 進(jìn)入登陸界面 輸入正確的用名,錯(cuò)誤的密測(cè)試結(jié)果:100%通過(guò)。系統(tǒng)提示登陸失敗系統(tǒng)提示登陸失敗通過(guò)
主要測(cè)試了用戶對(duì)個(gè)人信息的管理。表5.3用戶個(gè)人信息管理測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 進(jìn)入個(gè)人用
中心輸入修改的名字
并點(diǎn)進(jìn)入個(gè)人用
中心輸入修改的名字
并點(diǎn)擊save系統(tǒng)提示“修改
成功”通過(guò)功能系統(tǒng)用戶頭管理進(jìn)入個(gè)人用中心用戶點(diǎn)擊頭像單元格并點(diǎn)save系統(tǒng)提示“設(shè)置成功”登出功能測(cè)試進(jìn)入個(gè)人用中心點(diǎn)擊登出按鈕 登出并返回主頁(yè)低分辨率顯示使用低分辨設(shè)備打開(kāi)網(wǎng)頁(yè)測(cè)試結(jié)果:100%通過(guò)。首頁(yè)模塊測(cè)試查看導(dǎo)航頭不并點(diǎn)擊按鈕系統(tǒng)提示“修改成功查看導(dǎo)航頭部并查看導(dǎo)航頭部并
觀察頭部?jī)?nèi)容顯示詳細(xì)頭部操顯示詳細(xì)頭部操
作通過(guò)主要為了測(cè)試主頁(yè)的響應(yīng)式頭部和并發(fā)接口的數(shù)據(jù)獲取
表5.3用戶個(gè)人信息管理測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 首頁(yè)高分辨率使用高分辨率設(shè)備打開(kāi)網(wǎng)頁(yè)首頁(yè)搜索功能使用高分辨設(shè)備打開(kāi)網(wǎng)頁(yè)不輸入內(nèi)容直接回車停留首頁(yè) 首頁(yè)搜索功能使用高分辨設(shè)備打開(kāi)網(wǎng)頁(yè)點(diǎn)擊頭部的搜索框并輸入內(nèi)容后按回車鍵進(jìn)入搜索內(nèi)容的詳細(xì)頁(yè)Singer按鈕試使用高分辨設(shè)備打開(kāi)網(wǎng)頁(yè)查看導(dǎo)航頭部并點(diǎn)擊Singer進(jìn)入熱門歌手推薦頁(yè)Runk按鈕測(cè)試使用高分辨設(shè)備打開(kāi)網(wǎng)頁(yè)查看導(dǎo)航頭部并點(diǎn)擊Rank進(jìn)入熱門榜單推薦頁(yè)低分辨率頭按鈕使用低分辨設(shè)備打開(kāi)網(wǎng)頁(yè)查看導(dǎo)航頭部并點(diǎn)擊下拉按鈕顯示下拉操作
Gallery試使用高分辨設(shè)備打開(kāi)網(wǎng)頁(yè)查看導(dǎo)航頭部并點(diǎn)擊Gallery進(jìn)入熱門專輯推薦頁(yè)低分辨率顯示使用低分辨設(shè)備打開(kāi)網(wǎng)頁(yè)測(cè)試結(jié)果:100%通過(guò)。查看導(dǎo)航頭部并顯示縮略式的頭部跳轉(zhuǎn)詳細(xì)搜索詳跳轉(zhuǎn)詳細(xì)搜索詳
細(xì)通過(guò)主要測(cè)試了用戶搜索功能。表5.3用戶個(gè)人信息管理測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 搜索框的使用進(jìn)入任意界面在頭部搜索欄輸入任意內(nèi)容并按
回車搜索框的使用進(jìn)入任意界面頭部搜索欄不輸入內(nèi)容并按回車不會(huì)挑戰(zhàn)詳細(xì)頁(yè)內(nèi)容搜索框的使用進(jìn)入搜索詳頁(yè)面搜索框的使用進(jìn)入搜索詳頁(yè)面在搜索頁(yè)內(nèi)的搜索框輸入仍以內(nèi)容并回車在頭部導(dǎo)航欄的搜索欄輸入內(nèi)容并回車跳轉(zhuǎn)制定內(nèi)容的搜索頁(yè)并且頭部搜索框內(nèi)容同步搜索頁(yè)的搜索框搜索頁(yè)的搜索框同步頭部的內(nèi)容
主要測(cè)試了用戶搜索功能。表5.3用戶個(gè)人信息管理測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 進(jìn)入熱門榜
頁(yè)右側(cè)內(nèi)容切換至
進(jìn)入熱門榜
頁(yè)右側(cè)內(nèi)容切換至
選中的榜單
容。通過(guò)進(jìn)入熱門榜單頁(yè)
進(jìn)入熱門榜單頁(yè)
并且點(diǎn)擊左側(cè)音
樂(lè)巔峰榜的選項(xiàng)
按鈕。熱門榜單右播放全部單曲熱門榜單右更多按鈕進(jìn)入熱門榜頁(yè)進(jìn)入熱門榜頁(yè)進(jìn)入熱門榜單頁(yè)并且點(diǎn)擊右“播放全部曲”按鈕。進(jìn)入熱門榜單頁(yè)并且點(diǎn)擊右“更多”按鈕。播放列表會(huì)添加當(dāng)前榜單的容,并且開(kāi)始播放。榜單歌曲若沒(méi)有超過(guò)15條就繼續(xù)顯示15條。返回頂部按測(cè)試進(jìn)入任意頁(yè)面將頁(yè)面往下滾動(dòng)按鈕,點(diǎn)擊UP按鈕頁(yè)面返回頂部熱門歌手頂類型選擇歌曲詳細(xì)頁(yè)歌詞熱門榜單添收藏進(jìn)入歌手列頁(yè)進(jìn)入歌曲詳頁(yè)進(jìn)入熱門榜頁(yè)點(diǎn)擊不同的歌手類型選項(xiàng)點(diǎn)擊右側(cè)展開(kāi)按鈕進(jìn)入熱門榜單頁(yè)并且點(diǎn)擊右“收藏榜單”按鈕。底部歌手會(huì)切換至指定頁(yè)面若是有歌曲信息則會(huì)將完整歌曲信息顯示出來(lái)若用戶已登錄添加收藏內(nèi)容并提示收藏成若是沒(méi)有登錄提示未登錄測(cè)試結(jié)果:
主要測(cè)試了用戶搜索功能。表5.3用戶個(gè)人信息管理測(cè)試用例測(cè)試功能 前提條件 操作步驟 預(yù)期條件 進(jìn)入播放頁(yè) 點(diǎn)擊播放器左側(cè)
的帶有音樂(lè)圖片
進(jìn)入播放頁(yè) 點(diǎn)擊播放器左側(cè)
的帶有音樂(lè)圖片
的按鈕通過(guò)若是播放狀態(tài)則
若是播放狀態(tài)則
會(huì)暫停音樂(lè)
放,若是暫停狀
態(tài)則開(kāi)始播放播放器進(jìn)度拖動(dòng)進(jìn)入播放頁(yè) 點(diǎn)擊進(jìn)度條的任意地方或者拖動(dòng)進(jìn)度條到任意地方在拖動(dòng)時(shí)音樂(lè)暫停播放,并且事件顯示與歌詞會(huì)同步移動(dòng)播放器歌詞示模塊進(jìn)入播放頁(yè) 播放任意歌曲 歌詞顯示頁(yè)面會(huì)隨播放時(shí)間動(dòng),并顯示制定的歌詞隨機(jī)按鈕功能進(jìn)入播放頁(yè) 將復(fù)數(shù)音樂(lè)加入播放列表當(dāng)前音樂(lè)播放完后會(huì)隨機(jī)播放播放列表切功能進(jìn)入播放頁(yè)面將復(fù)數(shù)音樂(lè)加入播放列表點(diǎn)擊其他沒(méi)有在播放的音樂(lè)切換到點(diǎn)擊的音樂(lè)進(jìn)行播放音量按鈕 進(jìn)入播放頁(yè) 播放任意音樂(lè) 播放的音量隨著播放條的長(zhǎng)度變化
6結(jié)論在起初畢業(yè)設(shè)計(jì)選題的過(guò)程中我對(duì)自身的選擇的題目還有是有一定擔(dān)憂和迷茫的,因?yàn)槠渲羞\(yùn)用到了很多比較新的開(kāi)發(fā)技術(shù),一是自己沒(méi)有實(shí)際完成過(guò)這類新技術(shù)的摸索,二是作為一個(gè)整體的全棧項(xiàng)目由個(gè)人完成也是沒(méi)有經(jīng)歷過(guò)的。我認(rèn)為這也是對(duì)我個(gè)人的一種鍛煉和提升,在參與工作的一個(gè)月里這些技術(shù)也經(jīng)常的被運(yùn)用到我在公司的開(kāi)發(fā)中實(shí)際上也有多問(wèn)題是我從實(shí)際開(kāi)發(fā)中反饋到畢設(shè)中的。在本次設(shè)計(jì)中,最為突出的一點(diǎn)我認(rèn)為就是前后端分離的思想,也是因?yàn)檫@是近期各種互聯(lián)網(wǎng)公司的發(fā)展趨勢(shì),所以我認(rèn)為我做的這系統(tǒng)必須是要能經(jīng)得住技術(shù)考驗(yàn)的,與時(shí)俱進(jìn)的。作為互聯(lián)網(wǎng)開(kāi)發(fā)的工程化的象征之一,前后端分離的web項(xiàng)目很多都是項(xiàng)目并且由于Vue框架是國(guó)人開(kāi)發(fā)的框架本身對(duì)于國(guó)人開(kāi)發(fā)者就有一定的友好度,由于完善的機(jī)制如VueRouter、VueX等官方插件的補(bǔ)充使得Vue生態(tài)在國(guó)內(nèi)種企業(yè)中都有著諸多引用,甚至發(fā)展到mpVue等使用Vue單頁(yè)去做微信小程序此次畢設(shè)選擇使Vue去寫也是對(duì)我自己進(jìn)入工作的一個(gè)考驗(yàn),它讓我近一步的對(duì)要面對(duì)的技術(shù)以及開(kāi)發(fā)問(wèn)題有了一個(gè)提前的涉足,不至于進(jìn)到公司就一臉懵的情況在我身上發(fā)生,事實(shí)也正是如此我通過(guò)畢設(shè)制作中遇到的各種問(wèn)題的深入了解和探索使得我在公司面試中很輕松的就通過(guò)了。并且由于現(xiàn)在Web應(yīng)用的跨平臺(tái)特性越來(lái)越多的公司要求前端開(kāi)發(fā)必須要P端開(kāi)發(fā)以及移動(dòng)端開(kāi)發(fā)的經(jīng)歷,因?yàn)轫憫?yīng)式布局可以為公司節(jié)省大量的維護(hù)成本,以及開(kāi)發(fā)的時(shí)間成本。使得現(xiàn)在越來(lái)越多的Web應(yīng)用取代了原的原生APP等技術(shù)。這也是此次我選擇部分頁(yè)面實(shí)行響應(yīng)式布局的原因,其中局的實(shí)現(xiàn)方法有幾種,我用的是兼容性以及適用性最好flex+vh+vw+媒體查詢這套較成熟的思路去完成的。這次畢業(yè)設(shè)計(jì)很好的鍛煉了我的編程能力和全棧開(kāi)發(fā)的過(guò)程中的理解和感受,最要的是它當(dāng)我有了更多的機(jī)會(huì)去適應(yīng)工作環(huán)境和工作狀態(tài),讓我更加容易的過(guò)渡到階段。
參考文獻(xiàn)[1]阮一峰.ECMAScript6入門[M].電子工業(yè)出版社:,2014-4-30.[2][美]AdamFreeman.HTML5權(quán)威指南[M].人民郵電出版社:,2014-1.[3][美]NicholasC.Zakas.深入理解ES6[M].電子工業(yè)出版社:,2017-7-1.[4][美]DavidFlanagan.JavaScript權(quán)威指南(第6[5]吉倫瓦特.CSS3實(shí)用指南[M].人民郵電出版社:,2012-3;[6]福達(dá)(BenForta).SQ必知必會(huì)(4版)[M].人民郵電出版社:,2013-5-1.[7][美]AndrewS·Tanenbaum.計(jì)算機(jī)網(wǎng)絡(luò)[M].清華大學(xué)出社:,2004-8-1.[8]張耀春.Vue.js權(quán)威指南[M].電子工業(yè)出版社:,2016-8-1.[9][法]紀(jì)堯姆·周.Vue.js項(xiàng)目實(shí)戰(zhàn)[M].人民郵電出版社:,2019-1.[10]樸靈.深入淺Node.js[M].人民郵電出版社:,2013-12-1.
附錄附錄constdb=require("./db");constexpress=require("express");
constrouter=express.Router();
constjwt=require("jsonwebtoken");
constpath=require("path");/**************(create)(get)(update)**************///注冊(cè)router.post("/api/admin/signUp",(req,res)=>{console.log("req",req);if(!||!req.body.password||!req.body.nickName){
res.send({status:0,msg:"注冊(cè)失敗"}); return;}db.User.find({name:},(err,docs)=>{
if(err){ res.send(err); return; } if(docs.length>0){ res.send({status:0,msg:"用戶名已注冊(cè)"}); }else{ db.User.find({nickName:req.body.nickName},(err,docs)=>{
if(err){ res.send(err); return; } if(docs.length>0){ res.send({status:0,msg:"昵稱已注冊(cè)"}); }else{
letnewUser=newdb.User({ name:, password:req.body.password, nickName:req.body.nickName, avatar:null, type:2, }); newUser.save(function(err){ if(err){ res.send(err); }else{ res.send({status:1,msg:"注冊(cè)成功"}); } }); } }); }
});});//登錄router.post("/api/admin/signIn",(req,res)=>{db.User.find({name:=>{if(err){ res.send(err); return;}if(docs.length>0){ letcontent={name:};//要生成token的主題信息
letsecretOrPrivateKey="123456";//這是加密的key(密鑰)
lettoken=jwt.sign(content,secretOrPrivateKey,{
expiresIn:60*60*24,//2小時(shí)過(guò)期 }); docs[0].token=token;
db.User(docs[0]).save(function(err){
if(err){ res.status(500).send(); return; } res.send({
status:1, msg:"登陸成功", token:docs[0].token, user_name:docs[0]["name"], type:docs[0]["type"], nickName:docs[0]["nickName"],
avatar:docs[0]["avatar"], }); }); }else{ res.send({status:0,msg:"登錄失敗"}); }});});//退出router.post("/api/admin/signOut",(req,res)=>{db.User.find({name:
{if(err){ return;}if(docs.length>0){
docs[0].token="";
db.User(docs[0]).save(function(err){
if(err){ res.status(500).send(); return; } res.send({status:1,msg:退出成功"});
});}else{ res.send({status:0,msg:"退出失敗"});}});});//用戶信息更新router.post("/api/admin/updateUser",(req,res)=>{db.User.find({name:
{if(err){ return;}
if(docs.length>0){ if(req.body.avatar=="null"||req.body.avatar==null){
//不需更新圖片 docs[0].nickName=req.body.nickName;
db.User(docs[0]).save(function(err){
if(err){ res.status(500).send(); return; } res.send({ status:1, msg:"更新成功", user_name:docs[0]["name"], type:docs[0]["type"], nickName:docs[0]["nickName"], avatar:docs[0]["avatar"], }); }); }else{ constfs=require("fs");
letD=Date.now(); letsaveImg=path.join(__dirname,"../static/upload/avatar/"+D+
".png"); letpathImg=D+".png"; letbase64=req.body.avatar.replace(/^data:image\/\w+;base64,/,"");
letdataBuffer=newBuffer(base64,"base64");
fs.writeFile(saveImg,dataBuffer,function(err){
//用fs寫入文件 if(err){ console.log(err); }else{ console.log("寫入成功!",saveImg); docs[0].nickName=req.body.nickName;
docs[0].avatar=pathImg; db.User(docs[0]).save(function(err){
if(err){ res.status(500).send(); return; } res.send({ status:1, msg:"更新成功",
user_name:docs[0]["name"], type:docs[0]["type"], nickName:docs[0]["nickName"], avatar:docs[0]["avatar"], }); }); } }); } }else{ res.send({status:0,msg:"更新失敗"}); }});});//檢測(cè)tokenrouter.post("/api/admin/checkUser",(req,res)=>{db.User.find({name:req.body.user_name=>{if(err){ res.send(err); return;}if(docs.length>0){ lettoken=req.body.token; letsecretOrPrivateKey="123456";//這是加密的key jwt.verify(token,secretOrPrivateKey,function(err,decode){
if(err){ res.send({status:0}); }else{ res.send({ status:1, type:docs[0]["type"], user_name:docs[0]["name"], avatar:docs[0]["avatar"], nickName:docs[0]["nickName"], }); } });}else{ res.send({status:0});
}
});
});//獲取用戶的收藏列表通過(guò)tokenrouter.get("/api/collect/all",(req,res)=>{
console.log(req);lettoken=req.body.token||req.query.token;
console.log("token==>",token);if(token){ db.User.find({token},{password:0,token:0,_id:0})
.populate("collections",{_id:0})
.populate("history",{_id:0})
.exec(function(error,doc){ console.log(doc); if(error){ console.log(error); res.send({status:0,msg:"獲取失敗"});
returnfalse; }elseif(doc.length>0){ res.send({status:1,msg:"ok",data:doc[0]});
} });}
});
//添加router.post("/api/collect/add",(req,res)=>{console.log(req);let{token,typeId,type,picSrc,name}=req.body;console.log(token&&typeId&&type);if(token&&typeId!=undefined&&type){ db.Collection.create({typeId,type,picSrc,name},(eo,doc)=>{
console.log("doc===>",doc._id); db.User.findOneAndUpdate({token},{$push:{collections:doc._id}},function(err,user){ console.log("user====>",user); if(err){ console.log("錯(cuò)誤==>",err); res.send({status:0,msg:"error",data:err});
}else{ res.send({status:1,msg:"ok",data:"收藏成功"}); } });
});}else{ res.send({status:0,msg:"error",data:"參數(shù)錯(cuò)誤"});}});//獲取用戶的歷史列表通過(guò)tokenrouter.get("/api/history/all",(req,res)=>{
console.log(req);lettoken=req.body.token||req.query.token;
console.log("token==>",token);if(token){ db.User.find({token},{password:0,token:0,_id:0})
.populate("history",{_id:0})
.exec(function(error,doc){ console.log(doc); if(error){ console.log(error); res.send({status:0,msg:"獲取失敗"});
returnfalse; }elseif(doc.length>0){ res.send({status:1,msg:"ok",data:doc});
} });}});router.post("/api/history/add",(req,res)=>{
console.log("req==>",req);lettoken=req.body.token||req.query.token;letsongList=req.body.songList||req.query.songList;if(token&&songList){ db.User.find({token},(error,doc)=>{
console.log("doc==>",doc); if(doc.length>0){
db.History.insertMany(songList,(error,history)=>{
letlist=history.map((e)=>{ returne._id; }); db.User.findOneAndUpdate( {token},
{$addToSet:{history:{$each:list}}},
(errorco,user)=>{ console.log("user===>",user); res.send({status:1,msg:"添加歷史成功"}); } ); }); }else{ res.send({status:0,msg:"沒(méi)有用戶信息或參數(shù)錯(cuò)誤"}); } });}});module.exports=router;
附錄constmongoose=require("mongoose");mongoose.connect("mongodb://localhost/tao");
constSchema=mongoose.Schema;constdb=mongoose.connection;db.once("error",()=>console.log("Mongoconnectionerror"));db.once("open",()=>console.log("Mongoconnectionsuccessed"));constuserSchema=newmongoose.Schema({name:String,password:String,nickName:String,type:String,token:String,avatar:String,history:[{type:Schema.Types.ObjectId,ref:"History"}],
});consthistory=newmongoose.Schema({al:Object,artist:String,id:String,lrc:String,pic:String,publishTime:String,singerId:Array,src:String,title:String,src:String,createTime:{ type:Date, default:Date.now,
},updateTime:{
type:Date, default:Date.now,
},
user:{type:Schema.Types.ObjectId,ref:"User"},},{ versionKey:false, timestamps:{createdAt:"createTime",updatedAt:"updateTime"},
});//收藏constcollection=newmongoose.Schema({ picSrc:String, name:String, typeId:String, type:String, createTime:{ type:Date, default:Date.now,
}, updateTime:{
type:Date, default:Date.now, }, user:{type:Schema.Types.ObjectId,ref:"User"},},{ versionKey:false, timestamps:{createdAt:"createTime",updatedAt:"updateTime"},
});constModels={User:mongoose.model("User",userSchema),History:mongoose.model("History",history),
Collection:mongoose.model("Collection",collection),
};module.exports=Models;
附錄exportconstcheckSign={beforeCreate:function(){letuser_name=localStorage.getItem("user_name");lettoken=localStorage.getItem("token"); CheckUser({user_name:user_name,token:token}).then(response=>{
if(response.data.status==0){
this.$mit("changeIsSignIn",0);
localStorage.setItem("avatar",'avatar.png');
localStorage.clear(); }else{ if(response.data.avatar!=null){
localStorage.setItem("avatar",response.data.avatar);
}else{ localStorage.setItem("avatar",'avatar.png');
} getPortaldata({token}).then(res=>{
w
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 平臺(tái)經(jīng)濟(jì)領(lǐng)域“二選一”行為的法律規(guī)制研究
- CEV模型下歐式未定權(quán)益的緊致差分格式研究
- 商鋪轉(zhuǎn)讓居間合同范本
- 2025至2030年中國(guó)文胸氣袋數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 商標(biāo)出租合同范本
- 業(yè)務(wù)保障協(xié)議合同范例
- 基于深度學(xué)習(xí)的事件因果關(guān)系識(shí)別方法研究
- 2025至2030年中國(guó)婚紗飾品數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 云南融資租賃合同范本
- 現(xiàn)代漢語(yǔ)形容詞重疊的形式語(yǔ)義學(xué)研究
- 復(fù)工復(fù)產(chǎn)安全培訓(xùn)考試題
- 外賣報(bào)告數(shù)據(jù)分析
- 《神奇糖果店》教學(xué)課件
- 青少年健康教育知識(shí)講座課件
- 辦公室裝修方案計(jì)劃書(shū)模板
- 《避孕藥具知識(shí)培訓(xùn)》課件
- AGV介紹教學(xué)課件
- 人教版小學(xué)語(yǔ)文背誦篇目匯編
- 重癥醫(yī)學(xué)科Respironics V60呼吸機(jī)使用指引
- 心理團(tuán)體輔導(dǎo)的保密協(xié)議
- 工會(huì)法人變更登記申請(qǐng)表
評(píng)論
0/150
提交評(píng)論