diff --git a/portal-ui/src/components/VideoComposeCard.vue b/portal-ui/src/components/VideoComposeCard.vue index 98b10a4..ec0145d 100644 --- a/portal-ui/src/components/VideoComposeCard.vue +++ b/portal-ui/src/components/VideoComposeCard.vue @@ -74,12 +74,6 @@ 上传资产 -
- - - 新建素材组 - -
@@ -115,12 +109,34 @@
- + +
+
当前分组暂无可用素材
+ +
+
+
描述画面与动态
@@ -178,7 +194,7 @@ import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'v import { Message } from '@arco-design/web-vue' import { uploadFile, extractUploadUrlFromResponse, PORTAL_TENCENT_COS_UPLOAD_URL } from '@/utils/file' -/** 参考素材:同类最多不同素材条数(同一素材可多次 @),与 maxMediaCount 对齐 */ +/** 参考素材:@ 引用同一类(图/视频/音频)最多 9 种不同素材;左侧列表最多可插入 12 条(由 maxMediaCount 控制) */ const MAX_REFERENCE_UNIQUE_KIND = 9 const props = defineProps({ @@ -223,7 +239,9 @@ const assetGroupId = ref('') const assetLoading = ref(false) const groupLoading = ref(false) const assetGroups = ref([]) -const newGroupName = ref('') +const assetPickerVisible = ref(false) +const assetQueryResults = ref([]) +const assetPickerSelectedKeys = ref([]) watch( () => props.modelValue, @@ -415,35 +433,6 @@ const loadAssetGroups = async () => { } } -const createAssetGroup = async () => { - const name = String(newGroupName.value || '').trim() - if (!name) { - Message.warning('请输入素材组名称') - return - } - if (!proxy?.$axios) return - groupLoading.value = true - try { - const res = await proxy.$axios({ - url: 'api/byteAssetGroup/createAssetGroup', - method: 'POST', - data: { - Name: name, - ProjectName: 'default' - } - }) - const gid = res?.data?.Id || res?.data?.id || '' - newGroupName.value = '' - await loadAssetGroups() - if (gid) assetGroupId.value = gid - Message.success('素材组创建成功') - } catch (err) { - Message.error(err?.message || '创建素材组失败') - } finally { - groupLoading.value = false - } -} - const loadAssetsByGroup = async () => { const gid = String(assetGroupId.value || '').trim() if (!gid) { @@ -487,8 +476,10 @@ const loadAssetsByGroup = async () => { } }) .filter((x) => x.assetId && /^https?:\/\//i.test(String(x.url || '').trim())) - mergeAssetsToMediaList(assets) - Message.success(`已加载 ${assets.length} 条可用素材`) + assetQueryResults.value = assets + assetPickerSelectedKeys.value = [] + assetPickerVisible.value = true + Message.success(`查询到 ${assets.length} 条可用素材`) } catch (err) { Message.error(err?.message || '查询素材失败') } finally { @@ -496,6 +487,16 @@ const loadAssetsByGroup = async () => { } } +const confirmPickAssets = () => { + const pickedKeys = new Set((assetPickerSelectedKeys.value || []).map((x) => String(x))) + const picked = (assetQueryResults.value || []).filter((x) => + pickedKeys.has(String(x.assetId || x.id)) + ) + mergeAssetsToMediaList(picked) + assetPickerVisible.value = false + assetPickerSelectedKeys.value = [] +} + const handleSelectFiles = async (event) => { const input = event.target const files = Array.from(input.files || []) @@ -1136,22 +1137,22 @@ defineExpose({ diff --git a/portal-ui/src/views/VideoGen.vue b/portal-ui/src/views/VideoGen.vue index b9af896..577725b 100644 --- a/portal-ui/src/views/VideoGen.vue +++ b/portal-ui/src/views/VideoGen.vue @@ -183,7 +183,7 @@ @click="generateVideo" :title="price ? $t('common.createVideo', { price }) : $t('common.generateVideo')"> - + @@ -262,7 +262,7 @@ export default { maxMediaCount() { if (this.videoMode === 'image-first-frame') return 1 if (this.videoMode === 'image-first-last-frame') return 2 - if (this.videoMode === 'image-reference') return 9 + if (this.videoMode === 'image-reference') return 12 return 12 }, allowedMediaTypes() { @@ -989,8 +989,8 @@ export default { flex-direction: column; min-height: 100%; height: 100%; - gap: 20px; - padding: 28px 28px 32px; + gap: 14px; + padding: 20px 20px 16px; box-sizing: border-box; overflow-y: hidden; overflow-x: hidden; @@ -1001,11 +1001,11 @@ export default { /* —— Body —— */ .vg-body { display: flex; - flex: 0 0 auto; + flex: 0 1 auto; order: 1; min-height: 0; - max-height: none; - gap: 16px; + max-height: min(48vh, 560px); + gap: 12px; align-items: stretch; } @@ -1075,12 +1075,13 @@ export default { .vg-generator-inner { flex: 1; min-height: 0; - overflow-y: visible; + overflow-y: auto; + overflow-x: hidden; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; - gap: 16px; - padding: 16px; + gap: 10px; + padding: 12px 14px; background: var(--vg-panel); border: 1px solid var(--vg-border); border-radius: 20px; @@ -1194,11 +1195,11 @@ export default { .vg-toolbar { display: flex; - align-items: center; + align-items: flex-start; justify-content: space-between; - gap: 16px; - margin-top: 14px; - padding-top: 14px; + gap: 10px; + margin-top: 8px; + padding-top: 10px; border-top: 1px solid var(--vg-border); } @@ -1211,10 +1212,10 @@ export default { display: flex; flex-wrap: wrap; align-items: center; - gap: 12px 14px; - padding: 6px 10px; + gap: 8px 10px; + padding: 4px 8px; background: rgba(0, 0, 0, 0.2); - border-radius: 12px; + border-radius: 10px; border: 1px solid var(--vg-border); } @@ -1222,41 +1223,44 @@ export default { display: flex; flex-direction: row; align-items: center; - gap: 8px; - flex: 1 1 220px; - min-width: 200px; + gap: 6px; + flex: 1 1 160px; + min-width: 0; } .vg-param-label { - font-size: 12px; + font-size: 11px; color: var(--vg-muted); font-weight: 600; white-space: nowrap; - min-width: 48px; + min-width: 44px; } .vg-param-select { flex: 1; - min-width: 120px; + min-width: 0; :deep(.arco-select-view-single) { background: rgba(0, 0, 0, 0.2) !important; border: 1px solid var(--vg-border) !important; - border-radius: 10px !important; + border-radius: 8px !important; color: var(--vg-text) !important; + min-height: 30px !important; } :deep(.arco-select-view-value) { color: var(--vg-text) !important; + font-size: 12px; } } .vg-toolbar-actions { flex-shrink: 0; + align-self: center; } .vg-submit-circle { - width: 52px; - height: 52px; + width: 42px; + height: 42px; padding: 0; border: none; border-radius: 50%; @@ -1424,13 +1428,13 @@ export default { .vg-chat-section { order: 0; - flex: 1; - margin-top: 8px; - padding: 18px 22px; + flex: 1 1 auto; + margin-top: 0; + padding: 14px 18px; background: var(--vg-panel); border: 1px solid var(--vg-border); border-radius: 16px; - min-height: 0; + min-height: min(42vh, 480px); display: flex; flex-direction: column; } @@ -1685,4 +1689,48 @@ export default { .vg-link:hover { text-decoration: underline; } + +/* 小于 1920×1080 常见宽度:底部参数区纵向排布,避免挤压富文本 */ +@media (max-width: 1919px) { + .video-gen { + padding: 14px 12px 12px; + gap: 10px; + } + + .vg-chat-section { + min-height: min(40vh, 440px); + padding: 12px 14px; + } + + .vg-body { + max-height: min(50vh, 540px); + } + + .vg-generator-inner { + padding: 10px 12px; + gap: 8px; + } + + .vg-toolbar { + flex-direction: column; + align-items: stretch; + gap: 8px; + } + + .vg-toolbar-actions { + align-self: flex-end; + } + + .vg-params-row { + flex-direction: column; + align-items: stretch; + gap: 8px; + } + + .vg-param { + flex: 1 1 auto; + width: 100%; + min-width: 0; + } +}