fix: 移除 dialogBox 中残留的平台分支,统一为 descriptor 接口方法

This commit is contained in:
王佑琳 2026-06-09 11:55:22 +08:00
parent ec81dce28a
commit 3507eddfb3
4 changed files with 80 additions and 159 deletions

View File

@ -104,16 +104,7 @@ const showUploader = computed(() => {
return platform.value.showImageUploader() return platform.value.showImageUploader()
}) })
const uploaderBindings = computed(() => { const uploaderBindings = computed(() => platform.value.getUploaderBindings())
const p = platform.value
if (p.id === 'painting') {
return { limit: p.imageUploadLimit() }
}
if (p.id === 'video') {
return { modelType: p.modelType.value, imagesCount: p.imageUploadLimit() }
}
return {}
})
const autoSizeConfig = computed(() => { const autoSizeConfig = computed(() => {
if (useDisplay.Sender_variant !== 'default') { if (useDisplay.Sender_variant !== 'default') {
@ -125,8 +116,9 @@ const autoSizeConfig = computed(() => {
const handleStart = async () => { const handleStart = async () => {
const p = platform.value const p = platform.value
if (props.type === 'Video' && p.model.value === 'Seedance 2.0') { const validationError = p.validateBeforeSubmit()
ElMessage.primary('敬请期待 Seedance 2.0') if (validationError) {
ElMessage.primary(validationError)
return return
} }
@ -195,11 +187,7 @@ watch(
[() => platform.value.model.value, () => platform.value.modelType.value], [() => platform.value.model.value, () => platform.value.modelType.value],
async ([newModel, newModelType]) => { async ([newModel, newModelType]) => {
if (!newModel) return if (!newModel) return
if (platform.value.id === 'video') {
await platform.value.loadConfig(newModel, newModelType) await platform.value.loadConfig(newModel, newModelType)
} else {
platform.value.loadConfig(newModel)
}
}, },
) )

View File

@ -26,7 +26,6 @@
<div <div
v-for="renderItem in visibleItems" v-for="renderItem in visibleItems"
:key="getItemKey(renderItem.item, renderItem.index)" :key="getItemKey(renderItem.item, renderItem.index)"
:ref="el => setItemRef(el, renderItem.index)"
class="virtual-scroller-item" class="virtual-scroller-item"
:style="getItemStyle(renderItem)" :style="getItemStyle(renderItem)"
:data-index="renderItem.index" :data-index="renderItem.index"
@ -119,15 +118,11 @@ const emit = defineEmits(['scroll', 'scroll-start', 'scroll-end', 'visible-chang
const containerRef = ref(null) const containerRef = ref(null)
const wrapperRef = ref(null) const wrapperRef = ref(null)
const renderContainerRef = ref(null) const renderContainerRef = ref(null)
const itemRefs = new Map()
const itemHeights = ref(new Map()) const itemHeights = ref(new Map())
const heightVersion = ref(0)
const resizeObserver = ref(null) const resizeObserver = ref(null)
const scrollTop = ref(0) const scrollTop = ref(0)
const isScrolling = ref(false)
const scrollTimeout = ref(null)
const isInitialized = ref(false)
const pendingScrollToBottom = ref(false) const pendingScrollToBottom = ref(false)
const previousDataLength = ref(0)
const containerStyle = computed(() => { const containerStyle = computed(() => {
return { return {
@ -138,6 +133,7 @@ const containerStyle = computed(() => {
}) })
const totalHeight = computed(() => { const totalHeight = computed(() => {
heightVersion.value // measureItem mutate Map
let height = 0 let height = 0
const len = computedData.value.length const len = computedData.value.length
@ -174,50 +170,49 @@ const visibleRange = computed(() => {
return { start: 0, end: 0, offset: 0 } return { start: 0, end: 0, offset: 0 }
} }
heightVersion.value // measureItem mutate Map
const viewportHeight = containerHeight.value const viewportHeight = containerHeight.value
const currentScrollTop = scrollTop.value const currentScrollTop = scrollTop.value
const bufferCount = computedBuffer.value const bufferCount = computedBuffer.value
const len = computedData.value.length
let startIndex = 0 //
let endIndex = computedData.value.length - 1
let startOffset = 0
let offset = 0 let offset = 0
for (let i = 0; i < computedData.value.length; i++) { let firstVisibleIdx = 0
const cachedHeight = itemHeights.value.get(i) for (let i = 0; i < len; i++) {
const height = cachedHeight !== undefined ? cachedHeight : props.estimatedHeight const height = itemHeights.value.get(i) ?? props.estimatedHeight
if (offset + height > currentScrollTop) { if (offset + height > currentScrollTop) {
startIndex = Math.max(0, i - bufferCount) firstVisibleIdx = i
break break
} }
offset += height offset += height
} }
startOffset = 0 const startIndex = Math.max(0, firstVisibleIdx - bufferCount)
for (let i = 0; i < startIndex; i++) {
const cachedHeight = itemHeights.value.get(i) // startOffset endIndex
startOffset += cachedHeight !== undefined ? cachedHeight : props.estimatedHeight let startOffset = 0
let endIndex = len - 1
offset = 0
for (let i = 0; i < len; i++) {
const height = itemHeights.value.get(i) ?? props.estimatedHeight
if (i < startIndex) {
startOffset += height
} }
offset = startOffset if (i >= startIndex) {
endIndex = startIndex if (offset + height > currentScrollTop + viewportHeight) {
for (let i = startIndex; i < computedData.value.length; i++) { endIndex = Math.min(len - 1, i + bufferCount)
const cachedHeight = itemHeights.value.get(i)
const height = cachedHeight !== undefined ? cachedHeight : props.estimatedHeight
offset += height
if (offset > currentScrollTop + viewportHeight) {
endIndex = Math.min(computedData.value.length - 1, i + bufferCount)
break break
} }
endIndex = i endIndex = i
} }
return { start: Math.min(startIndex, endIndex), end: Math.max(startIndex, endIndex), offset: startOffset } offset += height
}
return { start: startIndex, end: endIndex, offset: startOffset }
}) })
const visibleItems = computed(() => { const visibleItems = computed(() => {
@ -247,7 +242,6 @@ const wrapperStyle = computed(() => ({
direction: 'rtl', direction: 'rtl',
height: '100%', height: '100%',
position: 'relative', position: 'relative',
scrollbarWidth: 'auto',
overflow: 'hidden', overflow: 'hidden',
transform: 'rotate(180deg)', transform: 'rotate(180deg)',
width: '100%' width: '100%'
@ -302,14 +296,6 @@ const getItemStyle = (renderItem) => {
} }
} }
const setItemRef = (el, index) => {
if (el) {
itemRefs.set(index, el)
} else {
itemRefs.delete(index)
}
}
const measureItem = (index, element) => { const measureItem = (index, element) => {
if (!element) return if (!element) return
@ -321,9 +307,8 @@ const measureItem = (index, element) => {
if (height > 0) { if (height > 0) {
const cachedHeight = itemHeights.value.get(index) const cachedHeight = itemHeights.value.get(index)
if (cachedHeight !== height) { if (cachedHeight !== height) {
const newHeights = new Map(itemHeights.value) itemHeights.value.set(index, height)
newHeights.set(index, height) heightVersion.value++
itemHeights.value = newHeights
} }
} }
} }
@ -357,28 +342,9 @@ const handleWheel = (event) => {
event.preventDefault() event.preventDefault()
} }
const scrollCleanupTimeout = ref(null)
const handleScroll = (event) => { const handleScroll = (event) => {
const target = event.target const target = event.target
scrollTop.value = target.scrollTop scrollTop.value = target.scrollTop
isScrolling.value = true
if (scrollTimeout.value) {
clearTimeout(scrollTimeout.value)
}
scrollTimeout.value = setTimeout(() => {
isScrolling.value = false
}, 150)
// ,100ms
if (scrollCleanupTimeout.value) {
clearTimeout(scrollCleanupTimeout.value)
}
scrollCleanupTimeout.value = setTimeout(() => {
cleanupExtraItems(visibleItems.value)
}, 300)
const st = target.scrollTop const st = target.scrollTop
const scrollHeight = target.scrollHeight const scrollHeight = target.scrollHeight
@ -462,7 +428,6 @@ const getVisibleIndices = () => {
const resetMeasurements = () => { const resetMeasurements = () => {
itemHeights.value = new Map() itemHeights.value = new Map()
itemRefs.clear()
} }
const isAtPageBottom = () => { const isAtPageBottom = () => {
@ -478,13 +443,15 @@ const isAtPageTop = () => {
} }
const observeVisibleItems = () => { const observeVisibleItems = () => {
if (!resizeObserver.value) return if (!resizeObserver.value || !renderContainerRef.value) return
resizeObserver.value.disconnect() resizeObserver.value.disconnect()
for (const [index, element] of itemRefs) { // visibleItems index DOM itemRefs DOM
if (element) { for (const item of visibleItems.value) {
resizeObserver.value.observe(element) const el = renderContainerRef.value.querySelector(`[data-index="${item.index}"]`)
if (el) {
resizeObserver.value.observe(el)
} }
} }
} }
@ -509,14 +476,11 @@ watch(() => computedData.value, (newData, oldData) => {
observeVisibleItems() observeVisibleItems()
}) })
} }
previousDataLength.value = newLength
}, { deep: false }) }, { deep: false })
watch(visibleItems, (newItems) => { watch(visibleItems, (newItems) => {
nextTick(() => { nextTick(() => {
observeVisibleItems() observeVisibleItems()
cleanupExtraItems(newItems)
}) })
if (newItems.length > 0) { if (newItems.length > 0) {
const firstItem = newItems[0] const firstItem = newItems[0]
@ -525,47 +489,8 @@ watch(visibleItems, (newItems) => {
} }
}, { deep: true }) }, { deep: true })
const cleanupExtraItems = (currentVisibleItems) => {
if (!renderContainerRef.value || !currentVisibleItems.length) return
//
const visibleIndices = new Set(currentVisibleItems.map(item => item.index))
// render-container .virtual-scroller-item
const renderedItems = renderContainerRef.value.querySelectorAll('.virtual-scroller-item')
const toRemove = []
for (const el of renderedItems) {
const dataIndex = parseInt(el.getAttribute('data-index'), 10)
// data-index ,
if (!isNaN(dataIndex) && !visibleIndices.has(dataIndex)) {
toRemove.push(el)
}
}
// DOM
for (const el of toRemove) {
if (el.parentNode) {
el.parentNode.removeChild(el)
}
// itemRefs Map
const index = parseInt(el.getAttribute('data-index'), 10)
if (!isNaN(index)) {
itemRefs.delete(index)
}
}
if (toRemove.length > 0) {
console.log(`[VirtualScroller] 清理了 ${toRemove.length} 个多余DOM元素`)
}
}
onMounted(() => { onMounted(() => {
setupResizeObserver() setupResizeObserver()
isInitialized.value = true
previousDataLength.value = computedData.value.length
nextTick(() => { nextTick(() => {
if (pendingScrollToBottom.value) { if (pendingScrollToBottom.value) {
@ -574,7 +499,6 @@ onMounted(() => {
} }
observeVisibleItems() observeVisibleItems()
cleanupExtraItems(visibleItems.value)
}) })
}) })
@ -582,16 +506,6 @@ onBeforeUnmount(() => {
if (resizeObserver.value) { if (resizeObserver.value) {
resizeObserver.value.disconnect() resizeObserver.value.disconnect()
} }
if (scrollTimeout.value) {
clearTimeout(scrollTimeout.value)
}
if (scrollCleanupTimeout.value) {
clearTimeout(scrollCleanupTimeout.value)
}
itemRefs.clear()
}) })
defineExpose({ defineExpose({

View File

@ -191,7 +191,7 @@ export function definePaintingPlatform() {
return fetchPlatformModels(code) return fetchPlatformModels(code)
}, },
async loadConfig(modelName) { async loadConfig(modelName, _modelType) {
const config = getModelConfig(modelName) const config = getModelConfig(modelName)
syncDefaults(config) syncDefaults(config)
return config return config
@ -201,6 +201,14 @@ export function definePaintingPlatform() {
return 'Flux 2' return 'Flux 2'
}, },
validateBeforeSubmit() {
return null // 无阻塞,返回 null 表示通过
},
getUploaderBindings() {
return { limit: imageUploadLimit() }
},
showImageUploader() { showImageUploader() {
if (modelType.value !== 'text') return true if (modelType.value !== 'text') return true
return modelConfig.value?.inputType === 'image' || modelConfig.value?.inputType === 'both' return modelConfig.value?.inputType === 'image' || modelConfig.value?.inputType === 'both'

View File

@ -127,6 +127,17 @@ export function defineVideoPlatform() {
return 'LTX2.0' return 'LTX2.0'
}, },
validateBeforeSubmit() {
if (model.value === 'Seedance 2.0') {
return '敬请期待 Seedance 2.0'
}
return null // 通过
},
getUploaderBindings() {
return { modelType: modelType.value, imagesCount: imageUploadLimit() }
},
showImageUploader() { showImageUploader() {
return modelType.value !== 'text' return modelType.value !== 'text'
}, },