调整版本树使用的数据结构和后端一致

This commit is contained in:
X1627315083@163.com
2026-02-24 13:20:05 +08:00
parent 5c00b54f27
commit 927bb6de67
9 changed files with 215 additions and 35 deletions

View File

@@ -7,3 +7,4 @@ store.use(createPersistedState())
export default store export default store
export * from './global' export * from './global'
export * from './userInfo' export * from './userInfo'
export * from './projectData'

20
src/stores/projectData.ts Normal file
View File

@@ -0,0 +1,20 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useProjectStore = defineStore('project', () => {
const state = ref({// 项目参数
id: '',
})
const setProject = (obj: any) => {
for (const key in obj) {
if(state.value[key]){
state.value[key] = obj[key]
}
}
}
return {
state,
setProject,
}
})

View File

@@ -19,9 +19,6 @@
<img :src="reportNull" alt="" /> <img :src="reportNull" alt="" />
</div> </div>
<div v-else class="report-content"> <div v-else class="report-content">
<div class="">
</div>
<div class="downBtnBox"> <div class="downBtnBox">
<div class="downBtn"> <div class="downBtn">
<div class="icon"> <div class="icon">
@@ -32,6 +29,81 @@
</div> </div>
<div class="content"> <div class="content">
# 一级标题 # 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题 <br />
# 一级标题
<br />
# 一级标题
</div> </div>
</div> </div>
</div> </div>
@@ -113,6 +185,8 @@
justify-content: center; justify-content: center;
--border-width: 3px; --border-width: 3px;
flex: 1; flex: 1;
overflow: hidden;
height: 100%;
&::before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
@@ -141,6 +215,7 @@
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden;
.downBtnBox{ .downBtnBox{
padding: 2.2rem 5.2rem 0; padding: 2.2rem 5.2rem 0;
.downBtn{ .downBtn{
@@ -165,6 +240,8 @@
.content{ .content{
word-break: break-word; word-break: break-word;
white-space: pre-wrap; white-space: pre-wrap;
overflow-y: auto;
margin: 2rem;
} }
} }
} }

View File

@@ -1,9 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from 'vue' import { ref, onMounted, onUnmounted, reactive, toRefs, watch } from 'vue'
import Tree from './tree/index.vue' import Tree from './tree/index.vue'
import Detail from './detail/index.vue' import Detail from './detail/index.vue'
import { versionsList } from './tools/versionsData' // import { versionsList } from './tools/versionsData'
import { findAndAddChild, findAndRemoveChild } from './tools/tools' import { findAndAddChild, findAndRemoveChild } from './tools/tools'
import { useProjectStore } from '@/stores'
import { versionTree, getChatNodeDetail } from '@/api/versitonTree'
const props = defineProps({ const props = defineProps({
versionTreeData: { versionTreeData: {
@@ -11,14 +13,79 @@ const props = defineProps({
default: () => { default: () => {
return { return {
drawer: false, drawer: false,
list: [] // list: []
} }
} }
} }
}) })
//const emit = defineEmits([ //const emit = defineEmits([
//]) //])
const versionsList = ref([])
const projectStore = useProjectStore()
watch(()=>projectStore.state.id, (newVal, oldVal) => {
if(newVal){
versionTree({
projectId: projectStore.state.id
}).then(res => {
console.log(res)
// versionsList.value = res.data
})
}
})
const setVersionsList = (res)=>{
versionsList.value = [{
"id": "node_001",
"url": "https://example.com/images/cover_001.jpg",
"children": [
{
"id": "node_002",
"url": "https://example.com/images/cover_002.jpg",
"children": [
{
"id": "node_003",
"url": "https://example.com/images/cover_003.jpg",
"children": []
},
{
"id": "node_004",
"url": "https://example.com/images/cover_004.jpg",
"children": []
}
]
},
{
"id": "node_005",
"url": "https://example.com/images/cover_005.jpg",
"children": [
{
"id": "node_006",
"url": "https://example.com/images/cover_006.jpg",
"children": []
}
]
}
]
}]
//设置versionId
function traverseArray(items,father, callback) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
callback(item, i,father)
if (item.children && Array.isArray(item.children) && item.children.length > 0) {
traverseArray(item.children, item, callback)
}
}
}
traverseArray(versionsList.value,'',(item,i,father)=>{
item.versionId = father?`${father.versionId}-${i+1}`:'1'
})
}
const treeRef = ref(null) const treeRef = ref(null)
const treeKey = ref(0) const treeKey = ref(0)
const treeState = ref(true)// const treeState = ref(true)//
@@ -31,13 +98,13 @@ const openTree = (state)=>{
const versionRestore = ()=>{ const versionRestore = ()=>{
let id = '' let id = ''
if(selectItem.value?.child?.length > 0){ if(selectItem.value?.children?.length > 0){
function findMaxForYourFormat(items) { function findMaxForYourFormat(items) {
let max = 0 let max = 0
for (const item of items) { for (const item of items) {
// 直接分割并取最后一部分 // 直接分割并取最后一部分
const parts = item.id.split('-') const parts = item?.versionId.split('-')
const lastNumber = parseInt(parts[parts.length - 1], 10) const lastNumber = parseInt(parts[parts.length - 1], 10)
if (lastNumber > max) { if (lastNumber > max) {
@@ -47,26 +114,26 @@ const versionRestore = ()=>{
return max return max
} }
id = `${selectItem.value?.id}-${findMaxForYourFormat(selectItem.value?.child) + 1}` id = `${selectItem.value?.versionId}-${findMaxForYourFormat(selectItem.value?.children) + 1}`
}else{ }else{
id = `${selectItem.value?.id}-1` id = `${selectItem.value?.versionId}-1`
} }
let addObj = { let addObj = {
id, id,
name:`V${id}` name:`V${id}`
} }
findAndAddChild(versionsList, selectItem.value?.id, addObj) findAndAddChild(versionsList.value, selectItem.value?.versionId, addObj)
selectItem.value = {...addObj} selectItem.value = {...addObj}
treeKey.value++ treeKey.value++
} }
const versionDelete = (versionDetail)=>{ const versionDelete = (versionDetail)=>{
if(!selectItem.value.id)return if(!selectItem.value?.versionId)return
findAndRemoveChild(versionsList, selectItem.value.id) findAndRemoveChild(versionsList.value, selectItem.value?.versionId)
treeKey.value++ treeKey.value++
} }
let data = reactive({}) let data = reactive({})
onMounted(() => {}) onMounted(() => {setVersionsList('')})
onUnmounted(() => {}) onUnmounted(() => {})
defineExpose({}) defineExpose({})
const {} = toRefs(data) const {} = toRefs(data)

View File

@@ -101,17 +101,17 @@ export function findAndAddChild(items, targetId, newChild) {
// 如果找到目标节点 // 如果找到目标节点
if (item.id === targetId) { if (item.id === targetId) {
// 初始化child数组如果不存在 // 初始化child数组如果不存在
if (!item.child) { if (!item.children) {
item.child = [] item.children = []
} }
// 添加新子节点 // 添加新子节点
item.child.push(newChild) item.children.push(newChild)
return true return true
} }
// 递归搜索子节点 // 递归搜索子节点
if (item.child && item.child.length > 0) { if (item.children && item.children.length > 0) {
const found = findAndAddChild(item.child, targetId, newChild) const found = findAndAddChild(item.children, targetId, newChild)
if (found) return true if (found) return true
} }
} }
@@ -135,8 +135,8 @@ export function findAndRemoveChild(items, targetId) {
} }
// 递归搜索子节点 // 递归搜索子节点
if (item.child && item.child.length > 0) { if (item.children && item.children.length > 0) {
const found = findAndRemoveChild(item.child, targetId) const found = findAndRemoveChild(item.children, targetId)
if (found) return true if (found) return true
} }
} }

View File

@@ -49,24 +49,25 @@ function traverseArray(items, callback) {
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
const item = items[i] const item = items[i]
callback(item, i) callback(item, i)
if (item.child && Array.isArray(item.child) && item.child.length > 0) { if (item.children && Array.isArray(item.children) && item.children.length > 0) {
traverseArray(item.child, callback) traverseArray(item.children, callback)
} }
} }
} }
const initialize = ()=>{ const initialize = ()=>{
isLoad.value = false isLoad.value = false
treeList.value = [] treeList.value = []
treeList.value.push({id: null,name:'index',}) treeList.value.push({versionId: null,name:'index',})
traverseArray(props.versionsList, (item, index) => { traverseArray(props.versionsList, (item, index) => {
treeList.value.push(item) treeList.value.push(item)
}) })
console.log(treeList)
isLoad.value = true isLoad.value = true
if(!props.selectItem?.id)setSelectItem(treeList.value[treeList.value.length - 1]) if(!props.selectItem?.versionId)setSelectItem(treeList.value[treeList.value.length - 1])
} }
const setSelectItem = (item)=>{ const setSelectItem = (item)=>{
if(!item.id)return if(!item.versionId)return
emit('update:selectItem', {...item}) emit('update:selectItem', {...item})
} }

View File

@@ -55,12 +55,12 @@ async function layoutGraph(direction) {
} }
const push = (item)=>{ const push = (item)=>{
if(!item.id){ if(!item.versionId){
nodes.value.push({ id: '0', type: 'InputNode', class: 'custom-node', position }) nodes.value.push({ id: '0', type: 'InputNode', class: 'custom-node', position })
}else{ }else{
let className = `custom-node item${item.id.replace(/-/g, "_")}` let className = `custom-node item${item.versionId.replace(/-/g, "_")}`
let id = item.id let id = item.versionId
let source = edges.value.length == 0?'0':item.id.slice(0, -2) let source = edges.value.length == 0?'0':item.versionId.slice(0, -2)
nodes.value.push({id,type:'SecondaryNode',class:className,position,data:item}) nodes.value.push({id,type:'SecondaryNode',class:className,position,data:item})
edges.value.push({ id, target:id, source, type: 'smoothstep' }) edges.value.push({ id, target:id, source, type: 'smoothstep' })
} }
@@ -77,7 +77,7 @@ const toggleNodesDraggable = () => {
} }
const handleVueFlowNodeClick = ({node}) => { const handleVueFlowNodeClick = ({node}) => {
if(node.data.id)emit('setSelectItem', node.data) if(node.data.versionId)emit('setSelectItem', node.data)
} }
watch(()=>props.treeList.length, (newVal, oldVal) => { watch(()=>props.treeList.length, (newVal, oldVal) => {
@@ -87,7 +87,7 @@ watch(()=>props.treeList.length, (newVal, oldVal) => {
push(item) push(item)
}) })
},{immediate:true}) },{immediate:true})
watch(()=>props.selectItem.id, (newVal, oldVal) => { watch(()=>props.selectItem.versionId, (newVal, oldVal) => {
}) })
const versionRestore = ()=>{ const versionRestore = ()=>{

View File

@@ -22,10 +22,24 @@ const props = defineProps<{
<Handle type="source" id="Bottom" :position="Position.Bottom" /> <Handle type="source" id="Bottom" :position="Position.Bottom" />
<!-- <Handle type="source" id="Right" :position="Position.Right" /> <!-- <Handle type="source" id="Right" :position="Position.Right" />
<Handle type="target" id="Left" :position="Position.Left" /> --> <Handle type="target" id="Left" :position="Position.Left" /> -->
<div>{{ props.data.id }}</div> <!-- <div>{{ props.data.id }}</div> -->
<div class="item">
<!-- {{ props.data.url }} -->
<img :src="props.data.url" />
</div>
</div> </div>
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>
.node{
.item{
width: 100%;
height: 100%;
img{
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
</style> </style>

View File

@@ -68,7 +68,7 @@
display: flex; display: flex;
flex: 1; flex: 1;
justify-content: space-between; justify-content: space-between;
// overflow: hidden; overflow: hidden;
} }
.c-svg { .c-svg {