全部开发者教程

企业级在线办公系统

上节课我们用Swagger测试了Web方法,可以创建报销申请,数据表中的记录我们都看到了。这节课我们把前端JS代码写了,然后就可以在VUE页面上测试创建报销申请了。

图片描述

一、熟悉前端页面

创建报销申请的弹窗页面是reim-add.vue,弹窗页面虽然内容比较复杂,但是模型层比较简单,所以我们先来看看模型层的代码。

data: function() {
    return {
        visible: false,
        dataForm: {
            type: '普通报销',
            anleihen: null,
            project: []
        },
        dataRule: {
            anleihen: [
                {
                    required: true,
                    pattern: '(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)',
                    message: '金额格式错误'
                }
            ]
        }
    };
},

虽然视图层的代码有点多,但是认真阅读也能理解其中的意思。我们现在写的是普通报销,差旅报销部分,我放在本章附录中,大家可以课后实现一下。

<el-dialog title="报销申请" :close-on-click-modal="false" v-model="visible" width="550px">
    <el-scrollbar height="470px">
        <el-form :model="dataForm" ref="dataForm" :rules="dataRule" label-width="100px">
            <el-form-item label="报销种类" prop="type">
                <el-radio-group v-model="dataForm.type" size="medium">
                    <el-radio-button label="普通报销"></el-radio-button>
                    <el-radio-button label="差旅报销"></el-radio-button>
                </el-radio-group>
            </el-form-item>
            <el-form-item label="借款金额" prop="anleihen">
                <el-input
                    v-model="dataForm.anleihen"
                    placeholder="借款金额"
                    size="medium"
                    style="width:160px;"
                    clearable="clearable"
                    prop="anleihen"
                />
                <span class="note">请如实填写借款金额</span>
            </el-form-item>
            <div v-for="(one, $index) in dataForm.project" class="project">
                <h3>【 报销项目 】</h3>
                <i class="el-icon-delete icon-delete" @click="deleteProjectHandle($index)"></i>
                <el-form-item
                    label="项目名称"
                    :prop="'project.' + $index + '.title'"
                    :rules="{
                        required: true,
                        message: '项目名称必填'
                    }"
                >
                    <el-input v-model="one.title" size="medium" style="width:95%" maxlength="20" clearable />
                </el-form-item>
                <el-form-item
                    label="项目类别"
                    :prop="'project.' + $index + '.type'"
                    :rules="{
                        required: true,
                        message: '项目类别必填'
                    }"
                >
                    <el-select v-model="one.type" class="input" size="medium" clearable>
                        <el-option label="办公用品" value="办公用品" />
                        <el-option label="招待费" value="招待费" />
                        <el-option label="采购费" value="采购费" />
                        <el-option label="劳务费" value="劳务费" />
                        <el-option label="培训费" value="培训费" />
                        <el-option label="维修费" value="维修费" />
                        <el-option label="办公费" value="办公费" />
                        <el-option label="其他" value="其他" />
                    </el-select>
                    <span class="note">请选择项目报销的类别</span>
                </el-form-item>
                <el-form-item label="备注信息" prop="projectDesc">
                    <el-input
                        v-model="one.desc"
                        type="textarea"
                        size="medium"
                        maxlength="50"
                        style="width:95%"
                        resize="none"
                        show-word-limit
                        clearable
                    />
                </el-form-item>
                <el-form-item
                    label="报销金额"
                    :prop="'project.' + $index + '.money'"
                    :rules="{
                        required: true,
                        pattern: '(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)',
                        message: '报销金额必填'
                    }"
                >
                    <el-input v-model="one.money" size="medium" style="width:160px;" clearable />
                    <span class="note">认真核对该项目的报销金额</span>
                </el-form-item>
            </div>
        </el-form>
    </el-scrollbar>
    <template #footer>
        <span class="dialog-footer">
            <el-button type="danger" size="medium" @click="addHandle">添加项目</el-button>
            <el-button size="medium" @click="visible = false">取消</el-button>
            <el-button type="primary" size="medium" @click="dataFormSubmit">确定</el-button>
        </span>
    </template>
</el-dialog>

该页面的init()函数也应该简单了解一下,弹窗页面中自带的报销项目其实就是往project数组中添加了一个元素而已。

init: function() {
    let that = this;
    that.visible = true;
    that.$nextTick(() => {
        that.$refs['dataForm'].resetFields();
        that.dataForm.type = '普通报销',
        that.dataForm.anleihen = null,
        that.dataForm.project = [{ title: null, type: null, desc: null, money: null }];
    });
},

二、动态添加/删除报销项目

动态添加报销项目按钮的点击事件回调函数是addHandle(),无非就是往project数据中追加一个新元素而已,但是每笔报销申请不能超过5个报销项目。

addHandle: function() {
    let that = this;
    if (that.dataForm.project.length == 5) {
        that.$message({
            message: '这笔报销不能超过5个报销项目',
            type: 'warning',
            duration: 1200
        });
        return;
    }
    that.dataForm.project.push({ title: null, type: null, desc: null, money: null });
    that.$message({
        message: '添加成功',
        type: 'success',
        duration: 1200
    });
},

每个报销项目标题的右侧有垃圾桶图标,用户点击该图标就能删除当前的报销项目,但是如果仅剩一个报销项目是不能删除的。

deleteProjectHandle: function(index) {
    let that = this;
    if (that.dataForm.project.length == 1) {
        that.$message({
            message: '不能删除仅存的报销项目',
            type: 'warning',
            duration: 1200
        });
    } else {
        that.dataForm.project.splice(index, 1);
        that.$message({
            message: '删除成功',
            type: 'success',
            duration: 1200
        });
    }
},

三、提交Ajax请求,创建报销申请

用户填写好报销申请,点击确定按钮,按理说应该发出Ajax请求,但是我们需要先把报销总金额和差额给计算出来。为了避免从文本框中取出字符串,干扰加法计算,所以要先转换成数字类型。提交的content数据需要转换成JSON格式的字符串,所以需要转义。

dataFormSubmit: function() {
    let that = this;
    this.$refs['dataForm'].validate(valid => {
        if (valid) {
            let amount = 0;
            for (let one of that.dataForm.project) {
                amount += Number(one.money);
            }
            let data = {
                typeId: that.dataForm.type == '普通报销' ? 1 : 2,
                amount: amount,
                anleihen: that.dataForm.anleihen,
                balance: amount - Number(that.dataForm.anleihen),
                content: JSON.stringify(that.dataForm.project)
            };
            that.$http(`reim/insert`, 'POST', data, true, function(resp) {
                if (resp.rows == 1) {
                    that.$message({
                        message: '操作成功',
                        type: 'success',
                        duration: 1200
                    });
                    that.visible = false;
                    that.$emit('refreshDataList');
                } else {
                    that.$message({
                        message: '操作失败',
                        type: 'error',
                        duration: 1200
                    });
                }
            });
        }
    });
}

四、显示弹窗页面

reim.vue页面已经引用了reim-add.vue弹窗,所以我们把新增按钮的点击事件回调函数给写一下,然后大家就可以调试前端程序了。

<el-button size="medium" type="primary" @click="addHandle()">新增</el-button>
addHandle: function() {
    this.addVisible = true;
    this.$nextTick(() => {
        this.$refs.add.init();
    });
},