本篇实战文章通过给财务模块的收支记账页面增加筛选条件来教大家怎么进行二次开发。你会学到前端和后端的修改,以及整个的思考过程,而不仅仅是直接给你修改的步骤。
【实战目标】:在收支记账列表的顶部增加合同名称和客户名称的筛选。
【实战内容】:
1. 首先我们弄清楚筛选的条件是怎么实现的。
通过浏览器的路径,定位前端页面位置。在这里是/admin/fd/enterprise/list/index。admin对应的是views/目录下的pc目录前端代码。views/pc下的前端代码起点是src/views。然后顺着fd/enterprise/list/index找到对应的前端vue源文件完整路径就是:views\pc\src\views\fd\enterprise\list\index.vue了。
找到源文件后,那我们看看顶部搜索框是怎么实现的。看了一圈index.vue代码似乎没有筛选框的相关文本框,但是可以肯定的是筛选框肯定是在页面顶部对吧,那源代码顶部只有一个formBox组件,那大概率筛选框就是封装在这个组件里面了。
通过引入路径定位到formBox的位置:
formBox: () => import('./components/formBox'),
我们打开它,然后分析一下代码。
分析后发现,里面再次引入了一个oaFromBox的组件,这个组件传入了一个search参数,search的值就刚好对应了已有筛选框的定义。那么这就是列表定义筛选条件的位置。经过对比,陀螺匠其他页面的筛选框都是通过页面的search参数来定义的。
然后我们看看search的字段是怎么定义的:
{
field_name: '支付方式',
field_name_en: 'type_id',
form_value: 'select',
// multiple: true,
data_dict: []
}
field_name应该是筛选条件中文名,field_name_en是对应的数据字段名,form_value应该是字段类型,select代表下拉列表。最重要的应该是data_dict,填充这个下拉列表的选项。我们需要添加合同名称和客户名称实际上也需要用到这样的定义,填充data_dict来做筛选。好的,那第一步就完成了,我们知道了筛选是通过定义search来实现。
2. 修改search的值,添加[客户名称]和[合同名称]筛选条件。
在修改之前,我们先分析一下接口和收支表的数据结构。可以看到列表是通过api/ent/bill/list接口一个POST请求来获取数据的。
数据结构如下图:
可以看到合同信息是有返回的,存储在contract字段,只是默认没有显示出来。如果我们要添加合同的筛选,先要确认search数组当中field_name_en该用哪个字段名,这里contract本身是个对象,具体用什么字段还不好说,先看看后端代码再决定。
前面我们知道了后端接口是api/ent/bill/list,那么我们先定位到接口的后端代码。陀螺匠的后端用的Laravel框架,按照框架的路由规则,我们要定位到接口的源代码,只需要在VSCODE当中搜中间部分的路由就好了。比如在这里我们搜ent/bill,可以看到BillController.php实现了相关的路由方法,可以确定路由的起点就是这个类。然后我们要找的是list方法,在BillController当中list方法首先通过getSearchField获取了搜索参数字段,然后直接调用了BillService的getList方法。
getList的第一个参数$where就是我们客户端提交的search筛选条件,$field是获取哪些字段*代表全部,$sort是排序,$with相当于是联表查询。根据下面的代码,可以分析出来,最终返回结果当中的contract数据就是通过$with定义来获取数据的。我们既然要添加筛选字段,那就得从$where入手。这里的$where没有处理,直接传给了dao的getList,那我们继续打开BillDao.php来继续分析。
通过BillDao的setModel函数,我们知道BillDao关联的数据表是eb_bill,我们用数据库管理工具(宝塔面板的数据库管理)看一下bill表的数据结构,发现这个表并没有存储实际的收支数据,然后通过对比,发现eb_client_bill才是实际存储收支数据的表,并且bill和client_bill之间是用link_id来关联的。然后分析client_bill表,可以看到表当中有cid字段来表示收支来自哪个合同,eid来标记收支是来自哪个客户,那这就是我们要找的合同筛选、客户筛选的实际的字段。
然后我们再看BillDao的getList方法,$where最终是传给了search方法,并且search方法是重写了,针对筛选条件做了预处理。
那我们把合同筛选的字段也放到这里。我这里直接给出实现方案:
①对于合同筛选,我们实际传参是合同ID:前端的field_name_en设置为contract_id,然后在后端针对$where做判断,如果存在contract_id,那么添加一个限定eb_client_bill表cid的where条件,查询出client_bill的记录,再把查询bill列表的link_id限定在查询出来的client_bill范围内。因为BillController.php当中对可筛选的字段做了前期处理,还需要在BillController的getSearchField当中添加contract_id(默认值为空),才能够获取到前端传进来的参数值。
②对于客户筛选,我们实际传参的也是客户ID:前端的field_name_en设置为eid,然后在后端针对$where做判断,如果存在eid,那么添加一个限定eb_client_bill表eid的where条件,查询出client_bill的记录,再把查询bill列表的link_id限定在查询出来的client_bill范围内。因为BillController.php当中对可筛选的字段做了前期处理,还需要在BillController的getSearchField当中添加eid(默认值为空),才能够获取到前端传进来的参数值。
具体写法如下:
在BillDao当中先引入App\Http\Service\Client\ClientBillService;
对于合同ID,先处理好$where当中的contract_id,因为eb_bill当中并不存在contract_id,所以这里取出来后,一定要在$where当中去掉。然后根据cid=contract_id来查询client_bill的记录,取ids。然后限定bill的link_id在ids范围内。
对于客户ID,逻辑是相似的,完整的代码如下。
好了,到这里后端的代码就改好了。
接下来,还需要想办法填充前端下拉列表data_dict的值。对比其他已有的筛选项,和翻看了一下其他列表页的实现方式,我发现项目列表页前端有现成的客户列表和合同列表筛选,和我们需求一致,那我们可以直接拿来用。这里讲一下前端的实现逻辑。因为在陀螺匠当中,客户和合同是关联的,所以这里实际上客户和合同是联动的,也就是选择了客户,然后再选择合同,这样也减少了合同下拉的数量。
先在tableFrom当中增加eid和contract_id定义。
再引入请求接口:
import { selectContractListApi, customerSelectApi } from '@/api/enterprise'
然后我们把views\pc\src\views\program\programList\index.vue的getCustomer方法和getContractList、getContract拷贝过来(注意改cid为contract_id)。然后getCustomer是在页面创建的时候created()方法当中调用。getContractList是在tableFrom.eid值变化的时候调用。
search的新增字段定义如下:
默认情况下,列表里是没有合同名称和客户名称的,这里我们再额外添加一下。在pc\src\views\fd\enterprise\list\index.vue页面,找到el-table标签,然后增加el-table-column标签行来显示合同和客户名称。参考下图。
这样前端代码就修改完成。前端打包请参考官方的文档(地址)。
最终效果如图:
然后别忘了代码修改用Git管理起来。
个人水平有限,如果错误或者更好的实现方式,欢迎指出和交流。有疑问欢迎留言。
最后,介绍一下自己:我是陀螺匠官方服务商,承接陀螺匠的二次开发业务,有需要深度定制OA系统的公司欢迎联系。目前已收陀螺匠定制开发费用2万+。