零基础快速开发Vue图书管理系统—主体列表实现篇(四)

简介: 零基础快速开发Vue图书管理系统—主体列表实现篇(四)

一、书籍编辑操作

服务端相关代码

const Router = require('@koa/router');
const mongoose = require('mongoose');
const { getBody } = require('../../helpers/utils')
const BOOK_CONST = {
    IN: 'IN_COUNT',
    OUT: 'OUT_COUNT',
}
const Book = mongoose.model('Book');
const router = new Router({
    prefix: '/book',
});
router.post('/add', async(ctx) => {
    const {
        name,
        price,
        author,
        publishDate,
        classify,
        count
    } = getBody(ctx);
    const book = new Book({
        name,
        price,
        author,
        publishDate,
        classify,
        count
    });
    const res = await book.save();
    ctx.body = {
        data: res,
        code: 1,
        msg: '添加成功'
    };
});
router.get('/list', async(ctx) => {
    const {
        page = 1,
            size = 10,
            keyword = ''
    } = ctx.query;
    //1 20
    //2 20
    //3 40 
    const query = {};
    if (keyword) {
        query.name = keyword;
    }
    const list = await Book
        .find(query)
        //实现分页效果
        .skip((page - 1) * size)
        .limit(size)
        .exec();
    const total = await Book.countDocuments();
    ctx.body = {
        data: {
            list,
            total,
            page,
            size,
        },
        code: 1,
        msg: '获取列表成功'
    };
});
router.delete('/:id', async(ctx) => {
    const { id } = ctx.params;
    const delMsg = await Book.deleteOne({
        _id: id,
    });
    ctx.body = {
        data: delMsg,
        msg: '删除成功',
        code: 1,
    };
});
router.post('/update/count', async(ctx) => {
    const { id, type } = ctx.request.body;
    let { num, } = ctx.request.body;
    num = Number(num);
    const book = await Book.findOne({
        _id: id,
    }).exec();
    if (!book) {
        ctx.body = {
            code: 0,
            msg: '没有找到书籍'
        };
        return;
    }
    //找到了书
    if (type === BOOK_CONST.IN) {
        //入库操作
        num = Math.abs(num);
    } else {
        //出库操作
        num = -Math.abs(num);
    }
    book.count = book.count + num;
    if (book.count < 0) {
        ctx.body = {
            code: 0,
            msg: '剩下的量不足以出库'
        };
        return;
    }
    const res = await book.save();
    ctx.body = {
        data: res,
        code: 1,
        msg: '操作成功'
    };
});
router.post('/update', async(ctx) => {
    const {
        id,
        // name,
        // price,
        // author,
        // publishDate,
        // classify
        //剩余参数运算符
        ...others
    } = ctx.request.body;
    const one = await Book.findOne({
        _id: id,
    }).exec();
    //没有找到书
    if (!one) {
        ctx.body = {
            msg: '没有找到书籍',
            code: 0,
        }
        return;
    }
    const newQuery = {};
    Object.entries(others).forEach(([key, value]) => {
        if (value) {
            newQuery[key] = value;
        }
    });
    Object.assign(one, newQuery);
    const res = await one.save();
    ctx.body = {
        data: res,
        code: 1,
        msg: '保存成功'
    };
});
module.exports = router;

客户端相关代码:

<template>
    <div>
        <a-modal title="添加书籍" 
        :visible="props.show" 
        @ok="submit" 
        @cancel="close">
            <a-form :label-col="{span:6}">
                <a-form-item label="书名">
                    <a-input v-model:value="editForm.name" />
                </a-form-item>
                <a-form-item label="价格">
                    <a-input-number v-model:value="editForm.price" :min="0" :max="9999999" />
                </a-form-item>
                <a-form-item label="作者">
                    <a-input v-model:value="editForm.author" />
                </a-form-item>
                <a-form-item label="出版日期">
                    <a-date-picker v-model:value="editForm.publishDate" />
                </a-form-item>
                <a-form-item label="分类">
                    <a-input v-model:value="editForm.classify" />
                </a-form-item>
            </a-form>
        </a-modal>
    </div>
</template>
<script src="./index.js">
</script>
<style lang="scss" scoped>
    @import './index.scss'
</style>
import { defineComponent, reactive, watch } from 'vue'
import { book } from '@/service';
import { message } from 'ant-design-vue'
import { result, clone } from '../../../helpers/utils/index';
import moment from 'moment';
export default defineComponent({
    props: {
        show: Boolean,
        book: Object,
    },
    setup(props, context) {
        const editForm = reactive({
            name: '',
            price: 0,
            author: '',
            publishDate: 0,
            classify: '',
        })
        const close = () => {
            context.emit('update:show', false);
        };
        watch(() => props.book, (current) => {
            Object.assign(editForm, current);
            editForm.publishDate = moment(Number(editForm.publishDate));
        });
        const submit = async() => {
            const res = await book.update({
                id: props.book._id,
                //…扩展运算符
                name: editForm.name,
                price: editForm.price,
                author: editForm.author,
                publishDate: editForm.publishDate.valueOf(),
                classify: editForm.classify,
            });
            result(res)
                .success(({ data, msg }) => {
                    context.emit('update', data);
                    message.success(msg);
                    close();
                })
        }
        return {
            editForm,
            submit,
            props,
            close,
        }
    }
})

二、书籍详情页面开发

<template>
    <div>
        <a-card>
            <space-between>
                <h2>书籍的名字</h2>
                <div>
                    <a-button size="small" type="primary">编辑</a-button>
                    &nbsp;
                    <a-button size="small" type="danger">删除</a-button>
                </div>
            </space-between>
            <a-divider></a-divider>
            <div class="base-info">
                <div class="items">
                    <div class="item">
                        <div class="title">价格</div>
                        <div class="content">1</div>
                    </div>
                    <div class="item">
                        <div class="title">作者</div>
                        <div class="content">2</div>
                    </div>
                    <div class="item">
                        <div class="title">分类</div>
                        <div class="content">3</div>
                    </div>
                </div>
                <div class="items">
                    <div class="item">
                        <div class="title">出版日期</div>
                        <div class="content">4</div>
                    </div>
                </div>
            </div>
        </a-card>
        <div class="log">
            <a-card title="出入库日志">
                <template #extra>
                    <span>
                        <a href="javascript:;">出库日志</a>
                    </span>
                    <span style="margin-left:12px">
                        <a href="javascript:;">入库日志</a>
                    </span>
                </template>
                <div>
                    <a-table bordered :pagination="false"></a-table>
                </div>
                <space-between style="margin-top:24px">
                    <div />
                    <a-pagination></a-pagination>
                </space-between>
            </a-card>
        </div>
    </div>
</template>
<script src="./index.js">
</script>
<style lang="scss" scoped>
    @import './index.scss'
</style>

三、书籍详情接口实现

四、库存日志相关内容实现

import { defineComponent, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { book, inventoryLog } from '@/service'
import { result, formatTimestamp } from '@/helpers/utils';
import { CheckOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import Update from '@/views/Books/Update/index'
const columns = [{
        title: '数量',
        dataIndex: 'num',
    },
    {
        title: '操作时间',
        slots: {
            customRender: 'createdAt'
        }
    }
]
export default defineComponent({
    components: {
        Update,
        CheckOutlined
    },
    setup() {
        const route = useRoute();
        const router = useRouter();
        const showUpdateModal = ref(false);
        const { id } = route.params;
        const detailInfo = ref({});
        const log = ref([]);
        const logTotal = ref(0);
        const logCurPage = ref(1);
        const curLogType = ref('IN_COUNT')
        const getDetail = async() => {
            const res = await book.detail(id);
            result(res)
                .success(({ data }) => {
                    detailInfo.value = data;
                })
        };
        //获取出库入库日志
        const getInventoryLog = async() => {
            const res = await inventoryLog.list(
                curLogType.value,
                logCurPage.value,
                10);
            result(res)
                .success(({ data: { list, total } }) => {
                    log.value = list;
                    logTotal.value = total;
                })
        };
        onMounted(() => {
            getDetail();
            getInventoryLog();
        });
        const remove = async() => {
            const res = await book.remove(id);
            result(res)
                .success(({ msg }) => {
                    message.success(msg);
                    router.replace('/books')
                });
        };
        //更新操作
        const update = (book) => {
            Object.assign(detailInfo.value, book)
        };
        //日志分页切换的时候
        const setLogPage = (page) => {
            logCurPage.value = page;
            getInventoryLog();
        };
        //筛选日志
        const logFilter = (type) => {
            curLogType.value = type;
            getInventoryLog();
        };
        return {
            d: detailInfo,
            formatTimestamp,
            remove,
            showUpdateModal,
            update,
            log,
            logTotal,
            setLogPage,
            columns,
            logFilter,
            curLogType,
            logCurPage
        }
    }
});
<template>
    <div>
        <a-card>
            <space-between>
                <h2>{{d.name}}</h2>
                <div>
                    <a-button size="small" type="primary" @click="showUpdateModal=true">编辑</a-button>
                    &nbsp;
                    <a-button size="small" type="danger" @click="remove">删除</a-button>
                </div>
            </space-between>
            <a-divider />
            <div class="base-info">
                <div class="items">
                    <div class="item">
                        <div class="title">价格</div>
                        <div class="content">{{d.price}}</div>
                    </div>
                    <div class="item">
                        <div class="title">作者</div>
                        <div class="content">{{d.author}}</div>
                    </div>
                    <div class="item">
                        <div class="title">分类</div>
                        <div class="content">{{d.classify}}</div>
                    </div>
                </div>
                <div class="items">
                    <div class="item">
                        <div class="title">出版日期</div>
                        <div class="content">{{formatTimestamp(d.publishDate)}}</div>
                    </div>
                </div>
            </div>
        </a-card>
        <div class="log">
            <a-card title="出入库日志">
                <template #extra>
                    <span>
                        <a href="javascript:;" @click="logFilter('IN_COUNT')">
                            <CheckOutlined v-if="curLogType==='IN_COUNT'" />
                            入库日志</a>
                    </span>
                    <span style="margin-left:12px">
                        <a href="javascript:;" @click="logFilter('OUT_COUNT')">
                            <CheckOutlined v-if="curLogType==='OUT_COUNT'" />
                            出库日志</a>
                    </span>
                </template>
                <div>
                    <a-table :data-source="log" :columns="columns" bordered :pagination="false">
                        <template #createdAt="{record}">
                            {{ formatTimestamp(record.meta.createdAt) }}
                        </template>
                    </a-table>
                </div>
                <space-between style="margin-top:24px">
                    <div />
                    <a-pagination 
                    v-model:current="logCurPage" 
                    :total="logTotal" 
                    :page-size="10" 
                    @change="setLogPage">
                    </a-pagination>
                </space-between>
            </a-card>
        </div>
        <update v-model:show="showUpdateModal" :book="d" @update="update" />
    </div>
</template>
<script src="./index.js">
</script>
<style lang="scss" scoped>
    @import './index.scss'
</style>

五、书籍相关内容的优化

给列表增加排序功能


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
4天前
|
缓存 监控 JavaScript
探讨优化Vue应用性能和加载速度的策略
【5月更文挑战第17天】本文探讨了优化Vue应用性能和加载速度的策略:1) 精简代码和组件拆分以减少冗余;2) 使用计算属性和侦听器、懒加载、预加载和预获取优化路由;3) 数据懒加载和防抖节流处理高频事件;4) 图片压缩和选择合适格式,使用CDN加速资源加载;5) 利用浏览器缓存和组件缓存提高效率;6) 使用Vue Devtools和性能分析工具监控及调试。通过这些方法,可提升用户在复杂应用中的体验。
16 0
|
5天前
|
JavaScript 前端开发
vue(1),小白看完都会了
vue(1),小白看完都会了
|
3天前
|
监控 安全 NoSQL
采用java+springboot+vue.js+uniapp开发的一整套云MES系统源码 MES制造管理系统源码
MES系统是一套具备实时管理能力,建立一个全面的、集成的、稳定的制造物流质量控制体系;对生产线、工艺、人员、品质、效率等多方位的监控、分析、改进,满足精细化、透明化、自动化、实时化、数据化、一体化管理,实现企业柔性化制造管理。
28 3
|
4天前
|
JavaScript 开发工具 git
Vue 入门系列:.env 环境变量
Vue 入门系列:.env 环境变量
10 1
|
5天前
|
JavaScript 前端开发 定位技术
Vue使用地图以及实现轨迹回放 附完整代码
Vue使用地图以及实现轨迹回放 附完整代码
Vue使用地图以及实现轨迹回放 附完整代码
|
5天前
|
JavaScript
Vue中避免滥用this去读取data中数据
Vue中避免滥用this去读取data中数据
|
5天前
|
JavaScript
vue中使用pinia及持久化
vue中使用pinia及持久化
8 0
|
5天前
|
JavaScript 前端开发 UED
Vue class和style绑定:动态美化你的组件
Vue class和style绑定:动态美化你的组件
|
5天前
|
JavaScript 数据库
ant design vue日期组件怎么清空 取消默认当天日期
ant design vue日期组件怎么清空 取消默认当天日期
|
5天前
|
JavaScript C++
vue高亮显示组件--转载
vue高亮显示组件--转载
9 0