Commit 0594891d authored by yanzhongrong's avatar yanzhongrong

org tree button style

parent a4463412
<template>
<div>
<el-tree
ref="elTree"
class="el-select-tree__list"
:default-expanded-keys="defaultExpandedKeys"
:show-checkbox="multiple"
:expand-on-click-node="multiple"
:style="{ 'min-width': minWidth + 'px' }"
@node-click="nodeClick"
@check-change="checkChange"
:data="data"
:props="props"
:node-key="propsValue"
:default-expand-all="defaultExpandAll"
:check-strictly="checkStrictly"
:lazy="lazy"
:load="load"
:icon-class="iconClass"
:indent="indent"
:accordion="accordion"
:filter-node-method="filterNode"
:auto-expand-parent="autoExpandParent"
:render-content="renderContent"
:render-after-expand="renderAfterExpand"
>
<span
slot-scope="{ data }"
class="el-select-tree__item"
:class="treeItemClass(data)"
>
<template v-if="data.type === 1">
<svg-icon icon-class="org" />
<span class="ml10" :title="data[propsLabel]">{{
data[propsLabel]
}}</span>
</template>
<template v-else-if="data.type === 2">
<svg-icon
:icon-class="`car_${data.data.carstatus}`"
/>
<span class="ml10" :title="data[propsLabel]">{{ data[propsLabel] }}</span>
</template>
<template v-else-if="data.type === 3">
<svg-icon
icon-class="human"
/>
<span class="ml10" :title="data[propsLabel]">{{ data[propsLabel] }}</span>
</template>
<template v-else-if="hasChannel">
<svg-icon
icon-class="camera"
/>
<span class="ml10" :title="data[propsLabel]">{{ data[propsLabel] }}</span>
</template>
</span>
</el-tree>
</div>
</template>
<script>
import Emitter from 'element-ui/lib/mixins/emitter'
import {
addResizeListener,
removeResizeListener
} from 'element-ui/lib/utils/resize-event'
export default {
name: 'tree',
data() {
return {
minWidth: 0
}
},
mixins: [Emitter],
model: {
prop: 'value',
event: 'change'
},
props: {
data: {
type: Array,
default() {
return []
}
},
props: {
type: Object,
default() {
return {
value: 'value',
label: 'label',
children: 'children',
disabled: 'disabled',
isLeaf: 'isLeaf'
};
}
},
canFilter: Boolean,
filterText: String,
checkStrictly: Boolean,
nodeKey: String,
defaultExpandAll: Boolean,
lazy: Boolean,
load: Function,
iconClass: String,
indent: Number,
accordion: Boolean,
autoExpandParent: {
type: Boolean,
default: true
},
renderContent: Function,
renderAfterExpand: Boolean,
// [el-tree] forwarding parameters end
multiple: Boolean,
value: {
type: [Number, String, Array, Object],
default: ''
},
},
computed: {
propsValue() {
return this.nodeKey || this.props.value || 'value'
},
propsLabel() {
return this.props.label || 'label'
},
propsIsLeaf() {
return this.props.isLeaf || 'isLeaf'
},
defaultExpandedKeys() {
return Array.isArray(this.value)
? this.value
: this.value || this.value === 0
? [this.value]
: []
}
},
watch: {
value: {
immediate: true,
handler(val) {
if(val.length > 0) {
this.setSelected()
}
}
},
data: {
immediate: true,
handler(val) {
if(val.length > 0) {
this.setSelected()
}
}
},
filterText: {
immediate: true,
handler(val) {
if (this.canFilter && this.$refs.elTree) {
this.$refs.elTree.filter(val)
}
}
}
},
methods: {
filterNode(value, data, node) {
if(!value){
return true
}
if(data.label.indexOf(value) !==-1) {
return true
}
return this.checkBelongToChooseNode(value, data, node)
},
checkBelongToChooseNode(value, data, node) {
const level = node.level
let parentData = node.parent
let index =0
while(index < level -1) {
if(parentData.data.label.indexOf(value) !==-1) {
return true
}
parentData = parentData.parent
index ++
}
return false
},
valueChange(value, node) {
this.$emit('change', value, node)
},
clear() {
if (this.multiple) {
this.valueChange([])
this.$nextTick(() => {
this.$refs.elTree.setCheckedKeys([])
})
} else {
this.valueChange('')
}
this.$emit('clear')
},
nodeClick(data, _, component) {
const children = data[this.props.children]
const value = data[this.propsValue]
if (
((children && children.length) ||
(this.lazy && !data[this.propsIsLeaf])) &&
!this.checkStrictly
) {
component.handleExpandIconClick()
} else if (!this.multiple && !data.disabled) {
if (value !== this.value) {
this.valueChange(value, data)
}
}
},
checkChange() {
const elTree = this.$refs.elTree
const leafOnly = !this.checkStrictly
const keys = elTree.getCheckedKeys(leafOnly)
const nodes = elTree.getCheckedNodes(leafOnly)
this.valueChange(keys, nodes)
},
setSelected() {
this.$nextTick(() => {
const elTree = this.$refs.elTree
if (!elTree) return
if (this.multiple) {
elTree.setCheckedKeys(this.value)
this.checkChange()
} else {
const selectedNode = elTree.getNode(this.value)
this.valueChange(this.value, selectedNode)
}
})
},
treeItemClass(data) {
return {
'is-selected': this.multiple
? false
: data[this.propsValue] === this.value,
'is-disabled': data.disabled
}
},
handleResize() {
// set the `tree` default `min-width`
// border's width is 2px
this.minWidth = this.$el.clientWidth - 2
}
},
mounted() {
this.setSelected()
addResizeListener(this.$el, this.handleResize)
},
beforeDestroy() {
if (this.$el && this.handleResize) {
removeResizeListener(this.$el, this.handleResize)
}
}
}
</script>
\ No newline at end of file
<template> <template>
<div class="el-select-tree"> <div class="el-select-tree">
<el-popover <el-row class="tree_header mb10">
ref="elPopover" <el-col>
v-model="visible" <el-select v-model="value" placeholder="请选择" size="mini">
transition="el-zoom-in-top" <el-option
popper-class="el-select-tree__popover" v-for="item in options"
trigger="click" :key="item.id"
:disabled="disabled" :label="item.label"
:placement="placement" :value="item.id"
:width="popoverWidth"
@after-enter="handleScroll()"
> >
<div class="card-board"> </el-option>
<el-input </el-select>
v-model="keyword" </el-col>
:placeholder="searchPlaceholder" <el-col class="ml20">
:size="size" <el-button type="primary" icon="el-icon-s-unfold" size="mini">展开</el-button>
clearable> </el-col>
</el-input> <el-col>
<!-- scrollbar wrap --> <el-button type="primary" size="mini" icon="el-icon-refresh-right">刷新</el-button>
<el-scrollbar </el-col>
wrap-class="el-select-dropdown__wrap" </el-row>
view-class="el-select-dropdown__list" <el-tree
ref="scrollbar" v-loading="loading"
ref="vuetree"
:props="defaultProps"
:data="data"
:render-content="renderContent"
:default-expand-all = 'true'
nodeKey="id"
class="el-tree"
:current-node-key='id'
:expand-on-click-node="false"
@node-click="handleClick"
> >
<tree </el-tree>
ref="tree"
v-model="valueInner"
@change="change"
:canFilter="canFilter"
:filterText="keyword"
:checkStrictly="checkStrictly"
:defaultExpandAll=true
:data="treeData">
</tree>
</el-scrollbar>
</div>
<!-- trigger input -->
<el-input
v-model="selectedLabel"
ref="reference"
slot="reference"
readonly
:style="selectStyle"
:validate-event="false"
:size="size"
:class="{
'is-active': visible,
'is-selected': selectedLabel,
'is-clearable': clearable
}"
:disabled="disabled"
:placeholder="placeholder"
>
<i
v-if="clearable"
@click.stop="clear()"
slot="suffix"
class="el-input__icon el-input__icon-close el-icon-circle-close"
></i>
<i
slot="suffix"
class="el-input__icon el-input__icon-arrow-down el-icon-arrow-down"
></i>
</el-input>
</el-popover>
</div> </div>
</template> </template>
<script> <script>
import {
TreeMixin,
} from '@/mixins/tree'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
export default { export default {
data() { data() {
return { return {
canFilter: true value: '',
options: [
{
id: 0,
label: '手动监控'
},
{
id: 1,
label: '自动监控'
}
],
data: [
{
id: 0,
label: '张呼铁路客运专线',
children: [
{
id: 1,
label: 'STATION1未开通',
children: [{
label: '三级 1-1-1'
}]
},
{
id: 2,
label: 'STATION2未开通',
children: [{
label: '三级 1-1-1'
}]
},
{
id: 3,
label: '(7)VLCB-ZZT02',
children: [{
id: 4,
label: 'PSU(现场管理单元)',
children: [{
id: 5,
label: '漏缆K362+784张...'
},
{
id: 6,
label: '漏缆K362+784张...'
}]
},
{
id: 7,
label: '故障定位单位_K3...',
children: [{
id: 8,
label: '漏缆K362+784张...'
},
{
id:9,
label: '漏缆K362+784张...'
}]
}]
},
]
}
],
defaultProps: {
children: 'children',
label: 'label'
},
loading: false,
} }
}, },
name: 'org-tree', name: 'org-tree',
mixins: [TreeMixin],
computed: { computed: {
...mapGetters('tree', [ ...mapGetters('tree', [
'treeData', 'treeData',
]) ])
}, },
methods: {
handleClick(data) {
console.log(data);
},
renderContent (h, {node, data, store}) {
return (
<div>
<span style="padding-right:10px;" id={data.id} >
<span style={{ color: data.myColor, marginRight: '5px', fontSize: '16px' }}><svg-icon icon-class="org" /></span>
<span style={{ color: data.myColor, marginRight: '5px', fontSize: '16px' }}>{node.label}</span>
</span>
</div>
)
},
}
} }
</script> </script>
...@@ -96,87 +138,21 @@ export default { ...@@ -96,87 +138,21 @@ export default {
@import '@/styles/variables'; @import '@/styles/variables';
.el-select-tree { .el-select-tree {
border: 1px dotted; width: 300px;
display: inline-block; height: calc(100vh - 10px);
.el-input__icon { background: rgba(238, 247, 254, 0.39);
cursor: pointer; .tree_header {
transition: transform 0.3s; display: flex;
&-close { justify-content: center;
display: none; align-items: center;
} padding: 10px;
} height: 44px;
.el-input__inner { background: rgba(196, 214, 255, 0.39);
cursor: pointer; opacity: 1;
padding-right: 30px; box-sizing: border-box;
}
.el-input {
&:hover:not(.is-disabled) {
.el-input__inner {
// border-color: $--input-border-color-hover;
}
&.is-selected.is-clearable {
.el-input__icon {
&-close {
display: inline-block;
}
&-arrow-down {
display: none;
}
}
}
}
&.is-active {
.el-input__icon-arrow-down {
transform: rotate(-180deg);
}
.el-input__inner {
// border-color: $--button-primary-border-color;
}
}
}
&__popover {
padding: 0 !important;
// extends el-select-dropdown - start
// border: $--select-dropdown-border !important;
// border-radius: $--border-radius-base !important;
// extends el-select-dropdown - end
.popper__arrow {
left: 35px !important;
} }
.el-tree-node__expand-icon.is-leaf { // border: 1px dotted;
cursor: pointer; // display: inline-block;
}
}
&__list {
overflow-y: auto;
// scroll style - start
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
}
// scroll style - end
}
&__item {
position: relative;
white-space: nowrap;
// padding-right: $spacing-medium;
&.is-selected {
// color: $--select-option-selected-font-color;
font-weight: bolder;
}
&.is-disabled {
// color: $--font-color-disabled-base;
cursor: not-allowed;
}
}
} }
</style> </style>
\ No newline at end of file
<svg id="ic_dashboard" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style>
.cls-1 {
fill: none;
}
.cls-2 {
fill: #666;
}
</style>
</defs>
<g id="home">
<path id="路径_372" data-name="路径 372" class="cls-1" d="M0,0H24V24H0Z"/>
</g>
<path id="Shape" class="cls-2" d="M13,20H1a1,1,0,0,1-1-1V6.5a2,2,0,0,1,2-2H6V2A2,2,0,0,1,8,0h4a2,2,0,0,1,2,2V9h4a2,2,0,0,1,2,2v8a1,1,0,0,1-1,1Zm5-2V11H14v7ZM8,18h4V11q0-.03,0-.059V2H8ZM2,18H6V6.5H2Z" transform="translate(2 2)"/>
</svg>
import Tree from "@/components/Tree";
export const TreeMixin = {
model: {
prop: "value",
event: "change",
},
props: {
clearable: Boolean,
selectWidth: Number,
popoverWidth: Number,
placement: {
type: String,
default: "bottom-start",
},
disabled: Boolean,
placeholder: {
type: String,
default: "请选择",
},
searchPlaceholder: {
type: String,
default: "请输入",
},
size: {
type: String,
default: "small",
},
multiple: { type: Boolean, default: false },
value: {
type: [Number, String, Array, Object],
default: "",
},
},
data() {
return {
visible: false,
checkStrictly: true,
selectedNode: null,
keyword: "",
};
},
components: {
Tree,
},
watch: {
value(newV) {
if (!newV) {
this.selectedNode = null
}
}
},
mounted() {
this.init && this.init();
},
computed: {
valueInner: {
get() {
return this.value;
},
set(val) {
this.$emit("change", val);
},
},
selectedLabel() {
if (!this.selectedNode) return "";
return this.selectedNode.label;
},
selectStyle() {
if (this.selectWidth) {
return {
width: this.selectWidth + "px",
};
}
},
},
methods: {
change(value, data) {
if (!value.leaf && this.ignoreParentChoose) return;
if (data) {
this.selectedNode = data;
}
this.$emit("change", value, data);
if (!this.multiple) {
this.visible = false;
}
},
valueChange(value, node) {
this.$emit("change", value, node);
},
clear() {
if (this.multiple) {
this.valueChange([]);
} else {
this.visible = false;
this.valueChange("");
this.selectedNode = null;
}
},
// 触发滚动条的重置
handleScroll() {
this.$refs.scrollbar && this.$refs.scrollbar.handleScroll();
},
},
};
export function travelTree(treeData, idKey, labelKey) {
let len = treeData.length;
for (let i = 0; i < len; i++) {
let curData = treeData[i];
if (curData.children && curData.children.length) {
curData.label = `${curData.data[labelKey]}(${curData.children.length})`;
travelTree(curData.children, idKey, labelKey);
} else {
curData.label = curData.data[labelKey];
}
curData.value = curData.data[idKey];
}
}
/**
公共样式
*/
.ml10 {
margin-left: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.ml20 {
margin-left: 20px;
}
\ No newline at end of file
...@@ -51,3 +51,21 @@ ...@@ -51,3 +51,21 @@
.el-pagination { .el-pagination {
margin-top: 20px; margin-top: 20px;
} }
.el-tree {
background: rgba(249, 249, 249, 0.39);
}
.el-tree-node__content {
height: 40px;
}
.el-tree-node__expand-icon {
color: rgba(0, 98, 255, 0.39);
}
// button
.el-button--primary {
color: #fff;
background: rgba(11, 65, 177);
opacity: 1;
border-radius: 4px;
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
@import './transition.scss'; @import './transition.scss';
@import './element-ui.scss'; @import './element-ui.scss';
@import './sidebar.scss'; @import './sidebar.scss';
@import './common.scss';
body { body {
height: 100%; height: 100%;
......
...@@ -23,7 +23,7 @@ export default { ...@@ -23,7 +23,7 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.dashboard { .dashboard {
&-container { &-container {
margin: 30px; margin: 0px;
} }
&-text { &-text {
font-size: 30px; font-size: 30px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment