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
922f75be
Commit
922f75be
authored
Aug 25, 2025
by
ningjihai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
项目管理
parent
49682210
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
444 行增加
和
30 行删除
+444
-30
src/api/project/index.js
+71
-0
src/views/project/Project/DownloadPluginDialog.vue
+32
-14
src/views/project/Project/ExportDialog.vue
+0
-0
src/views/project/Project/ImportProjectDialog.vue
+263
-0
src/views/project/Project/ProjectEditDialog.vue
+30
-11
src/views/project/Project/list.vue
+48
-5
没有找到文件。
src/api/project/index.js
View file @
922f75be
...
...
@@ -104,6 +104,77 @@ export function updateDataProject(data) {
data
:
data
})
}
export
function
showProxyInfo
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/showProxyInfo'
,
method
:
'post'
,
data
:
data
})
}
export
function
saveProxyJarInfo
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/saveProxyJarInfo'
,
method
:
'post'
,
data
:
data
})
}
export
function
getProjectTree
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/getProjectTree'
,
method
:
'post'
,
data
:
data
})
}
export
function
getEncryptExcel
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/getEncryptExcel'
,
method
:
'post'
,
data
:
data
,
responseType
:
'blob'
//
})
}
export
function
checkEncryptExcel
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/checkEncryptExcel'
,
method
:
'post'
,
data
:
data
})
}
export
function
exportToExcel
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/exportToExcel'
,
method
:
'post'
,
data
:
data
,
responseType
:
'blob'
//
})
}
export
function
tdatasourceQuery
(
data
)
{
return
request
({
url
:
'/core/tdatasource/query'
,
method
:
'post'
,
data
:
data
})
}
export
function
queryShemasmodifysubsettask
(
data
)
{
return
request
({
url
:
'/core/modifysubsettask/queryShemas'
,
method
:
'post'
,
data
:
data
})
}
export
function
rowsensitivelevelType
(
type
,
data
)
{
return
request
({
url
:
'/core/rowsensitivelevel/'
+
type
,
method
:
'post'
,
data
:
data
})
}
src/views/project/Project/DownloadPluginDialog.vue
View file @
922f75be
...
...
@@ -11,8 +11,8 @@
<div
class=
"section-content"
>
<div
class=
"readonly-input-group"
>
<span
class=
"input-label"
>
加密网关平台:
</span>
<el-input
v-model=
"gatewayConfig.url"
disabled
class=
"input-field"
/>
<el-input
v-model=
"gatewayConfig.port"
disabled
class=
"input-field port-input"
/>
<el-input
v-model=
"gatewayConfig.url"
class=
"input-field"
/>
<el-input
v-model=
"gatewayConfig.port"
class=
"input-field port-input"
/>
<el-button
type=
"primary"
icon=
"Download"
@
click=
"downloadGatewayPlugin"
>
下载
</el-button>
</div>
</div>
...
...
@@ -63,7 +63,7 @@
<el-table-column
label=
"操作"
width=
"300"
align=
"center"
>
<
template
#
default=
"{ row, $index }"
>
<el-button
type=
"danger"
icon=
"Delete"
@
click=
"removeProjectConfig($index)"
>
删除
</el-button>
<el-button
type=
"primary"
icon=
"Download"
@
click=
"downloadProjectPlugin($index)"
>
下载
</el-button>
<el-button
type=
"primary"
icon=
"Download"
@
click=
"downloadProjectPlugin(
row,
$index)"
>
下载
</el-button>
</
template
>
</el-table-column>
</el-table>
...
...
@@ -85,7 +85,11 @@
import
{
ref
,
watch
,
computed
}
from
'vue'
import
{
Download
,
Plus
,
Delete
}
from
'@element-plus/icons-vue'
import
{
ElMessage
}
from
'element-plus'
import
{
saveProxyJarInfo
}
from
'@/api/project'
const
route
=
useRoute
()
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
...
...
@@ -119,9 +123,11 @@ const fetchGatewayConfig = async () => {
// 模拟API调用,实际项目中替换为真实API
return
new
Promise
(
resolve
=>
{
setTimeout
(()
=>
{
// let url = import.meta.env.VITE_APP_BASE_API
// const httpList = url.split(':')
resolve
({
url
:
'https://172.19.1.166
'
,
port
:
'9005
'
url
:
'
'
,
port
:
'
'
})
},
300
)
})
...
...
@@ -129,6 +135,7 @@ const fetchGatewayConfig = async () => {
// 添加项目配置
const
addProjectConfig
=
()
=>
{
console
.
log
(
'route'
,
location
.
origin
)
projectConfigs
.
value
.
push
({
name
:
''
,
url
:
''
,
...
...
@@ -143,19 +150,19 @@ const removeProjectConfig = (index) => {
// 下载网关插件
const
downloadGatewayPlugin
=
()
=>
{
ElMessage
.
success
(
'开始下载加密网关插件'
)
window
.
open
(
gatewayConfig
.
value
.
url
+
`/core/encryptionconfig/download?appProjectName='加密网关平台'&projectid=
${
props
.
projectId
}
&gatewayUrl=
${
gatewayConfig
.
value
.
url
}
&gatewayPort=
${
gatewayConfig
.
value
.
port
}
&appUrl=''&appPort=''`
)
// 实际项目中实现下载逻辑
}
// 下载项目插件
const
downloadProjectPlugin
=
(
index
)
=>
{
const
downloadProjectPlugin
=
(
i
tem
,
i
ndex
)
=>
{
const
project
=
projectConfigs
.
value
[
index
]
if
(
!
project
.
name
||
!
project
.
url
||
!
project
.
port
)
{
ElMessage
.
warning
(
'请先填写完整的项目配置'
)
return
}
ElMessage
.
success
(
`开始下载项目
${
project
.
name
}
的插件`
)
// 实际项目中实现下载逻辑
window
.
open
(
gatewayConfig
.
value
.
url
+
`/core/encryptionconfig/download?appProjectName=
${
item
.
name
}
&projectid=
${
props
.
projectId
}
&gatewayUrl=
${
gatewayConfig
.
value
.
url
}
&gatewayPort=
${
gatewayConfig
.
value
.
port
}
&appUrl=
${
item
.
url
}
&appPort=
${
item
.
port
}
`
)
}
// 确认操作
...
...
@@ -168,11 +175,22 @@ const handleConfirm = () => {
}
}
emit
(
'confirm'
,
{
projectId
:
props
.
projectId
,
projectConfigs
:
projectConfigs
.
value
})
dialogVisible
.
value
=
false
saveProxyJarInfo
(
'/core/encryptionconfig/saveProxyJarInfo'
,
{
gatewayUrl
:
gatewayConfig
.
value
.
url
,
gatewayPort
:
gatewayConfig
.
value
.
port
,
projectId
:
projectId
,
apps
:
projectConfigs
.
value
.
map
(
item
=>
{
return
{
appUrl
:
item
.
url
,
appProjectName
:
item
.
name
,
appPort
:
item
.
port
}
})
}).
then
(
res
=>
{
ElMessage
.
success
(
'存储成功!'
)
dialogVisible
.
value
=
false
})
}
...
...
src/views/project/Project/ExportDialog.vue
View file @
922f75be
差异被折叠。
点击展开。
src/views/project/Project/ImportProjectDialog.vue
0 → 100644
View file @
922f75be
<
template
>
<el-dialog
v-model=
"dialogVisible"
title=
"导入"
width=
"500px"
:close-on-click-modal=
"false"
:close-on-press-escape=
"false"
>
<div
class=
"import-dialog"
>
<el-upload
ref=
"uploadRef"
class=
"upload-container"
drag
:action=
"uploadAction"
:headers=
"headers"
:data=
"uploadData"
:before-upload=
"beforeUpload"
:on-success=
"handleSuccess"
:on-error=
"handleError"
:on-progress=
"handleProgress"
:file-list=
"fileList"
:limit=
"1"
:auto-upload=
"true"
:show-file-list=
"false"
accept=
".xlsx,.xls"
>
<div
class=
"upload-content"
>
<el-icon
class=
"upload-icon"
><UploadFilled
/></el-icon>
<div
class=
"upload-text"
>
<p
class=
"upload-title"
>
点击或拖动Excel文件到此处进行上传目录结构
</p>
<p
class=
"upload-tip"
>
支持 .xlsx, .xls 格式文件
</p>
</div>
</div>
</el-upload>
<!-- 上传进度显示 -->
<div
v-if=
"uploading"
class=
"upload-progress"
>
<el-progress
:percentage=
"uploadProgress"
:status=
"uploadProgress === 100 ? 'success' : ''"
:show-text=
"false"
/>
<p
class=
"progress-text"
>
上传中...
{{
uploadProgress
}}
%
</p>
</div>
</div>
</el-dialog>
</
template
>
<
script
setup
>
import
{
ref
,
computed
,
watch
}
from
'vue'
import
{
getToken
,
removeToken
}
from
'@/utils/auth'
import
{
ElMessage
}
from
'element-plus'
import
{
UploadFilled
}
from
'@element-plus/icons-vue'
import
useAppStore
from
'@/store/modules/app'
const
appStore
=
useAppStore
()
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
default
:
false
},
projectId
:
{
type
:
String
,
required
:
true
}
})
const
emit
=
defineEmits
([
'update:visible'
,
'success'
])
// 控制弹窗显示
const
dialogVisible
=
computed
({
get
:
()
=>
props
.
visible
,
set
:
(
value
)
=>
emit
(
'update:visible'
,
value
)
})
const
uploadRef
=
ref
(
null
)
const
fileList
=
ref
([])
const
uploading
=
ref
(
false
)
const
uploadProgress
=
ref
(
0
)
// 获取token用于请求头
// const token = computed(() => appStore.token)
const
headers
=
ref
({
Token
:
getToken
()
})
// 上传参数
const
uploadData
=
computed
(()
=>
({
pid
:
props
.
projectId
}))
// 上传地址
const
uploadAction
=
computed
(()
=>
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/core/encryption/excelFileUpLoad'
)
// 上传前验证
const
beforeUpload
=
(
file
)
=>
{
const
isExcel
=
file
.
type
===
'application/vnd.ms-excel'
||
file
.
type
===
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
||
file
.
name
.
endsWith
(
'.xlsx'
)
||
file
.
name
.
endsWith
(
'.xls'
)
const
isLt10M
=
file
.
size
/
1024
/
1024
<
10
if
(
!
isExcel
)
{
ElMessage
.
error
(
'只能上传Excel文件!'
)
return
false
}
if
(
!
isLt10M
)
{
ElMessage
.
error
(
'文件大小不能超过10MB!'
)
return
false
}
// 开始上传
uploading
.
value
=
true
uploadProgress
.
value
=
0
return
true
}
// 上传成功处理
const
handleSuccess
=
(
response
,
file
,
fileList
)
=>
{
uploading
.
value
=
false
uploadProgress
.
value
=
0
if
(
response
&&
response
.
flag
)
{
ElMessage
.
success
(
'导入成功!'
)
emit
(
'success'
,
response
.
data
)
// 延迟关闭对话框,让用户看到成功提示
setTimeout
(()
=>
{
dialogVisible
.
value
=
false
},
1500
)
}
else
{
ElMessage
.
error
(
response
?.
msg
||
'导入失败'
)
uploading
.
value
=
false
}
}
// 上传错误处理
const
handleError
=
(
error
,
file
,
fileList
)
=>
{
uploading
.
value
=
false
uploadProgress
.
value
=
0
console
.
error
(
'上传错误:'
,
error
)
ElMessage
.
error
(
'上传失败,请重试'
)
}
// 上传进度处理
const
handleProgress
=
(
event
,
file
,
fileList
)
=>
{
uploadProgress
.
value
=
Math
.
round
(
event
.
percent
)
}
// 监听可见性变化,重置状态
watch
(()
=>
props
.
visible
,
(
newVal
)
=>
{
if
(
!
newVal
)
{
// 关闭时重置状态
fileList
.
value
=
[]
uploading
.
value
=
false
uploadProgress
.
value
=
0
}
else
{
// 打开时确保状态重置
fileList
.
value
=
[]
uploading
.
value
=
false
uploadProgress
.
value
=
0
}
})
// 监听上传完成或失败后自动关闭
watch
(
uploading
,
(
newVal
)
=>
{
if
(
!
newVal
&&
uploadProgress
.
value
===
100
)
{
// 上传完成,3秒后自动关闭
setTimeout
(()
=>
{
if
(
!
uploading
.
value
)
{
dialogVisible
.
value
=
false
}
},
3000
)
}
})
</
script
>
<
style
scoped
>
.import-dialog
{
padding
:
20px
;
text-align
:
center
;
}
.upload-container
{
width
:
100%
;
margin-bottom
:
20px
;
}
.upload-content
{
padding
:
40px
20px
;
text-align
:
center
;
}
.upload-icon
{
font-size
:
64px
;
color
:
#409EFF
;
margin-bottom
:
16px
;
}
.upload-title
{
font-size
:
16px
;
font-weight
:
500
;
color
:
#303133
;
margin-bottom
:
8px
;
line-height
:
1.5
;
}
.upload-tip
{
font-size
:
14px
;
color
:
#909399
;
margin-top
:
8px
;
}
.upload-progress
{
margin-top
:
20px
;
padding
:
0
20px
;
}
.progress-text
{
font-size
:
14px
;
color
:
#606266
;
margin-top
:
8px
;
text-align
:
center
;
}
:deep
(
.el-upload-dragger
)
{
width
:
100%
;
height
:
200px
;
padding
:
40px
20px
;
border
:
2px
dashed
#dcdfe6
;
border-radius
:
8px
;
background-color
:
#f5f7fa
;
transition
:
all
0.3s
ease
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
}
:deep
(
.el-upload-dragger
:hover
)
{
border-color
:
#409EFF
;
background-color
:
#ecf5ff
;
}
:deep
(
.el-dialog__header
)
{
padding
:
20px
20px
10px
;
margin-right
:
0
;
}
:deep
(
.el-dialog__headerbtn
)
{
display
:
none
;
/* 隐藏关闭按钮 */
}
:deep
(
.el-dialog__body
)
{
padding
:
0
;
}
:deep
(
.el-progress-bar
)
{
margin-top
:
8px
;
}
</
style
>
\ No newline at end of file
src/views/project/Project/ProjectEditDialog.vue
View file @
922f75be
...
...
@@ -165,13 +165,13 @@
<!-- 第四步:数据域选择 -->
<div
v-if=
"activeStep === 4"
>
<div
class=
"step-title"
>
数据域
选择
</div>
<div
class=
"step-title"
>
规则
选择
</div>
<div
class=
"domain-container"
>
<!-- 左侧可选择
数据域
-->
<!-- 左侧可选择
规则
-->
<div
class=
"available-domains"
>
<div
class=
"section-header"
>
<div
class=
"section-title"
>
可选择
数据域
</div>
<div
class=
"section-title"
>
可选择
规则
</div>
</div>
<div
class=
"domain-group"
v-for=
"group in domainGroups"
:key=
"group.id"
>
...
...
@@ -204,10 +204,10 @@
</div>
<!--
右侧已选择数据域
-->
<!--
已选择规则
-->
<div
class=
"selected-domains"
>
<div
class=
"section-header"
>
<div
class=
"section-title"
>
已选择
数据域
</div>
<div
class=
"section-title"
>
已选择
规则
</div>
<div
class=
"selection-info"
>
<span
class=
"count"
>
{{ selectedDomains.length }}
</span>
<el-button
type=
"text"
@
click=
"clearSelectedDomains"
>
清空
</el-button>
...
...
@@ -768,12 +768,23 @@ const fetchAllSchemas = async (databases) => {
}
// 处理数据域和规则数据
const
processAreaAndRuleList
=
(
areaAndRuleList
)
=>
{
if
(
!
areaAndRuleList
||
!
Array
.
isArray
(
areaAndRuleList
))
return
if
(
!
areaAndRuleList
||
!
Array
.
isArray
(
areaAndRuleList
))
{
console
.
warn
(
'areaAndRuleList为空或不是数组'
,
areaAndRuleList
)
selectedDomains
.
value
=
[]
// 确保设置为空数组而不是null或undefined
return
}
// 获取所有数据域分组信息
getAllDataAreaAndRule
().
then
(
res
=>
{
if
(
!
res
.
data
||
!
Array
.
isArray
(
res
.
data
))
{
console
.
error
(
'获取的数据域分组无效'
,
res
.
data
)
return
}
console
.
log
(
'所有数据域分组:'
,
res
.
data
)
console
.
log
(
'接口返回的areaAndRuleList:'
,
areaAndRuleList
)
// 处理已选择的数据域
const
selectedDomainIds
=
[]
...
...
@@ -781,13 +792,13 @@ const processAreaAndRuleList = (areaAndRuleList) => {
// 将接口返回的数据映射到 domainGroups
domainGroups
.
value
=
res
.
data
.
map
(
group
=>
{
// 处理组内的每个规则
const
processedList
=
group
.
list
.
map
(
domain
=>
{
const
processedList
=
(
group
.
list
||
[])
.
map
(
domain
=>
{
// 检查这个规则是否在已选择的列表中
const
isSelected
=
areaAndRuleList
.
some
(
item
=>
item
.
dataarea_id
===
group
.
dataarea_id
&&
item
.
rule_id
===
domain
.
id
item
&&
item
.
dataarea_id
===
group
.
dataarea_id
&&
item
.
rule_id
===
domain
.
id
)
if
(
isSelected
)
{
if
(
isSelected
&&
domain
.
id
)
{
selectedDomainIds
.
push
(
domain
.
id
)
}
...
...
@@ -798,7 +809,7 @@ const processAreaAndRuleList = (areaAndRuleList) => {
})
// 检查是否全选
const
groupDomainIds
=
processedList
.
map
(
d
=>
d
.
id
)
const
groupDomainIds
=
processedList
.
map
(
d
=>
d
.
id
)
.
filter
(
Boolean
)
const
selectedInGroup
=
selectedDomainIds
.
filter
(
id
=>
groupDomainIds
.
includes
(
id
))
group
.
selectedAll
=
selectedInGroup
.
length
===
groupDomainIds
.
length
&&
groupDomainIds
.
length
>
0
...
...
@@ -809,8 +820,16 @@ const processAreaAndRuleList = (areaAndRuleList) => {
})
// 设置已选择的数据域
selectedDomains
.
value
=
selectedDomainIds
selectedDomains
.
value
=
selectedDomainIds
.
filter
(
Boolean
)
// 过滤掉可能的空值
console
.
log
(
'已选择的数据域ID:'
,
selectedDomains
.
value
)
// 如果没有选择任何数据域,显示警告
if
(
selectedDomains
.
value
.
length
===
0
)
{
console
.
warn
(
'没有找到任何已选择的数据域,请检查数据映射逻辑'
)
}
}).
catch
(
error
=>
{
console
.
error
(
'获取数据域分组失败:'
,
error
)
ElMessage
.
error
(
'获取数据域分组失败'
)
})
}
// 处理Schema数据
...
...
src/views/project/Project/list.vue
View file @
922f75be
...
...
@@ -4,6 +4,7 @@ import { ElMessage,ElMessageBox } from 'element-plus'
import
QueryForm
from
'./QueryForm.vue'
import
ProjectEditDialog
from
'./ProjectEditDialog.vue'
import
DownloadPluginDialog
from
'./DownloadPluginDialog.vue'
import
ImportProjectDialog
from
'./ImportProjectDialog.vue'
import
ExportDialog
from
'./ExportDialog.vue'
import
{
useRouter
}
from
'vue-router'
import
{
changeRoute
}
from
'@/utils/switchRoute'
...
...
@@ -12,7 +13,8 @@ import {
checkProjectNum
,
addDataProject
,
deleteDataProject
,
updateDataProject
updateDataProject
,
showProxyInfo
}
from
'@/api/project'
import
useAppStore
from
'@/store/modules/app'
...
...
@@ -198,7 +200,9 @@ const handleCommandProject = (command, project) => {
console
.
warn
(
'未知命令:'
,
command
)
}
}
// 添加导入相关变量
const
importDialogVisible
=
ref
(
false
)
const
currentImportProjectId
=
ref
(
''
)
// 具体操作方法
const
handleEnterProject
=
(
project
)
=>
{
console
.
log
(
'进入项目:'
,
project
)
...
...
@@ -254,8 +258,18 @@ const handleDeleteProject = (val) => {
// 导入项目
const
handleImportProject
=
(
project
)
=>
{
ElMessage
.
info
(
'导入功能待实现'
)
currentImportProjectId
.
value
=
project
.
id
importDialogVisible
.
value
=
true
}
const
handleImportSuccess
=
(
data
)
=>
{
// ElMessage.success('项目导入成功')
// 刷新项目列表
handleQuery
()
}
// 导出项目
const
handleExportProject
=
(
project
)
=>
{
// ElMessage.success(`开始导出项目 "${project.proName}"`)
...
...
@@ -265,7 +279,24 @@ const handleExportProject = (project) => {
const
handleDownloadPlugin
=
(
project
)
=>
{
// ElMessage.success(`开始下载 "${project.proName}" 的插件`)
currentProjectId
.
value
=
project
.
id
// 假设项目对象中有id字段
downloadDialogVisible
.
value
=
true
showProxyInfo
({
projectId
:
project
.
id
}).
then
(
res
=>
{
if
(
res
.
flag
){
downloadDialogVisible
.
value
=
true
}
else
{
ElMessage
.
info
(
res
.
msg
)
}
}).
catch
(
err
=>
{
ElMessage
.
info
(
res
.
msg
)
})
console
.
log
(
123
)
}
// 处理确认操作
...
...
@@ -313,11 +344,14 @@ const handleSubmit = (formData) => {
loginUser
:
loginUser
,
project
:{
createtime
:
currentProject
.
value
.
createtime
,
createuser
:
currentProject
.
value
.
createuser
,
edition_id
:
''
,
note
:
formData
.
remark
,
project
:
formData
.
name
,
id
:
formData
.
id
,
projectType
:
"normal"
,
flag
:
null
,
projectType
:
"normal"
},
schemalist
:
formData
.
schemas
,
...
...
@@ -353,7 +387,9 @@ const exportDialogVisible = ref(false)
const
currentExportProjectId
=
ref
(
''
)
// 打开导出弹窗
const
exportProjectName
=
ref
(
''
)
const
openExportDialog
=
(
project
)
=>
{
exportProjectName
.
value
=
project
.
project
currentExportProjectId
.
value
=
project
.
id
exportDialogVisible
.
value
=
true
}
...
...
@@ -457,10 +493,17 @@ onMounted(()=>{
<ExportDialog
v-model:visible=
"exportDialogVisible"
:exportProjectName=
"exportProjectName"
:project-id=
"currentExportProjectId"
@
confirm=
"handleExportConfirm"
@
backup=
"handleBackup"
/>
<ImportProjectDialog
v-model:visible=
"importDialogVisible"
:project-id=
"currentImportProjectId"
@
success=
"handleImportSuccess"
/>
</div>
</template>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论