节点列表页操作列增加编辑schema图标
This commit is contained in:
parent
a75f58c6f3
commit
731babce12
@ -125,6 +125,7 @@ const handleClose = () => {
|
|||||||
|
|
||||||
const handleOverlayClick = (e: MouseEvent) => {
|
const handleOverlayClick = (e: MouseEvent) => {
|
||||||
if (e.target === e.currentTarget) {
|
if (e.target === e.currentTarget) {
|
||||||
|
e.stopPropagation() // 阻止事件冒泡,避免触发列表项的点击事件
|
||||||
handleClose()
|
handleClose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +162,7 @@ onUnmounted(() => {
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
z-index: 1000;
|
z-index: 10000; /* 提高 z-index,确保在列表项之上 */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 默认操作按钮 -->
|
||||||
|
<button class="action-btn" @click.stop="context.openDetail(context.row.name)" :title="context.t('View')">
|
||||||
|
<i class="fa fa-eye"></i>
|
||||||
|
</button>
|
||||||
|
<button class="action-btn" @click.stop="context.editRecord(context.row)" :title="context.t('Edit')">
|
||||||
|
<i class="fa fa-edit"></i>
|
||||||
|
</button>
|
||||||
|
<!-- Schema 编辑按钮 -->
|
||||||
|
<button
|
||||||
|
class="action-btn schema-btn"
|
||||||
|
@click.stop="handleOpenSchemaEditor"
|
||||||
|
:title="context.t('Edit Schema')"
|
||||||
|
:disabled="!canEditSchema"
|
||||||
|
>
|
||||||
|
<i class="fa fa-code"></i>
|
||||||
|
</button>
|
||||||
|
<button class="action-btn delete-btn" @click.stop="context.deleteRecord(context.row.name)" :title="context.t('Delete')">
|
||||||
|
<i class="fa fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Schema 编辑器模态框 - 使用 Teleport 渲染到 body,避免事件冒泡问题 -->
|
||||||
|
<Teleport to="body">
|
||||||
|
<SchemaEditorModal
|
||||||
|
v-model:visible="showSchemaEditor"
|
||||||
|
:node-type="nodeType"
|
||||||
|
:node-name="nodeName"
|
||||||
|
:initial-schema="initialSchema"
|
||||||
|
:on-save="handleSchemaSave"
|
||||||
|
@close="showSchemaEditor = false"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { Teleport } from 'vue'
|
||||||
|
import { useMessage } from 'naive-ui'
|
||||||
|
import axios from 'axios'
|
||||||
|
import { get_session_api_headers } from '@/shared/api/auth'
|
||||||
|
import SchemaEditorModal from '@/core/components/SchemaEditorModal.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
context: {
|
||||||
|
row: any
|
||||||
|
entity: string
|
||||||
|
openDetail: (name: string) => void
|
||||||
|
editRecord: (row: any) => void
|
||||||
|
deleteRecord: (name: string) => void
|
||||||
|
router: any
|
||||||
|
t: (key: string) => string
|
||||||
|
}
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const showSchemaEditor = ref(false)
|
||||||
|
|
||||||
|
const nodeName = computed(() => props.context.row.name || '')
|
||||||
|
const nodeType = computed(() => props.context.row.node_type || '')
|
||||||
|
const initialSchema = computed(() => {
|
||||||
|
const schema = props.context.row.node_schema
|
||||||
|
if (!schema) return {}
|
||||||
|
if (typeof schema === 'string') {
|
||||||
|
try {
|
||||||
|
return JSON.parse(schema)
|
||||||
|
} catch {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
})
|
||||||
|
|
||||||
|
const canEditSchema = computed(() => {
|
||||||
|
return !!nodeType.value
|
||||||
|
})
|
||||||
|
|
||||||
|
async function handleOpenSchemaEditor() {
|
||||||
|
if (!canEditSchema.value) {
|
||||||
|
message.warning(props.context.t('Please select node type first'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果列表数据中没有完整的 node_schema,需要从API获取完整记录
|
||||||
|
if (!props.context.row.node_schema) {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(
|
||||||
|
`/api/data/${encodeURIComponent(props.context.entity)}/${encodeURIComponent(nodeName.value)}`,
|
||||||
|
{
|
||||||
|
headers: get_session_api_headers(),
|
||||||
|
withCredentials: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const record = response.data?.data || {}
|
||||||
|
// 更新 row 数据以便后续使用
|
||||||
|
if (record.node_schema) {
|
||||||
|
props.context.row.node_schema = record.node_schema
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取节点数据失败:', error)
|
||||||
|
message.error(props.context.t('Failed to load node data'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showSchemaEditor.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSchemaSave(schemaData: any) {
|
||||||
|
try {
|
||||||
|
// 保存 Schema 数据到后端
|
||||||
|
const response = await axios.put(
|
||||||
|
`/api/data/${encodeURIComponent(props.context.entity)}/${encodeURIComponent(nodeName.value)}`,
|
||||||
|
{
|
||||||
|
node_schema: schemaData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: get_session_api_headers(),
|
||||||
|
withCredentials: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (response.data?.success !== false) {
|
||||||
|
// 更新本地 row 数据
|
||||||
|
props.context.row.node_schema = schemaData
|
||||||
|
message.success(props.context.t('Schema saved successfully'))
|
||||||
|
showSchemaEditor.value = false
|
||||||
|
} else {
|
||||||
|
throw new Error(response.data?.message || props.context.t('Save failed'))
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('保存 Schema 失败:', error)
|
||||||
|
message.error(error?.response?.data?.message || error?.message || props.context.t('Save failed, please check permission and server logs'))
|
||||||
|
throw error // 让组件处理错误显示
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 继承父组件的样式,只需要覆盖特定样式 */
|
||||||
|
.action-btn {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border: none;
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #6b7280;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 默认按钮(查看、编辑)使用更普通的颜色 */
|
||||||
|
.action-btn:hover:not(:disabled) {
|
||||||
|
background: #3b82f6;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schema 编辑按钮使用青绿色,与工具栏保持一致 */
|
||||||
|
.schema-btn:hover:not(:disabled) {
|
||||||
|
background: #0d684b;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 删除按钮使用红色 */
|
||||||
|
.delete-btn:hover:not(:disabled) {
|
||||||
|
background: #ef4444;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user