Commit 922f75be by ningjihai

项目管理

parent 49682210
......@@ -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
})
}
......@@ -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 = (item,index) => {
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
})
}
......
<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
......@@ -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数据
......
......@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论