上节课我们用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();
});
},