Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
D
dataease
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
zhu
dataease
Commits
2cf026ed
提交
2cf026ed
authored
5月 26, 2022
作者:
fit2cloud-chenyw
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 过滤条件增加下拉树
上级
adff0992
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
946 行增加
和
18 行删除
+946
-18
ShiroServiceImpl.java
.../java/io/dataease/auth/service/impl/ShiroServiceImpl.java
+1
-1
BaseTreeNode.java
...src/main/java/io/dataease/commons/model/BaseTreeNode.java
+28
-0
TreeUtils.java
...nd/src/main/java/io/dataease/commons/utils/TreeUtils.java
+41
-0
DataSetTableFieldController.java
...aease/controller/dataset/DataSetTableFieldController.java
+17
-0
DataSetFieldService.java
...java/io/dataease/service/dataset/DataSetFieldService.java
+2
-0
DirectFieldService.java
...aease/service/dataset/impl/direct/DirectFieldService.java
+56
-12
dataset.js
frontend/src/api/dataset/dataset.js
+13
-3
dom.js
frontend/src/components/ElTreeSelect/dom.js
+37
-0
index.vue
frontend/src/components/ElTreeSelect/index.vue
+0
-0
utils.js
frontend/src/components/ElTreeSelect/utils.js
+78
-0
DeSelectTree.vue
frontend/src/components/widget/DeWidget/DeSelectTree.vue
+331
-0
TextSelectTreeServiceImpl.js
...omponents/widget/serviceImpl/TextSelectTreeServiceImpl.js
+108
-0
en.js
frontend/src/lang/en.js
+4
-0
tw.js
frontend/src/lang/tw.js
+4
-0
zh.js
frontend/src/lang/zh.js
+5
-1
index.vue
frontend/src/views/panel/filter/index.vue
+2
-1
MyTree.vue
frontend/src/views/system/test/MyTree.vue
+150
-0
index.vue
frontend/src/views/system/test/index.vue
+69
-0
没有找到文件。
backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java
浏览文件 @
2cf026ed
...
...
@@ -54,7 +54,6 @@ public class ShiroServiceImpl implements ShiroService {
// 验证链接
filterChainDefinitionMap
.
put
(
"/api/link/validate**"
,
ANON
);
filterChainDefinitionMap
.
put
(
"/api/map/areaEntitys/**"
,
ANON
);
filterChainDefinitionMap
.
put
(
"/dataset/field/fieldValues/**"
,
ANON
);
filterChainDefinitionMap
.
put
(
"/linkJump/queryPanelJumpInfo/**"
,
ANON
);
filterChainDefinitionMap
.
put
(
"/linkJump/queryTargetPanelJumpInfo"
,
ANON
);
...
...
@@ -98,6 +97,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap
.
put
(
"/api/link/viewDetail/**"
,
"link"
);
filterChainDefinitionMap
.
put
(
"/panel/group/exportDetails"
,
ANON
);
filterChainDefinitionMap
.
put
(
"/dataset/field/linkMultFieldValues"
,
"link"
);
filterChainDefinitionMap
.
put
(
"/dataset/field/linkMappingFieldValues"
,
"link"
);
filterChainDefinitionMap
.
put
(
"/**"
,
"authc"
);
...
...
backend/src/main/java/io/dataease/commons/model/BaseTreeNode.java
0 → 100644
浏览文件 @
2cf026ed
package
io
.
dataease
.
commons
.
model
;
import
io.dataease.plugins.common.model.ITreeBase
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
BaseTreeNode
implements
ITreeBase
<
BaseTreeNode
>
{
private
String
id
;
private
String
pid
;
private
String
text
;
private
String
nodeType
;
private
List
<
BaseTreeNode
>
children
;
public
BaseTreeNode
(
String
id
,
String
pid
,
String
text
,
String
nodeType
)
{
this
.
id
=
id
;
this
.
pid
=
pid
;
this
.
text
=
text
;
this
.
nodeType
=
nodeType
;
}
}
backend/src/main/java/io/dataease/commons/utils/TreeUtils.java
浏览文件 @
2cf026ed
package
io
.
dataease
.
commons
.
utils
;
import
io.dataease.plugins.common.model.ITreeBase
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.util.Assert
;
import
org.springframework.util.CollectionUtils
;
...
...
@@ -14,6 +15,9 @@ import java.util.stream.Collectors;
*/
public
class
TreeUtils
{
public
final
static
String
DEFAULT_ROOT
=
"root"
;
public
final
static
String
SEPARATOR
=
"-de-"
;
/**
* Description: rootPid 是根节点PID
*/
...
...
@@ -53,4 +57,41 @@ public class TreeUtils{
return
mergeTree
(
tree
,
"0"
);
}
public
static
<
T
extends
ITreeBase
>
List
<
T
>
mergeDuplicateTree
(
List
<
T
>
tree
,
String
...
rootPid
)
{
Assert
.
notNull
(
rootPid
,
"Root Pid cannot be null"
);
if
(
CollectionUtils
.
isEmpty
(
tree
)){
return
null
;
}
List
<
T
>
result
=
new
ArrayList
<>();
// 构建id-节点map映射
Map
<
String
,
T
>
treePidMap
=
tree
.
stream
().
collect
(
Collectors
.
toMap
(
node
->
node
.
getNodeType
(),
t
->
t
));
tree
.
stream
().
filter
(
item
->
StringUtils
.
isNotBlank
(
item
.
getId
())).
forEach
(
node
->
{
String
nodeType
=
node
.
getNodeType
();
String
[]
links
=
nodeType
.
split
(
SEPARATOR
);
int
length
=
links
.
length
;
int
level
=
Integer
.
parseInt
(
links
[
length
-
1
]);
// 判断根节点
if
(
Arrays
.
asList
(
rootPid
).
contains
(
node
.
getPid
())
&&
0
==
level
)
{
result
.
add
(
node
);
}
else
{
//找到父元素
String
[]
pLinks
=
new
String
[
level
];
System
.
arraycopy
(
links
,
0
,
pLinks
,
0
,
level
);
String
parentType
=
Arrays
.
stream
(
pLinks
).
collect
(
Collectors
.
joining
(
SEPARATOR
))
+
TreeUtils
.
SEPARATOR
+
(
level
-
1
);
T
parentNode
=
treePidMap
.
get
(
parentType
);
if
(
parentNode
==
null
){
// 可能出现 rootPid 更高的节点 这个操作相当于截断
return
;
}
if
(
parentNode
.
getChildren
()
==
null
)
{
parentNode
.
setChildren
(
new
ArrayList
());
}
parentNode
.
getChildren
().
add
(
node
);
}
});
return
result
;
}
}
backend/src/main/java/io/dataease/controller/dataset/DataSetTableFieldController.java
浏览文件 @
2cf026ed
...
...
@@ -177,6 +177,23 @@ public class DataSetTableFieldController {
return
list
;
}
@ApiIgnore
@PostMapping
(
"linkMappingFieldValues"
)
public
List
<
Object
>
linkMappingFieldValues
(
@RequestBody
MultFieldValuesRequest
multFieldValuesRequest
)
throws
Exception
{
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
String
linkToken
=
request
.
getHeader
(
F2CLinkFilter
.
LINK_TOKEN_KEY
);
DecodedJWT
jwt
=
JWT
.
decode
(
linkToken
);
Long
userId
=
jwt
.
getClaim
(
"userId"
).
asLong
();
multFieldValuesRequest
.
setUserId
(
userId
);
return
dataSetFieldService
.
fieldValues
(
multFieldValuesRequest
.
getFieldIds
(),
multFieldValuesRequest
.
getUserId
(),
true
,
true
);
}
@ApiIgnore
@PostMapping
(
"mappingFieldValues"
)
public
List
<
Object
>
mappingFieldValues
(
@RequestBody
MultFieldValuesRequest
multFieldValuesRequest
)
throws
Exception
{
return
dataSetFieldService
.
fieldValues
(
multFieldValuesRequest
.
getFieldIds
(),
multFieldValuesRequest
.
getUserId
(),
true
,
true
);
}
@ApiIgnore
@PostMapping
(
"multFieldValuesForPermissions"
)
public
List
<
Object
>
multFieldValuesForPermissions
(
@RequestBody
MultFieldValuesRequest
multFieldValuesRequest
)
throws
Exception
{
...
...
backend/src/main/java/io/dataease/service/dataset/DataSetFieldService.java
浏览文件 @
2cf026ed
...
...
@@ -6,4 +6,6 @@ import java.util.List;
public
interface
DataSetFieldService
{
List
<
Object
>
fieldValues
(
String
fieldId
,
Long
userId
,
Boolean
userPermissions
)
throws
Exception
;
List
<
Object
>
fieldValues
(
List
<
String
>
fieldIds
,
Long
userId
,
Boolean
userPermissions
,
Boolean
needMapping
)
throws
Exception
;
}
backend/src/main/java/io/dataease/service/dataset/impl/direct/DirectFieldService.java
浏览文件 @
2cf026ed
package
io
.
dataease
.
service
.
dataset
.
impl
.
direct
;
import
com.google.gson.Gson
;
import
io.dataease.commons.model.BaseTreeNode
;
import
io.dataease.commons.utils.TreeUtils
;
import
io.dataease.plugins.common.base.domain.DatasetTable
;
import
io.dataease.plugins.common.base.domain.DatasetTableField
;
import
io.dataease.plugins.common.base.domain.Datasource
;
...
...
@@ -22,9 +24,7 @@ import org.apache.commons.lang3.StringUtils;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Resource
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -45,6 +45,14 @@ public class DirectFieldService implements DataSetFieldService {
@Override
public
List
<
Object
>
fieldValues
(
String
fieldId
,
Long
userId
,
Boolean
userPermissions
)
throws
Exception
{
List
<
String
>
filedIds
=
new
ArrayList
<>();
filedIds
.
add
(
fieldId
);
return
fieldValues
(
filedIds
,
userId
,
userPermissions
,
false
);
}
@Override
public
List
<
Object
>
fieldValues
(
List
<
String
>
fieldIds
,
Long
userId
,
Boolean
userPermissions
,
Boolean
needMapping
)
throws
Exception
{
String
fieldId
=
fieldIds
.
get
(
0
);
DatasetTableField
field
=
dataSetTableFieldsService
.
selectByPrimaryKey
(
fieldId
);
if
(
field
==
null
||
StringUtils
.
isEmpty
(
field
.
getTableId
()))
return
null
;
...
...
@@ -54,15 +62,23 @@ public class DirectFieldService implements DataSetFieldService {
DatasetTableField
datasetTableField
=
DatasetTableField
.
builder
().
tableId
(
field
.
getTableId
()).
checked
(
Boolean
.
TRUE
).
build
();
List
<
DatasetTableField
>
fields
=
dataSetTableFieldsService
.
list
(
datasetTableField
);
List
<
DatasetTableField
>
permissionFields
=
fields
;
List
<
ChartFieldCustomFilterDTO
>
customFilter
=
new
ArrayList
<>();
if
(
userPermissions
){
//列权限
List
<
String
>
desensitizationList
=
new
ArrayList
<>();
fields
=
permissionService
.
filterColumnPermissons
(
fields
,
desensitizationList
,
datasetTable
.
getId
(),
userId
);
//禁用的
if
(!
fields
.
stream
().
map
(
DatasetTableField:
:
getId
).
collect
(
Collectors
.
toList
()).
contains
(
fieldId
)){
permissionFields
=
fields
.
stream
().
filter
(
node
->
fieldIds
.
stream
().
anyMatch
(
item
->
StringUtils
.
equals
(
node
.
getId
(),
item
))).
collect
(
Collectors
.
toList
());
if
(
CollectionUtils
.
isEmpty
(
permissionFields
))
{
return
new
ArrayList
<>();
}
//禁用的
/*if(!fields.stream().map(DatasetTableField::getId).collect(Collectors.toList()).contains(fieldId)){
return new ArrayList<>();
}*/
if
(
CollectionUtils
.
isNotEmpty
(
desensitizationList
)
&&
desensitizationList
.
contains
(
field
.
getDataeaseName
()))
{
List
<
Object
>
results
=
new
ArrayList
<>();
results
.
add
(
ColumnPermissionConstants
.
Desensitization_desc
);
...
...
@@ -87,18 +103,18 @@ public class DirectFieldService implements DataSetFieldService {
QueryProvider
qp
=
ProviderFactory
.
getQueryProvider
(
ds
.
getType
());
if
(
StringUtils
.
equalsIgnoreCase
(
datasetTable
.
getType
(),
"db"
))
{
datasourceRequest
.
setTable
(
dataTableInfoDTO
.
getTable
());
datasourceRequest
.
setQuery
(
qp
.
createQuerySQL
(
dataTableInfoDTO
.
getTable
(),
Collections
.
singletonList
(
field
)
,
true
,
ds
,
customFilter
));
datasourceRequest
.
setQuery
(
qp
.
createQuerySQL
(
dataTableInfoDTO
.
getTable
(),
permissionFields
,
true
,
ds
,
customFilter
));
}
else
if
(
StringUtils
.
equalsIgnoreCase
(
datasetTable
.
getType
(),
"sql"
))
{
datasourceRequest
.
setQuery
(
qp
.
createQuerySQLAsTmp
(
dataTableInfoDTO
.
getSql
(),
Collections
.
singletonList
(
field
)
,
true
,
customFilter
));
datasourceRequest
.
setQuery
(
qp
.
createQuerySQLAsTmp
(
dataTableInfoDTO
.
getSql
(),
permissionFields
,
true
,
customFilter
));
}
else
if
(
StringUtils
.
equalsIgnoreCase
(
datasetTable
.
getType
(),
"custom"
))
{
DataTableInfoDTO
dt
=
new
Gson
().
fromJson
(
datasetTable
.
getInfo
(),
DataTableInfoDTO
.
class
);
List
<
DataSetTableUnionDTO
>
listUnion
=
dataSetTableUnionService
.
listByTableId
(
dt
.
getList
().
get
(
0
).
getTableId
());
String
sql
=
dataSetTableService
.
getCustomSQLDatasource
(
dt
,
listUnion
,
ds
);
datasourceRequest
.
setQuery
(
qp
.
createQuerySQLAsTmp
(
sql
,
Collections
.
singletonList
(
field
)
,
true
,
customFilter
));
datasourceRequest
.
setQuery
(
qp
.
createQuerySQLAsTmp
(
sql
,
permissionFields
,
true
,
customFilter
));
}
else
if
(
StringUtils
.
equalsIgnoreCase
(
datasetTable
.
getType
(),
"union"
))
{
DataTableInfoDTO
dt
=
new
Gson
().
fromJson
(
datasetTable
.
getInfo
(),
DataTableInfoDTO
.
class
);
String
sql
=
(
String
)
dataSetTableService
.
getUnionSQLDatasource
(
dt
,
ds
).
get
(
"sql"
);
datasourceRequest
.
setQuery
(
qp
.
createQuerySQLAsTmp
(
sql
,
Collections
.
singletonList
(
field
)
,
true
,
customFilter
));
datasourceRequest
.
setQuery
(
qp
.
createQuerySQLAsTmp
(
sql
,
permissionFields
,
true
,
customFilter
));
}
}
else
if
(
datasetTable
.
getMode
()
==
1
)
{
// 抽取
// 连接doris,构建doris数据源查询
...
...
@@ -109,11 +125,39 @@ public class DirectFieldService implements DataSetFieldService {
String
tableName
=
"ds_"
+
datasetTable
.
getId
().
replaceAll
(
"-"
,
"_"
);
datasourceRequest
.
setTable
(
tableName
);
QueryProvider
qp
=
ProviderFactory
.
getQueryProvider
(
ds
.
getType
());
datasourceRequest
.
setQuery
(
qp
.
createQuerySQL
(
tableName
,
Collections
.
singletonList
(
field
)
,
true
,
null
,
customFilter
));
datasourceRequest
.
setQuery
(
qp
.
createQuerySQL
(
tableName
,
permissionFields
,
true
,
null
,
customFilter
));
}
List
<
String
[]>
rows
=
datasourceProvider
.
getData
(
datasourceRequest
);
List
<
Object
>
results
=
rows
.
stream
().
map
(
row
->
row
[
0
]).
distinct
().
collect
(
Collectors
.
toList
());
return
results
;
if
(!
needMapping
)
{
List
<
Object
>
results
=
rows
.
stream
().
map
(
row
->
row
[
0
]).
distinct
().
collect
(
Collectors
.
toList
());
return
results
;
}
Set
<
String
>
pkSet
=
new
HashSet
<>();
List
<
BaseTreeNode
>
treeNodes
=
rows
.
stream
().
map
(
row
->
buildTreeNode
(
row
,
pkSet
)).
flatMap
(
Collection:
:
stream
).
collect
(
Collectors
.
toList
());
List
tree
=
TreeUtils
.
mergeDuplicateTree
(
treeNodes
,
TreeUtils
.
DEFAULT_ROOT
);
return
tree
;
}
private
List
<
BaseTreeNode
>
buildTreeNode
(
String
[]
row
,
Set
<
String
>
pkSet
)
{
List
<
BaseTreeNode
>
nodes
=
new
ArrayList
<>();
List
<
String
>
parentPkList
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
row
.
length
;
i
++)
{
String
text
=
row
[
i
];
parentPkList
.
add
(
text
);
String
val
=
parentPkList
.
stream
().
collect
(
Collectors
.
joining
(
TreeUtils
.
SEPARATOR
));
String
parentVal
=
i
==
0
?
TreeUtils
.
DEFAULT_ROOT
:
row
[
i
-
1
];
String
pk
=
parentPkList
.
stream
().
collect
(
Collectors
.
joining
(
TreeUtils
.
SEPARATOR
));
if
(
pkSet
.
contains
(
pk
))
continue
;
pkSet
.
add
(
pk
);
BaseTreeNode
node
=
new
BaseTreeNode
(
val
,
parentVal
,
text
,
pk
+
TreeUtils
.
SEPARATOR
+
i
);
nodes
.
add
(
node
);
}
return
nodes
;
}
}
frontend/src/api/dataset/dataset.js
浏览文件 @
2cf026ed
...
...
@@ -146,11 +146,21 @@ export function post(url, data, showLoading = true, timeout = 60000) {
})
}
export
function
fieldValues
(
fieldId
)
{
export
function
mappingFieldValues
(
data
)
{
return
request
({
url
:
'/dataset/field/
fieldValues/'
+
fieldId
,
url
:
'/dataset/field/
mappingFieldValues'
,
method
:
'post'
,
loading
:
true
loading
:
true
,
data
})
}
export
function
linkMappingFieldValues
(
data
)
{
return
request
({
url
:
'/dataset/field/linkMappingFieldValues'
,
method
:
'post'
,
loading
:
true
,
data
})
}
...
...
frontend/src/components/ElTreeSelect/dom.js
0 → 100644
浏览文件 @
2cf026ed
/*
* @moduleName:
* @Author: dawdler
* @LastModifiedBy: dawdler
* @Date: 2019-03-22 14:47:35
* @LastEditTime: 2019-03-22 16:31:38
*/
export
const
on
=
(
function
()
{
if
(
document
.
addEventListener
)
{
return
function
(
element
,
event
,
handler
)
{
if
(
element
&&
event
&&
handler
)
{
element
.
addEventListener
(
event
,
handler
,
false
)
}
}
}
else
{
return
function
(
element
,
event
,
handler
)
{
if
(
element
&&
event
&&
handler
)
{
element
.
attachEvent
(
'on'
+
event
,
handler
)
}
}
}
})()
export
const
off
=
(
function
()
{
if
(
document
.
removeEventListener
)
{
return
function
(
element
,
event
,
handler
)
{
if
(
element
&&
event
)
{
element
.
removeEventListener
(
event
,
handler
,
false
)
}
}
}
else
{
return
function
(
element
,
event
,
handler
)
{
if
(
element
&&
event
)
{
element
.
detachEvent
(
'on'
+
event
,
handler
)
}
}
}
})()
frontend/src/components/ElTreeSelect/index.vue
0 → 100644
浏览文件 @
2cf026ed
差异被折叠。
点击展开。
frontend/src/components/ElTreeSelect/utils.js
0 → 100644
浏览文件 @
2cf026ed
/*
* @moduleName:通用工具类
* @Author: dawdler
* @Date: 2019-01-09 15:30:18
* @LastModifiedBy: dawdler
* @LastEditTime: 2020-12-26 14:06:09
*/
export
default
{
getTreeData
,
each
}
/*
each(arr, (item, children) => {
item.value = xx;
// 该item 包含children,因此直接赋值,不需要单独处理children里面的值
});
* [_each description] 倒查、展平、数据回调返回回当前一条数据和子集
* @param {[Array]} data [description]
* @param {Function} callback [description]
* @param {String} childName[description]
* @return {[Array]} [description]
* 默认使用副本,在callback处理数据,如果不使用副本,那么需要重新对treeData赋值
treeData = each(treeData, (item, children) => {
item.value = xx;
});
*/
export
function
each
(
data
,
callback
,
childName
=
'children'
)
{
let
current
let
children
for
(
let
i
=
0
,
len
=
data
.
length
;
i
<
len
;
i
++
)
{
current
=
data
[
i
]
children
=
[]
if
(
current
[
childName
]
&&
current
[
childName
].
length
>
0
)
{
children
=
current
[
childName
]
}
callback
&&
callback
(
current
,
children
)
if
(
children
.
length
>
0
)
{
each
(
children
,
callback
,
childName
)
}
}
}
/**
* @Author yihuang",
* @param data 数据
* @param id 要比对的名称
* @param val 要比对的值
* @param name 要返回的名称
* @param children 子集名称
* @param isRow 是否返回这一行的数据
* @注 迭代判断多层
* //=======================
* 返回这一条数据的中文名
* let name=utils.getTreeData(arr, 'flowId', item.decategoryId, 'name');
* //=======================
* 返回所有匹配的数据
* let arr=utils.getTreeData(arr, 'flowId', item.decategoryId, 'name','children',true);
*/
export
function
getTreeData
(
data
,
id
=
'id'
,
val
=
''
,
name
=
'name'
,
children
=
'children'
,
isRow
=
false
)
{
const
arr
=
[]
each
(
data
,
item
=>
{
if
(
item
[
id
]
===
val
)
{
arr
.
push
(
item
)
}
},
children
)
return
arr
.
length
>
0
?
(
isRow
?
arr
:
arr
[
0
][
name
])
:
null
}
export
function
guid
()
{
return
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.
replace
(
/
[
xy
]
/g
,
function
(
c
)
{
const
r
=
(
Math
.
random
()
*
16
)
|
0
const
v
=
c
===
'x'
?
r
:
(
r
&
0x3
)
|
0x8
return
v
.
toString
(
16
)
})
}
frontend/src/components/widget/DeWidget/DeSelectTree.vue
0 → 100644
浏览文件 @
2cf026ed
<
template
>
<el-tree-select
v-if=
"element.options!== null && element.options.attrs!==null && show"
ref=
"deSelectTree"
v-model=
"value"
popover-class=
"test-class-wrap"
:is-single=
"isSingle"
:data=
"datas"
:select-params=
"selectParams"
:tree-params=
"treeParams"
:filter-node-method=
"_filterFun"
:tree-render-fun=
"_renderFun"
@
searchFun=
"_searchFun"
@
node-click=
"changeNode"
@
removeTag=
"changeNodeIds"
@
check=
"changeCheckNode"
@
select-clear=
"selectClear"
/>
</
template
>
<
script
>
import
{
mappingFieldValues
,
linkMappingFieldValues
}
from
'@/api/dataset/dataset'
import
bus
from
'@/utils/bus'
import
{
getLinkToken
,
getToken
}
from
'@/utils/auth'
import
ElTreeSelect
from
'@/components/ElTreeSelect'
export
default
{
components
:
{
ElTreeSelect
},
props
:
{
element
:
{
type
:
Object
,
default
:
()
=>
{}
},
inDraw
:
{
type
:
Boolean
,
default
:
true
},
inScreen
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
},
size
:
String
},
data
()
{
return
{
showNumber
:
false
,
selectOptionWidth
:
0
,
show
:
true
,
datas
:
[],
value
:
this
.
isSingle
?
''
:
[],
selectParams
:
{
clearable
:
true
,
placeholder
:
this
.
$t
(
this
.
element
.
options
.
attrs
.
placeholder
)
},
treeParams
:
{
showParent
:
true
,
clickParent
:
true
,
filterable
:
true
,
// 只想要子节点,不需要父节点
leafOnly
:
false
,
includeHalfChecked
:
false
,
'check-strictly'
:
false
,
'default-expand-all'
:
false
,
'expand-on-click-node'
:
false
,
'render-content'
:
this
.
_renderFun
,
data
:
[],
props
:
{
children
:
'children'
,
label
:
'text'
,
rootId
:
'root'
,
disabled
:
'disabled'
,
parentId
:
'pid'
,
value
:
'id'
}
}
}
},
computed
:
{
operator
()
{
return
this
.
element
.
options
.
attrs
.
multiple
?
'in'
:
'eq'
},
defaultValueStr
()
{
if
(
!
this
.
element
||
!
this
.
element
.
options
||
!
this
.
element
.
options
.
value
)
return
''
return
this
.
element
.
options
.
value
.
toString
()
},
viewIds
()
{
if
(
!
this
.
element
||
!
this
.
element
.
options
||
!
this
.
element
.
options
.
attrs
.
viewIds
)
return
''
return
this
.
element
.
options
.
attrs
.
viewIds
.
toString
()
},
manualModify
()
{
return
!!
this
.
element
.
options
.
manualModify
},
panelInfo
()
{
return
this
.
$store
.
state
.
panel
.
panelInfo
},
isSingle
()
{
return
this
.
element
.
options
.
attrs
.
multiple
}
},
watch
:
{
'viewIds'
:
function
(
value
,
old
)
{
if
(
typeof
value
===
'undefined'
||
value
===
old
)
return
this
.
setCondition
()
},
'defaultValueStr'
:
function
(
value
,
old
)
{
if
(
value
===
old
)
return
this
.
value
=
this
.
fillValueDerfault
()
this
.
changeValue
(
value
)
},
'element.options.attrs.fieldId'
:
function
(
value
,
old
)
{
if
(
value
===
null
||
typeof
value
===
'undefined'
||
value
===
old
)
return
this
.
datas
=
[]
let
method
=
mappingFieldValues
const
token
=
this
.
$store
.
getters
.
token
||
getToken
()
const
linkToken
=
this
.
$store
.
getters
.
linkToken
||
getLinkToken
()
if
(
!
token
&&
linkToken
)
{
method
=
linkMappingFieldValues
}
const
param
=
{
fieldIds
:
this
.
element
.
options
.
attrs
.
fieldId
.
split
(
','
)
}
if
(
this
.
panelInfo
.
proxy
)
{
param
.
userId
=
this
.
panelInfo
.
proxy
}
this
.
element
.
options
.
attrs
.
fieldId
&&
this
.
element
.
options
.
attrs
.
fieldId
.
length
>
0
&&
method
(
param
).
then
(
res
=>
{
this
.
datas
=
this
.
optionDatas
(
res
.
data
)
this
.
$nextTick
(()
=>
{
this
.
$refs
.
deSelectTree
.
treeDataUpdateFun
(
this
.
datas
)
})
})
||
(
this
.
element
.
options
.
value
=
''
)
},
'element.options.attrs.multiple'
:
function
(
value
,
old
)
{
if
(
typeof
old
===
'undefined'
||
value
===
old
)
return
if
(
!
this
.
inDraw
)
{
this
.
value
=
value
?
[]
:
null
this
.
element
.
options
.
value
=
''
}
this
.
show
=
false
this
.
$nextTick
(()
=>
{
this
.
show
=
true
})
}
},
created
()
{
this
.
initLoad
()
},
mounted
()
{
bus
.
$on
(
'onScroll'
,
()
=>
{
})
bus
.
$on
(
'reset-default-value'
,
id
=>
{
if
(
this
.
inDraw
&&
this
.
manualModify
&&
this
.
element
.
id
===
id
)
{
this
.
value
=
this
.
fillValueDerfault
()
this
.
changeValue
(
this
.
value
)
}
})
},
methods
:
{
selectClear
()
{
this
.
changeValue
(
this
.
value
)
},
changeNode
(
data
,
node
)
{
this
.
changeValue
(
this
.
value
)
},
changeCheckNode
(
data
,
obj
)
{
const
{
checkedKeys
}
=
obj
if
(
checkedKeys
)
this
.
value
=
checkedKeys
this
.
changeValue
(
this
.
value
)
},
changeNodeIds
(
ids
)
{
this
.
value
=
ids
this
.
changeValue
(
this
.
value
)
},
initLoad
()
{
this
.
value
=
this
.
fillValueDerfault
()
this
.
datas
=
[]
if
(
this
.
element
.
options
.
attrs
.
fieldId
)
{
let
method
=
mappingFieldValues
const
token
=
this
.
$store
.
getters
.
token
||
getToken
()
const
linkToken
=
this
.
$store
.
getters
.
linkToken
||
getLinkToken
()
if
(
!
token
&&
linkToken
)
{
method
=
linkMappingFieldValues
}
method
({
fieldIds
:
this
.
element
.
options
.
attrs
.
fieldId
.
split
(
','
)
}).
then
(
res
=>
{
this
.
datas
=
this
.
optionDatas
(
res
.
data
)
this
.
$nextTick
(()
=>
{
this
.
$refs
.
deSelectTree
.
treeDataUpdateFun
(
this
.
datas
)
})
})
}
if
(
this
.
element
.
options
.
value
)
{
this
.
value
=
this
.
fillValueDerfault
()
this
.
changeValue
(
this
.
value
)
}
},
changeValue
(
value
)
{
if
(
!
this
.
inDraw
)
{
if
(
value
===
null
)
{
this
.
element
.
options
.
value
=
''
}
else
{
this
.
element
.
options
.
value
=
Array
.
isArray
(
value
)
?
value
.
join
()
:
value
}
this
.
element
.
options
.
manualModify
=
false
}
else
{
this
.
element
.
options
.
manualModify
=
true
}
this
.
setCondition
()
this
.
showNumber
=
false
this
.
$nextTick
(()
=>
{
if
(
!
this
.
element
.
options
.
attrs
.
multiple
||
!
this
.
$refs
.
deSelect
||
!
this
.
$refs
.
deSelect
.
$refs
.
tags
)
{
return
}
const
kids
=
this
.
$refs
.
deSelect
.
$refs
.
tags
.
children
[
0
].
children
let
contentWidth
=
0
kids
.
forEach
(
kid
=>
{
contentWidth
+=
kid
.
offsetWidth
})
this
.
showNumber
=
contentWidth
>
((
this
.
$refs
.
deSelectTree
.
$refs
.
tags
.
clientWidth
-
30
)
*
0.9
)
})
},
setCondition
()
{
const
param
=
{
component
:
this
.
element
,
value
:
this
.
formatFilterValue
(),
operator
:
this
.
operator
}
this
.
inDraw
&&
this
.
$store
.
commit
(
'addViewFilter'
,
param
)
},
formatFilterValue
()
{
const
SEPARATOR
=
'-de-'
if
(
this
.
value
===
null
)
return
[]
if
(
Array
.
isArray
(
this
.
value
))
{
const
results
=
[]
const
duplicateMap
=
{}
this
.
value
.
forEach
(
item
=>
{
const
links
=
item
.
split
(
SEPARATOR
)
let
temp
=
''
for
(
let
index
=
0
;
index
<
links
.
length
;
index
++
)
{
const
isLast
=
index
===
(
links
.
length
-
1
)
const
isFirst
=
index
===
0
const
node
=
links
[
index
]
temp
+=
((
isFirst
?
''
:
SEPARATOR
)
+
node
)
if
(
duplicateMap
[
temp
]
&&
!
isLast
)
{
delete
duplicateMap
[
temp
]
}
}
duplicateMap
[
item
]
=
true
})
for
(
const
key
in
duplicateMap
)
{
if
(
Object
.
hasOwnProperty
.
call
(
duplicateMap
,
key
)
&&
duplicateMap
[
key
])
{
const
node
=
key
.
replaceAll
(
SEPARATOR
,
','
)
results
.
push
(
node
)
}
}
return
results
// return this.value
}
return
this
.
value
.
split
(
','
)
},
fillValueDerfault
()
{
const
defaultV
=
this
.
element
.
options
.
value
===
null
?
''
:
this
.
element
.
options
.
value
.
toString
()
if
(
this
.
element
.
options
.
attrs
.
multiple
)
{
if
(
defaultV
===
null
||
typeof
defaultV
===
'undefined'
||
defaultV
===
''
||
defaultV
===
'[object Object]'
)
return
[]
return
defaultV
.
split
(
','
)
}
else
{
if
(
defaultV
===
null
||
typeof
defaultV
===
'undefined'
||
defaultV
===
''
||
defaultV
===
'[object Object]'
)
return
null
return
defaultV
.
split
(
','
)[
0
]
}
},
optionDatas
(
datas
)
{
if
(
!
datas
)
return
null
return
datas
.
filter
(
item
=>
!!
item
)
},
setOptionWidth
(
event
)
{
// 下拉框弹出时,设置弹框的宽度
this
.
$nextTick
(()
=>
{
// this.selectOptionWidth = event.srcElement.offsetWidth + 'px'
this
.
selectOptionWidth
=
event
.
srcElement
.
parentElement
.
parentElement
.
offsetWidth
+
'px'
})
},
/* 下面是树的渲染方法 */
_filterFun
(
value
,
data
,
node
)
{
if
(
!
value
)
return
true
return
data
.
id
.
toString
().
indexOf
(
value
.
toString
())
!==
-
1
},
// 树点击
_nodeClickFun
(
data
,
node
,
vm
)
{
console
.
log
(
'this _nodeClickFun'
,
this
.
value
,
data
,
node
)
},
// 树过滤
_searchFun
(
value
)
{
console
.
log
(
value
,
'<--_searchFun'
)
// 自行判断 是走后台查询,还是前端过滤
this
.
$refs
.
treeSelect
.
filterFun
(
value
)
// 后台查询
// this.$refs.treeSelect.treeDataUpdateFun(treeData);
},
// 自定义render
_renderFun
(
h
,
{
node
,
data
,
store
})
{
const
{
props
,
clickParent
}
=
this
.
treeParams
return
(
<
span
class
=
{[
'custom-tree-node'
,
!
clickParent
&&
data
[
props
.
children
]
&&
data
[
props
.
children
].
length
?
'disabled'
:
null
]}
>
<
span
>
{
node
.
label
}
<
/span
>
<
/span
>
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
</
style
>
frontend/src/components/widget/serviceImpl/TextSelectTreeServiceImpl.js
0 → 100644
浏览文件 @
2cf026ed
import
{
WidgetService
}
from
'../service/WidgetService'
const
leftPanel
=
{
icon
:
'iconfont icon-xialashu'
,
label
:
'detextselectTree.label'
,
defaultClass
:
'text-filter'
}
const
dialogPanel
=
{
options
:
{
attrs
:
{
multiple
:
false
,
placeholder
:
'detextselectTree.placeholder'
,
viewIds
:
[],
datas
:
[],
key
:
'id'
,
label
:
'text'
,
value
:
'id'
,
fieldId
:
''
,
dragItems
:
[]
},
value
:
''
,
manualModify
:
false
},
defaultClass
:
'text-filter'
,
component
:
'de-select-tree'
,
miniSizex
:
1
,
miniSizey
:
1
}
const
drawPanel
=
{
type
:
'custom'
,
style
:
{
width
:
300
,
height
:
90
,
fontSize
:
14
,
fontWeight
:
500
,
lineHeight
:
''
,
letterSpacing
:
0
,
textAlign
:
''
,
color
:
''
,
hPosition
:
'left'
,
vPosition
:
'center'
},
component
:
'de-select-tree'
}
class
TextSelectTreeServiceImpl
extends
WidgetService
{
constructor
(
options
=
{})
{
Object
.
assign
(
options
,
{
name
:
'textSelectTreeWidget'
})
super
(
options
)
this
.
filterDialog
=
true
this
.
showSwitch
=
true
}
initLeftPanel
()
{
const
value
=
JSON
.
parse
(
JSON
.
stringify
(
leftPanel
))
return
value
}
initFilterDialog
()
{
const
value
=
JSON
.
parse
(
JSON
.
stringify
(
dialogPanel
))
return
value
}
initDrawPanel
()
{
const
value
=
JSON
.
parse
(
JSON
.
stringify
(
drawPanel
))
return
value
}
filterFieldMethod
(
fields
)
{
return
fields
.
filter
(
field
=>
{
return
field
[
'deType'
]
===
0
})
}
optionDatas
(
datas
)
{
if
(
!
datas
)
return
null
return
datas
.
filter
(
item
=>
!!
item
).
map
(
item
=>
{
return
{
id
:
item
,
text
:
item
}
})
}
getParam
(
element
)
{
const
value
=
this
.
fillValueDerfault
(
element
)
const
param
=
{
component
:
element
,
value
:
!
value
?
[]
:
Array
.
isArray
(
value
)
?
value
:
value
.
toString
().
split
(
','
),
operator
:
element
.
options
.
attrs
.
multiple
?
'in'
:
'eq'
}
return
param
}
fillValueDerfault
(
element
)
{
const
defaultV
=
element
.
options
.
value
===
null
?
''
:
element
.
options
.
value
.
toString
()
if
(
element
.
options
.
attrs
.
multiple
)
{
if
(
defaultV
===
null
||
typeof
defaultV
===
'undefined'
||
defaultV
===
''
||
defaultV
===
'[object Object]'
)
return
[]
return
defaultV
.
split
(
','
)
}
else
{
if
(
defaultV
===
null
||
typeof
defaultV
===
'undefined'
||
defaultV
===
''
||
defaultV
===
'[object Object]'
)
return
null
return
defaultV
.
split
(
','
)[
0
]
}
}
}
const
textSelectTreeServiceImpl
=
new
TextSelectTreeServiceImpl
()
export
default
textSelectTreeServiceImpl
frontend/src/lang/en.js
浏览文件 @
2cf026ed
...
...
@@ -1885,6 +1885,10 @@ export default {
label
:
'Text selector'
,
placeholder
:
'Please select'
},
detextselectTree
:
{
label
:
'Tree selector'
,
placeholder
:
'Please select'
},
detextgridselect
:
{
label
:
'Text list'
,
placeholder
:
'Please select'
...
...
frontend/src/lang/tw.js
浏览文件 @
2cf026ed
...
...
@@ -1897,6 +1897,10 @@ export default {
label
:
'文本下拉'
,
placeholder
:
'請選擇'
},
detextselectTree
:
{
label
:
'下拉树'
,
placeholder
:
'請選擇'
},
detextgridselect
:
{
label
:
'文本列錶'
,
placeholder
:
'請選擇'
...
...
frontend/src/lang/zh.js
浏览文件 @
2cf026ed
...
...
@@ -1331,7 +1331,7 @@ export default {
sql_ds_union_error
:
'直连模式下SQL数据集,不支持关联'
,
api_data
:
'API 数据集'
},
driver
:{
driver
:
{
driver
:
'驱动'
,
please_choose_driver
:
'请选择驱动'
,
mgm
:
'驱动管理'
,
...
...
@@ -1905,6 +1905,10 @@ export default {
label
:
'文本下拉'
,
placeholder
:
'请选择'
},
detextselectTree
:
{
label
:
'下拉树'
,
placeholder
:
'请选择'
},
detextgridselect
:
{
label
:
'文本列表'
,
placeholder
:
'请选择'
...
...
frontend/src/views/panel/filter/index.vue
浏览文件 @
2cf026ed
...
...
@@ -55,7 +55,8 @@ export default {
'文本过滤组件'
:
[
'textSelectWidget'
,
'textSelectGridWidget'
,
'textInputWidget'
'textInputWidget'
,
'textSelectTreeWidget'
],
'数字过滤组件'
:
[
'numberSelectWidget'
,
...
...
frontend/src/views/system/test/MyTree.vue
0 → 100644
浏览文件 @
2cf026ed
<!--
* @Author: dawdler
* @Date: 2020-12-26 11:52:05
* @Description: demo
* @LastModifiedBy: dawdler
-->
<
template
>
<el-tree-select
ref=
"treeSelect"
v-model=
"values"
popover-class=
"test-class-wrap"
:styles=
"styles"
:select-params=
"selectParams"
:tree-params=
"treeParams"
:filter-node-method=
"_filterFun"
:tree-render-fun=
"_renderFun"
@
searchFun=
"_searchFun"
/>
</
template
>
<
script
>
import
ElTreeSelect
from
'@/components/ElTreeSelect'
export
default
{
name
:
'MyTreeSelect'
,
components
:
{
ElTreeSelect
},
props
:
{
params
:
Object
,
isSingle
:
{
type
:
Boolean
,
default
()
{
return
false
}
}
},
data
()
{
return
{
styles
:
{
width
:
'300px'
},
// 单选value为字符串,多选为数组
values
:
this
.
isSingle
?
''
:
[],
selectParams
:
{
clearable
:
true
,
placeholder
:
'请输入内容'
},
treeParams
:
{
clickParent
:
false
,
filterable
:
true
,
// 只想要子节点,不需要父节点
leafOnly
:
false
,
includeHalfChecked
:
false
,
'check-strictly'
:
false
,
'default-expand-all'
:
true
,
'expand-on-click-node'
:
false
,
'render-content'
:
this
.
_renderFun
,
data
:
[],
props
:
{
children
:
'children'
,
label
:
'name'
,
rootId
:
'0'
,
disabled
:
'disabled'
,
parentId
:
'parentId'
,
value
:
'id'
},
...
this
.
params
}
}
},
watch
:
{},
created
()
{},
mounted
()
{
// 手动更新树数据
const
data
=
[]
const
{
label
,
children
,
parentId
,
value
,
rootId
}
=
this
.
treeParams
.
props
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
rootNode
=
{
[
label
]:
`节点
${
i
}
`
,
[
parentId
]:
rootId
,
[
value
]:
i
,
[
children
]:
[]
}
for
(
let
a
=
0
;
a
<
5
;
a
++
)
{
const
subId
=
`
${
rootNode
[
value
]}
_
${
a
}
`
const
subNode
=
{
[
label
]:
`子节点
${
subId
}
`
,
[
parentId
]:
rootNode
[
value
],
[
value
]:
subId
,
[
children
]:
[]
}
for
(
let
b
=
0
;
b
<
5
;
b
++
)
{
const
endId
=
`
${
subId
}
_
${
b
}
`
const
endNode
=
{
[
label
]:
`末级节点
${
endId
}
`
,
[
parentId
]:
subNode
[
value
],
[
value
]:
endId
,
[
children
]:
[]
}
subNode
[
children
].
push
(
endNode
)
}
rootNode
[
children
].
push
(
subNode
)
}
data
.
push
(
rootNode
)
}
const
myNode
=
{
[
label
]:
'测试超长节点啊啊啊测试超长节点啊啊啊测试超长节点啊啊啊测试超长节点啊啊啊测试超长节点啊啊啊测试超长节点啊啊啊'
,
[
parentId
]:
rootId
,
[
value
]:
1000
,
[
children
]:
[]
}
data
.
push
(
myNode
)
this
.
$nextTick
(()
=>
{
this
.
$refs
.
treeSelect
.
treeDataUpdateFun
(
data
)
})
},
methods
:
{
_filterFun
(
value
,
data
,
node
)
{
if
(
!
value
)
return
true
return
data
.
id
.
toString
().
indexOf
(
value
.
toString
())
!==
-
1
},
// 树点击
_nodeClickFun
(
data
,
node
,
vm
)
{
console
.
log
(
'this _nodeClickFun'
,
this
.
values
,
data
,
node
)
},
// 树过滤
_searchFun
(
value
)
{
console
.
log
(
value
,
'<--_searchFun'
)
// 自行判断 是走后台查询,还是前端过滤
this
.
$refs
.
treeSelect
.
filterFun
(
value
)
// 后台查询
// this.$refs.treeSelect.treeDataUpdateFun(treeData);
},
// 自定义render
_renderFun
(
h
,
{
node
,
data
,
store
})
{
const
{
props
,
clickParent
}
=
this
.
treeParams
return
(
<
span
class
=
{[
'custom-tree-node'
,
!
clickParent
&&
data
[
props
.
children
]
&&
data
[
props
.
children
].
length
?
'disabled'
:
null
]}
>
<
span
>
{
node
.
label
}
<
/span
>
<
/span
>
)
}
}
}
</
script
>
<
style
lang=
"less"
>
.disabled {
cursor: no-drop;
}
.custom-tree-node {
width: calc(100% - 40px);
}
</
style
>
frontend/src/views/system/test/index.vue
0 → 100644
浏览文件 @
2cf026ed
<!--
* @moduleName: 测试el-tree-select
* @Author: dawdler
* @Date: 2018-12-19 14:03:03
* @LastModifiedBy: dawdler
-->
<
template
>
<div
id=
"app111"
>
<el-form
label-width=
"120px"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"单选"
>
<MyTree
:is-single=
"true"
:params=
"
{ clickParent: true, showParent: true }" />
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"多选"
>
<MyTree
:params=
"
{ clickParent: true, showParent: true }" />
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"弹框关闭调试"
>
<el-select
v-model=
"test"
multiple
placeholder=
"请选择"
@
change=
"_selectChange"
>
<el-option
v-for=
"item in testData"
:key=
"item"
:label=
"item"
:value=
"item"
/>
</el-select>
<div>
测试焦点触发
<svg>
<circle
cx=
"100"
cy=
"50"
r=
"40"
stroke=
"black"
stroke-width=
"2"
fill=
"red"
/>
</svg>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</
template
>
<
script
>
import
MyTree
from
'./MyTree'
export
default
{
name
:
'App111'
,
components
:
{
MyTree
},
data
()
{
return
{
test
:
''
,
testData
:
[
'test1'
,
'test2'
]
}
},
created
()
{},
mounted
()
{},
methods
:
{
// 下拉框修改
_selectChange
(
val
)
{
console
.
log
(
val
,
'<-select change'
)
}
}
}
</
script
>
<
style
lang=
"less"
>
#app111 {
display: flex;
justify-content: space-between;
width: 100%;
}
.el-select {
width: 300px;
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论