Browse Source
- 添加 CatalogDefine 组件,用于编辑楼层目录结构 - 在 ModelMain 中集成 CatalogDefine 组件 - 实现目录树展示、添加目录、添加楼层、删除节点等功能 - 采用 Vue 3 的 <script setup> 语法,支持 TypeScript - 使用 Element Plus组件库master
2 changed files with 266 additions and 2 deletions
@ -0,0 +1,263 @@ |
|||
<script setup lang="ts"> |
|||
import { computed, createVNode, reactive, useTemplateRef } from "vue"; |
|||
import { ElButton, ElSpace, ElTree } from "element-plus"; |
|||
import YvSrcEditor from "@/components/YvSrcEditor.vue"; |
|||
import DataForm from "@/components/data-form/DataForm.vue"; |
|||
import lodash from "lodash"; |
|||
|
|||
defineOptions({ |
|||
name: 'CatalogDefine', |
|||
}); |
|||
|
|||
// 组件事件定义 |
|||
// const emit = defineEmits<{ |
|||
// /** 更新内联表格数据 */ |
|||
// "event01": [param01: string]; |
|||
// }>(); |
|||
|
|||
// 定义 Props 类型 |
|||
interface CatalogDefineProps { |
|||
} |
|||
|
|||
// 读取组件 props 属性 |
|||
const props = withDefaults(defineProps<CatalogDefineProps>(), {}); |
|||
|
|||
// 定义 State 类型 |
|||
interface CatalogDefineState { |
|||
// forceUpdateForCatalog: number; |
|||
} |
|||
|
|||
// state 属性 |
|||
const state = reactive<CatalogDefineState>({ |
|||
// forceUpdateForCatalog: Number.MIN_VALUE, |
|||
}); |
|||
|
|||
// 定义 Data 类型 |
|||
interface CatalogDefineData { |
|||
} |
|||
|
|||
// 内部数据 |
|||
const data: CatalogDefineData = {}; |
|||
const tree = useTemplateRef<InstanceType<typeof ElTree>>("treeRef"); |
|||
const worldModel = computed(() => window['worldModel']); |
|||
const catalog = computed<Array<any>>(() => { |
|||
// state.forceUpdateForCatalog; |
|||
return worldModel.value?.state?.catalog; |
|||
}); |
|||
const catalogTree = computed(() => { |
|||
const array = catalog.value; |
|||
const tree: Array<any> = []; |
|||
if (array) { |
|||
for (let item of array) { |
|||
const node: any = { |
|||
id: item.label, |
|||
label: item.label, |
|||
data: item, |
|||
}; |
|||
tree.push(node); |
|||
if (item.items && item.items.length > 0) { |
|||
node.children = []; |
|||
for (let row of item.items) { |
|||
const child = { |
|||
pid: item.label, |
|||
id: `${item.label}_${row.catalogCode}`, |
|||
label: row.label, |
|||
data: row, |
|||
}; |
|||
node.children.push(child); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return tree; |
|||
}); |
|||
const catalogJson = computed(() => { |
|||
if (catalog.value) return JSON.stringify(catalog.value, null, 4); |
|||
return ""; |
|||
}); |
|||
|
|||
function addCatalog() { |
|||
const data = { |
|||
label: "", |
|||
}; |
|||
system.showDialog(createVNode(DataForm, { |
|||
style: { |
|||
paddingRight: "12px", |
|||
}, |
|||
data: data, |
|||
formFields: [ |
|||
{ |
|||
dataPath: 'label', label: '目录名称', input: 'Input', |
|||
inputProps: { |
|||
placeholder: '目录名称', |
|||
}, |
|||
}, |
|||
], |
|||
columnCount: 1, |
|||
labelWidth: "80px", |
|||
}), { |
|||
title: '添加目录', |
|||
width: 480, |
|||
height: 150, |
|||
showClose: true, |
|||
showMax: false, |
|||
showCancelButton: true, |
|||
showOkButton: true, |
|||
okButtonText: "确定", |
|||
cancelButtonText: "取消", |
|||
}).then(() => { |
|||
const label = lodash.trim(data.label); |
|||
if (!label) { |
|||
system.msg("目录名称不能为空"); |
|||
return; |
|||
} |
|||
catalog.value.push({ label, items: [] }); |
|||
}).finally(); |
|||
} |
|||
|
|||
function addItem() { |
|||
const node = tree.value?.getCurrentNode(); |
|||
const catalogData = node?.data; |
|||
if (!catalogData?.items) { |
|||
system.msg("必须先选择一个目录"); |
|||
return; |
|||
} |
|||
// console.log("node", node); |
|||
const data = { |
|||
label: "", |
|||
catalogCode: "", |
|||
}; |
|||
system.showDialog(createVNode(DataForm, { |
|||
style: { |
|||
paddingRight: "12px", |
|||
}, |
|||
data: data, |
|||
formFields: [ |
|||
{ |
|||
dataPath: 'catalogCode', label: '楼层编码', input: 'Input', |
|||
inputProps: { |
|||
placeholder: '楼层唯一编码', |
|||
}, |
|||
}, |
|||
{ |
|||
dataPath: 'label', label: '楼层名称', input: 'Input', |
|||
inputProps: { |
|||
placeholder: '楼层名称', |
|||
}, |
|||
}, |
|||
], |
|||
columnCount: 1, |
|||
labelWidth: "80px", |
|||
}), { |
|||
title: '添加楼层', |
|||
width: 480, |
|||
height: 150, |
|||
showClose: true, |
|||
showMax: false, |
|||
showCancelButton: true, |
|||
showOkButton: true, |
|||
okButtonText: "确定", |
|||
cancelButtonText: "取消", |
|||
}).then(() => { |
|||
const catalogCode = lodash.trim(data.catalogCode); |
|||
const label = lodash.trim(data.label); |
|||
if (!catalogCode) { |
|||
system.msg("楼层编码不能为空"); |
|||
return; |
|||
} |
|||
if (!label) { |
|||
system.msg("楼层名称不能为空"); |
|||
return; |
|||
} |
|||
catalogData.items.push({ label, catalogCode }); |
|||
}).finally(); |
|||
} |
|||
|
|||
function del() { |
|||
const node = tree.value?.getCurrentNode(); |
|||
if (!node) { |
|||
system.msg("必须先选择一个节点"); |
|||
return; |
|||
} |
|||
// console.log("node", node); |
|||
const nodeData = node.data; |
|||
if (node.pid) { |
|||
let index = catalog.value.findIndex(item => item.label === node.pid); |
|||
if (index >= 0) { |
|||
const catalogData = catalog.value[index]; |
|||
index = catalogData.items.findIndex(item => item.catalogCode === nodeData.catalogCode); |
|||
if (index >= 0) { |
|||
catalogData.items.splice(index, 1); |
|||
// state.forceUpdateForCatalog++; |
|||
} |
|||
} |
|||
} else { |
|||
const index = catalog.value.findIndex(item => item.label === nodeData.label); |
|||
if (index >= 0) { |
|||
catalog.value.splice(index, 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
interface CatalogDefineExpose { |
|||
state: CatalogDefineState; |
|||
data: CatalogDefineData; |
|||
} |
|||
|
|||
const expose: CatalogDefineExpose = { |
|||
state, |
|||
data, |
|||
}; |
|||
// 定义组件公开内容 |
|||
defineExpose(expose); |
|||
|
|||
export type { |
|||
CatalogDefineProps, |
|||
CatalogDefineState, |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="flex-row-container root"> |
|||
<div class="flex-item-fixed flex-column-container left"> |
|||
<ElSpace class="flex-item-fixed tools-top"> |
|||
<ElButton @click="addCatalog" :disabled="!catalog">添加目录</ElButton> |
|||
<ElButton @click="addItem" :disabled="!catalog">添加楼层</ElButton> |
|||
<ElButton @click="del" :disabled="!catalog">删除</ElButton> |
|||
</ElSpace> |
|||
<div class="catalog-tree"> |
|||
<ElTree |
|||
ref="treeRef" |
|||
:data="catalogTree" |
|||
nodeKey="id" |
|||
:expandOnClickNode="false" |
|||
:highlightCurrent="true" |
|||
:defaultExpandAll="true" |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div class="flex-item-fill"> |
|||
<YvSrcEditor ref="editorRef" language="json" :modelValue="catalogJson"/> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
.root { |
|||
height: 100%; |
|||
} |
|||
|
|||
.left { |
|||
width: 300px; |
|||
border-right: 1px solid #ece2e2; |
|||
} |
|||
|
|||
.tools-top { |
|||
padding: 8px; |
|||
border-bottom: 1px solid #ece2e2; |
|||
} |
|||
|
|||
.catalog-tree { |
|||
|
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue