Appearance
树组件(懒加载)使用示例
注意事项:
- 树组件需要设置container-height属性
- 需要需要对懒加载树组件进行过滤,需要给关键字输入框加上防抖,避免段时间大量请求服务器
- loadData需要重点掌握
- 取数接口一定需要和后端同事提前约定好,如果业务上有通过关键字过滤或者通过查询条件过滤树组件的需求,则需要取数接口在设计上支持关键字过滤,如果接口没有传查询条件,则接口通过传入的parentCode逐级返回数据,如果有有传递关键字,则该接口
- 组件渲染之后,可调用updateNodeValue方法更新树组件节点属性值
- 如果功能从设计上有关键字过滤功能,则需要根据有无关键字调用组件init与filter方法
效果图
代码示例:
<!-- 侧边栏单位 -->
<template>
<!-- 容器 -->
<div>
<!-- 关键字过滤 -->
<el-input v-model="keyword" size="small" placeholder="输入关键字过滤" prefix-icon="el-icon-search" @input="debounceOnInput" style="width: 100%;" />
<!-- 懒加载树组件-不含有过滤单位数据时显示 -->
<!-- TODO: 树组件需要设置container-height属性 -->
<v-lazy-tree ref="layTree" :load="loadData" display="CODE_NAME" :props="treeProps" :container-height="treeHeight" @node-click="onNodeClick">
<!-- 可通过默认插槽自定义节点显示 -->
<template v-slot="{node}">
<i class="el-icon-location mr5 f16" v-if="isActive(node)"></i>
<span :class="statusColor(node)">{{node.agencyCode}} {{node.agencyName}}</span>
</template>
</v-lazy-tree>
<!-- 状态标示 -->
<div class="pfs-gfa-audit-manage-sidebar-agency-status">
<span class="pfs-gfa-audit-manage-sidebar-agency-status-item no-submit">未上报</span>
<span class="pfs-gfa-audit-manage-sidebar-agency-status-item submit">已上报</span>
<span class="pfs-gfa-audit-manage-sidebar-agency-status-item reject">已退回</span>
<span class="pfs-gfa-audit-manage-sidebar-agency-status-item finished">完成审核</span>
</div>
</div>
</template>
<script>
import fetch from '@/config/fetch';
import util from '@/assets/js/util';
import {
PAGE_TYPE,
AGENCY_STATE,
AUDITED_STATUS,
TOPIC,
} from '@/modules/pfs/pfs-gfa/pfs-gfa-audit-manage/constant';
export default {
props: {
contextInfo: Object, //上下文数据
agencyInfo: Object, //当前选的单位信息
agencyFilter: Array, //已过滤的单位数据
getHeight: Function, //获取高度
select: Function, //处理选择数据
},
data() {
return {
keyword: '', //关键字
treeProps: {
id: 'agencyCode',
label: 'agencyName',
pid: 'parentCode',
disabled: 'disabled',
leaf: 'isLeaf',
}, //树组件绑定的字段
treeHeight: 0, //树组件高度
};
},
created() {
// TODO:需要需要对懒加载树组件进行过滤,需要给关键字输入框加上防抖,避免段时间大量请求服务器
this.debounceOnInput = _.debounce(this.onInput, 500);
this.subscribe();
},
methods: {
/**
* 加载数据的方法(TODO:loadData需要重点掌握)
* 1、如果关键字为空
* 1、判断有无node节点数据,如果节点数据为空,则需要生成首节点数据,并自动展开
* 2、如果node节点数据不为空,则需要获取单位节点数据,如果node节点单位数据与首节点单位数据一致,则需要自动点击第一个节点(因为默认的首节点不能被选中)
* 2、如果关键字不为空,则通过关键字获取单位节点数据
*/
async loadData(node = {}, resolve) {
let data;
try {
if (util.isEmpty(this.keyword)) {
if (util.isEmptyObject(node)) {
data = this.generateFirstNode();
_.defer(() => {
this.$refs.layTree.onExpand(0);
});
} else {
data = await this.getData(
node.agencyCode,
node.mofDivCode,
node.dwType
);
if (
util.isNotEmpty(data) &&
this.contextInfo.agencyCode === node.agencyCode
) {
_.defer(() => {
this.$refs.layTree.onClick(1);
});
}
}
} else {
data = await this.getData(
this.contextInfo.agencyCode,
this.contextInfo.mofDivCode,
this.contextInfo.dwType
);
}
} catch (err) {
console.error(err);
this.$message({
type: 'error',
message: err.msg,
});
data = [];
} finally {
resolve(data);
}
},
/**
* 生成第一个节点数据
* 1、初始化加载时,需要自己从当前页面上下文环境中生成第一个单位节点数据,当前单位节点不可以被选中
*/
generateFirstNode() {
let { agencyCode, agencyName, mofDivCode, reportFormStatus, dwType } =
this.contextInfo;
return [
{
agencyCode,
agencyName,
mofDivCode,
parentCode: '',
status: reportFormStatus,
dwType,
disabled: true,
isLeaf: false,
},
];
},
/**
* 获取单位数据(如果关键字不为空,则返回所有的数据都应该平铺)
* TODO:取数接口一定需要和后端同事提前约定好,如果业务上有通过关键字过滤或者通过查询条件过滤树组件的需求,则需要取数接口在设计上支持关键字过滤,如果接口没有传查询条件,则接口通过传入的parentCode逐级返回数据,如果有有传递关键字,则该接口
*
*/
getData(parentCode, mofDivCode, dwType) {
return new Promise((resolve, reject) => {
let { transType, taskId, fiscalYear, fiscal } = this.contextInfo;
fetch
.post('/gfa/fr/gfa/org/query/reportAgyTree', {
transType,
groupId: taskId,
mofDivCode,
fiscalYear: fiscalYear || fiscal,
fiscal: fiscalYear || fiscal,
parentCode,
keyWord: this.keyword,
dwType,
receiveDwType: this.contextInfo.dwType,
})
.then(({ data }) => resolve(data))
.catch(reject);
});
},
/**
* 设置树组件高度
*/
setTreeHeight() {
this.treeHeight = this.getHeight() - 70;
},
/**
* 消息订阅
* 1、订阅单位上报状态变化消息
* 2、订阅单位完成审核状态变化消息
*/
subscribe() {
this.$observable.subscribe(
TOPIC.AGENCY_STATE_CHANGE,
this.onAgencyStateChange
);
this.$observable.subscribe(
TOPIC.AUDITED_STATUS_CHANGE,
this.onAuditedStatusChange
);
},
/**
* 消息取消订阅
* 1、订阅单位上报状态变化消息
* 2、订阅单位完成审核状态变化消息
*/
unsubscribe() {
this.$observable.unsubscribe(
TOPIC.AGENCY_STATE_CHANGE,
this.onAgencyStateChange
);
this.$observable.unsubscribe(
TOPIC.AUDITED_STATUS_CHANGE,
this.onAuditedStatusChange
);
},
/**
* 处理单位上报状态变化
* 1、如果不包含单位过滤数据,则需要获取懒加载树组件,并将指定单位的数据状态进行改变
*/
onAgencyStateChange(agencyCode, status) {
let ref = this.$refs.layTree;
if (ref) {
// TODO:组件渲染之后,可调用updateNodeValue方法更新树组件节点属性值
ref.updateNodeValue(agencyCode, { status });
}
},
/**
* 处理单位完成审核状态变化
* 1、如果不包含单位过滤数据,则需要获取懒加载树组件,并遍历已选单位,更新单位审核完成状态
* @param {*} auditedStatus 审核完成状态
* @param {*} agencyCodes 已选的单位code
*/
onAuditedStatusChange(auditedStatus, agencyCodes) {
let ref = this.$refs.layTree;
if (ref) {
agencyCodes.forEach((e) => {
ref.updateNodeValue(e, { auditedStatus });
});
}
},
/**
* 处理关键字输入
* 1、如果不包含单位过滤数据,则需要获取懒加载树组件,并对树组件数据进行过滤
*/
onInput() {
// TODO:如果功能从设计上有关键字过滤功能,则需要根据有无关键字调用组件init与filter方法
if (util.isEmpty(this.keyword)) {
this.$refs.layTree.init();
} else {
this.$refs.layTree.filter();
}
},
/**
* 处理节点点击
*/
onNodeClick(data) {
this.select(PAGE_TYPE.AGENCY, data);
},
/**
* 节点状态颜色
* 1、优先判断单位完成审核状态,已完成,标识绿色
* 2、单位未完成审核,标识单位上报状态
*/
statusColor({ auditedStatus, status }) {
if (auditedStatus === AUDITED_STATUS.FINISHED) {
return 'bs-color-green';
} else {
switch (status) {
case AGENCY_STATE.NO_SUBMIT:
return 'bs-text-color';
case AGENCY_STATE.SUBMIT:
return 'bs-color-blue';
case AGENCY_STATE.RETURN:
return 'bs-color-red';
default:
return '';
}
}
},
/**
* 节点是否激活
*/
isActive(nodeInfo) {
return nodeInfo.agencyCode === this.agencyInfo.agencyCode;
},
},
computed: {
/**
* 是否含有过滤单位数据
*/
hasAgencyFilter() {
return util.isNotEmpty(this.agencyFilter);
},
},
/**
* 1、设置树组件高度
*/
mounted() {
this.setTreeHeight();
},
beforeDestroy() {
this.debounceOnInput.cancel();
this.unsubscribe();
},
};
</script>
<style lang="scss" scoped>
@import '~@/assets/style/variables.scss';
.pfs-gfa-audit-manage-sidebar-agency-status {
height: 30px;
border-top: $-bs-border;
display: flex;
justify-content: space-around;
align-items: flex-end;
.pfs-gfa-audit-manage-sidebar-agency-status-item {
position: relative;
color: $-bs-text-color-light;
font-size: 15px;
&::before {
position: absolute;
content: ' ';
top: 6px;
left: -20px;
width: 15px;
height: 12px;
border-radius: $-bs-border-radius;
}
&.no-submit::before {
background-color: $-bs-text-color;
}
&.submit::before {
background-color: $-bs-color-blue;
}
&.reject::before {
background-color: $-bs-color-red;
}
&.finished::before {
background-color: $-bs-color-green;
}
}
}
</style>