Qualitis前端升级改造

Qualitis作为大数据生态中重要的一环,由于历史维护等原因,在功能和体验上有比较多的优化空间,改版迫在眉睫。


功能要点

Qualitis主要由工作概览、我的项目、指标管理、规则管理、数据源管理、任务查询、系统设置、引擎设置八大功能组成,在逻辑上有以下关键点:

1、复制规则组件仅在工作流项目中有效;

2、执行任务是全局组件并需要支持差异化调用;

3、普通项目和工作流项目支持的规则类型相同,包含单表校验、跨表校验、文件校验、跨库校验、单指标校验、多指标校验;

4、每种规则由基础信息、数据源、校验方式、执行参数四部分组成,其中数据源和校验方式的差异较大;

5、单表规则需要支持多种校验模板,并根据校验模板差异化数据源模块的展示;

6、工作流项目仅在被嵌入DSS的时候可以修改;

7、列表页的数据很多,并且点击可以跳转到详情页,再从详情页返回的时候需要根据进入详情页前的参数(页面、搜索参数)加载列表数据。


项目现状

现有项目使用的是vue2(该技术栈在应对大型项目时,会面临公共逻辑抽离组合方法有限的问题,比如有A、B两个mixins,A、B有部分逻辑相同,并且相互有数据依赖,就需要想办法保证A、B两个mixins按预期时许执行),主要存在以下问题:

1、项目文件

文件放置凌乱,没有体现系统功能层级。


2、缺少注释

功能逻辑缺少文档以及注释只能通过代码阅读、测试环境debug、询问后台确认逻辑的设计原理,比如FPS和上游表功能不能同时开启、是不是每个规则选择MYSQL的时候都需要显示连接输入框、单表规则在选择不同校验模板的时候数据源中的字段是怎么动态差异化展示的。


3、功能复用

功能复用严重不足,在规则项目编辑功能中尤为明显,每种规则对应的页面代码行数都达到了1000行以上,阅读非常消耗精力和时间。

4、逻辑未完成

存在未完成的功能代码,以下文件的测试环境数据竟然在生产上一直跑。


5、界面不合理

操作逻辑不清晰,样式兼容性差,不同部分结构产生重叠。

由于功能的交互经过重新设计,某些功能在原有功能上进行了优化,加上上面说几个问题,让改版的工作在最开始设计逻辑和review的时候非常消耗精力。


改造目的

1、重新设计界面交互,重新梳理代码层面的功能组合,提升用户操作效率和体验,并实现和优化原有的全部功能;

2、提升项目代码的维护性、阅读性、拓展性,解决之前vue2遗留的比如mixins的问题。


改造关键点

1、不同类型规则的功能设计

在规则功能模块划分方面力求做到,该复用的复用,该拆分的拆分。

尽管每个规则的数据源模块都不同,但是相同的操作,比如选择FPS需要创建数据表的操作,也单独抽离成了组件。

体现到代码目录则是如下图,该独自管理的放在对应的空间内,公共部分则放在尽量靠近的地方,让目录组织更加明朗。


2、规则详情轻量化设计

在详情页中,属于同一个组的所有类型的规则都会放在一起,简单说同一个组可能会有几十个规则,如果每个规则都是for循环渲染一遍,那整个详情页渲染的DOM结构无疑是巨大的,可能会出现卡顿的情况。

每次用户进入详情页面,不管这个组下面有多少个规则,都只能一个个看,所以在tab切换的时候,使用v-if控制不同规则的展示,这样做详情页面顶多渲染一个类型的规则的详情,DOM结构数量呈量级减少,核心代码如下:

<div v-if="rules.length > 0" class="wd-content-body">  <!-- 单表对比 -->  <SingleTableCheck v-if="currentRuleType === '1-1'"/>
<!-- 跨表对比 --> <CrossTableCheck v-else-if="currentRuleType === '3-1'"/>
<!-- 跨库对比 --> <CrossDbCheck v-else-if="currentRuleType === '3-2'"/>
<!-- 单指标 --> <CustomCheck v-else-if="currentRuleType === '2-1'"/>
<!-- 多指标 --> <SqlVerification v-else-if="currentRuleType === '2-2'"/>
<!-- 文件校验 --> <FileCheck v-else-if="currentRuleType === '4-1'"/></div>

核心逻辑是如果当前组存在规则,根据当前tab选定的规则设置currentRuleType字段的值,决定渲染具体类型的规则页面。

这个逻辑没有考虑到,当这个组下存在多个同类型规则时,预期是这个类型规则的组件可以在tab切换的时候多次渲染呈现不同的数据。但实际情况是,在vue中,如果一个组件已经成功渲染,再次使用这个组件的时候则默认不会重新执行初始化的操作,这就导致用户在同类型规则之间相互切换到时候,看到的始终是第一个规则的数据。

根据vue设计的逻辑,为了达到使用相同组件也可以重新初始化的逻辑,必须在组件引入的地方动态改变组件对应的key值,当key发生变化时,组件则重新渲染。

在规则详情页中,由于每个规则的id都不同,自然就可以用作每个组件唯一的key,至此同一个组件和不同组件的渲染问题都达到了预期效果。

<div v-if="rules.length > 0" class="wd-content-body">  <!-- 单表对比 -->  <SingleTableCheck v-if="currentRuleType === '1-1'" :key="currentRule.rule_id + '1'" />
  <!-- 跨表对比 --> <CrossTableCheck v-else-if="currentRuleType === '3-1'" :key="currentRule.rule_id + '2'" />
<!-- 跨库对比 -->  <CrossDbCheck v-else-if="currentRuleType === '3-2'" :key="currentRule.rule_id + '3'" />
<!-- 单指标 -->  <CustomCheck v-else-if="currentRuleType === '2-1'" :key="currentRule.rule_id + '4'" />
<!-- 多指标 -->  <SqlVerification v-else-if="currentRuleType === '2-2'" :key="currentRule.rule_id + '5'" />
<!-- 文件校验 -->  <FileCheck v-else-if="currentRuleType === '4-1'" :key="currentRule.rule_id + '6'" />
</div>


3、编辑规则取消时回填原有数据

用户在规则详情页点击编辑,编辑一些数据之后点击取消,需要把修改的数据复原,这种场景通常有两种做法:

A. 进入编辑状态时,使用内存数据保存当前组件的所有数据(组件快照),在点击取消时,将缓存的数据重新入组件;

B.进入编辑状态时不做任何操作,点击取消时重新执行组件的初始化函数。

方案A在重新数据时是毫秒级别操作,延时低,坑在于缓存的数据是否完整,方案B可以准确重新渲染最新的数据,重新初始化如果接口数据没有缓存的话还需要考虑网络请求消耗的时间,因此相对方案A延时没有过多优势,但是最简单有效。由于开发时间紧张,目前采用的是方案B,实际操作数据覆盖的延迟比预想中的要好。


4、组件的数据传递

在上诉第1点中我们对组件进行了抽离,在规范维护的同时,也要面临组件嵌套层级的问题,加上组件可能会相同的数据。比如在单表规则的数据源组件,已经嵌套在了第三层,需要使用到ruleId、集群列表、代理用户列表、规则类型等公共数据,其中集群列表、代理用户列表是所有规则通用的数据,如果这些数据都只通过props传递,那整个数据链路会非常复杂。

理论上这些公共数据应该由他们的上层组件“详情页”进行渲染,他们统一去详情页拿数据,这样能节省很多重复请求。


在vue3中提供了provide和inject的数据注入方式,因此可以简单实现数据的传递。

// 父组件
provide('key', value);
// 自组件
const injectData = inject('key');


当然,这个场景也可以使用vuex实现,不过规则场景中的数据共享只局限于本模块,而且公共数据只需要做到单向传递,所以也没有使用vuex。


5、组件的拓展性

系统中有多个组件基本功能相同,但需要同时具备很多差异化的使用模式,比如执行参数模块,需要支持详情页编辑模式、详情页预览模式、列表页modal编辑模式、列表页和详情页的选择以及动态编辑模式、单页面维护模式,另在在每个模式下,整个模块对应的数据字段也不相同。

因此我们在实现该组件基础编辑和预览功能之后,向外界暴露了info、mode、manual三个关键属性

// ExecutionParams.vue/*** mode 可选枚举 preview、edit* manual 决定基础数据的加载方式,一旦设置为true,公共数据比如集群列表等则需要自主获取,主要为了解决某些使用这个组件的地方缺少ganging数据的问题* info 绑定外部组件需要修改的字段,点击确定时通过update事件将数据回吐**/const props = defineProps({    mode: {        type: String,        default: 'preivew',    },    manual: {        type: Boolean,        default: false,    },    info: {        type: Object,        default: {},    },});

到这一步,该组件可以支持详情页编辑模式、详情页预览模式、modal编辑模式。

为了满足抽屉方式和单页模式的拓展使用,在此基础上,新建了template组件。

// template.vue
<template>
<!-- 新增 -->
<ExecutionParams v-model:info="data" mode="edit" />
<!-- 列表和编辑>
<div v-for="d in list" :key="d.id">
<ExecutionParams v-model:info="d" :mode="d.edit" />
</div>
</tempalte>


另外,选择的模式只能在抽屉展示的时候,因此在template组件增加了enableSelect以及@select回调,当enableSelect=true开启选择模式,并通过@select绑定的函数完成具体的业务操作,即满足单页面编辑模式和抽屉编辑模式。


<template :enableSelect="true" @select="confirm" />

执行参数作为一个基础组件,衍生另一个组件,满足了4种使用场景,最终核心的修改也只聚焦在这个基础组件,提供拓展性的同时,降低了代码维护的难度。


改造总结

新版本项目针对之前的问题和不足,很有针对性的提供了解决方案,以上只是举例了几个核心点,还有非常多的细节,因为篇幅问题不在一一描述,后面还会持续进行优化


— END —

如何成为社区贡献者

 官方文档贡献。发现文档的不足、优化文档,持续更新文档等方式参与社区贡献。通过文档贡献,让开发者熟悉如何提交PR和真正参与到社区的建设。参考攻略:保姆级教程:如何成为Apache Linkis文档贡献者


 代码贡献。我们梳理了社区中简单并且容易入门的的任务,非常适合新人做代码贡献。请查阅新手任务列表:https://github.com/apache/incubator-linkis/issues/1161


 内容贡献:发布WeDataSphere开源组件相关的内容,包括但不限于安装部署教程、使用经验、案例实践等,形式不限,请投稿给小助手。例如:


 社区答疑:积极在社区中进行答疑、分享技术、帮助开发者解决问题等;


 其他:积极参与社区活动、成为社区志愿者、帮助社区宣传、为社区发展提供有效建议等;

本文分享自微信公众号 - WeDataSphere(gh_273e85fce73b)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章