前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于华为AppCube搭建图书管理系统

基于华为AppCube搭建图书管理系统

作者头像
玛卡bug卡
发布2022-09-20 11:05:25
5220
发布2022-09-20 11:05:25
举报
文章被收录于专栏:Java后端修炼Java后端修炼

一、背景

由于之前有多次的低码平台开发经验,对利用低码平台开发有一定的积累,因此在华为云智慧校园大赛期间受组委会老师的邀请,开始制作文章以及视频讲解,从一个普通学生的视角出发,演示如何在AppCube平台上设计开发一个应用。主要方向是在平台理论实践指导基础上,对应用开发的路线进行大致的梳理,帮助参赛者去进行应用的构建,促进应用成型落地。回顾自己学习、上手平台的过程,很大程度都是依靠平台的文档去完成初步的认识,然后通过实操训练不断巩固,因此更加确信了实践的重要性。在有多次开发经验的背景下,我也希望我的学习历程以及掌握的知识可以帮助到更多的参赛者更快的熟悉和应用AppCube平台,真正的能够使用这一平台去实现应用的落地。

二、应用设计构思

这个应用主要是讲解如何完成一个应用的构建,所以逻辑和功能上都比较简单。该应用为图书管理系统,应用设计主要分为四步走:

1.确定应用功能

最基本的就是贡献图书、借阅图书、归还图书这三个功能点;

2.数据库设计

功能确定之后,需要一个数据库表用于存储数据,这里利用的是平台的对象建立功能,用于存储图书的各种信息;

3.前端展示

有了数据之后,还需要前端页面展示,因此需要用到平台的标准页面,在模型视图中添加对应的数据模型映射到我们之前建好的数据对象,然后由页面上的组件去从模型中获取数据,并展示给用户;

4.后端逻辑

数据展示模块也敲定了,那么当用户在贡献图书、借归图书时需要对数据进行操作,这怎么实现呢?答案是建立一个脚本去操作数据对象,对数据进行增删改查等。完成脚本功能之后还需要回到标准页面,将脚本和对应的组件去进行绑定。

三、应用设计剖析

1.对象建立

新建一个对象BookInfos,用于存储图书信息。字段设计方面,复用平台标准字段name,更改标签名为图书名称,新建七个自定义字段,分别为类别【选项】、简介【文本区】、作者【文本】、贡献者【查找user】、当前状态【选项】、当前借阅人【查找user】、借阅时间【时间】。其中状态选项为:闲置、借阅中;

2.后端脚本

新建脚本editBookInfo,用于添加、修改图书信息。用户在贡献、借阅、归还图书时调用该脚本。确定脚本入参为图书信息对象,由前端页面模型传入。出参为图书信息ID,指示脚本执行情况;

代码语言:javascript
复制
//本脚本用于新增或者修改信息
import * as db from 'db';//导入处理object相关的标准库
import * as context from 'context';//导入上下文相关的标准库
import * as date from 'date';
import * as buffer from 'buffer';

//定义入参结构,入参包含1个参数:业务对象,为必填字段
@action.object({ type: "param" })
export class ActionInput {
    @action.param({ type: 'Struct', required: true, label: 'object' })
    bookInfo: object;
}

//定义出参结构,出参包含1个参数,记录业务对象的id
@action.object({ type: "param" })
export class ActionOutput {
    @action.param({ type: 'String' })
    bookInfoId: string;
}

//使用数据对象h0ssapp__BookInfos__CST
@useObject(['h0ssapp__BookInfos__CST'])
@action.object({ type: "method" })
export class EditBookInfo {    //定义接口类,接口的入参为ActionInput,出参为ActionOutput
    @action.method({ input: 'ActionInput', output: 'ActionOutput' })
    public editBookInfo(input: ActionInput): ActionOutput {
        let out = new ActionOutput();    //新建出参ActionOutput类型的实例,作为返回值
        let error = new Error();    //新建错误类型的实例,用于在发生错误时保存错误信息
        try {
            let bookInfo = input.bookInfo;    //将入参赋值给bookInfo变量,方便后面使用
             //获取h0ssapp__BookInfos__CST这个Object的操作实例
            let s = db.object('h0ssapp__BookInfos__CST');   
            //贡献图书
            if (!bookInfo['id']) {
                bookInfo['h0ssapp__contributor__CST'] = context.getUserId();
                bookInfo['h0ssapp__status__CST'] = 'free';
                //向h0ssapp__BookInfos__CST插入一条数据,返回数据的唯一标识
                let bookInfoId = s.insert(bookInfo);   
                if (bookInfoId && bookInfoId != "") {
                    out.bookInfoId = bookInfoId;
                }
                else {
                    error.name = "EM";
                    error.message = "bookInfo Cannot Be Added.";
                    throw error;
                }

            }
            //修改图书状态信息
            else {
                // 归还图书
                if (bookInfo['h0ssapp__status__CST'] == "free") {
                    bookInfo['h0ssapp__borrower__CST'] = null;
                    bookInfo['h0ssapp__borrowTime__CST'] = null;
                }
                // 借阅图书
                else if (bookInfo['h0ssapp__status__CST'] == "borrowed") {
                    bookInfo['h0ssapp__borrower__CST'] = context.getUserId();
                    bookInfo['h0ssapp__borrowTime__CST'] = date.format(new Date(), 'yyyy-MM-dd HH:mm:ss', context.getTimeZone());
                }
                console.log(bookInfo);
                let id = bookInfo['id'];
                delete bookInfo['id'];
                //根据图书信息ID,编辑更新h0ssapp__BookInfos__CST的一条数据
                let count = s.update(id, bookInfo);    
                if (count && count == 1) {
                    out.bookInfoId = id;
                }
                else {
                    error.name = "EM";
                    error.message = "bookInfo Cannot Be Updated.";
                    throw error;
                }
            }
        } catch (error) {
            console.error(error.name, error.message);
            context.setError(error.name, error.message);
        }
        return out;
    }
}

3.前端页面

a、新建贡献图书页面,页面设置标题组件以及表单组件,表单用于获取用户输入的图书信息,点击提交后调用后端脚本,将信息添加到BookInfos对象中;

代码语言:javascript
复制
/**************************
** “贡献图书”按钮事件
***************************/
// 当前组件
let _component = context.getCurrentComponent();
//校验表单
_component.getForm().formValidate().then((val) => {
    //校验成功
    //从自定义模型bookInfo中获取界面表单数据
    let data = $model.ref('bookInfo').getData();
    if (data) {
        //构造Script的入参
        let inputs = data;
        //获取服务模型addBookInfo,执行模型的action,即执行模型关联的Script
        let _model = $model.ref('addBookInfo');
        _model.setValue('inputParam', { "bookInfo": inputs });
        _model.run().then(() => {
            //提交成功后显示提示信息
            this.$dialog.success({ title: '成功', content:'图书贡献成功'});
        }).catch((e) => {
            this.$dialog.error({
                title: '错误',
                content: e.resMsg
            })
        });
    }
}).catch((error) => {
});

b、新建借阅图书界面,页面设置标题组件以及表格容器组件,容器中分条显示当前闲置的图书信息,并且每条信息提供一个“借阅”按钮,用于完成借阅操作;

代码语言:javascript
复制
/**************************
** “借阅图书”按钮事件
***************************/
//获取当前组件(即table)
let _component = context.$component.current;
//获取当前行row
let data = _component.$attrs.row;
context.$dialog.confirm(
    {
        title: '借阅',
        content: '确认借阅该图书吗?',
        okText: '确定',
        cancelText: '取消',
        onOk: () => {
            data.h0ssapp__status__CST = "borrowed";
            delete data['_uid'];
            delete data['_index'];
            let inputs = data;
            //获取服务模型editBookInfo,执行模型的action,即执行模型关联的Script
            let _model = $model.ref("editBookInfo");
            _model.setValue('inputParam', { "bookInfo": inputs });
            _model.run().then(() => {
                //借阅成功弹出提示框
                this.$dialog.success({title: '成功',content: "借阅成功"});
                // 刷新表格信息
                let _table = context.$component.get('table_0');
                // 条件查询组件数据模型
                let condition = $model.ref("table_0_condition").getData();
                condition["queryInfo"]["h0ssapp__status__CST"] = "free";
                // 执行查询
                _table.doQuery();

            }).catch((e) => {
                this.$dialog.error({
                    title: '错误',
                    content: e.resMsg
                })
            });

        },
        onCancel: () => { }
    }
)
代码语言:javascript
复制
/**************************
** “查询空闲图书”事件
***************************/
//第一种方法
// 当前表格,通过表格控件名称获取
let _table = context.$component.get('table_0');
// 条件查询组件数据模型
let condition = $model.ref("table_0_condition").getData();
condition["queryInfo"]["h0ssapp__status__CST"] = "free";
// 执行查询
_table.doQuery();

c、新建归还图书界面,设置标题组件以及表格容器组件,显示当前用户的所有借阅图书信息,每条信息后添加“归还”按钮,用于完成归还操作。

代码语言:javascript
复制
/**************************
** “搜索”按钮事件
***************************/
// 当前表格,通过表格控件名称获取
let _table = context.$component.get('table_0');
let userId = context.$user.userId;
console.log(userId);
// 条件查询组件数据模型
let condition = $model.ref("table_0_condition").getData();
console.log(condition);
condition["queryInfo"]["h0ssapp__status__CST"] = "borrowed";
condition["queryInfo"]["h0ssapp__borrower__CST"] = userId;
console.log(condition);
// 执行查询
_table.doQuery();
代码语言:javascript
复制
/**************************
** “归还图盛”按钮事件
***************************/
//获取当前组件(即table)
let _component = context.$component.current;
//获取当前行row
let data = _component.$attrs.row;
context.$dialog.confirm(
    {
        title: '归还',
        content: '确认归还该图书吗?',
        okText: '确定',
        cancelText: '取消',
        onOk: () => {
            data.h0ssapp__status__CST = "free";
            delete data['_uid'];
            delete data['_index'];
            let inputs = data;
            //获取服务模型editBookInfo,执行模型的action,即执行模型关联的Script
            let _model = $model.ref("editBookInfo");
            _model.setValue('inputParam', { "bookInfo": inputs });
            _model.run().then(() => {
                //借阅成功弹出提示框
                this.$dialog.success({title: '成功',content: "归还成功"});
                // 刷新表格信息
                let _table = context.$component.get('table_0');
                let userId = context.$user.userId;
                // 条件查询组件数据模型
                let condition = $model.ref("table_0_condition").getData();
                condition["queryInfo"]["h0ssapp__status__CST"] = "borrowed";
                condition["queryInfo"]["h0ssapp__borrower__CST"] = userId;
                // 执行查询
                _table.doQuery();

            }).catch((e) => {
                this.$dialog.error({
                    title: '错误',
                    content: e.resMsg
                })
            });

        },
        onCancel: () => { }
    }
)

四、总结

本次分享仅展示如何通过AppCube平台快速搭建一个应用的流程,所以应用的内部逻辑、页面展示方面可能并不完美。所有人都可以基于本次分享的流程以及自己的想法去完成一个属于自己的应用,或者接着这一思路去拓展其他应用,增加一些复杂的逻辑、功能和设计,完成一个功能更加强大、页面更加美观的校园应用。

总的来说,用低码平台开发可以用到预置的模板,对于一些简单的内部应用来说,用这种方法构建会省时省力很多,同时也比较适合于重点关注于系统内部逻辑的应用的构建,适用于开发者即时实现想法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端修炼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档