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
ee17f5e4
Commit
ee17f5e4
authored
Aug 24, 2025
by
ningjihai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增项目
parent
807ea6ab
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
330 行增加
和
47 行删除
+330
-47
src/api/project/index.js
+56
-0
src/views/project/Project/ProjectEditDialog.vue
+243
-42
src/views/project/Project/list.vue
+31
-5
没有找到文件。
src/api/project/index.js
View file @
ee17f5e4
...
...
@@ -12,3 +12,59 @@ export function selectDataProject(data) {
data
:
data
})
}
export
function
checkProjectNum
(
data
)
{
return
request
({
url
:
'/core/tdataproject/checkProjectNum'
,
method
:
'post'
,
data
:
data
})
}
export
function
getdatascopeprojectlist
(
data
)
{
return
request
({
url
:
'/core/datascopeproject/getdatascopeprojectlist'
,
method
:
'post'
,
data
:
data
})
}
export
function
checkDatasystemName
(
data
)
{
return
request
({
url
:
'/core/tdataproject/checkDatasystemName'
,
method
:
'post'
,
data
:
data
})
}
export
function
checkDatasystem
(
data
)
{
return
request
({
url
:
'/core/tdataproject/checkDatasystem'
,
method
:
'post'
,
data
:
data
})
}
export
function
queryByEditSort
(
data
)
{
return
request
({
url
:
'/core/tdatasource/queryByEditSort'
,
method
:
'post'
,
data
:
data
})
}
export
function
selectProDataSource
(
data
)
{
return
request
({
url
:
'/core/tdatasource/selectProDataSource'
,
method
:
'post'
,
data
:
data
})
}
export
function
queryShemas
(
data
)
{
return
request
({
url
:
'/core/searchsensitivedata/queryShemas'
,
method
:
'post'
,
data
:
data
})
}
src/views/project/Project/ProjectEditDialog.vue
View file @
ee17f5e4
...
...
@@ -2,7 +2,7 @@
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
destroy-on-close
:before-close=
"handleClose"
>
<div
class=
"dialog-content"
>
...
...
@@ -17,9 +17,9 @@
label-width=
"100px"
label-position=
"top"
>
<el-form-item
label=
"项目名称"
prop=
"
projectN
ame"
required
>
<el-form-item
label=
"项目名称"
prop=
"
n
ame"
required
>
<el-input
v-model=
"formData.
projectN
ame"
v-model=
"formData.
n
ame"
placeholder=
"请输入项目名称"
maxlength=
"200"
show-word-limit
...
...
@@ -50,11 +50,9 @@
<div
v-if=
"activeStep === 2"
>
<div
class=
"step-title"
>
数据库
</div>
<div
class=
"filter-container"
>
<el-select
v-model=
"dbFilter.type"
placeholder=
"全部"
class=
"filter-select"
>
<el-option
label=
"全部"
value=
"all"
/>
<el-option
label=
"MySQL"
value=
"mysql"
/>
<el-option
label=
"Oracle"
value=
"oracle"
/>
<el-option
label=
"SQL Server"
value=
"sqlserver"
/>
<el-select
v-model=
"dbFilter.type"
placeholder=
"请选择"
class=
"filter-select"
>
<el-option
v-for=
"(item,index) in sourceTypeList"
:key=
"index"
:label=
"item.text"
:value=
"item.text"
/>
</el-select>
<el-input
...
...
@@ -82,8 +80,8 @@
:key=
"db.id"
class=
"db-item"
>
<el-checkbox
:label=
"db.id"
>
{{ db.name }}
<el-checkbox
:label=
"db.
t
id"
>
{{ db.
sys
name }}
</el-checkbox>
</div>
</el-checkbox-group>
...
...
@@ -99,12 +97,12 @@
<el-scrollbar
height=
"300px"
>
<div
v-for=
"db in selectedDbDetails"
:key=
"db.id"
:key=
"db.
t
id"
class=
"selected-db-item"
>
<div
class=
"db-name"
>
{{ db.name }}
</div>
<div
class=
"db-ip"
>
{{ db.ip }}
</div>
<div
class=
"db-username"
>
用户名:
{{ db.username }}
</div>
<div
class=
"db-name"
>
{{ db.
sys
name }}
</div>
<div
class=
"db-ip"
>
{{ db.
db
ip }}
</div>
<div
class=
"db-username"
>
{{ db.username }}
</div>
</div>
</el-scrollbar>
</div>
...
...
@@ -123,12 +121,12 @@
<div
class=
"datasource-list"
>
<div
v-for=
"db in selectedDbDetails"
:key=
"db.id"
:key=
"db.
t
id"
class=
"datasource-item"
:class=
"{ active: selectedDataSource === db.id }"
@
click=
"selectDataSource(db.id)"
:class=
"{ active: selectedDataSource === db.
t
id }"
@
click=
"selectDataSource(db.
t
id)"
>
{{ db.id }} {{ db.
name }}
{{ db.sys
name }}
</div>
</div>
</el-scrollbar>
...
...
@@ -256,8 +254,21 @@
<
script
setup
>
import
{
ref
,
computed
,
watch
}
from
'vue'
import
{
ElMessageBox
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
Search
}
from
'@element-plus/icons-vue'
import
{
getdatascopeprojectlist
,
checkDatasystemName
,
checkDatasystem
,
queryByEditSort
,
selectProDataSource
,
queryShemas
}
from
'@/api/project'
import
useAppStore
from
'@/store/modules/app'
const
appStore
=
useAppStore
()
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
...
...
@@ -266,7 +277,7 @@ const props = defineProps({
projectData
:
{
type
:
Object
,
default
:
()
=>
({
projectN
ame
:
''
,
n
ame
:
''
,
remark
:
''
,
projectType
:
'normal'
,
databases
:
[],
...
...
@@ -289,9 +300,55 @@ const dialogVisible = computed({
set
:
(
value
)
=>
emit
(
'update:visible'
,
value
)
})
// 初始化标志
const
initialized
=
ref
(
false
)
// 监听对话框显示状态变化
watch
(
dialogVisible
,
(
newVal
)
=>
{
if
(
newVal
&&
!
initialized
.
value
)
{
// 对话框打开且未初始化时执行
console
.
log
(
'初始化对话框数据'
)
initDialog
()
}
else
if
(
!
newVal
)
{
console
.
log
(
'重置对话框数据'
)
// 对话框关闭时重置初始化标志
initialized
.
value
=
false
}
},
{
deep
:
true
})
// 当对话框显示时执行的函数
const
initDialog
=
()
=>
{
console
.
log
(
'对话框已打开,执行初始化操作'
)
querySelectOrDic
()
initialized
.
value
=
true
}
const
querySelectOrDic
=
()
=>
{
selectProDataSource
({
systemstyle
:
1
}).
then
(
res
=>
{
console
.
log
(
'selectProDataSourceRes'
,
res
)
sourceTypeList
.
value
=
res
.
data
dbFilter
.
value
.
type
=
res
.
data
.
length
>
0
?
res
.
data
[
res
.
data
.
length
-
1
].
text
:
''
})
}
const
reset
=
()
=>
{
sourceTypeList
.
value
=
[]
formData
.
value
=
{}
activeStep
.
value
=
1
dbFilter
.
value
.
type
=
''
dbFilter
.
value
.
keyword
=
''
allDatabases
.
value
=
[]
selectedDbs
.
value
=
[]
}
const
sourceTypeList
=
ref
([])
// 表单数据
const
formData
=
ref
({
projectName
:
''
,
id
:
''
,
name
:
''
,
remark
:
''
,
projectType
:
'normal'
,
databases
:
[],
...
...
@@ -315,16 +372,16 @@ const dialogTitle = computed(() => {
// 第二步:数据库配置相关
const
dbFilter
=
ref
({
type
:
'
all
'
,
type
:
''
,
keyword
:
''
})
const
allDatabases
=
ref
([
{
id
:
1
,
name
:
'若依配测系统'
,
ip
:
'172.19.1.166'
,
username
:
'root'
,
type
:
'mysql'
},
{
id
:
2
,
name
:
'测试数据库1'
,
ip
:
'192.168.1.100'
,
username
:
'admin'
,
type
:
'mysql'
},
{
id
:
3
,
name
:
'生产数据库'
,
ip
:
'10.0.0.1'
,
username
:
'dba'
,
type
:
'oracle'
},
{
id
:
4
,
name
:
'开发数据库'
,
ip
:
'172.16.1.50'
,
username
:
'dev'
,
type
:
'mysql'
},
{
id
:
5
,
name
:
'备份数据库'
,
ip
:
'172.16.1.51'
,
username
:
'backup'
,
type
:
'sqlserver'
}
//
{ id: 1, name: '若依配测系统', ip: '172.19.1.166', username: 'root', type: 'mysql' },
//
{ id: 2, name: '测试数据库1', ip: '192.168.1.100', username: 'admin', type: 'mysql' },
//
{ id: 3, name: '生产数据库', ip: '10.0.0.1', username: 'dba', type: 'oracle' },
//
{ id: 4, name: '开发数据库', ip: '172.16.1.50', username: 'dev', type: 'mysql' },
//
{ id: 5, name: '备份数据库', ip: '172.16.1.51', username: 'backup', type: 'sqlserver' }
])
const
selectedDbs
=
ref
([])
...
...
@@ -333,11 +390,11 @@ const selectAll = ref(false)
// 第三步:Schema选择相关
const
selectedDataSource
=
ref
(
null
)
const
allSchemas
=
ref
([
'information_schema'
,
'mysql'
,
'performance_schema'
,
'ry'
,
'sys'
//
'information_schema',
//
'mysql',
//
'performance_schema',
//
'ry',
//
'sys'
])
const
selectedSchemas
=
ref
([])
const
selectAllSchemas
=
ref
(
false
)
...
...
@@ -379,14 +436,14 @@ const selectedDomains = ref(['domain2', 'domain3', 'domain4', 'domain6', 'domain
// 计算属性
const
filteredDatabases
=
computed
(()
=>
{
return
allDatabases
.
value
.
filter
(
db
=>
{
const
typeMatch
=
dbFilter
.
value
.
type
===
'all'
||
db
.
type
===
dbFilter
.
value
.
type
const
keywordMatch
=
db
.
name
.
includes
(
dbFilter
.
value
.
keyword
)
return
typeMatch
&&
keywordMatch
// const typeMatch =
db.type === dbFilter.value.type
const
keywordMatch
=
db
.
sys
name
.
includes
(
dbFilter
.
value
.
keyword
)
return
keywordMatch
})
})
const
selectedDbDetails
=
computed
(()
=>
{
return
allDatabases
.
value
.
filter
(
db
=>
selectedDbs
.
value
.
includes
(
db
.
id
))
return
allDatabases
.
value
.
filter
(
db
=>
selectedDbs
.
value
.
includes
(
db
.
t
id
))
})
const
selectedDomainDetails
=
computed
(()
=>
{
...
...
@@ -397,7 +454,7 @@ const selectedDomainDetails = computed(() => {
// 方法
const
handleSelectAll
=
(
val
)
=>
{
if
(
val
)
{
selectedDbs
.
value
=
filteredDatabases
.
value
.
map
(
db
=>
db
.
id
)
selectedDbs
.
value
=
filteredDatabases
.
value
.
map
(
db
=>
db
.
t
id
)
}
else
{
selectedDbs
.
value
=
[]
}
...
...
@@ -445,10 +502,59 @@ const handlePrevStep = () => {
}
}
// 下一步/完成
const
loginUser
=
{
tsysUser
:
{
id
:
appStore
.
userInfo
.
user
.
id
,
username
:
appStore
.
userInfo
.
user
.
username
}
}
const
handleNextStep
=
async
()
=>
{
if
(
activeStep
.
value
<
4
)
{
if
(
activeStep
.
value
===
1
)
{
try
{
// 调用第一步的验证接口
const
response
=
await
validateStep1
()
if
(
response
.
flag
===
true
)
{
checkDatasystem
().
then
(
res
=>
{
if
(
res
.
flag
===
true
){
activeStep
.
value
++
if
(
activeStep
.
value
===
2
){
queryByEditSort
({
projectId
:
formData
.
value
.
id
||
''
,
dbtype
:
dbFilter
.
value
.
type
,
loginUser
:
loginUser
,
flag
:
1
}).
then
(
res
=>
{
allDatabases
.
value
=
res
.
data
})
}
}
else
{
ElMessage
.
error
(
res
.
msg
)
}
}).
catch
(
err
=>
{
ElMessage
.
error
(
err
.
msg
)
})
}
else
{
// 验证失败,显示错误信息
ElMessage
.
error
(
response
.
msg
||
'第一步验证失败'
)
return
// 停止继续执行
}
}
catch
(
error
)
{
console
.
error
(
'第一步验证接口调用失败:'
,
error
)
ElMessage
.
error
(
'网络错误,请稍后重试'
)
return
}
}
else
if
(
activeStep
.
value
<
4
)
{
if
(
activeStep
.
value
===
3
)
{
// selectedDbDetails
}
// 其他步骤直接前进
activeStep
.
value
++
}
else
{
// 最后一步提交数据
formData
.
value
.
databases
=
selectedDbDetails
.
value
...
...
@@ -458,6 +564,31 @@ const handleNextStep = async () => {
dialogVisible
.
value
=
false
}
}
// 第一步验证接口函数
const
validateStep1
=
async
()
=>
{
// 这里调用实际的API接口
// 示例:return await api.validateStep1(formData)
return
await
checkDatasystemName
({
name
:
formData
.
value
.
name
,
id
:
formData
.
value
.
id
})
// 模拟API调用
// return new Promise((resolve) => {
// setTimeout(() => {
// // 模拟成功响应
// resolve({
// flag: true,
// msg: '验证成功'
// })
// // 模拟失败响应
// // resolve({
// // flag: false,
// // msg: '数据库连接失败,请检查连接信息'
// // })
// }, 1000)
// })
}
// 取消
const
handleCancel
=
()
=>
{
...
...
@@ -470,6 +601,7 @@ const handleClose = (done) => {
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
}).
then
(()
=>
{
reset
()
done
()
}).
catch
(()
=>
{
// 取消关闭
...
...
@@ -478,7 +610,7 @@ const handleClose = (done) => {
// 监听数据变化
watch
(
selectedDbs
,
(
newVal
)
=>
{
selectAll
.
value
=
newVal
.
length
>
0
&&
newVal
.
length
===
filtered
Databases
.
value
.
length
selectAll
.
value
=
newVal
.
length
>
0
&&
newVal
.
length
===
all
Databases
.
value
.
length
})
watch
(
selectedSchemas
,
(
newVal
)
=>
{
...
...
@@ -493,12 +625,81 @@ watch(selectedDomains, (newVal) => {
},
{
deep
:
true
})
// 初始化时自动选择第一个数据源
watch
(
selectedDbDetails
,
(
newVal
)
=>
{
if
(
newVal
.
length
>
0
&&
!
selectedDataSource
.
value
)
{
selectedDataSource
.
value
=
newVal
[
0
].
id
watch
(
selectedDbDetails
,
async
(
newVal
,
oldVal
)
=>
{
if
(
newVal
.
length
>
0
){
if
(
JSON
.
stringify
(
newVal
)
!==
JSON
.
stringify
(
oldVal
)){
await
fetchAllSchemas
(
newVal
)
}
if
(
!
selectedDataSource
.
value
){
selectedDataSource
.
value
=
newVal
[
0
].
tid
}
}
},
{
immediate
:
true
})
const
fetchAllSchemas
=
async
(
databases
)
=>
{
try
{
// 清空之前的数据
allSchemas
.
value
=
[]
// 使用Promise.all保证顺序但并行请求(如需严格顺序请使用for循环)
const
results
=
await
Promise
.
all
(
databases
.
map
(
db
=>
queryShemas
({
dbType
:
db
.
dbtype
,
dataSystemId
:
db
.
tid
}).
catch
(
error
=>
{
console
.
error
(
`获取数据库
${
db
.
sysname
}
的Schema失败:`
,
error
)
return
{
dataSystemId
:
db
.
tid
,
error
:
true
,
message
:
`获取数据库
${
db
.
sysname
}
的Schema失败`
}
})
)
)
// 处理结果
const
successResults
=
results
.
filter
(
r
=>
!
r
.
error
)
const
errorResults
=
results
.
filter
(
r
=>
r
.
error
)
// 合并成功的数据
successResults
.
forEach
(
res
=>
{
if
(
res
.
data
&&
Array
.
isArray
(
res
.
data
))
{
allSchemas
.
value
=
[...
allSchemas
.
value
,
...
res
.
data
]
}
})
// 显示结果信息
if
(
successResults
.
length
>
0
)
{
console
.
log
(
`成功获取
${
successResults
.
length
}
个数据库的Schema数据`
)
}
if
(
errorResults
.
length
>
0
)
{
console
.
log
(
`
${
errorResults
.
length
}
个数据库的Schema获取失败`
)
}
}
catch
(
error
)
{
console
.
error
(
'获取Schema数据过程中出错:'
,
error
)
ElMessage
.
error
(
'获取Schema数据过程中出错'
)
}
finally
{
// isLoading.value = false
}
}
// 监听传入的项目数据变化
watch
(()
=>
props
.
projectData
,
(
newVal
)
=>
{
if
(
props
.
mode
===
'edit'
)
{
...
...
src/views/project/Project/list.vue
View file @
ee17f5e4
...
...
@@ -8,7 +8,9 @@ import ExportDialog from './ExportDialog.vue'
import
{
useRouter
}
from
'vue-router'
import
{
changeRoute
}
from
'@/utils/switchRoute'
import
{
selectDataProject
selectDataProject
,
checkProjectNum
,
getdatascopeprojectlist
}
from
'@/api/project'
import
useAppStore
from
'@/store/modules/app'
...
...
@@ -139,12 +141,34 @@ function getList() {
const
dialogVisible
=
ref
(
false
)
const
dialogMode
=
ref
(
'add'
)
const
currentProject
=
ref
(
null
)
const
addLoading
=
ref
(
false
)
// 显示新增对话框
const
showAddDialog
=
()
=>
{
dialogMode
.
value
=
'add'
currentProject
.
value
=
null
dialogVisible
.
value
=
true
addLoading
.
value
=
true
checkProjectNum
().
then
(
res
=>
{
console
.
log
(
'checkProjectNum'
,
res
)
if
(
res
.
flag
){
currentProject
.
value
=
null
dialogVisible
.
value
=
true
// getdatascopeprojectlist().then(res=>{
// currentProject.value = null
// dialogVisible.value = true
// })
addLoading
.
value
=
false
}
else
{
addLoading
.
value
=
false
}
}).
catch
(
err
=>
{
addLoading
.
value
=
false
})
//
}
// 处理项目操作
...
...
@@ -177,6 +201,7 @@ const handleCommandProject = (command, project) => {
const
handleEnterProject
=
(
project
)
=>
{
console
.
log
(
'进入项目:'
,
project
)
changeRoute
()
router
.
push
({
path
:
'/indexManage/ItemManage'
,
query
:
{
projectId
:
project
.
id
}
})
...
...
@@ -280,6 +305,7 @@ onMounted(()=>{
</
template
>
<
template
#
buttons
>
<el-button
:loading=
"addLoading"
type=
"primary"
icon=
"Plus"
@
click=
"showAddDialog"
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论