Commit 15ab1ab3 by 周海峰

Merge branch 'master' of https://code.palacesun.com/wuchao/nse-ui

parents 32dc9cfc 50b958db
...@@ -34,6 +34,12 @@ const usePermissionStore = defineStore( ...@@ -34,6 +34,12 @@ const usePermissionStore = defineStore(
console.log('this.sidebarRoutersold',routes) console.log('this.sidebarRoutersold',routes)
let list = filterAsyncRouter(routes) let list = filterAsyncRouter(routes)
list.forEach(item => {
router.addRoute(item)
});
this.sidebarRouters = list this.sidebarRouters = list
console.log('this.sidebarRouters',this.sidebarRouters) console.log('this.sidebarRouters',this.sidebarRouters)
}, },
......
...@@ -120,8 +120,8 @@ function handleLogin() { ...@@ -120,8 +120,8 @@ function handleLogin() {
console.log('res123',res) console.log('res123',res)
let data = res let data = res
let menus = transformRoutes(data.menus) let menus = transformRoutes(data.menus)
console.log(1234,menus)
// return // return
// 用户数据整理 // 用户数据整理
let user = data.tsysUser let user = data.tsysUser
...@@ -207,8 +207,8 @@ function transformRoutes(originalRoutes) { ...@@ -207,8 +207,8 @@ function transformRoutes(originalRoutes) {
return originalRoutes.map(route => { return originalRoutes.map(route => {
// 基础转换 - 所有路由都使用Layout作为父组件 // 基础转换 - 所有路由都使用Layout作为父组件
const transformedRoute = { const transformedRoute = {
path: route.url.replace(/^\//, ''), path: route.url,
name: route.menuname.replace(/\s+/g, ''), name: route.menuname.replace(/\s+/g, '')+ new Date().getTime(),
hidden: false, hidden: false,
type: route.type, type: route.type,
component: 'Layout', // 所有路由都使用Layout component: 'Layout', // 所有路由都使用Layout
......
<template>
<el-dialog
v-model="dialogVisible"
title="下载插件"
width="1000px"
>
<div class="download-plugin-dialog">
<!-- 加密网关配置 -->
<div class="section">
<div class="section-title">加密网关配置(规则拉取插件下载区域)</div>
<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-button type="primary" icon="Download" @click="downloadGatewayPlugin">下载</el-button>
</div>
</div>
</div>
<!-- 服务端加解密 -->
<div class="section">
<div class="section-title">服务端加解密(参数展示区域)</div>
<div class="section-content">
<div class="readonly-input-group">
<span class="input-label">项目ID:</span>
<el-input :value="projectId" disabled class="input-field" />
</div>
</div>
</div>
<!-- 应用项目配置 -->
<div class="section">
<div class="section-title">应用项目配置(规则推送插件下载区域)</div>
<div class="section-content">
<div class="add-project-btn">
<el-button type="primary" plain @click="addProjectConfig">
<el-icon><Plus /></el-icon>
点击添加应用项目
</el-button>
</div>
<div class="project-config-list">
<el-table :data="projectConfigs" border style="width: 100%">
<el-table-column prop="name" label="项目名称" width="180">
<template #default="{ row, $index }">
<el-input v-model="row.name" placeholder="请输入项目名称" />
</template>
</el-table-column>
<el-table-column prop="url" label="地址">
<template #default="{ row, $index }">
<el-input v-model="row.url" placeholder="请输入地址 https://xxx.xxx.x.xxx" />
</template>
</el-table-column>
<el-table-column prop="port" label="端口" width="120">
<template #default="{ row, $index }">
<el-input v-model="row.port" placeholder="请输入端口 5544" />
</template>
</el-table-column>
<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>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, watch, computed } from 'vue'
import { Download, Plus, Delete } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
const props = defineProps({
visible: {
type: Boolean,
default: false
},
projectId: {
type: String,
required: true
}
})
const emit = defineEmits(['update:visible', 'confirm'])
// 控制弹窗显示
const dialogVisible = computed({
get: () => props.visible,
set: (value) => emit('update:visible', value)
})
// 加密网关配置
const gatewayConfig = ref({
url: '',
port: ''
})
// 应用项目配置列表
const projectConfigs = ref([])
// 根据项目ID获取网关配置
const fetchGatewayConfig = async () => {
// 模拟API调用,实际项目中替换为真实API
return new Promise(resolve => {
setTimeout(() => {
resolve({
url: 'https://172.19.1.166',
port: '9005'
})
}, 300)
})
}
// 添加项目配置
const addProjectConfig = () => {
projectConfigs.value.push({
name: '',
url: '',
port: ''
})
}
// 移除项目配置
const removeProjectConfig = (index) => {
projectConfigs.value.splice(index, 1)
}
// 下载网关插件
const downloadGatewayPlugin = () => {
ElMessage.success('开始下载加密网关插件')
// 实际项目中实现下载逻辑
}
// 下载项目插件
const downloadProjectPlugin = (index) => {
const project = projectConfigs.value[index]
if (!project.name || !project.url || !project.port) {
ElMessage.warning('请先填写完整的项目配置')
return
}
ElMessage.success(`开始下载项目 ${project.name} 的插件`)
// 实际项目中实现下载逻辑
}
// 确认操作
const handleConfirm = () => {
// 验证项目配置
for (const project of projectConfigs.value) {
if (!project.name || !project.url || !project.port) {
ElMessage.warning('请填写完整的项目配置')
return
}
}
emit('confirm', {
projectId: props.projectId,
projectConfigs: projectConfigs.value
})
dialogVisible.value = false
}
// 监听项目ID变化,获取网关配置
watch(() => props.projectId, async (newVal) => {
if (newVal) {
const config = await fetchGatewayConfig()
gatewayConfig.value = config
}
}, { immediate: true })
</script>
<style scoped>
.download-plugin-dialog {
padding: 10px;
}
.section {
margin-bottom: 20px;
}
.section-title {
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
.section-content {
padding: 10px;
background-color: #f9f9f9;
border-radius: 4px;
}
.readonly-input-group {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.input-label {
width: 120px;
text-align: right;
padding-right: 10px;
font-size: 14px;
}
.input-field {
flex: 1;
margin-right: 10px;
}
.port-input {
width: 100px;
}
.add-project-btn {
margin-bottom: 15px;
}
.project-config-list {
border-top: 1px solid #eee;
padding-top: 10px;
}
.project-config-item {
padding: 15px;
margin-bottom: 15px;
background-color: #fff;
border-radius: 4px;
border: 1px solid #eee;
position: relative;
}
.action-buttons {
display: flex;
justify-content: flex-end;
margin-top: 10px;
gap: 10px;
}
:deep(.el-form-item) {
margin-bottom: 10px;
}
</style>
\ No newline at end of file
<template>
<el-dialog
v-model="dialogVisible"
title="导出"
width="500px"
:before-close="handleClose"
>
<div class="export-dialog">
<!-- 树形选择器 -->
<el-tree
ref="treeRef"
:data="treeData"
node-key="id"
show-checkbox
:props="defaultProps"
:default-expand-all="true"
@check="handleNodeCheck"
/>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleBackup">加密规则备份</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const props = defineProps({
visible: {
type: Boolean,
default: false
},
projectId: {
type: String,
required: true
}
})
const emit = defineEmits(['update:visible', 'confirm', 'backup'])
// 控制弹窗显示
const dialogVisible = computed({
get: () => props.visible,
set: (value) => emit('update:visible', value)
})
// 树形数据
const treeData = ref([])
const treeRef = ref(null)
// 树形配置
const defaultProps = {
children: 'children',
label: 'name'
}
// 加密规则备份
const handleBackup = () => {
emit('backup', props.projectId)
ElMessage.info('加密规则备份功能待实现')
}
// 确认导出
const handleConfirm = () => {
const checkedNodes = treeRef.value.getCheckedNodes()
const checkedKeys = treeRef.value.getCheckedKeys()
if (checkedKeys.length === 0) {
ElMessage.warning('请至少选择一个导出项')
return
}
emit('confirm', {
projectId: props.projectId,
checkedNodes,
checkedKeys
})
dialogVisible.value = false
}
// 节点选中处理
const handleNodeCheck = (nodeData, checkStatus) => {
// 如果选中父节点,自动选中所有子节点
// if (checkStatus.checkedKeys.includes(nodeData.id) && nodeData.children) {
// treeRef.value.setCheckedNodes(nodeData.children, true)
// }
}
// 关闭前处理
const handleClose = (done) => {
done()
}
// 根据项目ID获取树形数据
const fetchTreeData = async (projectId) => {
// 模拟API调用,实际项目中替换为真实API
return new Promise(resolve => {
setTimeout(() => {
resolve({
id: 'root',
name: '若依配测系统',
children: [
{
id: 'ry',
name: 'ry',
children: [
{
id: 'tables',
name: '表',
children: [
{ id: 'gen_table', name: 'gen_table' },
{ id: 'gen_table_column', name: 'gen_table_column' },
{ id: 'sys_config', name: 'sys_config' },
{ id: 'sys_dept', name: 'sys_dept' },
{ id: 'sys_dict_data', name: 'sys_dict_data' },
{ id: 'sys_dict_type', name: 'sys_dict_type' },
{ id: 'sys_job', name: 'sys_job' },
{ id: 'sys_job_log', name: 'sys_job_log' },
{ id: 'sys_logininfor', name: 'sys_logininfor' },
{ id: 'sys_menu', name: 'sys_menu' },
{ id: 'sys_notice', name: 'sys_notice' },
{ id: 'sys_oper_log', name: 'sys_oper_log' },
{ id: 'sys_post', name: 'sys_post' },
{ id: 'sys_role', name: 'sys_role' },
{ id: 'sys_role_dept', name: 'sys_role_dept' },
{ id: 'sys_role_menu', name: 'sys_role_menu' },
{ id: 'sys_user', name: 'sys_user' },
{ id: 'sys_user_online', name: 'sys_user_online' },
{ id: 'sys_user_post', name: 'sys_user_post' },
{ id: 'sys_user_role', name: 'sys_user_role' }
]
}
]
}
]
})
}, 300)
})
}
// 监听项目ID变化,获取树形数据
watch(() => props.projectId, async (newVal) => {
if (newVal) {
const data = await fetchTreeData(newVal)
treeData.value = [data]
}
}, { immediate: true })
</script>
<style scoped>
.export-dialog {
padding: 10px;
}
.dialog-footer {
display: flex;
justify-content: space-between;
}
:deep(.el-tree) {
max-height: 400px;
overflow-y: auto;
}
:deep(.el-tree-node__content) {
height: 36px;
}
</style>
\ No newline at end of file
<script setup lang="ts" name="QueryForm">
import { computed,ref,watch } from 'vue'
import type { FormInstance } from 'element-plus'
import PageWrapperSearch from '@/components/search/PageWrapperSearch.vue'
// 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 invoice_status_filter = ref([])
const employeesList = ref([])
const props = defineProps<{
modelValue: any
}>()
const queryForm = computed({
get() {
return props.modelValue
},
set(val: any) {
console.log('query computed', val)
emit('update:modelValue', val)
}
})
// 搜索
function onSearch() {
emit('query')
}
// 重置
function onReset(formRef: FormInstance) {
queryForm.value.projectName = ''
queryForm.value.remark = ''
emit('reset', formRef)
}
</script>
<template>
<!-- el-form -->
<page-wrapper-search
:model="queryForm"
@search="onSearch"
@reset="onReset">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryForm.projectName"
placeholder="请输入项目名称"
clearable
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryForm.remark"
placeholder="请输入备注"
clearable
/>
</el-form-item>
</page-wrapper-search>
</template>
<style scoped>
</style>
<script setup lang="ts" name="projectManageIndex">
import { ref } from 'vue'
import list from './list.vue'
const widget = {
list: list
}
const page = ref('list')
const params = ref({})
function onChangePage(val: string, param?: any) {
page.value = val
params.value = param ?? {}
}
</script>
<template>
<component :is="widget[page]" v-bind="params" @page="onChangePage" />
</template>
<script setup name="ProjectManageList">
import { getCurrentInstance, reactive, ref, toRefs } from 'vue'
import { ElMessage } from 'element-plus'
import QueryForm from './QueryForm.vue'
import ProjectEditDialog from './ProjectEditDialog.vue'
import DownloadPluginDialog from './DownloadPluginDialog.vue'
import ExportDialog from './ExportDialog.vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const emit = defineEmits(['page'])
const { proxy } = getCurrentInstance()
function onReset(formQuery) {
console.log('onReset')
formQuery.resetFields()
handleQuery()
}
function onQuery() {
handleQuery()
}
// 搜索按钮操作
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 8,
projectName: '',
remark: ''
}
})
// 表格数据
const { queryParams } = toRefs(data)
const tableList = ref([
{
id: '1',
projectName: '若依配测系统1',
datasource: 'MySQL',
domain: '电商',
findRule: '自动发现'
},
{
id: '2',
projectName: '若依配测系统2',
datasource: 'Oracle',
domain: '金融',
findRule: '手动配置'
},
{
id: '3',
projectName: '若依配测系统3',
datasource: 'SQL Server',
domain: '医疗',
findRule: '规则匹配'
}
])
const total = ref(3)
const loading = ref(false)
// 查询列表
function getList() {
loading.value = true
setTimeout(() => {
loading.value = false
}, 3000);
}
// 弹窗相关
const dialogVisible = ref(false)
const dialogMode = ref('add')
const currentProject = ref(null)
// 显示新增对话框
const showAddDialog = () => {
dialogMode.value = 'add'
currentProject.value = null
dialogVisible.value = true
}
// 处理项目操作
const handleCommandProject = (command, project) => {
switch(command) {
case '1': // 进入
handleEnterProject(project)
break
case '2': // 编辑
handleEditProject(project)
break
case '3': // 删除
handleDeleteProject(project)
break
case '4': // 导入
handleImportProject(project)
break
case '5': // 导出
handleExportProject(project)
break
case '6': // 下载插件
handleDownloadPlugin(project)
break
default:
console.warn('未知命令:', command)
}
}
// 具体操作方法
const handleEnterProject = (project) => {
console.log('进入项目:', project)
// // ElMessage.success(`进入项目 ${project.projectName}`)
// emit('page', 'detail', { projectId: project.id})
router.push({ path:'/projectHome',query: { projectId: project.id } })
}
const handleEditProject = (project) => {
dialogMode.value = 'edit'
currentProject.value = { ...project }
dialogVisible.value = true
}
// 删除项目
const handleDeleteProject = (project) => {
}
// 导入项目
const handleImportProject = (project) => {
ElMessage.info('导入功能待实现')
}
// 导出项目
const handleExportProject = (project) => {
// ElMessage.success(`开始导出项目 "${project.projectName}"`)
openExportDialog(project)
}
// 下载插件
const handleDownloadPlugin = (project) => {
// ElMessage.success(`开始下载 "${project.projectName}" 的插件`)
currentProjectId.value = project.id // 假设项目对象中有id字段
downloadDialogVisible.value = true
console.log(123)
}
// 处理确认操作
const handleDownloadConfirm = (data) => {
console.log('确认下载插件:', data)
// 这里可以处理保存操作或调用API
}
// 提交表单
const handleSubmit = (formData) => {
if (dialogMode.value === 'add') {
// 模拟新增
const newProject = {
id: tableList.value.length + 1,
projectName: formData.projectName,
datasource: '待配置',
domain: '待配置',
findRule: '待配置'
}
tableList.value.push(newProject)
total.value++
ElMessage.success('新增项目成功')
} else {
// 模拟编辑
const index = tableList.value.findIndex(p => p.id === currentProject.value.id)
if (index !== -1) {
tableList.value[index].projectName = formData.projectName
ElMessage.success('编辑项目成功')
}
}
}
const downloadDialogVisible = ref(false)
const currentProjectId = ref('')
const exportDialogVisible = ref(false)
const currentExportProjectId = ref('')
// 打开导出弹窗
const openExportDialog = (project) => {
currentExportProjectId.value = project.id
exportDialogVisible.value = true
}
// 处理导出确认
const handleExportConfirm = (data) => {
console.log('导出数据:', data)
}
// 处理加密规则备份
const handleBackup = (projectId) => {
console.log('备份项目:', projectId)
}
</script>
<template>
<div class="app-container scroller">
<PageTitle @back="$emit('page', 'list')">
<template #title>
项目管理
</template>
<template #buttons>
<el-button
type="primary"
icon="Plus"
@click="showAddDialog"
>
新增
</el-button>
</template>
</PageTitle>
<div class="app-container__body">
<div>
<query-form
ref="QueryFormRef"
v-model="queryParams"
@query="onQuery"
@reset="onReset"/>
<el-row :gutter="20">
<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.projectName }}
<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>
<div class="item-content flex-container align-center">
<div class="label">数据源:</div>
<div class="value flex1">{{ item.datasource }}</div>
</div>
<div class="item-content flex-container align-center">
<div class="label">数据域:</div>
<div class="value flex1">{{ item.domain }}</div>
</div>
<div class="item-content flex-container align-center">
<div class="label">发现规则:</div>
<div class="value flex1">{{ item.findRule }}</div>
</div>
</el-card>
</el-col>
</el-row>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</div>
<ProjectEditDialog
v-model:visible="dialogVisible"
:mode="dialogMode"
:project-data="currentProject"
@submit="handleSubmit"
/>
<DownloadPluginDialog
v-model:visible="downloadDialogVisible"
:project-id="currentProjectId"
@confirm="handleDownloadConfirm"
/>
<ExportDialog
v-model:visible="exportDialogVisible"
:project-id="currentExportProjectId"
@confirm="handleExportConfirm"
@backup="handleBackup"
/>
</div>
</template>
<style lang="scss" scoped>
.table-item {
margin-top: var(--container-pd);
margin-bottom: 20px;
}
.item-content {
margin: 8px 0;
.label {
width: 80px;
color: #888;
}
}
.flex-container {
display: flex;
}
.align-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.flex1 {
flex: 1;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论