• 寻找写代码感觉(十三)之 编辑功能的开发


    写在前面

    昨晚又失眠了,四点半才睡着,还做了两个很糟心的梦,八点半就醒了,感觉好累,好想一醉方休呀,不行呀,害怕酒驾,哈哈哈。

    今年要做的事依旧很多,必须行动起来,自己尽管努力就好,剩下就看天意了。

    任务拆解

    上篇文章已经把前端页面画好,那么现在就是写后端逻辑的过程了,也就是编辑后的保存功能,拆解如下:

    • 增加后端保存接口
    • 点击保存时,调用保存接口
    • 保存成功刷新列表

    编辑功能实现

    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',
             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 {
       50px;
      height: 50px;
    }
    </style>
    

    知识点:

    • 响应式变量声明,贯穿始终,需要慢慢使用;
    • 入参是json对象,所以在controller中需要加入@RequestBody
    • 在table组件使用时需要加上 @change="handleTableChange"handleTableChange为方法实现分页跳转
    • 前端代码也需要好好处理下,让人看起来不那么难受至少,惭愧呀,因为我的变量声明和使用扔的哪都是,尴尬

    3、编译运行,查看效果

    写在最后

    如果你闲着无聊没什么事做,建议去学习或者做自己不擅长的事,这样时间会过得很快,不做情绪的奴隶,只做快乐的小跟班

    到此编辑功能开发完毕,有兴趣的同学,请自行尝试!

    坚持下去,其实你就是大神!

  • 相关阅读:
    PMP工具与技术篇--4.2.1-4 思维导图(数据表现技术)
    PMP工具与技术篇--4.2.1-3 决策--多标准决策分析技术
    PMP工具与技术篇--4.2.1-2 决策--投票(举手表决)
    PMP工具与技术篇--4.2.1-1 标杆对照技术(数据收集技术)
    PMP工具与技术篇--4.2.1 收集需求工具与技术总结
    PMP--4.2.1-2 需求跟踪矩阵
    PMP--4.2.1-1 需求文件
    PMP--4.2.1 收集需求--需求文件--需求跟踪矩阵
    PMP工具与技术篇--4.2 备案分析(数据分析技术)
    PMP--4.2-2 开发方法
  • 原文地址:https://www.cnblogs.com/longronglang/p/15861542.html
Copyright © 2020-2023  润新知