做調(diào)查賺錢的網(wǎng)站又哪些品牌傳播方案
??📝個(gè)人主頁:哈__
期待您的關(guān)注?
目錄
一、🔥今日內(nèi)容
二、🌏前端頁面的改造
2.1新增電子書管理頁面
2.2新增路由規(guī)則
2.3修改the-header代碼
三、🚗SpringBoot后端Ebook模塊改造
3.1增加電子書增/改接口
3.1.1新增EbookSaveParam
3.1.2添加Controller代碼
3.1.3在Ebook實(shí)體類上增加一個(gè)注解
3.2?增加電子書刪除接口
四、🔨測試?
4.1添加功能測試
4.2修改功能測試。
4.3刪除功能測試
一、🔥今日內(nèi)容
【wiki知識庫】03.前后端的初步交互(展現(xiàn)所有的電子書)-CSDN博客
上一次帶領(lǐng)大家把前端的首頁部分實(shí)現(xiàn)了一下,成功的從數(shù)據(jù)庫當(dāng)中取出了我們的信息并且展示在前端頁面,到了下圖的部分。
今天主要是把這個(gè)網(wǎng)頁的界面初步優(yōu)化一下,修改一下導(dǎo)航欄以及增加電子書管理模塊。包含電子書的查詢功能、新增功能、編輯功能和刪除功能(不包括文檔管理)。
二、🌏前端頁面的改造
2.1新增電子書管理頁面
我在src下新建了admin文件夾,這個(gè)文件夾中的內(nèi)容是給網(wǎng)站管理員看到的,所以放到了admin目錄,名字為admin-ebook.vue。
?admin-ebook.vue的具體內(nèi)容如下。這個(gè)文件里我注釋掉了一些信息,而且這個(gè)文件中的內(nèi)容包含了頁面需要的功能很多,有的一些并不是今天要講解的內(nèi)容,所以并沒有使用到。今天主要就是想帶著大家做出一個(gè)電子書管理的模塊來。
<template><a-layout><a-layout-content:style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"><p><a-form layout="inline" :model="param"><a-form-item><a-input v-model:value="param.name" placeholder="名稱"></a-input></a-form-item><a-form-item><a-button type="primary" @click="handleQuery({page: 1, size: pagination.pageSize})">查詢</a-button></a-form-item><a-form-item><a-button type="primary" @click="add()">新增</a-button></a-form-item></a-form></p><a-table:columns="columns":row-key="record => record.id":data-source="ebooks":pagination="pagination":loading="loading"@change="handleTableChange"><template #cover="{ text: cover }"><img v-if="cover" :src="cover" alt="avatar" /></template><template v-slot:category="{ text, record }"><!-- <span>{{ getCategoryName(record.category1Id) }} / {{ getCategoryName(record.category2Id) }}</span> --></template><template v-slot:action="{ text, record }"><a-space size="small"><!-- <router-link :to="'/admin/doc?ebookId=' + record.id"> --><a-button type="primary">文檔管理</a-button><!-- </router-link> --><a-button type="primary" @click="edit(record)">編輯</a-button><a-popconfirmtitle="刪除后不可恢復(fù),確認(rèn)刪除?"ok-text="是"cancel-text="否"@confirm="handleDelete(record.id)"><a-button type="danger">刪除</a-button></a-popconfirm></a-space></template></a-table></a-layout-content></a-layout><a-modaltitle="電子書表單"v-model:visible="modalVisible":confirm-loading="modalLoading"@ok="handleModalOk"><a-form :model="ebook" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }"><a-form-item label="封面"><a-input v-model:value="ebook.cover" /></a-form-item><a-form-item label="名稱"><a-input v-model:value="ebook.name" /></a-form-item><a-form-item label="分類"><a-cascaderv-model:value="categoryIds":field-names="{ label: 'name', value: 'id', children: 'children' }":options="level1"/></a-form-item><a-form-item label="描述"><a-input v-model:value="ebook.description" type="textarea" /></a-form-item></a-form></a-modal> </template><script lang="ts">import { defineComponent, onMounted, ref } from 'vue';import axios from 'axios';import { message } from 'ant-design-vue';import {Tool} from "@/util/tool";export default defineComponent({name: 'AdminEbook',setup() {const param = ref();param.value = {};const ebooks = ref();const pagination = ref({current: 1,pageSize: 10,total: 0});const loading = ref(false);const columns = [{title: '封面',dataIndex: 'cover',slots: { customRender: 'cover' }},{title: '名稱',dataIndex: 'name'},{title: '分類',slots: { customRender: 'category' }},{title: '文檔數(shù)',dataIndex: 'docCount'},{title: '閱讀數(shù)',dataIndex: 'viewCount'},{title: '點(diǎn)贊數(shù)',dataIndex: 'voteCount'},{title: 'Action',key: 'action',slots: { customRender: 'action' }}];/*** 數(shù)據(jù)查詢**/const handleQuery = (params: any) => {loading.value = true;// 如果不清空現(xiàn)有數(shù)據(jù),則編輯保存重新加載數(shù)據(jù)后,再點(diǎn)編輯,則列表顯示的還是編輯前的數(shù)據(jù)ebooks.value = [];axios.get("/ebook/list", {params: {page: params.page,size: params.size,name: param.value.name}}).then((response) => {loading.value = false;const data = response.data;if (data.success) {ebooks.value = data.content.list;// 重置分頁按鈕pagination.value.current = params.page;pagination.value.total = data.content.total;} else {message.error(data.message);}});};/*** 表格點(diǎn)擊頁碼時(shí)觸發(fā)*/const handleTableChange = (pagination: any) => {console.log("看看自帶的分頁參數(shù)都有啥:" + pagination);handleQuery({page: pagination.current,size: pagination.pageSize});};// -------- 表單 ---------/*** 數(shù)組,[100, 101]對應(yīng):前端開發(fā) / Vue*/const categoryIds = ref();const ebook = ref();const modalVisible = ref(false);const modalLoading = ref(false);const handleModalOk = () => {modalLoading.value = true;ebook.value.category1Id = categoryIds.value[0];ebook.value.category2Id = categoryIds.value[1];axios.post("/ebook/save", ebook.value).then((response) => {modalLoading.value = false;const data = response.data; // data = commonRespif (data.success) {modalVisible.value = false;// 重新加載列表handleQuery({page: pagination.value.current,size: pagination.value.pageSize,});} else {message.error(data.message);}});};/*** 編輯*/const edit = (record: any) => {modalVisible.value = true;ebook.value = Tool.copy(record);categoryIds.value = [ebook.value.category1Id, ebook.value.category2Id]};/*** 新增*/const add = () => {modalVisible.value = true;ebook.value = {};};const handleDelete = (id: number) => {axios.delete("/ebook/delete/" + id).then((response) => {const data = response.data; // data = commonRespif (data.success) {// 重新加載列表handleQuery({page: pagination.value.current,size: pagination.value.pageSize,});} else {message.error(data.message);}});};const level1 = ref();let categorys: any;/*** 查詢所有分類**/const handleQueryCategory = () => {loading.value = true;axios.get("/category/all").then((response) => {loading.value = false;const data = response.data;if (data.success) {categorys = data.content;console.log("原始數(shù)組:", categorys);level1.value = [];level1.value = Tool.array2Tree(categorys, 0);console.log("樹形結(jié)構(gòu):", level1.value);// 加載完分類后,再加載電子書,否則如果分類樹加載很慢,則電子書渲染會(huì)報(bào)錯(cuò)handleQuery({page: 1,size: pagination.value.pageSize,});} else {message.error(data.message);}});};const getCategoryName = (cid: number) => {// console.log(cid)let result = "";categorys.forEach((item: any) => {if (item.id === cid) {// return item.name; // 注意,這里直接return不起作用result = item.name;}});return result;};onMounted(() => {handleQuery({page: pagination.value.current,size: pagination.value.pageSize,});});return {param,ebooks,pagination,columns,loading,handleTableChange,handleQuery,getCategoryName,edit,add,ebook,modalVisible,modalLoading,handleModalOk,categoryIds,level1,handleDelete}}}); </script><style scoped>img {width: 50px;height: 50px;} </style>
上邊的內(nèi)容很多,但我們今天核心的前端調(diào)用部分是下邊的代碼。
const handleQuery = (params: any) => {loading.value = true;// 如果不清空現(xiàn)有數(shù)據(jù),則編輯保存重新加載數(shù)據(jù)后,再點(diǎn)編輯,則列表顯示的還是編輯前的數(shù)據(jù)ebooks.value = [];axios.get("/ebook/list", {params: {page: params.page,size: params.size,name: param.value.name}}).then((response) => {loading.value = false;const data = response.data;if (data.success) {ebooks.value = data.content.list;// 重置分頁按鈕pagination.value.current = params.page;pagination.value.total = data.content.total;} else {message.error(data.message);}});};
當(dāng)我們進(jìn)去這個(gè)頁面的時(shí)候,首先就會(huì)調(diào)用下方代碼,請求路徑也恰好是我們后端之前寫過的list接口,用來分頁查詢電子書信息。
onMounted(() => {handleQuery({page: pagination.value.current,size: pagination.value.pageSize,});});
2.2新增路由規(guī)則
既然都要新增一個(gè)電子書的管理頁面了,那我們也要為這個(gè)頁面分配一個(gè)能夠匹配到的路由路徑。
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' import HomeView from '../views/HomeView.vue' import AdminEbook from '@/views/admin/admin-ebook.vue' import AboutView from '../views/AboutView.vue' const routes: Array<RouteRecordRaw> = [{path: '/',name: 'home',component: HomeView},{path: '/about',name: 'about',component:AboutView},{path: '/admin/ebook',name: 'AdminEbook',component: AdminEbook}, ]const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes })export default router
2.3修改the-header代碼
?我們新增的組件是通過點(diǎn)擊the-header組件中的按鈕實(shí)現(xiàn)跳轉(zhuǎn)的,這里要修改一些代碼。我在這個(gè)頁面添加了一些路由用于跳轉(zhuǎn)我們的組件。
<template><a-layout-header class="header"><div class="logo" ></div><a-menutheme="dark"mode="horizontal"v-model:selectedKeys="sselectedKeys1":style="{ lineHeight: '64px' }"><a-menu-item key="/"><router-link to="/">首頁</router-link></a-menu-item><a-menu-item key="/admin/ebook"><router-link to="/admin/ebook">電子書管理</router-link></a-menu-item><a-menu-item key="/about"><router-link to="/about">關(guān)于我們</router-link></a-menu-item></a-menu></a-layout-header> </template>
至此我們前端改造成功,接下來就是后端了。
三、🚗SpringBoot后端Ebook模塊改造
3.1增加電子書增/改接口
在我們點(diǎn)擊新增按鈕或者編輯按鈕的時(shí)候,會(huì)彈出一個(gè)窗口來添加或者修改電子書的信息,當(dāng)我們點(diǎn)擊確定之后會(huì)向后端發(fā)送請求。請求接口是/ebook/save,注意,這里的save指代兩個(gè)功能,第一個(gè)是新增,第二個(gè)是修改。
3.1.1新增EbookSaveParam
這個(gè)實(shí)體類用于封裝我們前端傳過來的電子書的信息。
@Data public class EbookSaveParam {private Long id;@NotNull(message = "【名稱】不能為空")private String name;private Long category1Id;private Long category2Id;private String description;private String cover;private Integer docCount;private Integer viewCount;private Integer voteCount; }
3.1.2添加Controller代碼
這里我直接使用的MybatisPlus封裝好的函數(shù)
/*** 保存/修改電子書* @param ebookQueryParam* @return*/@PostMapping("/save")public CommonResp save(@Validated @RequestBody EbookSaveParam ebookQueryParam){boolean res = ebookService.saveOrUpdate(CopyUtil.copy(ebookQueryParam,Ebook.class));String message = Boolean.TRUE.equals(res) ? "操作成功":"操作失敗";return new CommonResp<>(true,message,null);}
3.1.3在Ebook實(shí)體類上增加一個(gè)注解
我們要使用雪花算法生成的id存儲(chǔ)在數(shù)據(jù)庫當(dāng)中。
/*** id*/@TableId(type = IdType.ASSIGN_UUID)private Long id;
當(dāng)然除了雪花id還有其他的id可供選擇。這里就不一一給大家說了。
3.2?增加電子書刪除接口
刪除功能的接口是下邊圖中所示。采用的是Restful風(fēng)格的請求。
?對應(yīng)Controller代碼。
/*** 刪除電子書* @param id 電子書id* @return*/@DeleteMapping("/delete/{id}")public CommonResp delete(@PathVariable("id") Long id){boolean res = ebookService.removeById(id);String message = Boolean.TRUE.equals(res) ? "刪除成功":"刪除失敗";return new CommonResp<>(true,message,null);}
四、🔨測試?
4.1添加功能測試
測試之前還要注釋兩行代碼。因?yàn)槲覀兊姆诸惸K還沒寫,這里不能傳值。
隨便加一個(gè)電子書上去。
結(jié)果還是沒問題的。
4.2修改功能測試。
不在截圖展示了,點(diǎn)擊編輯按鈕之后哦修改數(shù)據(jù)我這里是正確的。
4.3刪除功能測試
這時(shí)就有問題了,我刪除怎么成功不了?那么你是否會(huì)分析原因呢?先看看前端的打印。
仔細(xì)看看我們傳過去的id是什么,再看看你的數(shù)據(jù)庫里是否有這個(gè)id??顯然是沒有的。
這里就要說一下前后端傳輸數(shù)據(jù)的數(shù)據(jù)精度丟失問題了,因?yàn)槲覀儌鞯臄?shù)據(jù)是一個(gè)整形,而且數(shù)值很大,在傳輸?shù)倪^程總是有精度問題得,想要解決就需要在后端加一個(gè)配置類。
package com.my.hawiki.config;import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;/*** 統(tǒng)一注解,解決前后端交互Long類型精度丟失的問題*/ @Configuration public class JacksonConfig {@Beanpublic ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper objectMapper = builder.createXmlMapper(false).build();SimpleModule simpleModule = new SimpleModule();simpleModule.addSerializer(Long.class, ToStringSerializer.instance);objectMapper.registerModule(simpleModule);return objectMapper;} }
之后在運(yùn)行代碼試試。大功告成。
?電子書管理頁面的基本幾個(gè)功能差不多就這么多了。