Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
N
nse-ui
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Members
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
吴超
nse-ui
Commits
464710f1
Commit
464710f1
authored
Sep 19, 2025
by
ningjihai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
123
parent
6bc33388
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
602 行增加
和
286 行删除
+602
-286
src/assets/styles/element-ui.scss
+2
-1
src/views/project/Project/ProjectEditDialog.vue
+479
-233
src/views/project/Project/QueryForm.vue
+18
-8
src/views/project/Project/list.vue
+103
-44
没有找到文件。
src/assets/styles/element-ui.scss
View file @
464710f1
...
...
@@ -125,7 +125,8 @@
.custom-dialog
{
border-radius
:
8px
;
.custom-dialog-header
{
padding-top
:
30px
;
width
:
100%
;
// padding-top: 30px;
padding-left
:
28px
;
padding-right
:
32px
;
display
:
flex
;
...
...
src/views/project/Project/ProjectEditDialog.vue
View file @
464710f1
<
template
>
<el-dialog
style=
"padding: 0;"
class=
"custom-dialog"
v-model=
"dialogVisible"
:
title=
"dialogTitl
e"
:
show-close=
"fals
e"
destroy-on-close
width=
"920px"
:before-close=
"handleClose"
>
<template
#
header
>
<div
class=
"custom-dialog-header"
>
<div
class=
"custom-dialog-title"
>
{{
dialogTitle
}}
</div>
<img
class=
"custom-dialog-close"
:src=
"dialogCloseLogo"
alt=
""
@
click=
"closeDialog"
>
</div>
</
template
>
<!-- <el-divider class="dialog-divider"></el-divider> -->
<div
class=
"dialog-content"
>
<!-- 左侧表单 -->
<div
class=
"form-container"
>
<ItemTitle
title=
"基本信息"
/>
<!-- 第一步:基本信息 -->
<div
v-if=
"activeStep === 1
"
>
<div
class=
"item-form-container
"
>
<el-form
ref=
"basicInfoFormRef"
:model=
"formData"
:rules=
"formRules"
label-width=
"100px"
label-position=
"top"
label-width=
"90px"
label-position=
"left"
:inline=
"true"
>
<el-form-item
label=
"项目名称"
prop=
"name"
required
>
<el-input
v-model=
"formData.name"
placeholder=
"请输入项目名称"
maxlength=
"200"
show-word-limit
/>
</el-form-item>
<el-form-item
label=
"项目备注"
prop=
"remark"
>
<el-input
v-model=
"formData.remark"
type=
"textarea"
:rows=
"4"
placeholder=
"请输入项目备注信息"
maxlength=
"200"
show-word-limit
/>
</el-form-item>
...
...
@@ -46,212 +58,124 @@
</el-form>
</div>
<ItemTitle
title=
"数据源配置"
style=
"margin-top: 20px;"
/>
<!-- 第二步:数据库配置 -->
<div
v-if=
"activeStep === 2"
>
<div
class=
"step-title"
>
数据库
</div>
<div
class=
"filter-container"
>
<el-select
v-model=
"dbFilter.type"
placeholder=
"请选择"
class=
"filter-select"
@
change=
"selectChangeSql"
>
<el-option
v-for=
"(item,index) in sourceTypeList"
:key=
"index"
:label=
"item.text"
:value=
"item.text"
/>
</el-select>
<el-input
v-model=
"dbFilter.keyword"
placeholder=
"输入数据源名称搜索"
class=
"filter-input"
clearable
<div
class=
"item-form-container"
>
<!-- TreeSelect 组件 -->
<div
class=
"tree-select-container flex-container align-center"
style=
"flex-wrap: nowrap;"
>
<div
class=
"step-title master"
style=
"width: 90px;"
>
数据库
</div>
<el-tree-select
ref=
"treeSelectRef"
v-model=
"selectedDbNodes"
:data=
"treeData"
:props=
"treeProps"
:render-after-expand=
"false"
show-checkbox
node-key=
"tid"
:filter-node-method=
"filterNode"
placeholder=
"请选择数据源"
multiple
@
check=
"handleTreeSelectCheck"
@
node-click=
"handleNodeExpand"
:default-expand-all=
"false"
>
<template
#
prefix
>
<el-icon><search
/></el-icon>
<
template
#
default=
"{ node, data }"
>
<span
class=
"tree-node-label"
>
{{
data
.
sysname
||
data
.
text
}}
<span
v-if=
"data.dbtype"
class=
"tree-node-type"
>
(
{{
data
.
dbtype
}}
)
</span>
</span>
</
template
>
</el-input>
</div>
<div
class=
"db-select-container"
>
<!-- 左侧可选数据库 -->
<div
class=
"db-list"
>
<div
class=
"db-list-header"
>
<span>
可选择数据源(数据库)
</span>
</div>
<el-scrollbar
height=
"300px"
>
<div
v-for=
"db in filteredAvailableDatabases"
:key=
"db.tid"
class=
"db-item"
@
click=
"selectDatabase(db)"
>
<div
class=
"db-info"
>
<div
class=
"db-name"
>
{{ db.sysname }}
</div>
<div
class=
"db-type"
>
{{ db.dbtype }}
</div>
</div>
</div>
</el-scrollbar>
</div>
<!-- 右侧已选数据库 -->
<div
class=
"db-list selected"
>
<div
class=
"db-list-header"
>
<span>
已选择数据源(数据库)
</span>
<span
style=
"color: #2d8cf0;cursor: pointer;"
@
click=
"handleClearSelected"
>
清空
</span>
</div>
<el-scrollbar
height=
"300px"
>
<div
v-for=
"db in selectedDbDetails"
:key=
"db.tid"
class=
"selected-db-item"
@
click=
"deselectDatabase(db)"
>
<div
class=
"db-name"
>
{{ db.sysname }}
</div>
<!-- <div class="db-ip">{{ db.dbip }}</div> -->
<div
class=
"db-type"
>
{{ db.dbtype }}
</div>
</div>
</el-scrollbar>
</div>
</el-tree-select>
</div>
</div>
<ItemTitle
title=
"Schema选择"
style=
"margin-top: 20px;"
/>
<!-- 第三步:Schema选择 -->
<div
v-if=
"activeStep === 3"
>
<div
class=
"step-title"
>
Schema选择
</div>
<div
class=
"schema-container"
>
<!-- 左侧数据源 -->
<div
class=
"datasource-section"
>
<div
class=
"section-title"
>
数据源
</div>
<el-scrollbar
height=
"400px"
>
<div
class=
"datasource-list"
>
<div
v-for=
"(db, dbIndex) in selectedDbDetails"
:key=
"db.tid"
class=
"datasource-item"
:class=
"{ active: selectedDataSource === db.tid }"
@
click=
"selectDataSource(db.tid, dbIndex)"
>
{{ db.sysname }}
</div>
</div>
</el-scrollbar>
</div>
<!-- 右侧Schema选择 -->
<div
class=
"schema-section"
>
<div
class=
"schema-header"
>
<div
class=
"section-title"
>
SCHEMA
</div>
<div
class=
"schema-select-all"
>
<span
class=
"schema-count"
>
{{ selectedSchemas.length }}/{{ allSchemasCompute?.length }}
</span>
</div>
</div>
<el-scrollbar
height=
"400px"
>
<el-checkbox-group
v-model=
"selectedSchemas"
@
change=
"schemaChange"
>
<div
v-for=
"schema in allSchemasCompute"
:key=
"schema.value"
class=
"schema-item"
>
<el-checkbox
:value=
"schema.value"
:label=
"schema.text"
:checked=
"isSchemaSelected(schema.value)"
/>
</div>
</el-checkbox-group>
</el-scrollbar>
<div
class=
"item-form-container"
>
<div
v-if=
"selectedDbDetails.length === 0"
class=
"flex-container align-center"
>
请先选择数据库
</div>
<div
class=
"flex-container align-center wrap"
v-else
>
<div
v-for=
"(db, dbIndex) in selectedDbDetails"
:key=
"db.tid"
class=
"datasource-item flex-container align-center"
>
<div
style=
"width: 90px;"
>
{{ db.sysname }}
</div>
<el-select
v-model=
"selectedSchemas[dbIndex]"
multiple
placeholder=
"请选择"
style=
"width: 278px"
collapse-tags
collapse-tags-tooltip
:max-collapse-tags=
"2"
@
change=
"selectChangeSchema"
>
<el-option
v-for=
"schema in allSchemas[dbIndex]"
:key=
"schema.value"
:label=
"schema.text"
:value=
"schema.value"
/>
</el-select>
</div>
</div>
</div>
<!-- 其他步骤内容保持不变 -->
<!-- 第四步:数据域选择 -->
<ItemTitle
title=
"规则选择"
style=
"margin-top: 20px;"
/>
<!-- 第四步:数据域选择 -->
<div
v-if=
"activeStep === 4"
>
<div
class=
"step-title"
>
规则选择
</div>
<div
class=
"domain-container"
>
<!-- 左侧可选择规则 -->
<div
class=
"available-domains"
>
<div
class=
"section-header"
>
<div
class=
"section-title"
>
可选择规则
</div>
</div>
<div
class=
"domain-group"
v-for=
"group in domainGroups"
:key=
"group.id"
>
<div
class=
"group-header"
>
<el-checkbox
v-model=
"group.selectedAll"
@
change=
"(val) => toggleGroupSelection(group, val)"
>
{{ group.dataarea }}
</el-checkbox>
</div>
<el-scrollbar
height=
"150px"
>
<el-checkbox-group
v-model=
"selectedDomains"
@
change=
"handleDomainSelectionChange"
>
<div
v-for=
"domain in group.list"
:key=
"domain.id"
class=
"domain-item"
>
<el-checkbox
:value=
"domain.id"
:checked=
"isDomainSelected(domain.id)"
>
<div
class=
"domain-content"
>
<div
class=
"domain-name"
>
{{ domain.name }}
</div>
<div
v-if=
"domain.desc"
class=
"domain-desc"
>
{{ domain.desc }}
</div>
</div>
</el-checkbox>
</div>
</el-checkbox-group>
</el-scrollbar>
</div>
</div>
<!-- 已选择规则 -->
<div
class=
"selected-domains"
>
<div
class=
"section-header"
>
<div
class=
"section-title"
>
已选择规则
</div>
<div
class=
"selection-info"
>
<span
class=
"count"
>
{{ selectedDomains.length }}
</span>
<el-button
type=
"text"
@
click=
"clearSelectedDomains"
>
清空
</el-button>
</div>
</div>
<el-scrollbar
height=
"400px"
>
<div
v-for=
"domain in selectedDomainDetails"
:key=
"domain.id"
class=
"selected-domain-item"
>
<div
class=
"domain-name"
>
{{ domain.name }}
</div>
<div
v-if=
"domain.desc"
class=
"domain-desc"
>
{{ domain.desc }}
</div>
<div
class=
"domain-group-name"
v-if=
"findDomainGroupName(domain.id)"
>
所属分组: {{ findDomainGroupName(domain.id) }}
</div>
</div>
</el-scrollbar>
</div>
<div
class=
"item-form-container"
>
<div
class=
"tree-select-container flex-container align-center"
style=
"flex-wrap: nowrap;"
>
<div
class=
"step-title master"
style=
"width: 90px;"
>
规则
</div>
<el-tree-select
ref=
"treeSelectRuleRef"
v-model=
"selectedRuleNode"
node-key=
"id"
:data=
"transformedDomainGroups"
:props=
"treeRuleProps"
placeholder=
"请选择规则"
multiple
:render-after-expand=
"false"
show-checkbox
>
<
template
#
default=
"{ node, data }"
>
<span
class=
"tree-node-label"
>
{{
data
.
dataarea
||
data
.
name
}}
</span>
</
template
>
</el-tree-select>
</div>
</div>
</div>
<!-- 右侧步骤条 -->
<div
class=
"steps-container"
>
<
!-- <
div class="steps-container">
<el-steps direction="vertical" :active="activeStep">
<el-step :title="stepTitles[0]" />
<el-step :title="stepTitles[1]" />
<el-step :title="stepTitles[2]" />
<el-step :title="stepTitles[3]" />
</el-steps>
</div>
</div>
-->
</div>
<
template
#
footer
>
<span
class=
"dialog-footer"
>
<el-button
type=
"primary"
color=
"rgba(33, 103, 217, 1)"
@
click=
"handleSubmit"
>
确认
</el-button>
<el-button
type=
"primary"
plain
>
取消
</el-button>
<!--
<span
class=
"dialog-footer"
>
<el-button
@
click=
"handlePrevStep"
>
上一步
</el-button>
<el-button
type=
"primary"
@
click=
"handleNextStep"
>
{{
activeStep
===
4
?
'完成'
:
'下一步'
}}
</el-button>
</span>
</span>
-->
</
template
>
</el-dialog>
</template>
...
...
@@ -260,6 +184,8 @@
import
{
ref
,
computed
,
watch
}
from
'vue'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
{
Search
}
from
'@element-plus/icons-vue'
import
dialogCloseLogo
from
'@/assets/images/dialogCloseLogo.png'
import
{
getdatascopeprojectlist
,
checkDatasystemName
,
...
...
@@ -315,12 +241,53 @@ const initialized = ref(false)
// 监听对话框显示状态变化
watch
(
dialogVisible
,
(
newVal
)
=>
{
if
(
newVal
&&
!
initialized
.
value
)
{
initDialog
()
// initDialog()
fetchFirstLevelNodes
()
fetchRules
()
}
else
if
(
!
newVal
)
{
initialized
.
value
=
false
}
},
{
deep
:
true
})
const
fetchRules
=
()
=>
{
getAllDataAreaAndRule
().
then
(
res
=>
{
domainGroups
.
value
=
res
.
data
// 如果是编辑模式,需要处理已选择的规则
if
(
props
.
mode
===
'edit'
&&
areaAndRuleListRead
.
value
.
length
>
0
)
{
processAreaAndRuleListForEdit
(
areaAndRuleListRead
.
value
)
}
})
}
const
treeRuleProps
=
reactive
({
label
:
'dataarea'
,
children
:
'children'
});
const
selectedRuleNode
=
ref
([])
// 转换数据格式以适应el-tree-select
const
transformedDomainGroups
=
computed
(()
=>
{
return
domainGroups
.
value
.
map
(
group
=>
{
// 复制组的基本信息
const
transformedGroup
=
{
id
:
group
.
id
,
dataarea
:
group
.
dataarea
,
children
:
[]
};
// 将list转换为children
if
(
group
.
list
&&
Array
.
isArray
(
group
.
list
))
{
transformedGroup
.
children
=
group
.
list
.
map
(
rule
=>
({
...
rule
,
id
:
rule
.
id
,
name
:
rule
.
name
,
dataarea
:
rule
.
type
,
// 使用type作为数据域名称
ruleexample
:
rule
.
ruleexample
,
isRule
:
true
// 标记为规则节点
}));
}
return
transformedGroup
;
});
});
// 当对话框显示时执行的函数
const
initDialog
=
()
=>
{
querySelectOrDic
()
...
...
@@ -335,6 +302,167 @@ const querySelectOrDic = () => {
dbFilter
.
value
.
type
=
res
.
data
.
length
>
0
?
res
.
data
[
res
.
data
.
length
-
1
].
text
:
''
})
}
const
treeData
=
ref
([])
const
selectedDbNodes
=
ref
([])
const
treeProps
=
ref
({
label
:
'sysname'
,
// 显示文本的字段名
children
:
'children'
,
// disabled: (data) => !data.tid // 只有二级节点可以选择
})
// 获取树形数据
const
fetchFirstLevelNodes
=
async
()
=>
{
try
{
const
typeRes
=
await
selectProDataSource
({
systemstyle
:
1
})
if
(
typeRes
.
flag
&&
typeRes
.
data
)
{
treeData
.
value
=
typeRes
.
data
.
map
(
item
=>
({
id
:
item
.
value
,
tid
:
item
.
value
,
text
:
item
.
text
,
value
:
item
.
value
,
sysname
:
item
.
text
,
isFirstLevel
:
true
,
children
:
[]
// 初始化空children,用于懒加载
})).
filter
(
item
=>
item
.
value
!==
'0'
)
}
}
catch
(
error
)
{
console
.
error
(
'获取一级节点数据失败:'
,
error
)
ElMessage
.
error
(
'获取数据源类型失败'
)
}
}
// 处理节点展开事件(懒加载二级节点)
// 处理节点展开事件(懒加载二级节点)
const
handleNodeExpand
=
async
(
nodeData
)
=>
{
console
.
log
(
'节点展开:'
,
nodeData
)
// 只有一级节点需要懒加载,且没有子节点或子节点为空
if
(
nodeData
.
isFirstLevel
&&
(
!
nodeData
.
children
||
nodeData
.
children
.
length
===
0
))
{
try
{
// 设置加载状态
nodeData
.
loading
=
true
;
const
secondRes
=
await
queryByEditSort
({
projectId
:
formData
.
value
.
id
||
''
,
dbtype
:
nodeData
.
text
,
loginUser
:
loginUser
,
flag
:
1
})
if
(
secondRes
.
flag
&&
secondRes
.
data
)
{
// 使用 Vue.set 或创建新对象来确保响应式更新
const
newChildren
=
secondRes
.
data
.
map
(
db
=>
({
...
db
,
parentName
:
nodeData
.
text
,
parentId
:
nodeData
.
id
,
text
:
db
.
sysname
,
isFirstLevel
:
false
}))
// 关键:使用 Vue.set 或创建新数组来触发响应式更新
if
(
!
nodeData
.
children
)
{
nodeData
.
children
=
newChildren
;
}
else
{
nodeData
.
children
.
splice
(
0
,
nodeData
.
children
.
length
,
...
newChildren
);
}
// 强制更新树数据(创建新数组引用)
treeData
.
value
=
[...
treeData
.
value
]
// 手动触发节点展开
nextTick
(()
=>
{
const
treeInstance
=
treeSelectRef
.
value
;
if
(
treeInstance
&&
treeInstance
.
expandNode
)
{
treeInstance
.
expandNode
(
nodeData
,
true
);
}
});
}
}
catch
(
error
)
{
console
.
error
(
`获取
${
nodeData
.
text
}
的二级节点失败:`
,
error
)
ElMessage
.
error
(
`获取
${
nodeData
.
text
}
的数据源失败`
)
}
finally
{
nodeData
.
loading
=
false
;
}
}
}
const
treeSelectRef
=
ref
(
null
)
// 处理树选择变化
const
handleTreeSelectCheck
=
(
checkedNode
,
{
checkedNodes
,
checkedKeys
,
halfCheckedNodes
,
halfCheckedKeys
})
=>
{
// 完全排除一级节点的选择,只保留有tid的二级节点
const
secondaryNodes
=
checkedNodes
.
filter
(
node
=>
node
.
tid
&&
!
node
.
isFirstLevel
);
// selectedDbDetails.value = secondaryNodes;
// 更新选中节点的keys(只包含二级节点)
selectedDbNodes
.
value
=
secondaryNodes
.
map
(
node
=>
node
.
tid
);
// console.log('更新后的 selectedDbNodes:', selectedDbNodes.value);
};
watch
(
selectedDbNodes
,
(
newVal
)
=>
{
console
.
log
(
'getCheckedNodes'
,
treeSelectRef
.
value
.
getCheckedNodes
())
console
.
log
(
'节点监听器'
,
selectedDbNodes
.
value
)
if
(
newVal
)
{
selectedDbDetails
.
value
=
treeSelectRef
.
value
.
getCheckedNodes
()
fetchAllSchemas
(
selectedDbDetails
.
value
)
}
},
{
deep
:
true
})
// // 移除已选数据源
// const removeSelectedDb = (db) => {
// const index = selectedDbDetails.value.findIndex(item => item.tid === db.tid)
// if (index > -1) {
// selectedDbDetails.value.splice(index, 1)
// selectedDbNodes.value = selectedDbDetails.value.map(db => db.tid)
// // 从树选择器中移除
// const treeSelectRef = document.querySelector('.el-tree-select')
// if (treeSelectRef) {
// const selectedValues = selectedDbNodes.value
// // 这里需要根据实际情况更新树选择器的值
// }
// }
// }
// 过滤节点
const
filterNode
=
(
value
,
data
)
=>
{
if
(
!
value
)
return
true
return
data
.
sysname
?.
toLowerCase
().
includes
(
value
.
toLowerCase
())
||
data
.
text
?.
toLowerCase
().
includes
(
value
.
toLowerCase
())
}
// 获取显示名称(一级节点/二级节点)
const
getDbDisplayName
=
(
db
)
=>
{
return
`
${
db
.
parentName
}
/
${
db
.
sysname
}
`
}
// 自定义节点样式 - 隐藏一级节点的checkbox
const
customNodeClass
=
(
data
)
=>
{
return
data
.
isFirstLevel
?
'first-level-node'
:
'second-level-node'
}
// // 在对话框显示时加载数据
// watch(dialogVisible, (newVal) => {
// if (newVal) {
// setTimeout(() => {
// fetchTreeData()
// }, 1000);
// }
// })
const
reset
=
()
=>
{
sourceTypeList
.
value
=
[]
...
...
@@ -507,23 +635,7 @@ const schemaChange = () => {
})
}
const
toggleGroupSelection
=
(
group
,
selected
)
=>
{
const
groupDomainIds
=
group
.
list
.
map
(
d
=>
d
.
id
)
if
(
selected
)
{
const
newSelected
=
[...
new
Set
([...
selectedDomains
.
value
,
...
groupDomainIds
])]
selectedDomains
.
value
=
newSelected
}
else
{
selectedDomains
.
value
=
selectedDomains
.
value
.
filter
(
id
=>
!
groupDomainIds
.
includes
(
id
))
}
}
const
clearSelectedDomains
=
()
=>
{
selectedDomains
.
value
=
[]
domainGroups
.
value
.
forEach
(
group
=>
{
group
.
selectedAll
=
false
})
}
// 上一步
const
handlePrevStep
=
()
=>
{
...
...
@@ -664,6 +776,19 @@ const validateStep1 = async () => {
})
}
const
closeDialog
=
()
=>
{
ElMessageBox
.
confirm
(
'确定要关闭吗?未保存的更改将会丢失'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
}).
then
(()
=>
{
dialogVisible
.
value
=
false
reset
()
done
()
}).
catch
(()
=>
{
// 取消关闭
})
}
// 关闭前处理
const
handleClose
=
(
done
)
=>
{
ElMessageBox
.
confirm
(
'确定要关闭吗?未保存的更改将会丢失'
,
'提示'
,
{
...
...
@@ -691,28 +816,28 @@ watch(selectedDomains, (newVal) => {
}
},
{
deep
:
true
})
// 修改数据源监听器,确保编辑模式下正确显示schema
watch
(
selectedDbDetails
.
value
,
async
(
newVal
,
oldVal
)
=>
{
console
.
log
(
'数据源监听器'
)
if
(
newVal
.
length
>
0
)
{
console
.
log
(
'数据源监听器2'
)
console
.
log
(
newVal
)
console
.
log
(
oldVal
)
if
(
JSON
.
stringify
(
newVal
))
{
console
.
log
(
'数据源监听器3'
)
await
fetchAllSchemas
(
newVal
)
}
//
//
修改数据源监听器,确保编辑模式下正确显示schema
//
watch(selectedDbDetails.value, async (newVal, oldVal) => {
//
console.log('数据源监听器')
//
if(newVal.length > 0) {
//
console.log('数据源监听器2')
//
console.log(newVal)
//
console.log(oldVal)
//
if(JSON.stringify(newVal)) {
//
console.log('数据源监听器3')
//
await fetchAllSchemas(newVal)
//
}
if
(
!
selectedDataSource
.
value
)
{
selectedDataSource
.
value
=
newVal
[
0
].
tid
}
//
if(!selectedDataSource.value) {
//
selectedDataSource.value = newVal[0].tid
//
}
// 如果是编辑模式且有schema数据,确保正确回显
if
(
props
.
mode
===
'edit'
&&
originalSchemalist
.
value
.
length
>
0
)
{
processSchemalistForEdit
(
originalSchemalist
.
value
)
}
}
},
{
immediate
:
true
})
//
// 如果是编辑模式且有schema数据,确保正确回显
//
if (props.mode === 'edit' && originalSchemalist.value.length > 0) {
//
processSchemalistForEdit(originalSchemalist.value)
//
}
//
}
//
}, { immediate: true })
// 在第三步激活时确保数据正确加载
...
...
@@ -764,6 +889,22 @@ const fetchAllSchemas = async (databases) => {
}
}
const
selectChangeSchema
=
async
()
=>
{
console
.
log
(
'selectedSchemas'
,
selectedSchemas
.
value
)
let
list
=
[]
selectedSchemas
.
value
.
forEach
((
element
,
elementIndex
)
=>
{
element
.
forEach
(
item
=>
{
list
.
push
({
schemaname
:
item
,
dbtype
:
selectedDbDetails
.
value
[
elementIndex
].
dbtype
,
osdsid
:
selectedDbDetails
.
value
[
elementIndex
].
tid
,
})
});
});
console
.
log
(
list
)
schemalist
.
value
=
list
}
// 修改处理数据域和规则的方法
const
processAreaAndRuleListForEdit
=
(
areaAndRuleList
)
=>
{
if
(
!
areaAndRuleList
||
!
Array
.
isArray
(
areaAndRuleList
))
{
...
...
@@ -942,16 +1083,66 @@ const isSchemaSelected = (schemaValue) => {
return
selectedSchemas
.
value
.
includes
(
schemaValue
)
}
const
handleSubmit
=
()
=>
{
if
(
!
formData
.
value
.
name
||
formData
.
value
.
name
===
''
){
ElMessage
.
warning
(
'请输入项目名称'
)
return
}
if
(
!
selectedDbNodes
.
value
||
selectedDbNodes
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请选择数据库'
)
return
}
if
(
!
selectedSchemas
.
value
||
selectedSchemas
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请选择Schema'
)
return
}
if
(
!
selectedRuleNode
.
value
||
selectedRuleNode
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请选择规则'
)
return
}
console
.
log
(
'项目名称'
,
formData
.
value
.
name
)
console
.
log
(
'项目备注'
,
formData
.
value
.
remark
)
console
.
log
(
'项目数据源'
,
selectedDbDetails
.
value
)
console
.
log
(
'Schema'
,
schemalist
.
value
)
console
.
log
(
'Schema'
,
selectedRuleNode
.
value
)
formData
.
value
.
databases
=
selectedDbDetails
.
value
formData
.
value
.
schemas
=
schemalist
.
value
// formData.value.domains = selectedDomainDetails.value.map(item => ({
// dataarea_id: item.dataarea_id,
// rule_id: item.id
// }))
}
// const selectedDomainDetails = computed(() => {
// const allDomains = domainGroups.value.flatMap(group => group.list)
// return allDomains.filter(domain => selectedDomains.value.includes(domain.id))
// })
</
script
>
<
style
scoped
>
<
style
scoped
lang=
"scss"
>
.dialog-content
{
display
:
flex
;
min-height
:
500px
;
//
min-height
:
500px
;
}
.form-container
{
flex
:
1
;
padding-right
:
30px
;
.el-form-item--default{
margin-bottom
:
0px
;
}
//
padding-right
:
30px
;
}
.steps-container
{
...
...
@@ -961,9 +1152,11 @@ const isSchemaSelected = (schemaValue) => {
}
.step-title
{
font-size
:
16px
;
font-weight
:
bold
;
margin-bottom
:
20px
;
font-size
:
14px
;
font-weight
:
400
;
letter-spacing
:
0px
;
line-height
:
22px
;
color
:
rgba
(
148
,
148
,
148
,
1
);
}
/* 第二步样式 */
...
...
@@ -1066,15 +1259,15 @@ const isSchemaSelected = (schemaValue) => {
.datasource-item
{
padding
:
10px
15px
;
cursor
:
pointer
;
border-bottom
:
1px
solid
#f0f0f0
;
//
border-bottom
:
1px
solid
#f0f0f0
;
}
.datasource-item
:hover
{
background-color
:
#f0f7ff
;
//
background-color
:
#f0f7ff
;
}
.datasource-item.active
{
background-color
:
#e6f7ff
;
//
background-color
:
#e6f7ff
;
color
:
#1890ff
;
}
...
...
@@ -1199,4 +1392,58 @@ const isSchemaSelected = (schemaValue) => {
font-weight
:
bold
;
padding-bottom
:
8px
;
}
</
style
>
\ No newline at end of file
.item-form-container
{
margin-top
:
14px
;
border-radius
:
5px
;
background
:
rgba
(
247
,
248
,
250
,
1
);
padding-top
:
25px
;
padding-bottom
:
27px
;
padding-left
:
15px
;
padding-right
:
15px
;
:deep(.el-form-item__label)
{
font-size
:
14px
;
font-weight
:
400
;
letter-spacing
:
0px
;
color
:
rgba
(
148
,
148
,
148
,
1
);
}
:deep
(
.el-input__wrapper
)
{
width
:
278px
;
}
}
/* 一级节点隐藏checkbox */
:deep
(
.first-level-node
.el-checkbox
)
{
display
:
none
!important
;
}
/* 确保一级节点仍然可以点击展开 */
:deep
(
.first-level-node
.el-tree-node__expand-icon
)
{
display
:
inline-block
!important
;
}
/* 二级节点正常显示checkbox */
:deep
(
.second-level-node
.el-checkbox
)
{
display
:
inline-block
!important
;
}
.flex-container
{
display
:
flex
;
}
.wrap
{
flex-wrap
:
wrap
;
}
.align-center
{
align-items
:
center
;
}
.justify-center
{
justify-content
:
center
;
}
.master
{
&::before{
color
:
var
(
--el-color-danger
);
content
:
"*"
;
margin-right
:
4px
;
}
}
</
style
>
src/views/project/Project/QueryForm.vue
View file @
464710f1
...
...
@@ -3,20 +3,16 @@ import { computed,ref,watch } from 'vue'
import
type
{
FormInstance
}
from
'element-plus'
import
PageWrapperSearch
from
'@/components/search/PageWrapperSearch.vue'
import
{
Check
,
Delete
,
Edit
,
Message
,
Search
,
Star
,
Plus
}
from
'@element-plus/icons-vue'
import
{
color
}
from
'echarts'
// import { useDict } from '@/utils/dict'
// import { listDept } from '@/api/system/dept'// 部门
// const { approve_status, invoice_status} = useDict('approve_status', 'invoice_status')
const
emit
=
defineEmits
([
'update:modelValue'
,
'query'
,
'reset'
])
const
emit
=
defineEmits
([
'update:modelValue'
,
'query'
,
'reset'
,
'showAddDialog'
])
const
invoice_status_filter
=
ref
([])
const
employeesList
=
ref
([])
const
props
=
defineProps
<
{
...
...
@@ -48,12 +44,26 @@ function onReset(formRef: FormInstance) {
emit
(
'reset'
,
formRef
)
}
function
showAddDialog
()
{
emit
(
'showAddDialog'
)
}
</
script
>
<
template
>
<!-- el-form -->
<page-wrapper-search
:model=
"queryForm"
:extraButtons=
"[
{
text: '新增',
icon: Plus,
color: 'rgba(0, 189, 207, 1)',
type: 'success',
textClass: 'btn-fff',
onClick: showAddDialog
}
]"
@search="onSearch"
@reset="onReset">
<el-form-item
label=
"项目名称"
prop=
"proName"
>
...
...
@@ -108,6 +118,6 @@ function onReset(formRef: FormInstance) {
</page-wrapper-search>
-->
</
template
>
<
style
scoped
>
<
style
scoped
lang=
"scss"
>
</
style
>
src/views/project/Project/list.vue
View file @
464710f1
...
...
@@ -415,57 +415,116 @@ onMounted(()=>{
<template
#
title
>
项目管理
</
template
>
<
template
#
buttons
>
<el-button
:loading=
"addLoading"
type=
"primary"
icon=
"Plus"
@
click=
"showAddDialog"
>
新增
</el-button>
</
template
>
</PageTitle>
<div
class=
"app-container__body"
>
<
div
>
<
!-- <div> --
>
<query-form
ref=
"QueryFormRef"
v-model=
"queryParams"
@
query=
"onQuery"
@
reset=
"onReset"
/>
<el-row
:gutter=
"20"
v-loading=
"loading"
>
<el-col
class=
"table-item"
:span=
"6"
v-for=
"(item, index) in tableList"
:key=
"index"
>
<el-card
shadow=
"always"
>
<
template
#
header
>
<div
class=
"flex-container justify-between align-center"
>
{{
item
.
project
}}
<el-dropdown
placement=
"bottom-end"
@
command=
"(command) => handleCommandProject(command, item)"
>
<el-button
type=
"primary"
icon=
"Operation"
>
操作
</el-button>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
command=
"1"
>
进入
</el-dropdown-item>
<el-dropdown-item
command=
"2"
>
编辑
</el-dropdown-item>
<el-dropdown-item
command=
"3"
>
删除
</el-dropdown-item>
<el-dropdown-item
command=
"4"
>
导入
</el-dropdown-item>
<el-dropdown-item
command=
"5"
>
导出
</el-dropdown-item>
<el-dropdown-item
command=
"6"
>
下载插件
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</div>
</template>
@
reset=
"onReset"
@
showAddDialog=
"showAddDialog"
/>
<div
style=
"flex: 1;"
>
<el-table
height=
"100%"
:data=
"tableList"
v-loading=
"loading"
border
style=
"width: 100%; margin-top: 20px"
>
<el-table-column
type=
"index"
label=
"序号"
width=
"80"
align=
"center"
fixed
/>
<el-table-column
prop=
"project"
label=
"项目名称"
min-width=
"180"
show-overflow-tooltip
/>
<el-table-column
label=
"数据源"
width=
"100"
align=
"center"
>
<
template
#
default=
"{ row }"
>
{{
row
.
list
&&
row
.
list
[
0
]
?
row
.
list
[
0
].
value
:
'-'
}}
</
template
>
</el-table-column>
<el-table-column
label=
"数据域"
width=
"100"
align=
"center"
>
<
template
#
default=
"{ row }"
>
{{
row
.
list
&&
row
.
list
[
1
]
?
row
.
list
[
1
].
value
:
'-'
}}
</
template
>
</el-table-column>
<el-table-column
label=
"发现规则"
width=
"100"
align=
"center"
>
<
template
#
default=
"{ row }"
>
{{
row
.
list
&&
row
.
list
[
2
]
?
row
.
list
[
2
].
value
:
'-'
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"note"
label=
"项目备注"
min-width=
"100"
show-overflow-tooltip
/>
<el-table-column
label=
"操作"
min-width=
"520"
align=
"center"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
plain
color=
"rgba(0, 186, 173, 1)"
size=
"small"
icon=
"right"
@
click=
"handleEnterProject(row)"
>
进入
</el-button>
<el-button
plain
color=
"rgba(11, 136, 251, 1)"
size=
"small"
icon=
"edit"
@
click=
"handleEditProject(row)"
>
编辑
</el-button>
<el-button
plain
color=
"rgba(255, 141, 26, 1)"
size=
"small"
icon=
"delete"
@
click=
"handleDeleteProject(row)"
>
删除
</el-button>
<el-button
plain
color=
"rgba(121, 72, 234, 1)"
size=
"small"
icon=
"download"
@
click=
"handleDownloadPlugin(row)"
>
下载插件
</el-button>
<el-button
plain
color=
"rgba(237, 183, 5, 1)"
size=
"small"
icon=
"documentCopy"
@
click=
"handleImportProject(row)"
>
导入
</el-button>
<el-button
plain
color=
"rgba(172, 51, 193, 1)"
size=
"small"
icon=
"copyDocument"
@
click=
"handleExportProject(row)"
>
导出
</el-button>
<div
class=
"item-content flex-container align-center"
v-for=
"(x,y) in item.list"
>
<div
class=
"label"
>
{{x.label}}:
</div>
<div
class=
"value flex1"
>
{{x.value}}
</div>
</div>
</el-card>
</el-col>
</el-row>
<!--
<el-dropdown
placement=
"bottom-end"
@
command=
"(command) => handleCommandProject(command, row)"
>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
command=
"1"
>
进入
</el-dropdown-item>
<el-dropdown-item
command=
"2"
>
编辑
</el-dropdown-item>
<el-dropdown-item
command=
"3"
>
删除
</el-dropdown-item>
<el-dropdown-item
command=
"4"
>
导入
</el-dropdown-item>
<el-dropdown-item
command=
"5"
>
导出
</el-dropdown-item>
<el-dropdown-item
command=
"6"
>
下载插件
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
-->
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show=
"total > 0"
...
...
@@ -474,7 +533,7 @@ onMounted(()=>{
v-model:limit=
"queryParams.everypage"
@
pagination=
"getList"
/>
<
/div
>
<
!-- </div> --
>
</div>
<ProjectEditDialog
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论