從壹開始 [ Nuxt.js ] 之二 || 項目搭建 與 接口API


前言

哈嘍大家周一好,今天的內容比較多,主要就是包括:把前端頁面的展示頁給搭出來,然后調通接口API,可以添加數據,這兩天我也一直在開發,本來想一篇一篇的寫,發現可能會比較簡單,就索性把項目搭建的過程簡化,一次寫好了,在開發 Nuxt.js 框架的過程中,我發現相比之前還是有些變化的,如果你是讀過我第一個前后端分離系列的小伙伴,可能看過我簡單說過Nuxt框架的一些知識《Nuxt.js 是什么?》,我發現現在在項目搭建的過程中,已經優化了一些功能,今天就重頭搭建一下。

如果你沒有看過之前的文章,可以簡單看看,主要是看看理論方面,如果是只想看搭建過程,直接看這個即可了,畢竟現在已經是最新的了,老的方案可以舍棄,不過個人建議,前邊那幾篇可以花幾分鍾看看,了解下,比如:什么是SSR渲染,為啥要使用它,是如何進行渲染的等等,畢竟很多基礎概念我這里不會再說了,因為這是一個只有四篇的小系列,在上個系列都會有說到,這里就不多敘述了,直接進行項目的搭建。

今天是從簡到繁的過程,並不會把每個頁面的說明都寫上,因為頁面是千篇一律的,項目設計只寫這一篇吧,下一篇重點說如何服務端部署。現在已經基本完成了(因為我還沒有來得及發布,如果你想現在查看具體的效果,可以下載下來運行即可,注意要配置咱們的Blog.Core 項目,也可以關注的 Github 地址 https://github.com/anjoy8/Nuxt.tBug,這兩天我會發布一版本,在線地址:http://123.206.33.109:7090/):

 

一、Nuxt項目搭建

1、通過腳手架工具初始化項目

 這里我們就直接使用了官方腳手架工具創建,當然你也可以一步一步的創建,手動創建比較麻煩,不適合新手,想了解更多,查看官網:新手模板

這里默認你的電腦上已經安裝了 npm 環境了,如果不確定是否安裝了,可以查使用命令查看 npm -v

 

不僅如此,如果你想使用官方腳手架搭建項目,要確保npm版本在 5.2+ ,目前已經是6.5.0了,我的本地是 5.6.0 ,符合要求,開始動手搭建。

首先你找好一個放置你項目的文件夾作為你的倉庫,然后通過CMD或者 PowerShell 來創建項目,很簡單 :

npx create-nuxt-app 項目名

 

在安裝的過程中,會出現幾個選項,這里先放上我的動圖,具體如何選,圖下我會解釋:

 

具體的選擇是這樣的:

Project name TiBug.Nuxt //項目名稱
Project description  //項目描述
Use a custom server framework //選擇通用的服務端渲染模板框架:none,是默認服務 Nuxt default serve
Use a custom UI framework  //選擇通用UI框架:Element
Choose rendering mode  //選擇渲染模式:SSR或SPA
Use axios module   //是否使用 axios 進行http請求:yes
Use eslint  //是否使用代碼格式糾錯: no,會各種格式警告
Use prettier  //是否代碼美化:yes
Author name  //作者名
Choose a package //選擇一個包管理:npm

你可以根據情況自己去選擇,比如你不喜歡用 nuxt 自帶的服務器渲染,想使用 Express ,比如你可以直接在這里就選擇好你喜歡的樣式,比如我就喜歡 ElementUI 樣式框架。這相對以前的版本,已經有很大的改觀了,我認為很棒的。

這樣我們就等待安裝成功了,中間可能大概需要2~5分鍾,看個人網絡而定。

 

2、項目整體目錄結構

安裝好后,我們會看到生成的全部文件夾,而且是已經安裝好依賴包的:

 

 如果你稍微有一些 Vue 的開發經驗,應該都能知道大概的文件夾包含的意思,比如Component,Pages,Store等,咱們具體說說每一個文件夾都是干啥的:

├── assets                         // 資源文件。用於組織未編譯的靜態資源入LESS、SASS 或 JavaScript
│   └── logo.jpg                   // 默認logo圖片
├── components                     // 組件。用於自己編寫的Vue組件,比如滾動組件,日歷組件,分頁組件
│   └── AppLogo.vue                // 默認logo組件
├── layouts                        // 布局。頁面都需要有一個布局,默認為 default。它規定了一個頁面如何布局頁面。所有頁面都會加載在布局頁面中的 <nuxt /> 標簽中。
│   └── default.vue                // 默認模板頁面,類似mvc中的layout
├── middleware                     // 中間件。存放中間件。可以在頁面中調用: middleware: 'middlewareName' 。
├── pages                         // 頁面。一個 vue 文件即為一個頁面。
│   └── index.vue                  // 默認首頁面
├── plugins                        // 用於存放JavaScript插件的地方
│   └── element-ui.js              // 上邊我們安裝的UI框架
├── static                         // 用於存放靜態資源文件,比如圖片,此類文件不會被 Nuxt.js 調用 Webpack 進行構建編譯處理。 服務器啟動的時候,該目錄下的文件會映射至應用的根路徑 / 下。
├── store                         // 用於組織應用的Vuex 狀態管理。
├── .editorconfig                  // 開發工具格式配置
├── .eslintrc.js                   // ESLint的配置文件,用於檢查代碼格式
├── .gitignore                     // 配置git不上傳的文件
├── nuxt.config.js                 // 用於組織Nuxt.js應用的個性化配置,比如網站title,已便覆蓋默認配置
├── package.json                   // npm包管理配置文件
└── README.md                      // 說明文檔

其實整理看起來,和之前的沒多少差別,至少在頁面結構上沒太大差別,主要更新是把項目搭建前的配置交給了開發者了,不過有一個地方是被去掉了的,你先和 Vue 結構對比下,看看少了一個什么配置

 

3、路由根據頁面定

大家看上邊的文檔架構層次圖,你可能會發現,nuxt 和 vue 還是有些不一樣的,這里沒有了 路由Route 的配置,發現了么?

這個就是 nuxt 框架的獨到之處,為了能實現更好的SSR渲染,它使用的是根據頁面結構,自動路由,所以你的文件名,就是你的路由名稱:

在 Nuxt.js 里面定義帶參數的動態路由,需要創建對應的以下划線作為前綴的 Vue 文件 或 目錄。

以下目錄結構:

pages/
--| _slug // 以下划線開頭的文件夾,代表參數
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue //以 下划線 開頭的頁面,動態路由
--| index.vue

 

Nuxt.js 生成對應的路由配置表為:

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'users-id',
      path: '/users/:id?',
      component: 'pages/users/_id.vue'
    },
    {
      name: 'slug',
      path: '/:slug',
      component: 'pages/_slug/index.vue'
    },
    {
      name: 'slug-comments',
      path: '/:slug/comments',
      component: 'pages/_slug/comments.vue'
    }
  ]
}

具體的請查看官網:路 由

 

4、項目加載歡迎頁面

 我在webstorm 中運行上邊搭建好的項目,可以看到初始歡迎頁:

 

下邊我們就正式對這個頁面進行完善,進行整體設計。

 

二、首頁結構布局

 下邊我就簡要的寫了,具體的代碼,請看我的 Github 地址就行。我這里先把 pages/index.vue 的默認內容清空,

 

1、創建布局模板

 這個時候你可以先練習練習,布局頁面在哪里配置?先停下來想一想,或者看看剛剛創建的文件夾,沒錯,就是 layouts 文件夾下的 default.vue 頁面,咱們看看這個初始的是什么樣子:

<template>
  <div>
    <nuxt/> //這個就是頁面入口,其他頁面就是在這里進行嵌入的,可以對比MVC中 layout.cshtml 中的 @RenderBody()
  </div>
</template>

<style>
</style>

 

我們直接對其進行改造,設計模板結構,

<template>
  <div id="app">
    <el-row :gutter="0" >
      <el-col class="nav">
        <el-col class="nav-bar" :sx="22" :sm="22" :md="22" :lg="16">
          <div class="nav-bar-body">
            <div class="nav-bar-inner">
              <div id="logo">
                <img
                  src="../assets/logoa.png" />
              </div>
            </div>
           ............
    </el-row>
    <div class="footer">京ICP備xxxxxxxx號</div>
  </div>
</template>

 

因為我已經在安裝的時候,選擇了ElementUI 框架,所以可以直接使用相關 el 組件,而不用在各種配置和引用了,你一定會問:之前在開發 Vue 的時候,也使用過 ElementUI 呀,不是應該先安裝,然后在 Mian.js 中引用么,可是你為啥直接就可以用呢?能提這個問題的,表示真的是已經看懂了,別着急,請往下看。

 

2、插件是如何運行的

首先,我們應該清楚插件是什么?

插件其實就是一個 .js 文件,將我們需要的組件注入到我們的項目中去,可拔插,很方便替換任何一個我們需要的。

 

其實,我們應該了解插件是在哪里定義:

(同樣,你這里也可以先停一停,自己去文件夾里找找,感覺哪一個像是定義插件的),在腳手架整體結構中,我們知道每一個文件夾都有自己的作用,其中 plugins 文件夾,就是用來存放我們的插件的,插件目錄 plugins 用於組織那些需要在 根vue.js應用 實例化之前需要運行的 Javascript 插件。說人話就是,我們的vue項目想要運行,必須實例化 vue,這個大家肯定都知道,那實例化之前,當然就必須要加載插件了,就是這個目的。

我們在上邊用官方腳手架搭建的時候,已經安裝了 elementUI 的插件,所以我們會在 plugins 文件夾里,看到這個 elemengt-ui.js 文件:

以后我們如果還需要建立其他組件的話,都在這里處理,比如以后我們會對axios請求訪問進行封裝插件,如果你不是很明白,這里舉個栗子:

如果你是一直看我的文章,一定知道我在第一個系列的 Vue 項目里,為了進行 axios 請求,創建了一個 http.js 的問題,這個其實就是一個插件:

 

我定義好以后,並在 main.js 中注冊引入,這樣在其他頁面內,就可以隨心使用了。

 

最后,我們應該知道如何注冊這些插件:

這個時候,就用到我們的配置文件: nuxt.config.js 了,這里邊就是我們整個項目的配置文件,比如 head 中的 title 、icon呀,還有css,還有跨域本地代理,最后,當然就是我們的插件注冊了:

 

這個時候,我們重新運行下我們的項目(注意:如果修改了nuxt.config.js,要重新編譯下),這個時候我們看下效果:

 

嗯,很正常的顯示了,並且已經支持了SSR渲染,感覺很開心,就是樣式太丑,那我們就需要添加進一個樣式文件,在根目錄下新建 style 文件夾,並添加 style.css,具體的直接從 Github 拉取即可,不過,不僅僅要添加這個文件,還要在配置文件中,進行注冊引用,

 

頁面 Banner 最終的效果是這樣的:

 

我們頁面的模板已經加載好了,並且也 mock 了專題的數據,剩下的就是首頁結構了。

 

3、首頁正文結構布局

 這里因為和 vue 中開發組件或頁面是一樣的,就不多說了,具體的代碼可以參考我的 Github 代碼,這里把結構說一下:

 

其中最重要的,就是 asyncData 異步數據加載,這個和 vue 還是不同的:

 asyncData方法會在組件(限於頁面組件)每次加載之前被調用。它可以在服務端或路由更新之前被調用。 在這個方法被調用的時候,第一個參數被設定為當前頁面的上下文對象,你可以利用 asyncData方法來獲取數據,Nuxt.js 會將 asyncData 返回的數據融合組件 data 方法返回的數據一並返回給當前組件。

 

4、異步數據加載

是在頁面加載之前,加載數據,然后融合着 data ,一起返回,最后渲染頁面。注意:由於asyncData方法是在組件 初始化 前被調用的,所以在方法內是沒有辦法通過 this 來引用組件的實例對象。

我這里通過編譯后的代碼,可以看到是異步請求數據是這樣的,下文中,我會配合着 axios 異步請求,一起說說:

 data: function data() {
    return {
      data: 0,
    };
  },
  asyncData: function () {
    var _asyncData = _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_2___default()(
    /*#__PURE__*/
    regeneratorRuntime.mark(function _callee(_ref) {
      var params, tag, _ref2, data;

      return regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              params = _ref.params;
              _context.prev = 1;
              tag = params.tag;
              _context.next = 5;//axios http數據請求 return _plugins_axios__WEBPACK_IMPORTED_MODULE_3__["default"].get("/api/TopicDetail?page=1&tname=".concat(tag));

            case 5:
              _ref2 = _context.sent;
              data = _ref2.data.data;
              console.log(data);
              debugger;
              return _context.abrupt("return", {
                tagList: data.data,
                tagtitle: tag,
                fadetitle: true,
                notfound: !data.data.length
              });

            case 12:
              _context.prev = 12;
              _context.t0 = _context["catch"](1);

            case 14:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this, [[1, 12]]);
    }));

    function asyncData(_x) {
      return _asyncData.apply(this, arguments);
    }

    return asyncData;
  }(),
  components: {
    ArticleList: _components_ArticleList__WEBPACK_IMPORTED_MODULE_4__["default"]
  },

 

 

三、其他頁面說明 

除了上邊的首頁以外,還有詳情頁,分類頁,以及數據添加頁,這里就過多的說明了,其中主要說的是:

1、上拉加載分頁

這個其實很簡單的,就是在 mounted() 中,注冊瀏覽器滾動事件就好了,如果這里你不知道 mounted 是vue生命周期的什么時候的話,就應該好好的再學學了,因為生命周期鈎子是很重要的,至少我個人任務是這樣的:

在created的時候,視圖中的html並沒有渲染出來,所以此時如果直接去操作html的dom節點,一定找不到相關的元素
而在 mounted中,由於此時html已經渲染出來了,所以可以直接操作dom節點。

 這個時候我們就自定義事件:

 //頁面渲染完畢后,監聽滾動事件
 mounted() {
   window.addEventListener('scroll', this.handleScroll)
 },
  methods: {
    //處理方法,在頁面具體底部30像素的時候,觸發事件
    handleScroll() {
        const jrscrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollT
        let scrollBottom = document.body.clientHeight - window.innerHeight - jrscrollTop
        if (scrollBottom < 30) {
          if (this.ScrollFirst) {
            this.nextpage() //觸發這個,下拉加載分頁事件
          }
        }
      }
  },
  //記得在銷毀當前頁面的時候,也就是切換的時候,把監聽去掉
  beforeDestroy() {
    window.removeEventListener('scroll', this.handleScroll, fa
  }

整體很簡單,和我們的平時的 JS 上拉加載很相似,具體的可以查看我的代碼。 

 

2、設計 axios 插件對接API(兩種方式)

這里如果你有一定的 Vue 開發基礎,應該能會八成以上,為什么是八成呢,因為可能還是會有一些小問題需要注意,比如重點的就是異步數據加載了。

因為 Nuxt.js 是基於SSR渲染的,所以必須先獲取到數據,然后生成 Html 片,才能去渲染,這個和客戶端渲染還是不一樣的,客戶端兩者可以同步,甚至先渲染,再去進行 axios 數據請求,但是這樣不能實現 SEO 的作用,所以就在原先 axios 請求的基礎上,封裝了一個異步請求,這樣就能達到目的。但是這個在使用的時候,可能不是很順手,因為很多人已經習慣了直接用當然組件的 data() 中的數據了,在上邊我們也看到了,asyncData 編譯后的模板,它其實也是當前組件頁面中 data 的一部分,我們甚至就可以當成 data 來使用,只不過這個data里,可以寫邏輯,可以進行 axios 異步請求,那下邊咱們就看看具體用法:

首先我們應該說說如何定義這個插件,當然,我們在每一個頁面,通過引入 axios 也行,但是這樣有一些問題,除了不方便以為,還有一個就是無法定義一些公共的東西,比如 api 域名路徑,所以,我們需要定義一個插件:

 

A:首先,我們在 plugins 文件夾中定義 axios.js 插件:

import axios from 'axios'//引入 axios 服務
let options = {}
if (process.server) {
  // 配置基路由
  options.baseURL = 'http://localhost:5000' // http://123.xx.xx.xx:5000(服務端地址)
}
export default axios.create(options) // 注意這里是直接 export 了一個對象實例,而不是 Vue.use,這個插件不需要注冊

 

B:在頁面中使用:

 

這里聰明的你可能看到了,為什么沒有像 element-ui 插件那樣,沒有在 nuxt.config.js 中配置這個插件???
這里說下,因為這里是直接返回的一個對象,我們不需要關心是不是要去安裝它,它不像 element和下邊的markdown那樣,我們只有安裝了才能用,因為element和 markdown 不是一個返回值的狀態,而是 Vue.use ,是直接集成到了 vue 對象內的,所以需要在項目配置文件中進行安裝,這里的 axios.js 插件就不需要安裝,如果你還不明白的話,我用 http.js 也封裝了一個插件,一個就像 element那樣,集成到vue 的插件:

這樣的話,我們在組件頁面中,就可以直接這么用:

const {data: {response}} = await Vue.http.get('/api/TopicDetail/'+ id);//這個就是使用到了 Vue 對象

所以這個就需要安裝,因為我們必須在 app(也就是vue)被實例化之前,安裝這個插件:

 

如果你還看不懂 axios.js插件(返回對象,可直接使用)和 http.js插件(集成到vue對象里,需要注冊),這兩者之間的區別的話,請留言,或者加群,我詳細給你說說。

 

C:最后為了使用接口,我們需要進行跨域,使用 proxy 代理:

  proxy: [
    ['/api', { target: 'http://localhost:5000' }],
    ['/images', { target: 'http://localhost:5000' }],// 將圖片也代理到本地,下文的<上傳圖片>欄目會說到 // ['/api', { target: 'http://123.xx.xx.xx:3080' }],//服務端配置
  ]

//還有這里
modules: [
    // Doc: https://github.com/nuxt-community/axios-module#usage
'@nuxtjs/axios',
'@nuxtjs/proxy'
],

 

D:接下來我們就說說如何進行異步獲取數據 

就拿我們的首頁數據加載來說,我們的需求是加載出來全部的 Bug 數據,首先 index.vue 中肯定有一些基本的數據,比如當前頁數等常量參數,這些參數不需要我們異步去獲取,因為它們在頁面渲染之前已經被定義了:

 //當前組件中的數據變量
 data() {
   return {
     page: 0,
     lastpage: true,
     ScrollFirst: true,
   };
 }, 

 

但是,上邊我們也說了,我們為了實現 SSR 渲染,必須在渲染前就要異步獲取數據,所以這里我們就使用到了異步數據加載 asyncData:

 // 一共有三種方法,這個最常用的一種方法,asyncData() 方法
 async asyncData({ params }) {
      try {
        // 路由參數
        const { tag } = params
        // 獲取異步得到的數據,必須使用 {} 大括號包裹
        let { data } = await axios.get(`/api/TopicDetail/24`)
        console.log(data)
        
        // 如果想要獲取返回數據 data 中的某一個屬性,可以這么嵌套
        const { data: { article } } = await axios.get(`/api/TopicDetail?page=1`)
        console.log(article)

        // 然后將得到的數據返回過去,其實和本身的 data() 有異曲同工之妙
        return {
          articleList: article,
          tagtitle: tag,
          fadetitle: true,
          notfound: !article.length
        }
      } catch (err) {
        error({statusCode: 404})
      }
    },

提示:如果你不需要使用異步的話,直接用 let data= axios.get(`/api/TopicDetail/24`) 就可以了。

其實通過這里,你應該也能看的明白,這個異步獲取數據,本身和 data() 是很像的,通過操作,把數據返回到頁面里,這里只是要注意兩點:

1、一定要是異步的 await;

2、一定注意返回的數據格式,你可以用debugger 或者 console 來查看,也可以直接用 mock 數據測試。

 

最后,就是像 data 數據一樣,直接在頁面其他地方進行使用了,

<el-col :xs="24" :sm="24" :md="24" :lg="12"  v-for="item in articleList" :key="item.id" class="artitem" >

如果你是第一次使用,肯定會遇到找不到數據而報錯的情況,用我說的方法,斷點調試+mock 數據,相信很快你會游刃有余了。

 

3、選擇Mavon-Editor富文本編輯器

關於富文本編輯器,我也找了幾個做對比,因為平時更喜歡用 markdown ,所以,就選用了這個 mavon-editor 編輯器了,使用方法很簡單,還是插件三步走:

1、安裝依賴:

      npm install mavon-editor --save

2、在plugins中創建vue-markdown.js

import Vue from 'vue'
import mavonEditor from 'mavon-editor'
Vue.use(mavonEditor)

3、在nuxt.config.js中引入

 

具體如何在詳情頁展示呢,我用的是 highlight.js 和 marked 來實現的,使用方法很簡單,安裝過包以后,在頁面內引用,然后對我們添加的 content 代碼進行 marked() 方法即可,具體使用請查看我的代碼。

 

4、上傳圖片

這個上傳圖片還是比較簡單的,只不過需要有一些細節需要注意下,我這里有兩個版本的上傳圖片的方法 ,一個是 element-upload 上傳用戶頭像的,一個是 mavon 富文本編輯器中的上傳圖片的方法,后台方法是同一個,只不過前端控制稍微不同罷了,這里先說下后端API:

  [HttpPost]
  [Route("Pic")]
  public async Task<MessageModel<string>> InsertPicture([FromServices]IHostingEnvironment environment)
        {
            var data = new MessageModel<string>();
            string path = string.Empty;
            string foldername = "images";
            var files = Request.Form.Files;
            if (files == null || files.Count() <= 0) { data.Msg = "請選擇上傳的文件。"; return data; }
            //格式限制
            var allowType = new string[] { "image/jpg", "image/png", "image/jpeg" };
            string folderpath = Path.Combine(environment.WebRootPath, foldername);
            if (!System.IO.Directory.Exists(folderpath))
            {
                System.IO.Directory.CreateDirectory(folderpath);
            }
            if (files.Any(c => allowType.Contains(c.ContentType)))
            {
                if (files.Sum(c => c.Length) <= 1024 * 1024 * 4)
                {
                    //foreach (var file in files)
                    var file = files.FirstOrDefault();
                    string strpath = Path.Combine(foldername, DateTime.Now.ToString("MMddHHmmss") + file.FileName);
                    path = Path.Combine(environment.WebRootPath, strpath);

                    using (var stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        await file.CopyToAsync(stream);
                    }

                    data = new MessageModel<string>()
                    {
                        Response = strpath,
                        Msg = "上傳成功",
                        Success = true,
                    };
                    return data;
                }
                else
                {
                    data.Msg = "圖片過大";
                    return data;
                }
            }
            else

            {
                data.Msg = "圖片格式錯誤";
                return data;
            }
        }

 

然后看看前端是怎么操作的:

1、element-ui 的 upload 上傳圖片方法:

這個很簡單,官方栗子中,已經說的很明白了,幾乎不用做任何的修改就能達到目的,只需要我們修改下后端的api地址即可,注意這里有跨域的問題,我直接用的是本地代理的地址:

注意注意下邊三個問題就行了:

1、接口地址配置在 action;

2、一定要跨域,本項目使用的是本地代理 proxy,你也可以使用后端的CORS實現跨域;

3、記得要在后端配置使用靜態資源文件 app.UseStaticFiles(); ,因為我把圖片放到了wwwroot里了;

其他的和官方地址一模一樣的。http://element-cn.eleme.io/#/zh-CN/component/upload

 

2、mavon 富文本編輯器上傳圖片 :

這個完全照搬官方文檔即可,幾乎不用修改什么,只不過注意事項還是上邊的那三個,跨域+靜態資源使用,不多說:圖片上傳詳情點擊這里...,或者看我的Github代碼。

 

 

四、服務端接口設計

1、設計統一數據結構接口

 我這里使用了異步的統一泛型返回數據模型,大家也都能看懂,因為第一個系列已經說的很多了:

        /// <summary>
        /// 獲取Bug數據列表(帶分頁)
        /// </summary>
        /// <param name="page">頁數</param>
        /// <param name="tname">專題類型</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<PageModel<TopicDetail>>> Get(int page = 1, string tname = "")
        {
            var data = new MessageModel<PageModel<TopicDetail>>();
            int intTotalCount = 6;
            int TotalCount = 0;
            int PageCount = 1;
            List<TopicDetail> topicDetails = new List<TopicDetail>();

            //總數據,使用AOP切面緩存
            topicDetails = await _topicDetailServices.GetTopicDetails();
            if (!string.IsNullOrEmpty(tname))
            {
                var tid = (await _topicServices.Query(ts => ts.tName == tname)).FirstOrDefault()?.Id.ObjToInt();
                topicDetails = topicDetails.Where(t => t.TopicId == tid).ToList();
            }
            //數據總數
            TotalCount = topicDetails.Count;

            //總頁數
            PageCount = (Math.Ceiling(topicDetails.Count.ObjToDecimal() / intTotalCount.ObjToDecimal())).ObjToInt();

            //當前頁數據
            topicDetails = topicDetails.OrderByDescending(d => d.Id).Skip((page - 1) * intTotalCount).Take(intTotalCount).ToList();

            return new MessageModel<PageModel<TopicDetail>>()
            {
                Msg = "獲取成功",
                Success = topicDetails.Count >= 0,
                Response = new PageModel<TopicDetail>()
                {
                    page = page,
                    pageCount = PageCount,
                    dataCount = TotalCount,
                    data = topicDetails,
                }
            };

        }

通用返回信息類 和 通用分頁類:

 /// <summary>
 /// 通用返回信息類
 /// </summary>
 public class MessageModel<T>
 {
     /// <summary>
     /// 操作是否成功
     /// </summary>
     public bool Success { get; set; } = false;
     /// <summary>
     /// 返回信息
     /// </summary>
     public string Msg { get; set; } = "服務器異常";
     /// <summary>
     /// 返回數據集合
     /// </summary>
     public T Response { get; set; }

 }

/// <summary>
/// 通用分頁信息類
/// </summary>
public class PageModel<T>
{
    /// <summary>
    /// 當前頁數
    /// </summary>
    public int page { get; set; } = 1;
    /// <summary>
    /// 總頁數
    /// </summary>
    public int pageCount { get; set; } = 6;
    /// <summary>
    /// 數據總數
    /// </summary>
    public int dataCount { get; set; } = 0;
    /// <summary>
    /// 返回數據
    /// </summary>
    public List<T> data { get; set; }

}

 

五、對接口進行配置權限

因為我們的TiBug 1.0 還沒有設計用戶登錄問題,所以,這一塊還沒有,不過別慌,過些天我會加上,這幾天先把1.0版本發布到服務器。

然后開始開發 TiBug 1.5版本,設計管理后台,初步是基於VueAdmin的,主要是用戶管理和Bug管理,權限管理等,大家也看到了,目前的版本是只能添加不能修改,還是基於我們之前設計的 [Authorize("Permission")],數據庫配置,我本地簡單試了試,還是挺好用的,到時候也會嘗試下滑動過期等問題的解決方案。 

 

 

六、結語

到這里我們已經把項目的結構定義好了,而且也自適應了設備,內容簡單,主要的就是講解了:

1、如何通過 nuxt 官方腳手架搭建項目;2、頁面是如何加載的;3、插件的使用;4、異步數據運行;5、使用富文本編輯器以及上傳圖片等等,作為展示。

這幾天把整體頁面都設計好了,也上傳到Github上了,下篇開始部署,發布到服務器。

 

七、Github

https://github.com/anjoy8/Nuxt.tBug

https://github.com/anjoy8/Blog.Core

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM