Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mengchangaigc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
姚珂
mengchangaigc
Commits
626b653c
Commit
626b653c
authored
Aug 29, 2026
by
黄同智
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
工具类页面
parent
96e60a33
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
890 additions
and
9 deletions
+890
-9
index.ts
apps/web-vue/src/router/index.ts
+18
-0
CreativeComposer.vue
...e/src/views/quickCreation/components/CreativeComposer.vue
+0
-0
DigitalHumanDialog.vue
...src/views/quickCreation/components/DigitalHumanDialog.vue
+218
-0
InspirationGallery.vue
...src/views/quickCreation/components/InspirationGallery.vue
+2
-2
MediaMaterialDialog.vue
...rc/views/quickCreation/components/MediaMaterialDialog.vue
+238
-0
ModelTryOnDialog.vue
...e/src/views/quickCreation/components/ModelTryOnDialog.vue
+0
-0
Remove-video.vue
...b-vue/src/views/quickCreation/components/Remove-video.vue
+198
-0
ToolGroup.vue
.../web-vue/src/views/quickCreation/components/ToolGroup.vue
+42
-7
remove-quality.vue
apps/web-vue/src/views/quickCreation/remove-quality.vue
+0
-0
remove-subtitles.vue
apps/web-vue/src/views/quickCreation/remove-subtitles.vue
+126
-0
remove-watermark.vue
apps/web-vue/src/views/quickCreation/remove-watermark.vue
+40
-0
types.ts
apps/web-vue/src/views/quickCreation/types.ts
+8
-0
Item.vue
apps/web-vue/src/views/resource/components/Item.vue
+0
-0
No files found.
apps/web-vue/src/router/index.ts
View file @
626b653c
...
...
@@ -51,6 +51,24 @@ const routes = [
name
:
'QuickCreation'
,
component
:
QuickCreation
,
meta
:
{
title
:
'快速创作'
,
icon
:
'add'
,
affix
:
true
}
},
{
path
:
'remove-watermark'
,
name
:
'RemoveWatermark'
,
component
:
()
=>
import
(
'@/views/quickCreation/remove-watermark.vue'
),
meta
:
{
title
:
'视频去水印'
,
hidden
:
true
}
},
{
path
:
'remove-subtitles'
,
name
:
'RemoveSubtitles'
,
component
:
()
=>
import
(
'@/views/quickCreation/remove-subtitles.vue'
),
meta
:
{
title
:
'视频去字幕'
,
hidden
:
true
}
},
{
path
:
'remove-quality'
,
name
:
'RemoveQuality'
,
component
:
()
=>
import
(
'@/views/quickCreation/remove-quality.vue'
),
meta
:
{
title
:
'视频画质增强'
,
hidden
:
true
}
}
]
},
...
...
apps/web-vue/src/views/quickCreation/components/CreativeComposer.vue
View file @
626b653c
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/quickCreation/components/DigitalHumanDialog.vue
0 → 100644
View file @
626b653c
<
template
>
<Dialog
v-model=
"dialogVisible"
bg-color=
"#fff"
width=
"1000"
>
<div
class=
"bg-fff hidden round-10"
>
<header
class=
"dialog-header flex-items-center gap-12 px-24 py-18"
>
<span
class=
"header-icon flex-center wh-32 round-6"
>
<el-icon
class=
"fs-20"
>
<User
/>
</el-icon>
</span>
<div>
<div
class=
"flex-items-center gap-8"
>
<h3
class=
"fs-16 lh-22 color-000"
>
AI 智能数字人分身工作台
</h3>
</div>
<p
class=
"fs-12 lh-20 color-888"
>
高保真音容笑貌克隆,无需实景拍摄,分钟级输出口播带货视频
</p>
</div>
</header>
<section
class=
"dialog-body flex gap-24 px-24 py-24"
>
<div
class=
"left-column flex-col gap-24 flex-1"
>
<div>
<div
class=
"lh-22 mb-14"
>
1 · 选择主播模特分身
</div>
<div
class=
"anchor-list flex flex-wrap gap-12 w-full"
>
<div
v-for=
"item in anchors"
:key=
"item.id"
class=
"anchor-option pointer"
:class=
"
{ active: selectedAnchor === item.id }"
@click="selectAnchor(item.id)">
<div
class=
"anchor-card flex-items-center gap-12 p-14 round-12 bg-fff"
>
<span
class=
"avatar flex-center wh-42 round hidden"
:style=
"
{ background: item.avatarBg }">
<img
v-if=
"item.avatar"
:src=
"item.avatar"
:alt=
"item.name"
class=
"w-full h-full cover"
/>
<span
v-else
class=
"color-fff"
>
{{
item
.
name
.
slice
(
0
,
1
)
}}
</span>
</span>
<span
class=
"anchor-copy flex-col text-left"
>
<span
class=
"anchor-name lh-20 color-000"
>
{{
item
.
name
}}
</span>
<span
class=
"anchor-desc fs-12 lh-20 color-888"
>
{{
item
.
desc
}}
</span>
</span>
</div>
</div>
</div>
</div>
<div>
<div
class=
"lh-22 mb-10"
>
2 · 调节声音音色及音速
</div>
<div
class=
"voice-panel p-16 round-14"
>
<div
class=
"fs-12 lh-20 color-888 mb-8"
>
推荐音色标签
</div>
<el-select
v-model=
"voiceStyle"
class=
"w-full"
size=
"large"
>
<el-option
label=
"热情高亢(带货爆款)"
value=
"hot"
/>
<el-option
label=
"温柔亲和(护肤种草)"
value=
"soft"
/>
<el-option
label=
"专业可信(知识讲解)"
value=
"pro"
/>
</el-select>
<div
class=
"flex-between mt-14"
>
<span
class=
"fs-12 lh-20 color-888"
>
口播语速倍率
</span>
<span
class=
"fs-12 lh-20 speed-value"
>
{{
speed
.
toFixed
(
2
)
}}
x
</span>
</div>
<el-slider
v-model=
"speed"
:min=
"0.8"
:max=
"1.3"
:step=
"0.05"
:show-tooltip=
"false"
/>
</div>
</div>
</div>
<div
class=
"right-column flex-col gap-24 flex-1"
>
<div>
<div
class=
"lh-22 mb-10"
>
3 · 设定数字人播报文案
</div>
<el-input
v-model=
"scriptText"
class=
"script-input"
type=
"textarea"
resize=
"none"
:rows=
"7"
maxlength=
"300"
show-word-limit
/>
<div
class=
"flex-between mt-12 fs-12 color-888"
>
<span>
建议文案字数控制在 300 字以内
</span>
<span>
当前:
{{
scriptText
.
length
}}
字
</span>
</div>
</div>
<div
class=
"cost-card flex-col gap-12 p-18 round-14 mt-auto"
>
<div
class=
"flex-between"
>
<div
class=
" lh-22 color-888"
>
所需积分消耗
</div>
<div
class=
" lh-22 cost-value"
>
40 点算力
</div>
</div>
<el-button
type=
"primary"
class=
"submit-btn h-40 round-10 border-none"
>
<el-icon>
<User
/>
</el-icon>
<span>
一键合成数字人推流视频
</span>
</el-button>
</div>
</div>
</section>
</div>
</Dialog>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
{
User
}
from
'@element-plus/icons-vue'
;
import
peopleImg
from
'@/static/image/meinv.png'
;
import
productImg
from
'@/static/image/huaban.png'
;
type
AnchorItem
=
{
id
:
string
;
name
:
string
;
desc
:
string
;
avatar
?:
string
;
avatarBg
:
string
;
};
const
props
=
defineProps
<
{
modelValue
:
boolean
;
}
>
();
const
emit
=
defineEmits
<
{
'update:modelValue'
:
[
value
:
boolean
];
}
>
();
const
dialogVisible
=
computed
({
get
:
()
=>
props
.
modelValue
,
set
:
(
value
)
=>
emit
(
'update:modelValue'
,
value
),
});
const
anchors
:
AnchorItem
[]
=
[
{
id
:
'xiaomei'
,
name
:
'主播小美'
,
desc
:
'甜美知性 · 亲和力极佳'
,
avatar
:
peopleImg
,
avatarBg
:
'#edf3fb'
},
{
id
:
'daliu'
,
name
:
'主播大刘'
,
desc
:
'专业严谨 · 沉稳有说服力'
,
avatarBg
:
'linear-gradient(135deg, #ba7a43, #16324f)'
},
{
id
:
'luoxi'
,
name
:
'主播露西'
,
desc
:
'外籍超模 · 时尚气息浓郁'
,
avatar
:
productImg
,
avatarBg
:
'#dff4fb'
},
{
id
:
'wang'
,
name
:
'主播王总'
,
desc
:
'中年精英 · 行业大咖气质'
,
avatarBg
:
'linear-gradient(135deg, #d9c4ae, #2e3b32)'
},
];
const
selectedAnchor
=
ref
(
'xiaomei'
);
const
voiceStyle
=
ref
(
'hot'
);
const
speed
=
ref
(
1.05
);
const
scriptText
=
ref
(
'哈罗各位宝宝们!今天给大家带来一款超级好用的黑科技香水。轻轻一喷,香味持久一整天,而且前中后调都特别有层次感。现在下单还享受买一送一哦,心动的宝宝赶紧点击下方链接抢购吧!'
);
const
selectAnchor
=
(
id
:
string
)
=>
{
selectedAnchor
.
value
=
id
;
};
</
script
>
<
style
scoped
lang=
"scss"
>
.dialog-header
{
border-bottom
:
1px
solid
#edf2f7
;
}
.header-icon
{
color
:
#f23594
;
background
:
#fff0f7
;
}
.anchor-list
{
align-items
:
stretch
;
}
.anchor-option
{
flex
:
0
0
calc
((
100%
-
12px
)
/
2
);
border
:
1px
solid
#dfe7f2
;
border-radius
:
14px
;
transition
:
border-color
.2s
,
box-shadow
.2s
;
}
.anchor-option.active
{
border-color
:
#f23594
;
box-shadow
:
0
0
0
1px
#f23594
;
}
.anchor-option
:hover
{
border-color
:
#f23594
;
}
.anchor-card
{
min-height
:
66px
;
}
.voice-panel
,
.script-input
:deep
(
.el-textarea__inner
),
.cost-card
{
border
:
1px
solid
#dfe7f2
;
background
:
#fbfdff
;
}
:deep
(
.el-select__wrapper
)
{
border-radius
:
10px
;
box-shadow
:
0
0
0
1px
#dfe7f2
inset
;
background
:
#fff
;
}
:deep
(
.el-slider__bar
),
:deep
(
.el-slider__button
)
{
background
:
#f23594
;
}
:deep
(
.el-slider__button
)
{
border-color
:
#f23594
;
}
.speed-value
,
.cost-value
{
color
:
#f23594
;
}
.script-input
:deep
(
.el-textarea__inner
)
{
min-height
:
174px
!
important
;
padding
:
16px
;
border-radius
:
14px
;
box-shadow
:
none
;
color
:
#183151
;
line-height
:
24px
;
}
.script-input
:deep
(
.el-input__count
)
{
display
:
none
;
}
.submit-btn
{
width
:
100%
;
background
:
#f23594
;
box-shadow
:
0
8px
18px
rgba
(
242
,
53
,
148
,
.24
);
}
.right-column
{
min-width
:
0
;
}
</
style
>
apps/web-vue/src/views/quickCreation/components/InspirationGallery.vue
View file @
626b653c
...
...
@@ -224,7 +224,7 @@ const openPreview = (index: number) => {
}
.gallery-card
{
flex
:
0
0
calc
((
100%
-
60px
)
/
4
);
flex
:
0
0
calc
((
100%
-
80px
)
/
5
);
background
:
#fff
;
transition
:
border-color
.24s
,
box-shadow
.24s
,
transform
.24s
;
}
...
...
@@ -294,7 +294,7 @@ h3 {
@media
(
max-width
:
1280px
)
{
.gallery-card
{
flex-basis
:
calc
((
100%
-
40px
)
/
3
);
flex-basis
:
calc
((
100%
-
60px
)
/
4
);
}
}
...
...
apps/web-vue/src/views/quickCreation/components/MediaMaterialDialog.vue
0 → 100644
View file @
626b653c
<
template
>
<el-dialog
v-model=
"dialogVisible"
width=
"672"
align-center
append-to-body
class=
"quick-media-dialog"
>
<div
class=
"media-dialog hidden round-12"
>
<div
class=
"flex-between px-18 py-16"
>
<div
class=
"flex-items-center gap-8"
>
<el-icon
class=
"color-main fs-18"
>
<Picture
/>
</el-icon>
<h3
class=
"fs-16 lh-24 color-000"
>
选择参考素材
</h3>
</div>
<el-button
class=
"close-btn wh-28 p-0 border-none bg-none color-888 pointer"
circle
@
click=
"dialogVisible = false"
>
<el-icon>
<Close
/>
</el-icon>
</el-button>
</div>
<div
class=
"flex-between px-14 pb-14"
>
<div
class=
"media-tabs flex-items-center h-32 p-4 round-4"
>
<el-button
v-for=
"item in mediaTabs"
:key=
"item"
class=
"h-26 px-16 round-4 border-none bg-none"
:class=
"
{ active: mediaTab === item }" text @click="mediaTab = item">
{{
item
}}
</el-button>
</div>
<div
class=
"flex-items-center gap-8"
>
<div
class=
"search-mini flex-items-center h-32 w-194 px-10 round-4 bg-fff"
>
<el-icon
class=
"color-888"
>
<Search
/>
</el-icon>
<el-input
v-model=
"mediaKeyword"
class=
"media-search flex-1 minw-0 ml-8"
placeholder=
"搜索资产..."
/>
</div>
<el-button
class=
"upload-local flex-center gap-6 h-32 px-14"
>
<el-icon>
<Upload
/>
</el-icon>
<span>
本地上传
</span>
</el-button>
</div>
</div>
<el-radio-group
v-model=
"selectedId"
class=
"material-list flex flex-wrap gap-12 px-14 pt-14 minh-300"
>
<el-radio
v-for=
"item in filteredMaterials"
:key=
"item.id"
class=
"media-card relative round-8 hidden border-none pointer text-left h-150"
:class=
"
{ selected: selectedId === item.id }" :value="item.id">
<img
v-if=
"item.image"
:src=
"item.image"
:alt=
"item.name"
class=
"w-full h-full cover"
/>
<span
v-else
class=
"video-placeholder flex-center w-full h-full color-888"
>
VIDEO
</span>
<span
v-if=
"item.kind === '视频'"
class=
"video-tag absolute top-8 right-8 h-18 lh-18 px-6 round-4 color-fff fs-10"
>
VIDEO
</span>
<span
class=
"media-mask absolute bottom-0 left-0 w-full px-8 py-8 color-fff"
>
<div
class=
"lh-18 ellipsis fs-12 fw-400"
>
{{
item
.
name
}}
</div>
<div
class=
"fs-10 fw-400"
>
{{
item
.
size
}}
</div>
</span>
</el-radio>
</el-radio-group>
<div
class=
"media-footer flex justify-end px-18 py-16 mt-18"
>
<div
class=
"flex-items-center"
>
<el-button
class=
"h-32 px-16 fs-12"
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
class=
"h-32 px-16 fs-12"
type=
"primary"
@
click=
"handleConfirm"
>
确认选择
</el-button>
</div>
</div>
</div>
</el-dialog>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
,
watch
}
from
'vue'
;
import
{
Close
,
Picture
,
Search
,
Upload
}
from
'@element-plus/icons-vue'
;
import
productImg
from
'@/static/image/huaban.png'
;
import
peopleImg
from
'@/static/image/meinv.png'
;
import
detailImg
from
'@/static/image/long.png'
;
import
type
{
MaterialItem
}
from
'../types'
;
const
props
=
defineProps
<
{
modelValue
:
boolean
;
selected
:
MaterialItem
[];
}
>
();
const
emit
=
defineEmits
<
{
'update:modelValue'
:
[
value
:
boolean
];
'update:selected'
:
[
value
:
MaterialItem
[]];
confirm
:
[
value
:
MaterialItem
[]];
}
>
();
const
mediaTabs
=
[
'全部'
,
'图片'
,
'视频'
];
const
mediaTab
=
ref
(
'全部'
);
const
mediaKeyword
=
ref
(
''
);
const
selectedId
=
ref
(
props
.
selected
[
0
]?.
id
??
''
);
const
materials
:
MaterialItem
[]
=
[
{
id
:
'm1'
,
name
:
'雅诗兰黛精华空瓶主图主体.png'
,
kind
:
'图片'
,
size
:
'1.2 MB'
,
image
:
productImg
},
{
id
:
'm2'
,
name
:
'智能蓝牙音箱白色高对比展示.jpg'
,
kind
:
'图片'
,
size
:
'980 KB'
,
image
:
detailImg
},
{
id
:
'm3'
,
name
:
'模特红裙走秀素材_原画.mp4'
,
kind
:
'视频'
,
size
:
'18.4 MB'
,
image
:
''
},
{
id
:
'm4'
,
name
:
'七夕美妆礼盒_烫礼场景成片.mp4'
,
kind
:
'视频'
,
size
:
'42.6 MB'
,
image
:
''
},
{
id
:
'm5'
,
name
:
'AI生成 精华液晨间护肤场景.jpg'
,
kind
:
'图片'
,
size
:
'2.3 MB'
,
image
:
peopleImg
},
];
const
dialogVisible
=
computed
({
get
:
()
=>
props
.
modelValue
,
set
:
(
value
)
=>
emit
(
'update:modelValue'
,
value
),
});
const
selectedMaterials
=
computed
(()
=>
{
const
current
=
materials
.
find
((
item
)
=>
item
.
id
===
selectedId
.
value
);
return
current
?
[
current
]
:
[];
});
const
filteredMaterials
=
computed
(()
=>
{
const
keyword
=
mediaKeyword
.
value
.
trim
().
toLowerCase
();
return
materials
.
filter
((
item
)
=>
{
const
matchTab
=
mediaTab
.
value
===
'全部'
||
item
.
kind
===
mediaTab
.
value
;
const
matchKeyword
=
!
keyword
||
item
.
name
.
toLowerCase
().
includes
(
keyword
);
return
matchTab
&&
matchKeyword
;
});
});
const
handleConfirm
=
()
=>
{
emit
(
'confirm'
,
selectedMaterials
.
value
);
dialogVisible
.
value
=
false
;
};
watch
(
()
=>
props
.
selected
,
(
value
)
=>
{
const
id
=
value
[
0
]?.
id
??
''
;
if
(
id
!==
selectedId
.
value
)
{
selectedId
.
value
=
id
;
}
},
{
deep
:
true
}
);
watch
(
selectedId
,
()
=>
{
const
propId
=
props
.
selected
[
0
]?.
id
??
''
;
if
(
selectedId
.
value
!==
propId
)
{
emit
(
'update:selected'
,
selectedMaterials
.
value
);
}
});
</
script
>
<
style
lang=
"scss"
scoped
>
:deep
(
.media-search
.el-input__wrapper
)
{
padding
:
0
;
box-shadow
:
none
;
background
:
transparent
;
}
:deep
(
.media-search
.el-input__inner
)
{
height
:
30px
;
font-size
:
12px
;
}
:deep
(
.material-list
.el-radio__input
)
{
position
:
absolute
;
top
:
8px
;
left
:
8px
;
z-index
:
1
;
}
:deep
(
.material-list
.el-radio__label
)
{
display
:
block
;
width
:
100%
;
height
:
100%
;
padding-left
:
0
;
}
.soft-pill
,
.media-tabs
{
background
:
#f3f7fc
;
}
.search-mini
{
border
:
1px
solid
#dfe7f2
;
}
.media-tabs
button
.active
{
color
:
#183151
;
background
:
#fff
;
box-shadow
:
0
1px
4px
rgba
(
17
,
36
,
62
,
.08
);
}
.upload-local
{
color
:
#fff
;
background
:
rgba
(
var
(
--
main-color
)
,
1
);
}
.material-list
{
align-items
:
stretch
;
}
.media-card
{
flex
:
0
0
calc
((
100%
-
36px
)
/
4
);
aspect-ratio
:
1
/
1
;
margin
:
0
;
background
:
#eef3f8
;
}
.media-card.selected
{
box-shadow
:
0
0
0
2px
rgba
(
var
(
--
main-color
)
,
1
);
}
.video-placeholder
{
background
:
linear-gradient
(
180deg
,
#f4f7fb
0%
,
#dce5ee
100%
);
}
.video-tag
{
background
:
rgba
(
34
,
44
,
58
,
.72
);
}
.media-mask
{
background
:
linear-gradient
(
180deg
,
transparent
0%
,
rgba
(
18
,
25
,
38
,
.72
)
35%
,
rgba
(
18
,
25
,
38
,
.9
)
100%
);
}
.media-footer
{
border-top
:
1px
solid
#edf2f7
;
}
</
style
>
<
style
lang=
"scss"
>
.quick-media-dialog
{
padding
:
0
;
border-radius
:
12px
;
overflow
:
hidden
;
.el-dialog__header
{
display
:
none
;
}
.el-dialog__body
{
padding
:
0
;
}
}
</
style
>
apps/web-vue/src/views/quickCreation/components/ModelTryOnDialog.vue
0 → 100644
View file @
626b653c
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/quickCreation/components/Remove-video.vue
0 → 100644
View file @
626b653c
<
template
>
<div
class=
"flex items-start gap-24"
>
<div
class=
"left-panel flex-col gap-20"
>
<el-card
class=
"panel-card round-10"
shadow=
"never"
>
<template
#
header
>
<div
class=
" lh-22 fw-700 color-000"
>
选择待处理视频
</div>
</
template
>
<div
class=
"upload-area w-full pointer"
@
click=
"mediaVisible = true"
>
<div
class=
"flex-col flex-center h-150"
>
<span
class=
"upload-icon flex-center wh-40 round mb-10"
>
<el-icon
class=
"fs-22"
>
<UploadFilled
/>
</el-icon>
</span>
<div
class=
"lh-22 fs-12"
>
选择待擦除水印视频
</div>
<p
class=
"fs-12 color-999"
>
智能分析格式,支持最高4K源文件输入
</p>
</div>
</div>
</el-card>
<el-card
class=
"panel-card round-10"
shadow=
"never"
>
<
template
#
header
>
<div
class=
"flex-between"
>
<div
class=
" lh-22 fw-700 color-000"
>
标定水印区域 (1)
</div>
<el-button
class=
"h-28 px-8 fs-12 color-main"
text
>
<el-icon>
<Plus
/>
</el-icon>
<span>
添加选区
</span>
</el-button>
</div>
</
template
>
<div
class=
"flex-items-center flex-wrap gap-10"
>
<el-tag
class=
"watermark-tag h-30 lh-30 px-12 round-6 color-main"
closable
effect=
"plain"
>
水印区 1:78,4 / 96,14
</el-tag>
</div>
</el-card>
<el-card
class=
"guide-card round-10 pt-16"
shadow=
"never"
>
<div
class=
"flex-items-center gap-6 mb-10"
>
<el-icon
class=
"color-main fs-16"
>
<QuestionFilled
/>
</el-icon>
<span
class=
" lh-22 fw-700 color-333"
>
智能擦除操作指引
</span>
</div>
<div
class=
"fs-12 lh-26 color-888"
>
<p>
1. 上传视频素材,并在右侧视频静止帧中直接拖动/画框。
</p>
<p>
2. 如果水印在视频的不同位置,可多次点击「添加选区」进行联合擦除。
</p>
<p>
3. 点击执行,系统会提取水印周围相邻多帧的纹理流,智能重构无瑕背景。
</p>
</div>
</el-card>
<el-button
type=
"primary"
class=
"run-btn h-40 round-6 border-none"
>
立即执行智能重绘擦除 (预计 2.50)
</el-button>
</div>
<el-card
class=
"preview-card flex-1 round-10"
shadow=
"never"
>
<
template
#
header
>
<div
class=
"flex-between"
>
<div
class=
" lh-22 fw-700 color-000"
>
画面预览与划定框
</div>
<span
class=
"fs-12 color-999"
>
模拟视频帧排布
</span>
</div>
</
template
>
<div
class=
"preview-frame relative hidden round-12"
>
<img
:src=
"previewImage"
alt=
"待处理视频预览"
class=
"w-full h-full cover"
/>
<div
class=
"preview-mask absolute top-0 left-0 w-full h-full"
></div>
<div
class=
"selection-box absolute top-16 right-26 w-108 h-34"
>
<el-tag
class=
"selection-label m-6 h-22 lh-22 px-8 round-6 color-fff fs-12 border-none"
>
选区
1
</el-tag>
<el-button
class=
"selection-close absolute top-20 right-6 wh-14 p-0 border-none color-fff"
type=
"danger"
circle
>
<el-icon
class=
"fs-10"
>
<Close
/>
</el-icon>
</el-button>
</div>
<div
class=
"empty-state absolute flex-col flex-center text-center"
>
<span
class=
"video-icon flex-center wh-42 round mb-10"
>
<el-icon
class=
"fs-22"
>
<VideoCamera
/>
</el-icon>
</span>
<div
class=
"lh-24"
>
尚未加载工作视频
</div>
<p
class=
"fs-12 lh-20 color-999"
>
请在左侧点击上传视频,以便框选水印或字幕边界
</p>
</div>
</div>
<div
class=
"status-bar flex-between h-38 px-12 mt-16 round-6 fs-12 color-999"
>
<span>
状态:GPU像素缓存区待命
</span>
<span>
分辨率:1920 × 1080px
</span>
</div>
</el-card>
<MediaMaterialDialog
v-model=
"mediaVisible"
v-model:selected=
"selectedMaterials"
/>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
{
Close
,
Plus
,
QuestionFilled
,
UploadFilled
,
VideoCamera
}
from
'@element-plus/icons-vue'
;
import
previewImage
from
'@/static/image/meinv.png'
;
import
MediaMaterialDialog
from
'./MediaMaterialDialog.vue'
;
import
type
{
MaterialItem
,
SceneKey
}
from
'../types'
;
const
mediaVisible
=
ref
(
false
);
const
selectedMaterials
=
ref
<
MaterialItem
[]
>
([]);
</
script
>
<
style
scoped
lang=
"scss"
>
.left-panel
{
flex
:
0
0
40%
;
}
.panel-card
,
.preview-card
,
.guide-card
{
border
:
1px
solid
#dfe7f2
;
}
:deep
(
.el-card__header
)
{
padding
:
16px
16px
10px
;
border-bottom
:
0
;
}
:deep
(
.el-card__body
)
{
padding
:
0
20px
20px
;
}
.upload-area
{
width
:
100%
;
border
:
1px
dashed
#ddd
;
border-radius
:
10px
;
}
:deep
(
.upload-area
.el-upload-dragger
)
{
padding
:
0
;
border-color
:
#d9e4f2
;
border-style
:
dashed
;
background
:
#fbfdff
;
}
.upload-icon
,
.video-icon
{
color
:
#708aaf
;
background
:
#edf3fb
;
}
.watermark-tag
{
border-color
:
rgba
(
var
(
--
main-color
)
,
.1
);
background
:
rgba
(
var
(
--
main-color
)
,
.06
);
}
.guide-card
{
background
:
#f8fbff
;
}
.run-btn
{
background
:
linear-gradient
(
90deg
,
#9d19ff
0%
,
#f23594
100%
);
}
.preview-frame
{
height
:
348px
;
background
:
#eef3f8
;
}
.preview-mask
{
background
:
rgba
(
248
,
250
,
252
,
.68
);
backdrop-filter
:
blur
(
1px
);
}
.selection-box
{
border
:
2px
dashed
#c77dff
;
background
:
rgba
(
199
,
125
,
255
,
.08
);
}
.selection-label
{
background
:
#b45cff
;
}
.selection-close
{
background
:
#ff6b8b
;
}
.empty-state
{
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
}
.video-icon
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
background
:
#fff
;
}
.status-bar
{
border
:
1px
solid
#dfe7f2
;
background
:
#f8fbff
;
}
</
style
>
\ No newline at end of file
apps/web-vue/src/views/quickCreation/components/ToolGroup.vue
View file @
626b653c
...
...
@@ -2,16 +2,16 @@
<section>
<div
class=
"fs-18 lh-28 fw-700 mb-16"
>
电商核心创意工具组
</div>
<div
class=
"tool-grid flex gap-16"
>
<
div
v-for=
"item in tools"
:key=
"item.title"
<
el-card
v-for=
"item in tools"
:key=
"item.title"
class=
"core-card flex-col justify-between flex-1 minh-160 p-16 round-14 bg-fff text-left pointer"
:style=
"
{ '--accent': item.color, '--soft': item.bgColor }">
:style=
"
{ '--accent': item.color, '--soft': item.bgColor }"
shadow="never" @click="handleToolClick(item)"
>
<div>
<span
class=
"core-icon flex-center wh-36 round-10 mb-12 fs-20"
>
<el-icon>
<component
:is=
"item.icon"
/>
</el-icon>
</span>
<div
class=
"lh-22 fw-700"
>
{{
item
.
title
}}
</div>
<div
class=
"
core-title
lh-22 fw-700"
>
{{
item
.
title
}}
</div>
<p
class=
"fs-12 lh-20"
>
{{
item
.
desc
}}
</p>
</div>
<div
class=
"card-action flex-items-center gap-4 fs-12 fw-700"
>
...
...
@@ -20,14 +20,19 @@
<ArrowRight
/>
</el-icon>
</div>
</el-card>
</div>
</div>
<DigitalHumanDialog
v-model=
"digitalHumanVisible"
/>
<ModelTryOnDialog
v-model=
"modelTryOnVisible"
/>
</section>
</
template
>
<
script
setup
lang=
"ts"
>
import
type
{
Component
}
from
'vue'
;
import
{
ref
,
type
Component
}
from
'vue'
;
import
{
useRouter
}
from
'vue-router'
;
import
{
ArrowRight
,
Edit
,
Picture
,
Scissor
,
User
,
ZoomIn
}
from
'@element-plus/icons-vue'
;
import
DigitalHumanDialog
from
'./DigitalHumanDialog.vue'
;
import
ModelTryOnDialog
from
'./ModelTryOnDialog.vue'
;
type
ToolItem
=
{
title
:
string
;
...
...
@@ -36,8 +41,14 @@ type ToolItem = {
color
:
string
;
bgColor
:
string
;
icon
:
Component
;
path
?:
string
;
dialog
?:
'digitalHuman'
|
'modelTryOn'
;
};
const
router
=
useRouter
();
const
digitalHumanVisible
=
ref
(
false
);
const
modelTryOnVisible
=
ref
(
false
);
const
tools
:
ToolItem
[]
=
[
{
title
:
'视频去水印'
,
...
...
@@ -46,6 +57,7 @@ const tools: ToolItem[] = [
color
:
'#ff1f82'
,
bgColor
:
'#fff0f7'
,
icon
:
Edit
,
path
:
'/quickCreation/remove-watermark'
,
},
{
title
:
'字幕擦除'
,
...
...
@@ -54,6 +66,7 @@ const tools: ToolItem[] = [
color
:
'#1877ff'
,
bgColor
:
'#edf5ff'
,
icon
:
Scissor
,
path
:
'/quickCreation/remove-subtitles'
},
{
title
:
'画质增强'
,
...
...
@@ -62,6 +75,7 @@ const tools: ToolItem[] = [
color
:
'#ff9900'
,
bgColor
:
'#fff8e8'
,
icon
:
ZoomIn
,
path
:
'/quickCreation/remove-quality'
,
},
{
title
:
'数字人分身'
,
...
...
@@ -70,6 +84,7 @@ const tools: ToolItem[] = [
color
:
'#f2187d'
,
bgColor
:
'#fff0f7'
,
icon
:
User
,
dialog
:
'digitalHuman'
,
},
{
title
:
'模特换衣'
,
...
...
@@ -78,8 +93,23 @@ const tools: ToolItem[] = [
color
:
'#1877ff'
,
bgColor
:
'#edf5ff'
,
icon
:
Picture
,
dialog
:
'modelTryOn'
,
},
];
const
handleToolClick
=
(
item
:
ToolItem
)
=>
{
if
(
item
.
dialog
===
'digitalHuman'
)
{
digitalHumanVisible
.
value
=
true
;
return
;
}
if
(
item
.
dialog
===
'modelTryOn'
)
{
modelTryOnVisible
.
value
=
true
;
return
;
}
if
(
item
.
path
)
{
router
.
push
(
item
.
path
);
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
@@ -90,7 +120,7 @@ const tools: ToolItem[] = [
transition
:
border-color
.2s
,
box-shadow
.2s
,
transform
.2s
;
}
:deep
(
.core-card
>
span
)
{
:deep
(
.core-card
.el-card__body
)
{
display
:
flex
;
flex
:
1
;
flex-direction
:
column
;
...
...
@@ -98,6 +128,7 @@ const tools: ToolItem[] = [
justify-content
:
space-between
;
width
:
100%
;
height
:
100%
;
padding
:
0
;
}
.core-card
p
,
...
...
@@ -105,6 +136,10 @@ const tools: ToolItem[] = [
color
:
#86a0bd
;
}
.core-title
{
color
:
#001a3d
;
}
.core-icon
{
color
:
var
(
--
accent
);
background
:
var
(
--
soft
);
...
...
@@ -116,7 +151,7 @@ const tools: ToolItem[] = [
transform
:
translateY
(
-2px
);
}
.core-card
:hover
h3
,
.core-card
:hover
.core-title
,
.core-card
:hover
.card-action
{
color
:
var
(
--
accent
);
}
...
...
apps/web-vue/src/views/quickCreation/remove-quality.vue
0 → 100644
View file @
626b653c
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/quickCreation/remove-subtitles.vue
0 → 100644
View file @
626b653c
<
template
>
<div
class=
"h-full over-y-auto p-20 bgmr"
>
<div
class=
"remove-content"
>
<div
class=
"flex-between mb-20"
>
<div>
<div
class=
"fw-600 fs-16 flex-items-center color-000 gap-10"
>
视频字幕擦除
<span
class=
"color-main fs-10 round-4 px-6 py-2 tagssss"
>
SUBTITLE ERASE
</span></div>
<div
class=
"fs-12 color-888 mt-6"
>
一键分析字幕所在底条,智能无痕还原带货视频底部像素
</div>
</div>
<el-button
class=
"h-28 px-8 fs-12"
>
<el-icon>
<BrushFilled
/>
</el-icon>
<span>
新建擦除
</span>
</el-button>
</div>
<RemoveVideo
/>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
BrushFilled
}
from
'@element-plus/icons-vue'
;
import
RemoveVideo
from
'./components/Remove-video.vue'
;
</
script
>
<
style
scoped
lang=
"scss"
>
.remove-content
{
max-width
:
1600px
;
margin
:
auto
;
}
.tagssss
{
background-color
:
rgba
(
var
(
--
main-color
)
,
.04
);
box-shadow
:
0
0
0
1px
rgba
(
var
(
--
main-color
)
,
.1
);
}
.left-panel
{
flex
:
0
0
40%
;
}
.panel-card
,
.preview-card
,
.guide-card
{
border
:
1px
solid
#dfe7f2
;
}
:deep
(
.el-card__header
)
{
padding
:
16px
16px
10px
;
border-bottom
:
0
;
}
:deep
(
.el-card__body
)
{
padding
:
0
20px
20px
;
}
:deep
(
.upload-area
.el-upload
)
{
width
:
100%
;
}
:deep
(
.upload-area
.el-upload-dragger
)
{
padding
:
0
;
border-color
:
#d9e4f2
;
border-style
:
dashed
;
background
:
#fbfdff
;
}
.upload-icon
,
.video-icon
{
color
:
#708aaf
;
background
:
#edf3fb
;
}
.watermark-tag
{
border-color
:
rgba
(
var
(
--
main-color
)
,
.1
);
background
:
rgba
(
var
(
--
main-color
)
,
.06
);
}
.guide-card
{
background
:
#f8fbff
;
}
.run-btn
{
background
:
linear-gradient
(
90deg
,
#9d19ff
0%
,
#f23594
100%
);
}
.preview-frame
{
height
:
348px
;
background
:
#eef3f8
;
}
.preview-mask
{
background
:
rgba
(
248
,
250
,
252
,
.68
);
backdrop-filter
:
blur
(
1px
);
}
.selection-box
{
border
:
2px
dashed
#c77dff
;
background
:
rgba
(
199
,
125
,
255
,
.08
);
}
.selection-label
{
background
:
#b45cff
;
}
.selection-close
{
background
:
#ff6b8b
;
}
.empty-state
{
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
}
.video-icon
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
background
:
#fff
;
}
.status-bar
{
border
:
1px
solid
#dfe7f2
;
background
:
#f8fbff
;
}
</
style
>
apps/web-vue/src/views/quickCreation/remove-watermark.vue
0 → 100644
View file @
626b653c
<
template
>
<div
class=
"h-full over-y-auto p-20 bgmr"
>
<div
class=
"remove-content"
>
<div
class=
"flex-between mb-20"
>
<div>
<div
class=
"fw-600 fs-16 flex-items-center color-000 gap-10"
>
视频去水印
<span
class=
"color-main fs-10 round-4 px-6 py-2 tagssss"
>
WATERMARK REMOVAL
</span></div>
<div
class=
"fs-12 color-888 mt-6"
>
采用多维光流时间轴补全算法,干净擦除顽固角标,动态品牌浮窗与遮挡物
</div>
</div>
<el-button
class=
"h-28 px-8 fs-12"
>
<el-icon>
<BrushFilled
/>
</el-icon>
<span>
新建擦除
</span>
</el-button>
</div>
<RemoveVideo
/>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
BrushFilled
}
from
'@element-plus/icons-vue'
;
import
RemoveVideo
from
'./components/Remove-video.vue'
;
</
script
>
<
style
scoped
lang=
"scss"
>
.remove-content
{
max-width
:
1600px
;
margin
:
auto
;
}
.tagssss
{
background-color
:
rgba
(
var
(
--
main-color
)
,
.04
);
box-shadow
:
0
0
0
1px
rgba
(
var
(
--
main-color
)
,
.1
);
}
</
style
>
apps/web-vue/src/views/quickCreation/types.ts
View file @
626b653c
export
type
SceneKey
=
'product'
|
'pain'
|
'process'
|
'koc'
|
'story'
;
export
type
MaterialItem
=
{
id
:
string
;
name
:
string
;
kind
:
'图片'
|
'视频'
;
size
:
string
;
image
:
string
;
};
apps/web-vue/src/views/resource/components/Item.vue
deleted
100644 → 0
View file @
96e60a33
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment