为了账号安全,请及时绑定邮箱和手机立即绑定

【学习打卡】第13天 报销管理模块

标签:
Java Vue.js

课程名称: SpringBoot+Vue3 项目实战,打造企业级在线办公系统
课程章节: 第9章 报销管理
主讲老师: 神思者

课程内容

在Emos当中,员工可以在管理页面上进行报销申请,然后管理员审批通过以后,能够生成pdf的费用报销单文件。详细可以查看思维导图:
图片描述

费用报销的具体时序图参考如下:

图片描述

同样也去请求了工作流项目,在工作流项目上发起申请。然后申请工单,审批通过以后,生成PDF文件。

课程收获

使用异步线程开启工作流审批

创建报销申请,既要向tb_reim表保存数据,还要创建工作流实例,所以我们先把异步线程任务类创建出来,调用工作流项目的Web方法。

URI路径:/workflow/startReimProcess

序号 参数 类型 含义
1 url String 接收审批结果的URL地址
2 creatorId String 申请人userId
3 creatorName String 申请人姓名
4 code String 慕课网授权字符串
5 tcode String 课程授权字符串
6 title String 报销申请标题
7 managerId int 部门经理的userId
8 gmId int 总经理的userId

com.example.emos.api.task包中创建ReimWorkflowTask.java类,代码如下:

@Component
@Slf4j
public class ReimWorkflowTask {
    @Value("${emos.code}")
    private String code;

    @Value("${emos.tcode}")
    private String tcode;

    @Value("${workflow.url}")
    private String workflow;

    @Value("${emos.recieveNotify}")
    private String recieveNotify;

    @Autowired
    private TbUserDao userDao;

    @Autowired
    private TbReimDao reimDao;

    @Async("AsyncTaskExecutor")
    public void startReimWorkflow(int id, int creatorId) {
        HashMap info = userDao.searchUserInfo(creatorId);
        JSONObject json = new JSONObject();
        json.set("url", recieveNotify);
        json.set("creatorId", creatorId);
        json.set("creatorName", info.get("name").toString());
        json.set("code", code);
        json.set("tcode", tcode);
        json.set("title", info.get("dept").toString() + info.get("name").toString() + "的报销");
        Integer managerId = userDao.searchDeptManagerId(creatorId);
        json.set("managerId", managerId);
        Integer gmId = userDao.searchGmId();
        json.set("gmId", gmId);

        String url = workflow + "/workflow/startReimProcess";
        HttpResponse resp = HttpRequest.post(url).header("Content-Type", "application/json")
                .body(json.toString()).execute();
        if (resp.getStatus() == 200) {
            json = JSONUtil.parseObj(resp.body());
            String instanceId = json.getStr("instanceId");
            HashMap param = new HashMap();
            param.put("id", id);
            param.put("instanceId", instanceId);
            int rows = reimDao.updateReimInstanceId(param);
            if (rows != 1) {
                throw new EmosException("保存报销申请工作流实例ID失败");
            }
        } else {
            log.error(resp.body());
        }
    }
}

使用异步线程开启工作流审批

报销离不开发票,所以财务和领导在审批报销的时候要核对员工的报销票据。因此员工先要在报销管理页面下载PDF报销单,打印出来之后,贴好报销的发票。然后找财务和领导审核签字。

图片描述

在报销单的右上角有二维码,内容是该报销申请的工作流实例instance_id。将来我们想要查询某个报销申请的时候,用扫码枪扫描这个二维码,就能查询到报销记录。

此处后端只返回了页面上所需要展示的字段数据,具体渲染实则放在前端实现。

具体代码实现如下:

报销单弹窗是reim_pdf.vue页面,因为要生成PDF文件,所以页面DIV控件设置了id属性,而且属性值必须为pdfDom才行。

<el-dialog width="800px" :close-on-click-modal="false" v-model="visible" :show-close="false" center>
    <div id="pdfDom">
        <img :src="qrCodeBase64" class="qrCode" />
        <h2 class="title">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</h2>
        <div class="top-info-container">
            <span class="info">报销部门:{{ dept }}</span>
            <span class="info">报销人:{{ name }}</span>
            <span class="info">报销日期:{{ date }}</span>
        </div>
        <div class="reim-table-container">
            <table class="reim-table">
                <tr align="center">
                    <th width="30%">报销项目</th>
                    <th width="34%">备注</th>
                    <th width="20%">类别</th>
                    <th width="16%">金额</th>
                </tr>
                <tr align="center" v-for="one in content">
                    <td align="left">{{ one.title }}</td>
                    <td align="left">{{ one.desc }}</td>
                    <td>{{ one.type }}</td>
                    <td align="left">{{ one.money != '' ? one.money + '元' : '' }}</td>
                </tr>
                <tr>
                    <th align="center">报销合计</th>
                    <td colspan="3">{{ amount }}元</td>
                </tr>
                <tr>
                    <th align="center">人民币大写</th>
                    <td colspan="3">{{ smalltoBIG(amount) }}</td>
                </tr>
                <tr>
                    <td colspan="5">
                        <div class="info-container">
                            <span class="info">借款金额:{{ anleihen }}元</span>
                            <span class="info">应退金额:{{ money_1 }}元</span>
                            <span class="info">应补金额:{{ money_2 }}元</span>
                        </div>
                    </td>
                </tr>
            </table>
        </div>
        <div class="bottom-info-container"></div>
        <div class="bottom-info-container">
            <span class="sig">会计主管:</span>
            <span class="sig">复核:</span>
            <span class="sig">出纳:</span>
            <span class="sig">报销人:</span>
        </div>
    </div>
    <template #footer>
        <span class="dialog-footer">
            <el-button type="primary" @click="getPdf()" size="medium">下载报销单</el-button>
            <el-button size="medium" @click="cancel()">关闭窗口</el-button>
        </span>
    </template>
</el-dialog>

写弹窗页面的init()函数,发起Ajax请求查询数据,然后把数据显示到报销单之中。

init: function(id) {
    let that = this;
    that.visible = true;
    that.dept = null;
    that.name = null;
    that.date = null;
    that.amount = null;
    that.balance = null;
    that.anleihen = null;
    that.money_1 = 0;
    that.money_2 = 0;
    that.content = [];
    that.$http('reim/searchReimById', 'POST', { id: id }, true, function(resp) {
        that.dept = resp.dept;
        that.name = resp.name;
        that.date = resp.date;
        that.amount = resp.amount;
        that.balance = resp.balance;
        that.anleihen = resp.anleihen;
        if (that.anleihen > that.amount) {
            that.money_1 = that.anleihen - that.amount;
        } else if (that.anleihen < that.amount) {
            that.money_2 = that.amount - that.anleihen;
        }
        let content = JSON.parse(resp.content);
        let temp = 5 - content.length;
        for (let i = 0; i < temp; i++) {
            content.push({ title: '', desc: '', type: '', money: '' });
        }
        that.content = content;
        that.qrCodeBase64 = resp.qrCodeBase64;
    });
},

下载报销单

main.js文件中封装了生成PDF文件的函数,所以我们调用getPdf()函数即可。

<span class="dialog-footer">
    <el-button type="primary" @click="getPdf()" size="medium">下载报销单</el-button>
    <el-button size="medium" @click="cancel()">关闭窗口</el-button>
</span>

课程截图

image-20220816130637961

image-20220816130703281

image-20220816130727568

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消