jvs-ppt-ui 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/jvs-ppt-ui.es.js +24043 -21814
- package/dist/lib/jvs-ppt-ui.umd.js +100 -100
- package/dist/lib/style.css +1 -1
- package/package.json +1 -1
- package/src/components/CanvasArea.vue +9739 -9566
- package/src/components/SidebarRight.vue +10 -6
- package/src/components/TemplateGallery.vue +437 -9
- package/src/components/canvas/elements/CanvasGroupElement.vue +214 -213
- package/src/components/canvas/elements/CanvasShapeElement.vue +894 -882
- package/src/components/material/CreateMaterialPanel.vue +2229 -0
- package/src/components/material/MyAssetsPanel.vue +1548 -0
- package/src/components/material/useDamAuth.ts +239 -0
- package/src/components/sidebar/panels/SidebarTextFormatPanel.vue +1 -1
- package/src/composables/canvas/useCanvasText.ts +44 -18
- package/src/composables/sidebar/useSidebarTextFormat.ts +72 -1
- package/src/composables/useSlides.ts +9804 -9627
- package/src/utils/canvas/elementStyles.ts +256 -0
|
@@ -465,12 +465,15 @@ function applyTextStyleToHtml(html: string, styles: any) {
|
|
|
465
465
|
paragraphs.forEach(applyTextStyles)
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
// 综合处理字体与样式覆盖:如果指定了 fontFamily
|
|
469
|
-
if (styles.fontFamily) {
|
|
468
|
+
// 综合处理字体与样式覆盖:如果指定了 fontFamily 或 fontSize,清理/更新所有块级和内联节点的原有硬编码值
|
|
469
|
+
if (styles.fontFamily || styles.fontSize) {
|
|
470
470
|
div.querySelectorAll('p, div, li, h1, h2, h3, h4, h5, h6, span, b, strong, i, em, a').forEach((elem: any) => {
|
|
471
|
-
if (elem.style && elem.style.fontFamily) {
|
|
471
|
+
if (styles.fontFamily && elem.style && elem.style.fontFamily) {
|
|
472
472
|
elem.style.fontFamily = styles.fontFamily
|
|
473
473
|
}
|
|
474
|
+
if (styles.fontSize && elem.style && elem.style.fontSize) {
|
|
475
|
+
elem.style.fontSize = styles.fontSize
|
|
476
|
+
}
|
|
474
477
|
})
|
|
475
478
|
}
|
|
476
479
|
|
|
@@ -571,11 +574,12 @@ function setStyleVal(prop: string, val: any) {
|
|
|
571
574
|
}
|
|
572
575
|
}
|
|
573
576
|
|
|
574
|
-
if (prop === 'fontFamily') {
|
|
577
|
+
if (prop === 'fontFamily' || prop === 'fontSize') {
|
|
575
578
|
const container = document.getElementById(`editable-${el.id}`)
|
|
576
579
|
if (container) {
|
|
577
|
-
container.style.fontFamily = val
|
|
578
|
-
container.
|
|
580
|
+
if (prop === 'fontFamily') container.style.fontFamily = val
|
|
581
|
+
else container.style.fontSize = val
|
|
582
|
+
container.innerHTML = applyTextStyleToHtml(container.innerHTML, { [prop]: val })
|
|
579
583
|
if (el.type === 'shape') {
|
|
580
584
|
el.text = container.innerHTML
|
|
581
585
|
} else {
|
|
@@ -11,6 +11,10 @@ import {
|
|
|
11
11
|
VideoPlay
|
|
12
12
|
} from '@element-plus/icons-vue'
|
|
13
13
|
import { useSlides, DEFAULT_MATERIAL_PAGE_API_URL } from '../composables/useSlides'
|
|
14
|
+
import { isImagePlaceholder } from '../utils/canvas/elementStyles'
|
|
15
|
+
import { useDamAuth } from './material/useDamAuth'
|
|
16
|
+
import MyAssetsPanel from './material/MyAssetsPanel.vue'
|
|
17
|
+
import CreateMaterialPanel from './material/CreateMaterialPanel.vue'
|
|
14
18
|
|
|
15
19
|
const {
|
|
16
20
|
addElement,
|
|
@@ -20,7 +24,12 @@ const {
|
|
|
20
24
|
materialPageApiUrl,
|
|
21
25
|
materialHeaders,
|
|
22
26
|
activeTab,
|
|
23
|
-
materialPopoverVisible
|
|
27
|
+
materialPopoverVisible,
|
|
28
|
+
activeSlide,
|
|
29
|
+
selectedElementId,
|
|
30
|
+
placeholderMaterialTargetId,
|
|
31
|
+
resolveActivePlaceholderTargetId,
|
|
32
|
+
replacePlaceholderElement
|
|
24
33
|
} = useSlides()
|
|
25
34
|
|
|
26
35
|
export interface MaterialItem {
|
|
@@ -97,6 +106,44 @@ const subTypeNameMap: Record<StockSubType, string> = {
|
|
|
97
106
|
Videos: '高清视频'
|
|
98
107
|
}
|
|
99
108
|
|
|
109
|
+
// 顶层 3-Tab 状态(检索 / 我的素材 / 创建素材)与 jvs_session_v3 鉴权
|
|
110
|
+
export type MaterialMainTab = 'search' | 'mine' | 'create'
|
|
111
|
+
const { isDamLoggedIn, sharedMaterialMainTab: activeMainTab, refreshSessionState } = useDamAuth()
|
|
112
|
+
|
|
113
|
+
const myAssetsRef = ref<InstanceType<typeof MyAssetsPanel> | null>(null)
|
|
114
|
+
const createPanelRef = ref<InstanceType<typeof CreateMaterialPanel> | null>(null)
|
|
115
|
+
|
|
116
|
+
// 未登录点击受限 Tab 时的顶部轻量胶囊提示(不遮挡 Tab,不暴露技术字段)
|
|
117
|
+
const guestToastVisible = ref(false)
|
|
118
|
+
const guestToastText = ref('请先登录后使用该功能')
|
|
119
|
+
let guestToastTimer: ReturnType<typeof setTimeout> | null = null
|
|
120
|
+
|
|
121
|
+
function showGuestAuthToast(tabName: string) {
|
|
122
|
+
guestToastText.value = tabName === '我的素材'
|
|
123
|
+
? '请先登录后查看「我的素材」'
|
|
124
|
+
: '请先登录后使用「创建素材」'
|
|
125
|
+
guestToastVisible.value = true
|
|
126
|
+
if (guestToastTimer) clearTimeout(guestToastTimer)
|
|
127
|
+
guestToastTimer = setTimeout(() => {
|
|
128
|
+
guestToastVisible.value = false
|
|
129
|
+
}, 2200)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleSwitchMainTab(tab: MaterialMainTab) {
|
|
133
|
+
refreshSessionState()
|
|
134
|
+
if (tab !== 'search' && !isDamLoggedIn.value) {
|
|
135
|
+
showGuestAuthToast(tab === 'mine' ? '我的素材' : '创建素材')
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
activeMainTab.value = tab
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
watch(isDamLoggedIn, (loggedIn) => {
|
|
142
|
+
if (!loggedIn && activeMainTab.value !== 'search') {
|
|
143
|
+
activeMainTab.value = 'search'
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
|
|
100
147
|
// 视图状态:先图二 (overview) 再图三 (detail)
|
|
101
148
|
const viewMode = ref<'overview' | 'detail'>('overview')
|
|
102
149
|
const overviewQuery = ref('')
|
|
@@ -242,6 +289,96 @@ function openPreview(item: MaterialItem, e?: Event) {
|
|
|
242
289
|
previewVisible.value = true
|
|
243
290
|
}
|
|
244
291
|
|
|
292
|
+
// 供「我的素材」与「创建素材」子面板复用的全屏大图/视频预览
|
|
293
|
+
function openCustomListPreview(item: MaterialItem, list: MaterialItem[], e?: Event) {
|
|
294
|
+
if (e) {
|
|
295
|
+
e.stopPropagation()
|
|
296
|
+
e.preventDefault()
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const currentUrl = isVideoMaterial(item)
|
|
300
|
+
? (item.sourceUrl || item.url || item.downloadUrl || getMaterialThumb(item))
|
|
301
|
+
: getMaterialThumb(item)
|
|
302
|
+
|
|
303
|
+
if (!currentUrl) {
|
|
304
|
+
notify('该素材暂无可用预览地址')
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const sourceList = Array.isArray(list) && list.length > 0 ? list : [item]
|
|
309
|
+
const validItems: PreviewItem[] = []
|
|
310
|
+
|
|
311
|
+
sourceList.forEach(m => {
|
|
312
|
+
const isVid = isVideoMaterial(m)
|
|
313
|
+
const u = isVid
|
|
314
|
+
? (m.sourceUrl || m.url || m.downloadUrl || getMaterialThumb(m))
|
|
315
|
+
: getMaterialThumb(m)
|
|
316
|
+
if (u) {
|
|
317
|
+
validItems.push({
|
|
318
|
+
url: u,
|
|
319
|
+
isVideo: isVid && isVideoUrl(u),
|
|
320
|
+
title: m.title || '素材预览',
|
|
321
|
+
format: getItemFormat(m),
|
|
322
|
+
meta: m
|
|
323
|
+
})
|
|
324
|
+
}
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
const targetIdx = validItems.findIndex(i => i.url === currentUrl)
|
|
328
|
+
if (targetIdx >= 0) {
|
|
329
|
+
previewInitialIndex.value = targetIdx
|
|
330
|
+
} else {
|
|
331
|
+
validItems.unshift({
|
|
332
|
+
url: currentUrl,
|
|
333
|
+
isVideo: isVideoMaterial(item) && isVideoUrl(currentUrl),
|
|
334
|
+
title: item.title || '素材预览',
|
|
335
|
+
format: getItemFormat(item),
|
|
336
|
+
meta: item
|
|
337
|
+
})
|
|
338
|
+
previewInitialIndex.value = 0
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
previewList.value = validItems
|
|
342
|
+
|
|
343
|
+
if (materialPopoverVisible && materialPopoverVisible.value) {
|
|
344
|
+
wasPopoverOpenBeforePreview.value = true
|
|
345
|
+
materialPopoverVisible.value = false
|
|
346
|
+
} else {
|
|
347
|
+
wasPopoverOpenBeforePreview.value = false
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
previewVisible.value = true
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// 将「检索」或「我的素材」中的图片一键送入「创建素材」作为参考图
|
|
354
|
+
function handleSendToCreateRef(item: MaterialItem, e?: Event) {
|
|
355
|
+
if (e) {
|
|
356
|
+
e.stopPropagation()
|
|
357
|
+
e.preventDefault()
|
|
358
|
+
}
|
|
359
|
+
refreshSessionState()
|
|
360
|
+
if (!isDamLoggedIn.value) {
|
|
361
|
+
showGuestAuthToast('创建素材')
|
|
362
|
+
return
|
|
363
|
+
}
|
|
364
|
+
const thumbUrl = getMaterialThumb(item)
|
|
365
|
+
if (!thumbUrl) {
|
|
366
|
+
notify('该素材暂无可用参考图地址')
|
|
367
|
+
return
|
|
368
|
+
}
|
|
369
|
+
activeMainTab.value = 'create'
|
|
370
|
+
nextTick(() => {
|
|
371
|
+
createPanelRef.value?.addReferenceItem({
|
|
372
|
+
url: thumbUrl,
|
|
373
|
+
name: item.title || '参考图'
|
|
374
|
+
})
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function handleOnMaterialGenerated() {
|
|
379
|
+
myAssetsRef.value?.reloadAssets?.()
|
|
380
|
+
}
|
|
381
|
+
|
|
245
382
|
function closePreview() {
|
|
246
383
|
previewVisible.value = false
|
|
247
384
|
if (wasPopoverOpenBeforePreview.value && materialPopoverVisible) {
|
|
@@ -682,7 +819,7 @@ function formatMaterialTitle(title?: string, fallback = '素材', maxLen = 12):
|
|
|
682
819
|
return text.length > maxLen ? `${text.slice(0, maxLen)}...` : text
|
|
683
820
|
}
|
|
684
821
|
|
|
685
|
-
//
|
|
822
|
+
// 点击素材卡片插入画布(区分视频与图片/矢量/插画,若当前处于图片占位符替换状态则优先替换占位符)
|
|
686
823
|
function handleSelectMaterial(meta: MaterialItem) {
|
|
687
824
|
const isVid = isVideoMaterial(meta)
|
|
688
825
|
const targetUrl = meta.sourceUrl || meta.url || meta.downloadUrl || meta.previewUrl
|
|
@@ -692,9 +829,36 @@ function handleSelectMaterial(meta: MaterialItem) {
|
|
|
692
829
|
return
|
|
693
830
|
}
|
|
694
831
|
|
|
695
|
-
let initialDimensions: { width?: number; height?: number } | undefined = undefined
|
|
696
832
|
const rawW = meta.originalWidth || meta.width
|
|
697
833
|
const rawH = meta.originalHeight || meta.height
|
|
834
|
+
|
|
835
|
+
const currentSelectedEl = selectedElementId?.value
|
|
836
|
+
? activeSlide?.value?.elements?.find((el: any) => el.id === selectedElementId.value)
|
|
837
|
+
: null
|
|
838
|
+
|
|
839
|
+
const explicitTargetId =
|
|
840
|
+
placeholderMaterialTargetId?.value ||
|
|
841
|
+
(typeof window !== 'undefined' ? (window as any).__jvsPlaceholderTargetId : null)
|
|
842
|
+
|
|
843
|
+
const targetPlaceholderId =
|
|
844
|
+
(resolveActivePlaceholderTargetId ? resolveActivePlaceholderTargetId() : null) ||
|
|
845
|
+
(explicitTargetId && (!currentSelectedEl || currentSelectedEl.id === explicitTargetId)
|
|
846
|
+
? explicitTargetId
|
|
847
|
+
: (currentSelectedEl && isImagePlaceholder(currentSelectedEl) ? currentSelectedEl.id : null))
|
|
848
|
+
|
|
849
|
+
if (targetPlaceholderId && replacePlaceholderElement) {
|
|
850
|
+
const replaced = replacePlaceholderElement(targetPlaceholderId, targetUrl, {
|
|
851
|
+
isVideo: isVid,
|
|
852
|
+
width: Number(rawW) || undefined,
|
|
853
|
+
height: Number(rawH) || undefined,
|
|
854
|
+
notifyMessage: isVid
|
|
855
|
+
? `已使用视频 "${formatMaterialTitle(meta.title, '高清视频', 12)}" 替换占位符`
|
|
856
|
+
: `已使用素材 "${formatMaterialTitle(meta.title, '图片', 12)}" 替换占位符图片`
|
|
857
|
+
})
|
|
858
|
+
if (replaced) return
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
let initialDimensions: { width?: number; height?: number } | undefined = undefined
|
|
698
862
|
if (rawW && rawH && rawW > 0 && rawH > 0) {
|
|
699
863
|
const maxWidth = 480
|
|
700
864
|
const maxHeight = 360
|
|
@@ -737,9 +901,21 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
737
901
|
|
|
738
902
|
<template>
|
|
739
903
|
<div class="material-drawer-container">
|
|
904
|
+
<!-- 未登录点击「我的素材/创建素材」时的顶部轻量胶囊提示 -->
|
|
905
|
+
<transition name="guest-toast-fade">
|
|
906
|
+
<div v-if="guestToastVisible" class="guest-auth-toast">
|
|
907
|
+
<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="#d97706" stroke-width="2.2">
|
|
908
|
+
<circle cx="12" cy="12" r="10" />
|
|
909
|
+
<line x1="12" y1="8" x2="12" y2="12" />
|
|
910
|
+
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
911
|
+
</svg>
|
|
912
|
+
<span>{{ guestToastText }}</span>
|
|
913
|
+
</div>
|
|
914
|
+
</transition>
|
|
915
|
+
|
|
740
916
|
<!-- 顶部抽屉标题栏:图二显示「素材库」,图三显示「← 分类/搜索词」 -->
|
|
741
917
|
<div class="material-drawer-header">
|
|
742
|
-
<div v-if="viewMode === 'overview'" class="drawer-header-left">
|
|
918
|
+
<div v-if="activeMainTab !== 'search' || viewMode === 'overview'" class="drawer-header-left">
|
|
743
919
|
<span class="drawer-header-title">素材库</span>
|
|
744
920
|
</div>
|
|
745
921
|
<button v-else type="button" class="drawer-back-btn" @click="backToOverview">
|
|
@@ -760,8 +936,77 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
760
936
|
</button>
|
|
761
937
|
</div>
|
|
762
938
|
|
|
763
|
-
<!--
|
|
764
|
-
<div v-if="viewMode === 'overview'" class="material-
|
|
939
|
+
<!-- 顶层 3-Tab 分段切换器(检索 | 我的素材 | 创建素材) -->
|
|
940
|
+
<div v-if="activeMainTab !== 'search' || viewMode === 'overview'" class="material-top-tabs-wrap">
|
|
941
|
+
<div class="material-top-segmented">
|
|
942
|
+
<button
|
|
943
|
+
type="button"
|
|
944
|
+
class="material-main-tab-btn"
|
|
945
|
+
:class="{ active: activeMainTab === 'search' }"
|
|
946
|
+
@click="handleSwitchMainTab('search')"
|
|
947
|
+
>
|
|
948
|
+
<span>检索</span>
|
|
949
|
+
</button>
|
|
950
|
+
|
|
951
|
+
<button
|
|
952
|
+
type="button"
|
|
953
|
+
class="material-main-tab-btn"
|
|
954
|
+
:class="{
|
|
955
|
+
active: activeMainTab === 'mine',
|
|
956
|
+
'is-disabled': !isDamLoggedIn
|
|
957
|
+
}"
|
|
958
|
+
:title="!isDamLoggedIn ? '请先登录后查看我的素材' : '查看我的项目与个人素材'"
|
|
959
|
+
@click="handleSwitchMainTab('mine')"
|
|
960
|
+
>
|
|
961
|
+
<span>我的素材</span>
|
|
962
|
+
<svg
|
|
963
|
+
v-if="!isDamLoggedIn"
|
|
964
|
+
class="tab-lock-svg"
|
|
965
|
+
viewBox="0 0 24 24"
|
|
966
|
+
width="11"
|
|
967
|
+
height="11"
|
|
968
|
+
fill="none"
|
|
969
|
+
stroke="currentColor"
|
|
970
|
+
stroke-width="2.2"
|
|
971
|
+
>
|
|
972
|
+
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
973
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
974
|
+
</svg>
|
|
975
|
+
</button>
|
|
976
|
+
|
|
977
|
+
<button
|
|
978
|
+
type="button"
|
|
979
|
+
class="material-main-tab-btn"
|
|
980
|
+
:class="{
|
|
981
|
+
active: activeMainTab === 'create',
|
|
982
|
+
'is-disabled': !isDamLoggedIn
|
|
983
|
+
}"
|
|
984
|
+
:title="!isDamLoggedIn ? '请先登录后使用创建素材' : 'AI 生成图片或视频素材'"
|
|
985
|
+
@click="handleSwitchMainTab('create')"
|
|
986
|
+
>
|
|
987
|
+
<span>创建素材</span>
|
|
988
|
+
<span v-if="isDamLoggedIn" class="tab-ai-spark">✦</span>
|
|
989
|
+
<svg
|
|
990
|
+
v-else
|
|
991
|
+
class="tab-lock-svg"
|
|
992
|
+
viewBox="0 0 24 24"
|
|
993
|
+
width="11"
|
|
994
|
+
height="11"
|
|
995
|
+
fill="none"
|
|
996
|
+
stroke="currentColor"
|
|
997
|
+
stroke-width="2.2"
|
|
998
|
+
>
|
|
999
|
+
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
1000
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
1001
|
+
</svg>
|
|
1002
|
+
</button>
|
|
1003
|
+
</div>
|
|
1004
|
+
</div>
|
|
1005
|
+
|
|
1006
|
+
<!-- ==================== Tab 1:检索(公网素材分类概览 & 详情瀑布流) ==================== -->
|
|
1007
|
+
<template v-if="activeMainTab === 'search'">
|
|
1008
|
+
<!-- 图二:素材库分类概览视图 -->
|
|
1009
|
+
<div v-if="viewMode === 'overview'" class="material-overview-body">
|
|
765
1010
|
<!-- 搜索框 -->
|
|
766
1011
|
<div class="overview-search-wrap">
|
|
767
1012
|
<div class="overview-search-box">
|
|
@@ -840,6 +1085,15 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
840
1085
|
<span v-if="cat.subType === 'Videos' || isVideoMaterial(item)" class="video-badge-icon">
|
|
841
1086
|
<el-icon><VideoPlay /></el-icon>
|
|
842
1087
|
</span>
|
|
1088
|
+
<button
|
|
1089
|
+
v-if="isDamLoggedIn && cat.subType !== 'Videos' && !isVideoMaterial(item) && getMaterialThumb(item)"
|
|
1090
|
+
type="button"
|
|
1091
|
+
class="overview-card-ref-btn"
|
|
1092
|
+
title="作为参考图发送到「创建素材」"
|
|
1093
|
+
@click.stop.prevent="handleSendToCreateRef(item, $event)"
|
|
1094
|
+
>
|
|
1095
|
+
@参考
|
|
1096
|
+
</button>
|
|
843
1097
|
</div>
|
|
844
1098
|
</template>
|
|
845
1099
|
|
|
@@ -981,6 +1235,17 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
981
1235
|
<el-icon><VideoPlay /></el-icon>
|
|
982
1236
|
</span>
|
|
983
1237
|
|
|
1238
|
+
<!-- 悬浮设为参考图按钮 -->
|
|
1239
|
+
<button
|
|
1240
|
+
v-if="isDamLoggedIn && filterParams.activeSubType !== 'Videos' && !isVideoMaterial(item) && getMaterialThumb(item)"
|
|
1241
|
+
type="button"
|
|
1242
|
+
class="detail-card-ref-btn"
|
|
1243
|
+
title="作为参考图发送到「创建素材」"
|
|
1244
|
+
@click.stop.prevent="handleSendToCreateRef(item, $event)"
|
|
1245
|
+
>
|
|
1246
|
+
@参考
|
|
1247
|
+
</button>
|
|
1248
|
+
|
|
984
1249
|
<!-- 悬浮预览小按钮 -->
|
|
985
1250
|
<button
|
|
986
1251
|
v-if="getMaterialThumb(item)"
|
|
@@ -1031,6 +1296,25 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
1031
1296
|
</div>
|
|
1032
1297
|
</div>
|
|
1033
1298
|
</div>
|
|
1299
|
+
</template>
|
|
1300
|
+
|
|
1301
|
+
<!-- ==================== Tab 2:我的素材(jvs-material-ui 资产库接入) ==================== -->
|
|
1302
|
+
<MyAssetsPanel
|
|
1303
|
+
v-else-if="activeMainTab === 'mine' && isDamLoggedIn"
|
|
1304
|
+
ref="myAssetsRef"
|
|
1305
|
+
@select="handleSelectMaterial"
|
|
1306
|
+
@preview="openCustomListPreview"
|
|
1307
|
+
@use-as-ref="(item) => handleSendToCreateRef(item)"
|
|
1308
|
+
/>
|
|
1309
|
+
|
|
1310
|
+
<!-- ==================== Tab 3:创建素材(AI 图片生成器 & 视频生成) ==================== -->
|
|
1311
|
+
<CreateMaterialPanel
|
|
1312
|
+
v-else-if="activeMainTab === 'create' && isDamLoggedIn"
|
|
1313
|
+
ref="createPanelRef"
|
|
1314
|
+
@select="handleSelectMaterial"
|
|
1315
|
+
@preview="openCustomListPreview"
|
|
1316
|
+
@generated="handleOnMaterialGenerated"
|
|
1317
|
+
/>
|
|
1034
1318
|
|
|
1035
1319
|
<!-- 全屏大图/视频预览 Modal -->
|
|
1036
1320
|
<teleport to="body">
|
|
@@ -1113,6 +1397,7 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
1113
1397
|
|
|
1114
1398
|
<style scoped lang="scss">
|
|
1115
1399
|
.material-drawer-container {
|
|
1400
|
+
position: relative;
|
|
1116
1401
|
display: flex;
|
|
1117
1402
|
flex-direction: column;
|
|
1118
1403
|
width: 288px;
|
|
@@ -1124,18 +1409,112 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
1124
1409
|
user-select: none;
|
|
1125
1410
|
}
|
|
1126
1411
|
|
|
1412
|
+
/* 未登录点击受限 Tab 时的顶部轻量胶囊提示 */
|
|
1413
|
+
.guest-auth-toast {
|
|
1414
|
+
position: absolute;
|
|
1415
|
+
top: 10px;
|
|
1416
|
+
left: 50%;
|
|
1417
|
+
transform: translateX(-50%);
|
|
1418
|
+
background: #fffbeb;
|
|
1419
|
+
border: 1px solid #fde68a;
|
|
1420
|
+
color: #b45309;
|
|
1421
|
+
font-size: 11.5px;
|
|
1422
|
+
font-weight: 500;
|
|
1423
|
+
padding: 5px 12px;
|
|
1424
|
+
border-radius: 99px;
|
|
1425
|
+
white-space: nowrap;
|
|
1426
|
+
z-index: 200;
|
|
1427
|
+
box-shadow: 0 4px 12px rgba(217, 119, 6, 0.12);
|
|
1428
|
+
display: flex;
|
|
1429
|
+
align-items: center;
|
|
1430
|
+
gap: 5px;
|
|
1431
|
+
pointer-events: none;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
.guest-toast-fade-enter-active,
|
|
1435
|
+
.guest-toast-fade-leave-active {
|
|
1436
|
+
transition: opacity 0.18s ease, transform 0.18s ease;
|
|
1437
|
+
}
|
|
1438
|
+
.guest-toast-fade-enter-from,
|
|
1439
|
+
.guest-toast-fade-leave-to {
|
|
1440
|
+
opacity: 0;
|
|
1441
|
+
transform: translate(-50%, -6px);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1127
1444
|
/* 顶部栏(图二:素材库 / 图三:← 分类名) */
|
|
1128
1445
|
.material-drawer-header {
|
|
1129
1446
|
display: flex;
|
|
1130
1447
|
align-items: center;
|
|
1131
1448
|
justify-content: space-between;
|
|
1132
|
-
height:
|
|
1449
|
+
height: 44px;
|
|
1133
1450
|
padding: 0 16px;
|
|
1134
|
-
border-bottom:
|
|
1451
|
+
border-bottom: none;
|
|
1135
1452
|
flex-shrink: 0;
|
|
1136
1453
|
box-sizing: border-box;
|
|
1137
1454
|
}
|
|
1138
1455
|
|
|
1456
|
+
/* 顶层 3-Tab 分段切换器(检索 | 我的素材 | 创建素材) */
|
|
1457
|
+
.material-top-tabs-wrap {
|
|
1458
|
+
padding: 2px 16px 10px;
|
|
1459
|
+
border-bottom: 1px solid #f1f5f9;
|
|
1460
|
+
flex-shrink: 0;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
.material-top-segmented {
|
|
1464
|
+
display: grid;
|
|
1465
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1466
|
+
background: #f1f5f9;
|
|
1467
|
+
padding: 3px;
|
|
1468
|
+
border-radius: 8px;
|
|
1469
|
+
gap: 2px;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
.material-main-tab-btn {
|
|
1473
|
+
height: 28px;
|
|
1474
|
+
border: none;
|
|
1475
|
+
background: transparent;
|
|
1476
|
+
border-radius: 6px;
|
|
1477
|
+
font-size: 12px;
|
|
1478
|
+
font-weight: 500;
|
|
1479
|
+
color: #64748b;
|
|
1480
|
+
cursor: pointer;
|
|
1481
|
+
display: inline-flex;
|
|
1482
|
+
align-items: center;
|
|
1483
|
+
justify-content: center;
|
|
1484
|
+
gap: 3px;
|
|
1485
|
+
padding: 0 4px;
|
|
1486
|
+
white-space: nowrap;
|
|
1487
|
+
transition: all 0.18s ease;
|
|
1488
|
+
|
|
1489
|
+
&:hover:not(.active):not(.is-disabled) {
|
|
1490
|
+
color: #1e293b;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
&.active {
|
|
1494
|
+
background: #ffffff;
|
|
1495
|
+
color: #1e6fff;
|
|
1496
|
+
font-weight: 600;
|
|
1497
|
+
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
&.is-disabled {
|
|
1501
|
+
color: #94a3b8;
|
|
1502
|
+
cursor: not-allowed;
|
|
1503
|
+
opacity: 0.72;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
.tab-ai-spark {
|
|
1508
|
+
font-size: 11px;
|
|
1509
|
+
line-height: 1;
|
|
1510
|
+
color: #8b5cf6;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
.tab-lock-svg {
|
|
1514
|
+
flex-shrink: 0;
|
|
1515
|
+
color: #94a3b8;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1139
1518
|
.drawer-header-left {
|
|
1140
1519
|
display: flex;
|
|
1141
1520
|
align-items: center;
|
|
@@ -1349,6 +1728,32 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
1349
1728
|
&:hover .overview-thumb-img {
|
|
1350
1729
|
transform: scale(1.04);
|
|
1351
1730
|
}
|
|
1731
|
+
|
|
1732
|
+
&:hover .overview-card-ref-btn {
|
|
1733
|
+
opacity: 1;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
.overview-card-ref-btn {
|
|
1738
|
+
position: absolute;
|
|
1739
|
+
left: 5px;
|
|
1740
|
+
bottom: 5px;
|
|
1741
|
+
height: 19px;
|
|
1742
|
+
padding: 0 6px;
|
|
1743
|
+
border-radius: 4px;
|
|
1744
|
+
border: none;
|
|
1745
|
+
background: rgba(15, 23, 42, 0.68);
|
|
1746
|
+
color: #ffffff;
|
|
1747
|
+
font-size: 10px;
|
|
1748
|
+
font-weight: 500;
|
|
1749
|
+
cursor: pointer;
|
|
1750
|
+
opacity: 0;
|
|
1751
|
+
transition: all 0.15s ease;
|
|
1752
|
+
z-index: 3;
|
|
1753
|
+
|
|
1754
|
+
&:hover {
|
|
1755
|
+
background: #1e6fff;
|
|
1756
|
+
}
|
|
1352
1757
|
}
|
|
1353
1758
|
|
|
1354
1759
|
.overview-thumb-img {
|
|
@@ -1546,11 +1951,34 @@ watch([() => materialApiUrl?.value, () => materialPageApiUrl?.value, () => mater
|
|
|
1546
1951
|
transform: scale(1.03);
|
|
1547
1952
|
}
|
|
1548
1953
|
|
|
1549
|
-
&:hover .detail-card-preview-btn
|
|
1954
|
+
&:hover .detail-card-preview-btn,
|
|
1955
|
+
&:hover .detail-card-ref-btn {
|
|
1550
1956
|
opacity: 1;
|
|
1551
1957
|
}
|
|
1552
1958
|
}
|
|
1553
1959
|
|
|
1960
|
+
.detail-card-ref-btn {
|
|
1961
|
+
position: absolute;
|
|
1962
|
+
left: 6px;
|
|
1963
|
+
bottom: 6px;
|
|
1964
|
+
height: 20px;
|
|
1965
|
+
padding: 0 6px;
|
|
1966
|
+
border-radius: 4px;
|
|
1967
|
+
border: none;
|
|
1968
|
+
background: rgba(15, 23, 42, 0.68);
|
|
1969
|
+
color: #ffffff;
|
|
1970
|
+
font-size: 10px;
|
|
1971
|
+
font-weight: 500;
|
|
1972
|
+
cursor: pointer;
|
|
1973
|
+
opacity: 0;
|
|
1974
|
+
transition: all 0.15s ease;
|
|
1975
|
+
z-index: 3;
|
|
1976
|
+
|
|
1977
|
+
&:hover {
|
|
1978
|
+
background: #1e6fff;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1554
1982
|
.detail-card-img {
|
|
1555
1983
|
width: 100%;
|
|
1556
1984
|
height: auto;
|