寫在前面
昨晚又失眠了,四點半才睡著,還做了兩個很糟心的夢,八點半就醒了,感覺好累,好想一醉方休呀,不行呀,害怕酒駕,哈哈哈。
今年要做的事依舊很多,必須行動起來,自己儘管努力就好,剩下就看天意了。
任務拆解
上篇文章已經把前端頁面畫好,那麼現在就是寫後端邏輯的過程了,也就是編輯後的儲存功能,拆解如下:
- 增加後端儲存介面
- 點選儲存時,呼叫儲存介面
- 儲存成功重新整理列表
編輯功能實現
1、增加後端儲存介面
同樣還是兩步走,第一,先在controller
中呼叫,第二,在service
中實現。
首先,需要在controller
中加入呼叫儲存方法,示例程式碼如下:
/**
* 儲存或更新操作
*
* @param eBookSaveReq
* @return
*/
@PostMapping("/save")
public CommonResp save(@RequestBody EBookSaveReq eBookSaveReq) {
CommonResp resp = new CommonResp<>();
eBookService.save(eBookSaveReq);
return resp;
}
同樣, 我們在service
中實現,示例程式碼如下:
/**
* 儲存或更新操作
* @param eBookSaveReq
*/
public void save(EBookSaveReq eBookSaveReq) {
EBook eBook = copy(eBookSaveReq, EBook.class);
if(ObjectUtils.isEmpty(eBook.getId())){
//資料庫中沒查到,走新增方法
eBookMapper.insert(eBook);
}else{
//資料庫中查到,有該條資訊,走編輯操作
eBookMapper.updateByPrimaryKey(eBook);
}
}
知識點:
EBookSaveReq
是拷貝domain
中的實體Ebook
,早期程式碼中的EBookReq
讓我改為EBookQueryReq
,僅為查詢時候所用,這樣做的好處就是專類專用,可能有的人會說,這不是程式碼冗餘嗎,真的是個人習慣。
EBook eBook = copy(eBookSaveReq, EBook.class);
,這段程式碼是單體拷貝,不懂得同學可以參考《尋找寫程式碼感覺(七)之封裝請求引數和返回引數 》這篇文章。
2、點選儲存時,呼叫儲存方法,儲存成功並重新整理列表
後端邏輯寫完了,這時候我們可以用PostMan本地測試下,該介面是否可用,這裡我就直接在頁面裡呼叫測試了。
這時我們需要對點選儲存時候的方法進行修改,示例程式碼如下:
<template>
<a-layout class="layout">
<a-layout-content
:style="{ background: '#fff', padding: '24px', minHeight: '280px' }">
<a-table :columns="columns"
:row-key="record => record.id"
:data-source="ebooks1"
:pagination="pagination"
:loading="loading"
@change="handleTableChange"
>
<template #cover="{ text: cover }">
<img v-if="cover" :src="cover" alt="avatar"/>
</template>
<template #name="{ text: name }">
<a>{{ text }}</a>
</template>
<template #customTitle>
<span>
<smile-outlined/>
Name
</span>
</template>
<template #action="{ record }">
<span>
<a-space size="small">
<a-button type="primary" @click="edit(record)">
編輯
</a-button>
<a-modal
v-model:visible="modalVisible"
cancelText="取消"
okText="儲存"
title="編輯電子書"
:confirm-loading="modalLoading"
@ok="handleModalOk"
>
<a-form
:model="ebooks_data"
name="basic"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 16 }"
>
<a-form-item label="封面">
<a-input v-model:value="ebooks_data.cover"/>
</a-form-item>
<a-form-item label="名稱">
<a-input v-model:value="ebooks_data.name"/>
</a-form-item>
<a-form-item label="分類一">
<a-input v-model:value="ebooks_data.category1Id"/>
</a-form-item>
<a-form-item label="分類二">
<a-input v-model:value="ebooks_data.category2Id"/>
</a-form-item>
<a-form-item label="描述">
<a-input v-model:value="ebooks_data.description"/>
</a-form-item>
<a-form-item label="文件數">
<a-input v-model:value="ebooks_data.docCount"/>
</a-form-item>
<a-form-item label="閱讀數">
<a-input v-model:value="ebooks_data.viewCount"/>
</a-form-item>
<a-form-item label="點贊數">
<a-input v-model:value="ebooks_data.voteCount"/>
</a-form-item>
</a-form>
</a-modal>
<a-button type="danger">
刪除
</a-button>
</a-space>
</span>
</template>
</a-table>
</a-layout-content>
</a-layout>
</template>
<script lang="ts">
import {DownOutlined, SmileOutlined} from '@ant-design/icons-vue';
import {defineComponent, onMounted, reactive, ref, toRef} from 'vue';
import axios from 'axios';
import {message} from 'ant-design-vue';
export default defineComponent({
name: 'AdminEbook',
setup() {
//使用ref進行資料繫結
const ebooks = ref();
// 使用reactive進行資料繫結
const ebooks1 = reactive({books: []})
const pagination = ref({
current: 1,
pageSize: 2,
total: 0
});
const loading = ref(false);
const columns = [
{
title: '封面',
dataIndex: 'cover',
width: 120,
height: 120,
slots: {customRender: 'cover'}
},
{
title: '名稱',
dataIndex: 'name'
},
{
title: '分類一',
dataIndex: 'category1Id',
key: 'category1Id',
},
{
title: '分類二',
dataIndex: 'category2Id',
key: 'category2Id',
},
{
title: '描述',
dataIndex: 'description',
key: 'description',
},
{
title: '文件數',
dataIndex: 'docCount'
},
{
title: '閱讀數',
dataIndex: 'viewCount'
},
{
title: '點贊數',
dataIndex: 'voteCount'
},
{
title: 'Action',
key: 'action',
slots: {customRender: 'action'}
}
];
/**
* 資料查詢
**/
const handleQuery = (params: any) => {
loading.value = true;
// 如果不清空現有資料,則編輯儲存重新載入資料後,再點編輯,則列表顯示的還是編輯前的資料
ebooks.value = [];
axios.get("/ebook/list", {
params: {
page: params.page,
size: params.size,
name: params.name
}
}).then((response) => {
loading.value = false;
const data = response.data;
if (data.success) {
const data = response.data;
ebooks.value = data.content.list;
ebooks1.books = data.content.list;
// 重置分頁按鈕
pagination.value.current = params.page;
pagination.value.total = data.content.total;
} else {
message.error(data.message);
}
});
};
/**
* 表格點選頁碼時觸發
*/
const handleTableChange = (pagination: any) => {
console.log("看看自帶的分頁引數都有啥:" + pagination);
handleQuery({
page: pagination.current,
size: pagination.pageSize
});
};
const ebooks_data = ref();
const modalVisible = ref<boolean>(false);
const modalLoading = ref<boolean>(false);
/**
* 編輯/儲存
*/
const handleModalOk = () => {
modalLoading.value = true;
axios.post("/ebook/save", ebooks_data.value).then(response => {
const data = response.data;
if (data.success) {
modalVisible.value = false;
modalLoading.value = false;
//重新載入列表
handleQuery({
page: 1,
size: pagination.value.pageSize,
});
}
})
};
const edit = (record: any) => {
modalVisible.value = true;
ebooks_data.value = record;
};
onMounted(() => {
handleQuery({
page: 1,
size: pagination.value.pageSize,
});
})
return {
modalVisible,
modalLoading,
handleModalOk,
pagination,
handleTableChange,
loading,
columns,
edit,
ebooks_data,
ebooks1: ebooks,
ebooks2: toRef(ebooks1, "books")
}
},
components: {
SmileOutlined,
DownOutlined,
},
});
</script>
<style scoped>
img {
width: 50px;
height: 50px;
}
</style>
知識點:
- 響應式變數宣告,貫穿始終,需要慢慢使用;
- 入參是
json
物件,所以在controller
中需要加入@RequestBody
- 在table元件使用時需要加上
@change="handleTableChange"
,handleTableChange
為方法實現分頁跳轉 - 前端程式碼也需要好好處理下,讓人看起來不那麼難受至少,慚愧呀,因為我的變數宣告和使用扔的哪都是,尷尬
3、編譯執行,檢視效果
寫在最後
如果你閒著無聊沒什麼事做,建議去學習或者做自己不擅長的事,這樣時間會過得很快,不做情緒的奴隸,只做快樂的小跟班
。
到此編輯功能開發完畢,有興趣的同學,請自行嘗試!
堅持下去,其實你就是大神!