日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Node — 第九天 (大事件项目接口实现三)

發(fā)布時間:2023/12/13 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Node — 第九天 (大事件项目接口实现三) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章管理接口

設(shè)計數(shù)據(jù)表

添加文章接口

編寫接口,使用postman模擬提交formdata類型的數(shù)據(jù)

  • 在article.js 中,加入 /add 路由

  • postman模擬提交formdata類型的數(shù)據(jù)

multer處理文件上傳

  • 下載安裝multer

  • 加載模塊 const multer = require('multer')

  • 配置上傳文件的存放目錄 const upload = multer({ dest: '路徑' })

  • 路由(接口)使用

    router.post('/add', upload.single('接口文檔規(guī)定的圖片名字'), async (req, res) => {req.body 獲取文本類型的數(shù)據(jù)req.file 獲取文件的信息 });

實現(xiàn)發(fā)布文章

  • 前面已經(jīng)可以通過req.body 和 req.file 獲取到客戶端提交的數(shù)據(jù)了
  • 自己組裝數(shù)據(jù)表所需的字段
  • 通過db,執(zhí)行insert語句,完成添加
router.post('/add', upload.single('cover_img'), async (req, res) => {// 如何接收POST請求體。必須使用第三方模塊multer來處理POST請求體// console.log(req.body); // 獲取文本類型的數(shù)據(jù)/** {title: '哈哈哈',content: '哈哈哈哈哈哈哈哈',cate_id: '3',state: '已發(fā)布'}* */// console.log(req.file); // 獲取文件的信息/*** {fieldname: 'cover_img',originalname: '1.jpg',encoding: '7bit',mimetype: 'image/jpeg',destination: '/Users/tangfengpo/Study/bj97+sh60/Node-09/big-event-server/uploads',filename: '0c86456393a6bd78cb860968a53a089d', // 文件名path: '/Users/tangfengpo/Study/bj97+sh60/Node-09/big-event-server/uploads/0c86456393a6bd78cb860968a53a089d',size: 35774}*/// 組裝數(shù)據(jù)let obj = req.body;obj.cover_img = req.file.filename;obj.pub_date = '2020-03-11 23:15:25';obj.author_id = req.user.id; // 要求登錄之后,必須在token中保存用戶的id// 添加入庫let r = await db('insert into article set ?', obj);if (r && r.affectedRows > 0) {res.json({status: 0,message: '添加文章成功'});} else {res.json({status: 1,message: '添加文章失敗'});} });

moment處理添加時間

  • 把上述添加代碼中,時間的處理,修改如下
// obj.pub_date = '2020-03-11 23:15:25'; // obj.pub_date = moment('任何類型的時間/不填表示處理當(dāng)前時間').format('處理成你想要的格式'); obj.pub_date = moment().format('YYYY-MM-DD hh:mm:ss');

MySQL中的連接查詢

-- MySQL中的連接查詢 -- 能夠連接查詢的兩張或多張表,必須有關(guān)系才行-- 語法 select 字段 from1 join2 on 兩表的關(guān)系 [where ... order by .... limit ...] select 字段 from1 join2 on 兩表的關(guān)系 join3 on 表的關(guān)系 .... [where ... order by .... limit ...]-- select * from article join category on article.cate_id=category.Id -- 給表名定義別名,簡化SQL -- select * from article a join category c on a.cate_id=c.Id -- 指定字段查詢 -- select a.Id, a.title, a.pub_date, a.state, c.name cate_name from article a -- join category c -- on a.cate_id=c.Id-- 加入user表,實現(xiàn)每個用戶只能查看自己的文章 select a.Id, a.title, a.pub_date, a.state, c.name cate_name from article ajoin category c on a.cate_id=c.Idjoin user u on u.id=a.author_idwhere u.id = 14

獲取文章列表接口

判斷必須有必要的參數(shù)

// 獲取文章列表數(shù)據(jù) router.get('/list', async (req, res) => {// 接收所有的請求參數(shù)// let pagenum = req.query.pagenum;// let pagesize = req.query.pagesize;// let cate_id = req.query.cate_id;// let state = req.query.state;// 使用解構(gòu)的方式,獲取請求參數(shù)let {pagenum, pagesize, cate_id, state} = req.query;// 判斷必填參數(shù)是否存在if (!pagesize || !pagenum) {return res.json({status: 1,message: '缺少必要參數(shù)'});}});

多表連查,查詢結(jié)果

// 下面查詢數(shù)據(jù),把結(jié)果響應(yīng)給客戶端// 下面是SQL比較長,可以先在 Navicat中查詢,沒問題,復(fù)制過來let sql = `select a.Id, a.title, a.pub_date, a.state, c.name cate_name from article ajoin category c on a.cate_id=c.Idjoin user u on u.id=a.author_idwhere u.id = ?`;let r = await db(sql, req.user.id);if (r) {res.json({status: 0,message: '獲取數(shù)據(jù)列表成功',data: r});} else {res.json({status: 1,message: '查詢失敗'});}

此時,可以使用postman來測試了

如果你看到結(jié)果了,說明沒有問題。

相同條件查詢總記錄數(shù)

必須和查詢數(shù)據(jù)的條件一致

// 查詢總記錄數(shù) let r2 = await db('select count(*) as total from article where author_id=?', req.user.id); if (r && r2) {res.json({status: 0,message: '獲取數(shù)據(jù)列表成功',data: r,total: r2[0].total}); } else {res.json({status: 1,message: '查詢失敗'}); }

加入limit,完成分頁查詢

  • pagenum 表示當(dāng)前的頁碼,比如 1、2、3…

  • pagesize 表示每頁顯示多少條,由你自己來定(老師使用的是2)

  • 根據(jù)上述兩個參數(shù),可以完成SQL語句中l(wèi)imit的部分

    limit ${(pagenum-1) * pagesize} , ${pagesize}

使用postman的賬號和使用頁碼登錄的賬號最好統(tǒng)一。否則使用postman添加的文章頁面中可能看不見。

加入where條件,完成篩選查詢

對于獲取文章接口來說,請求參數(shù) cate_id 和 state,用于完成篩選。

如果服務(wù)器端,接收到了 cate_id 和 state,我們只需要加where條件即可。

// 獲取文章列表數(shù)據(jù) router.get('/list', async (req, res) => {// 接收所有的請求參數(shù)// let pagenum = req.query.pagenum;// let pagesize = req.query.pagesize;// let cate_id = req.query.cate_id;// let state = req.query.state;// 使用解構(gòu)的方式,獲取請求參數(shù)let {pagenum, pagesize, cate_id, state} = req.query;// 判斷必填參數(shù)是否存在if (!pagesize || !pagenum) {return res.json({status: 1,message: '缺少必要參數(shù)'});}// 生成where條件,完成篩選工作let w = '';if (cate_id) {w += ' and cate_id=' + cate_id; // 注意前面有空格}if (state) {w += ` and state = '${state}'`; // 注意前面有空格}// 下面查詢數(shù)據(jù),把結(jié)果響應(yīng)給客戶端// 下面是SQL比較長,可以先在 Navicat中查詢,沒問題,復(fù)制過來let sql = `select a.Id, a.title, a.pub_date, a.state, c.name cate_name from article ajoin category c on a.cate_id=c.Idjoin user u on u.id=a.author_idwhere u.id = ? ${w}limit ${(pagenum-1)*pagesize}, ${pagesize}`;let r = await db(sql, req.user.id);// 查詢總記錄數(shù)let r2 = await db('select count(*) as total from article where author_id=?' + w, req.user.id);if (r && r2) {res.json({status: 0,message: '獲取數(shù)據(jù)列表成功',data: r,total: r2[0].total});} else {res.json({status: 1,message: '查詢失敗'});} });

根據(jù)Id刪除文章接口

// 根據(jù)Id完成刪除文章接口 router.get('/delete/:id', async (req, res) => {let id = req.params.id;let r = await db('delete from article where Id=?', id);if (r && r.affectedRows>0) {res.json({status: 0,message: '刪除文章成功'});} else {res.json({status: 1,message: '刪除文章失敗'});} });

根據(jù)Id獲取文章詳情接口

// 根據(jù)Id獲取文章詳情接口 router.get('/:id', async (req, res) => {let id = req.params.id;let r = await db('select * from article where Id=?', id);// console.log(r);if (r && r.length > 0) {res.json({status: 0,message: '獲取文章詳情成功',data: r[0]});} else {res.json({status: 1,message: '獲取文章詳情失敗'});} });

根據(jù) Id 更新文章信息接口

  • 修改文章的時候,可以不選擇修改圖片,這是比較合理的
// 根據(jù)Id更新文章 router.post('/edit', upload.single('cover_img'), async (req, res) => {// req.body;// req.file;// console.log(req.file); // 如果沒有選擇圖片,req.file === undefinedlet obj = req.body; // 這樣的話,obj中有 Id、title、cate_id、content、state// 判斷,修改的時候,客戶端是否重新選擇了圖片(選擇了圖片,req.file是對象;沒有選擇圖片,req.file是undefined)if (req.file) {obj.cover_img = req.file.filename;}// obj.pub_date = moment().format('YYYY-MM-DD HH:mm:ss');let r = await db('update article set ? where Id=?', [obj, req.body.Id]);if (r && r.affectedRows>0) {res.json({status: 0,message: '更新文章成功'})} else {res.json({status: 1,message: '更新文章失敗'});} });

前端

回顧文章列表分頁實現(xiàn)

完成文章列表搜索功能

先顯示分類

// 獲取分類,渲染到下拉菜單位置 $.ajax({url: '/my/article/cates',success: function (res) {let str = template('tpl-category', res);$('#category').html(str);form.render('select'); // --------------- 一定要更新渲染 --- } });

模板代碼:

<!-- 分類的模板 --> <script type="text/html" id="tpl-category"><option value="">所有分類</option>{{each data val}}<option value="{{val.Id}}">{{val.name}}</option>{{/each}} </script>

完成篩選

思路:

  • 監(jiān)聽搜索區(qū)的表單,如果提交表單
  • 判斷并設(shè)置請求參數(shù)
    • 如果選擇了某個分類,設(shè)置請求參數(shù) data.cate_id = cate_id
    • 如果是所有分類,則刪除這個請求參數(shù) delete data.cate_id
    • 文章狀態(tài)一樣的操作
  • 修改頁碼為1,因為搜索完畢,應(yīng)該先看到第1頁的數(shù)據(jù)
  • 調(diào)用 renderArticle() 重新獲取數(shù)據(jù)并渲染到頁面中即可。
// -------------- 實現(xiàn)篩選功能 --------------- // 篩選之后,一定要重置 pagenum = 1; // 自己設(shè)置表單的id $('#search_form').on('submit', function (e) {e.preventDefault();let cate_id = $('#category').val();let state = $('select[name="state"]').val();if (cate_id) {data.cate_id = cate_id;} else {delete data.cate_id;}if (state) {data.state = state;} else {delete data.state;}// 修改頁碼為1data.pagenum = 1;// 更新渲染renderArticle(); })

回顧文章添加實現(xiàn)

  • 自己隨便寫個表單
  • 使用formdata收集數(shù)據(jù)
  • 提交給接口,就可以完成添加

后續(xù),為了有更好的效果:

  • 獲取分類
  • 使用富文本編輯器 tinymce
  • 使用圖片剪裁插件

完成文章編輯

  • 復(fù)制 publish.html 為edit.html (編輯頁面)

  • 文章列表頁面,給 ”編輯“ 掛超鏈接,鏈接到 edit.html ,并且傳遞 id參數(shù)

    // 點擊了編輯,應(yīng)該跳轉(zhuǎn)到 edit.html $('body').on('click', '.edit', function () {let id = $(this).attr('data-id');location.href = "/article/edit.html?id=" + id; })
  • 復(fù)制publish.js 為edit.js ,修改edit.html頁面,引入edit.js

  • 獲取地址欄的id,根據(jù)id查詢一篇文章詳情,然后完成表單數(shù)據(jù)渲染

    // ------------------ 新加入的代碼 ----------------// 獲取地址欄的id,根據(jù)id獲取一篇文章詳情。快速為表單賦值let id = new URLSearchParams(location.search).get('id');$.ajax({url: '/my/article/' + id,success: function (res) {console.log(res);if (res.status === 0) {form.val('editForm', res.data); // 標(biāo)題、內(nèi)容// 銷毀剪裁區(qū),更換圖片,重新創(chuàng)建剪裁區(qū)$image.cropper('destroy').attr('src', 'http://localhost:3007/' + res.data.cover_img).cropper(options);// 這里完成了文章獲取,下面開始查詢分類// 獲取所有的分類,渲染到下拉列表中$.ajax({url: '/my/article/cates',success: function (r) {if (r.status === 0) {// 使用模板引擎,渲染數(shù)據(jù)到頁面中// 把當(dāng)前分類的id,分配到模板r.cate_id = res.data.cate_id;let str = template('cate', r);$('select').html(str);// 執(zhí)行更新渲染方法form.render('select');}}});}}});
  • 模板加入判斷,控制哪個分類是默認(rèn)勾選

    <script type="text/html" id="cate">{{each data val}}<option value="{{val.Id}}" {{if val.Id == cate_id}}selected{{/if}}>{{val.name}}</option>{{/each}} </script>
  • 圖片剪裁默認(rèn)鋪滿整個區(qū)域

    let options = {// 寬高比aspectRatio: 400 / 280,autoCropArea: 1, // 讓剪裁框鋪滿整個剪裁區(qū)// 設(shè)置預(yù)覽區(qū)的選擇器preview: '.img-preview'};
  • 修改添加文章的接口為更新文章的接口即可,其他都不需要修改。

總結(jié)

以上是生活随笔為你收集整理的Node — 第九天 (大事件项目接口实现三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。