尋找寫程式碼感覺(十三)之 編輯功能的開發

久曲健發表於2022-02-03

寫在前面

昨晚又失眠了,四點半才睡著,還做了兩個很糟心的夢,八點半就醒了,感覺好累,好想一醉方休呀,不行呀,害怕酒駕,哈哈哈。

今年要做的事依舊很多,必須行動起來,自己儘管努力就好,剩下就看天意了。

任務拆解

上篇文章已經把前端頁面畫好,那麼現在就是寫後端邏輯的過程了,也就是編輯後的儲存功能,拆解如下:

  • 增加後端儲存介面
  • 點選儲存時,呼叫儲存介面
  • 儲存成功重新整理列表

編輯功能實現

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、編譯執行,檢視效果

寫在最後

如果你閒著無聊沒什麼事做,建議去學習或者做自己不擅長的事,這樣時間會過得很快,不做情緒的奴隸,只做快樂的小跟班

到此編輯功能開發完畢,有興趣的同學,請自行嘗試!

堅持下去,其實你就是大神!

相關文章