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
048729dc
Commit
048729dc
authored
Sep 01, 2026
by
黄同智
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
基本完成agent 创作的模块内容
parent
4ebe9c71
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
764 additions
and
23 deletions
+764
-23
index.ts
apps/web-vue/src/router/index.ts
+6
-0
AgentHistoryDrawer.vue
...web-vue/src/views/agent/components/AgentHistoryDrawer.vue
+0
-0
Step1.vue
apps/web-vue/src/views/agent/components/Step1.vue
+269
-0
Step2.vue
apps/web-vue/src/views/agent/components/Step2.vue
+0
-0
Step2SubjectDialog.vue
...web-vue/src/views/agent/components/Step2SubjectDialog.vue
+0
-0
Step3.vue
apps/web-vue/src/views/agent/components/Step3.vue
+0
-0
Step4.vue
apps/web-vue/src/views/agent/components/Step4.vue
+171
-0
index.vue
apps/web-vue/src/views/agent/index.vue
+28
-23
product-video.vue
apps/web-vue/src/views/agent/product-video.vue
+290
-0
No files found.
apps/web-vue/src/router/index.ts
View file @
048729dc
...
...
@@ -82,6 +82,12 @@ const routes = [
name
:
'Agent'
,
component
:
Agent
,
meta
:
{
title
:
'Agent创作'
,
icon
:
'audio'
,
affix
:
true
}
},
{
path
:
'product-video'
,
name
:
'AgentProductVideo'
,
component
:
()
=>
import
(
'@/views/agent/product-video.vue'
),
meta
:
{
title
:
'商品营销视频'
,
hidden
:
true
}
}
]
},
...
...
apps/web-vue/src/views/agent/components/AgentHistoryDrawer.vue
0 → 100644
View file @
048729dc
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/agent/components/Step1.vue
0 → 100644
View file @
048729dc
<
template
>
<main
class=
"flex-1 flex-col"
>
<div
class=
"flex-1 over-y-auto hide-scroll py-20 px-20"
>
<div>
<div
class=
"mb-10"
>
1. 商品参考图
<span
class=
"fs-12 color-888"
>
(上传丰富的参考图有助于提升模型的生成质量)
</span>
</div>
<UploadFile
v-model=
"referenceFiles"
:width=
"104"
:show-file-list=
"false"
/>
</div>
<div
class=
"mt-20"
>
<div
class=
"fw-600"
>
2. 商品详细信息
</div>
<div
class=
"flex gap-12 flex-wrap mt-10"
>
<div
class=
"base-card px-16 py-10 round-10 bg-fff"
>
<div
class=
"mb-10"
>
商品名称
</div>
<el-input
v-model=
"product.name"
class=
"plain-input"
/>
</div>
<div
class=
"base-card px-16 py-10 round-10 bg-fff"
>
<div
class=
"mb-10"
>
商品行业
</div>
<el-input
v-model=
"product.industry"
class=
"plain-input"
/>
</div>
<div
class=
"base-card px-16 py-10 round-10 bg-fff"
>
<div
class=
"mb-10"
>
商品品类
</div>
<el-input
v-model=
"product.category"
class=
"plain-input"
/>
</div>
</div>
<div
class=
"flex flex-wrap gap-12 mt-20"
>
<div
v-for=
"section in productSections"
:key=
"section.key"
class=
"detail-card flex-col p-18 round-10 bg-fff"
:class=
"
{ editing: isSectionEditing(section.key) }">
<div
class=
"flex-between mb-14"
>
<div
class=
"fs-14 fw-600"
>
{{
section
.
title
}}
</div>
<el-icon
class=
"edit-icon pointer"
@
click
.
stop=
"toggleSectionEdit(section.key)"
>
<Check
v-if=
"isSectionEditing(section.key)"
/>
<Edit
v-else
/>
</el-icon>
</div>
<template
v-if=
"isSectionEditing(section.key)"
>
<template
v-if=
"section.items.length"
>
<div
v-for=
"(_, index) in section.items"
:key=
"`$
{section.key}-${index}`"
class="editable-row flex-items-center gap-8 h-34 px-8 mb-6 round-4">
<span
class=
"dot flex-center wh-6 round"
></span>
<el-input
v-model=
"section.items[index]"
class=
"row-input flex-1"
/>
<el-icon
class=
"delete-line color-999 pointer"
@
click=
"removeSectionItem(section.key, index)"
>
<Delete
/>
</el-icon>
</div>
</
template
>
<div
v-else
class=
"fs-14 color-666 mb-12"
>
暂无{{ section.title }}
</div>
<div
class=
"add-row flex-items-center gap-8 mt-8"
>
<el-input
v-model=
"section.draft"
class=
"add-input flex-1"
:placeholder=
"`添加${section.title}`"
@
keyup
.
enter=
"addSectionItem(section.key)"
/>
<el-button
type=
"primary"
class=
"add-btn wh-34 p-0 border-none"
@
click=
"addSectionItem(section.key)"
>
<el-icon>
<Plus
/>
</el-icon>
</el-button>
</div>
</template>
<
template
v-else
>
<div
v-if=
"section.items.length"
class=
"view-list flex-col gap-8"
>
<div
v-for=
"item in section.items"
:key=
"item"
class=
"view-row flex-items-center gap-8 fs-12 lh-22 color-333"
>
<span
class=
"dot flex-center wh-6 round"
></span>
<span>
{{
item
}}
</span>
</div>
</div>
<div
v-else
class=
"fs-14 color-666"
>
暂无
{{
section
.
title
}}
</div>
</
template
>
</div>
</div>
</div>
</div>
<footer
class=
"flex justify-end pt-12 pb-12 pr-20"
style=
"border-top: 1px solid #eee;"
>
<el-button
class=
"fs-12"
>
一键成片
</el-button>
<el-button
type=
"primary"
class=
"fs-12 border-none create-btn"
@
click=
"emit('createRecord')"
>
生成创意与分镜
</el-button>
</footer>
</main>
</template>
<
script
setup
lang=
"ts"
>
import
{
reactive
,
ref
}
from
'vue'
;
import
type
{
UploadUserFile
}
from
'element-plus'
;
import
{
Check
,
Delete
,
Edit
,
Plus
}
from
'@element-plus/icons-vue'
;
import
UploadFile
from
'@/components/Upload/index.vue'
;
type
ProductSection
=
{
key
:
string
;
title
:
string
;
draft
:
string
;
items
:
string
[];
};
const
emit
=
defineEmits
<
{
createRecord
:
[];
}
>
();
const
product
=
reactive
({
name
:
'看看卡萨斯'
,
industry
:
'电商零售'
,
category
:
'待补充具体品类'
,
});
const
referenceFiles
=
ref
<
UploadUserFile
[]
>
([]);
const
editingSectionKeys
=
ref
<
string
[]
>
([]);
const
productSections
=
reactive
<
ProductSection
[]
>
([
{
key
:
'selling'
,
title
:
'商品卖点'
,
draft
:
''
,
items
:
[
'核心功能突出'
,
'使用简单'
,
'效果直观'
,
'适配日常场景'
],
},
{
key
:
'pain'
,
title
:
'商品痛点'
,
draft
:
''
,
items
:
[
'现有产品使用体验不佳'
,
'难以直观看到使用效果'
,
'同类商品选择成本高'
],
},
{
key
:
'target'
,
title
:
'目标人群'
,
draft
:
''
,
items
:
[
'有看看卡萨斯相关使用需求的消费者'
,
'关注实际效果的人群'
,
'重视性价比的用户'
],
},
{
key
:
'scene'
,
title
:
'适用人群和场景'
,
draft
:
''
,
items
:
[
'日常家庭使用'
,
'需要快速解决问题时使用'
,
'购买同类商品前对比选择'
],
},
{
key
:
'spec'
,
title
:
'商品规格'
,
draft
:
''
,
items
:
[
'核心功能配置'
,
'便携易用设计'
,
'适配常见使用环境'
],
},
{
key
:
'discount'
,
title
:
'优惠信息'
,
draft
:
''
,
items
:
[],
},
]);
const
findSection
=
(
key
:
string
)
=>
productSections
.
find
((
section
)
=>
section
.
key
===
key
);
const
isSectionEditing
=
(
key
:
string
)
=>
editingSectionKeys
.
value
.
includes
(
key
);
const
toggleSectionEdit
=
(
key
:
string
)
=>
{
if
(
isSectionEditing
(
key
))
{
editingSectionKeys
.
value
=
editingSectionKeys
.
value
.
filter
((
item
)
=>
item
!==
key
);
return
;
}
editingSectionKeys
.
value
=
[...
editingSectionKeys
.
value
,
key
];
};
const
addSectionItem
=
(
key
:
string
)
=>
{
const
section
=
findSection
(
key
);
const
value
=
section
?.
draft
.
trim
();
if
(
!
section
||
!
value
)
{
return
;
}
section
.
items
.
push
(
value
);
section
.
draft
=
''
;
};
const
removeSectionItem
=
(
key
:
string
,
index
:
number
)
=>
{
const
section
=
findSection
(
key
);
section
?.
items
.
splice
(
index
,
1
);
};
</
script
>
<
style
scoped
lang=
"scss"
>
.base-card
,
.detail-card
{
border
:
1px
solid
#dce6f2
;
}
.base-card
{
flex
:
0
0
calc
((
100%
-
12px
)
/
2
);
&
:hover
{
border-color
:
rgba
(
var
(
--
main-color
)
,
.6
);
}
}
.detail-card
{
flex
:
0
0
calc
((
100%
-
12px
)
/
2
);
min-height
:
158px
;
transition
:
border-color
.2s
,
box-shadow
.2s
;
&
:hover
{
border-color
:
rgba
(
var
(
--
main-color
)
,
.6
);
}
&
.editing
{
border-color
:
#dce6f2
;
}
}
.editable-row
{
background
:
#f8fafc
;
&
:hover
{
background
:
#f3f6fa
;
}
}
.dot
{
flex
:
0
0
6px
;
background
:
#c8d4e3
;
}
.edit-icon
{
color
:
#8aa0bf
;
&
:hover
{
color
:
#7d28ff
;
}
}
.delete-line
{
flex
:
0
0
18px
;
}
.add-row
{
border-top
:
1px
solid
#edf2f7
;
padding-top
:
10px
;
}
.add-btn
,
.create-btn
{
background
:
#7d28ff
;
}
:deep
(
.plain-input
.el-input__wrapper
),
:deep
(
.row-input
.el-input__wrapper
),
:deep
(
.add-input
.el-input__wrapper
)
{
padding
:
0
;
box-shadow
:
none
;
background
:
transparent
;
}
:deep
(
.plain-input
.el-input__inner
)
{
height
:
26px
;
font-size
:
14px
;
color
:
#0a1b34
;
}
:deep
(
.row-input
.el-input__inner
),
:deep
(
.add-input
.el-input__inner
)
{
height
:
30px
;
font-size
:
12px
;
}
:deep
(
.add-input
.el-input__wrapper
)
{
padding
:
0
10px
;
border
:
1px
solid
#dce6f2
;
border-radius
:
4px
;
background
:
#fff
;
}
</
style
>
apps/web-vue/src/views/agent/components/Step2.vue
0 → 100644
View file @
048729dc
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/agent/components/Step2SubjectDialog.vue
0 → 100644
View file @
048729dc
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/agent/components/Step3.vue
0 → 100644
View file @
048729dc
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/agent/components/Step4.vue
0 → 100644
View file @
048729dc
<
template
>
<main
class=
"step4-main flex-1 flex-col hidden"
>
<section
class=
"flex-1 over-y-auto hide-scroll py-20 px-20"
>
<div
class=
"video-list flex flex-wrap gap-18"
>
<div
v-for=
"item in videos"
:key=
"item.id"
class=
"video-card flex-col round-8 hidden bg-fff"
:class=
"
{ active: selectedVideoIds.includes(item.id) }">
<div
class=
"video-cover relative hidden"
>
<img
:src=
"item.cover"
:alt=
"item.name"
class=
"w-full h-full cover"
/>
<el-checkbox
:model-value=
"selectedVideoIds.includes(item.id)"
class=
"select-check absolute top-12 left-12"
@
change=
"toggleVideo(item.id)"
/>
<span
v-if=
"item.recommend"
class=
"recommend-tag absolute top-10 right-10 h-24 lh-24 px-10 round-4 fs-12 fw-700 color-fff"
>
推荐
</span>
<span
class=
"duration-tag absolute right-10 bottom-10 h-24 lh-24 px-8 round-4 fs-12 color-fff"
>
{{
item
.
duration
}}
</span>
</div>
<div
class=
"p-12"
>
<div
class=
"fs-12 fw-700 color-000 lh-18 ellipsis mb-10"
>
{{
item
.
name
}}
</div>
<div
class=
"flex"
>
<el-button
class=
"detail-btn flex-1 h-34 fs-12"
>
<el-icon>
<View
/>
</el-icon>
<span>
详情
</span>
</el-button>
<el-button
class=
"icon-btn wh-34 p-0"
>
<el-icon>
<Upload
/>
</el-icon>
</el-button>
<el-button
class=
"icon-btn wh-34 p-0"
>
<el-icon>
<Download
/>
</el-icon>
</el-button>
</div>
</div>
</div>
</div>
</section>
<footer
class=
"flex-between items-center px-20 py-12"
style=
"border-top: 1px solid #eee;"
>
<div
class=
"flex justify-end"
>
<el-checkbox
v-model=
"isAllSelected"
:indeterminate=
"isIndeterminate"
class=
"fs-12"
>
全选
</el-checkbox>
</div>
<div
class=
"flex-items-center gap-10"
>
<div
class=
"fs-12 color-888 text-right"
>
已选择
<span
class=
"color-main fw-700"
>
{{
selectedVideoIds
.
length
}}
</span>
个视频
</div>
<el-button
type=
"primary"
class=
"fs-12 border-none create-btn"
@
click=
"emit('uploadResource')"
>
上传资源库
</el-button>
</div>
</footer>
</main>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
{
Download
,
Upload
,
View
}
from
'@element-plus/icons-vue'
;
import
productImg
from
'@/static/image/huaban.png'
;
import
peopleImg
from
'@/static/image/meinv.png'
;
type
VideoItem
=
{
id
:
string
;
name
:
string
;
cover
:
string
;
duration
:
string
;
recommend
?:
boolean
;
};
const
emit
=
defineEmits
<
{
uploadResource
:
[];
}
>
();
const
videos
:
VideoItem
[]
=
[
{
id
:
'video-1'
,
name
:
'推荐版_玻璃油膜擦营销成片.mp4'
,
cover
:
productImg
,
duration
:
'00:28'
,
recommend
:
true
,
},
{
id
:
'video-2'
,
name
:
'备选1版_玻璃油膜擦营销成片.mp4'
,
cover
:
peopleImg
,
duration
:
'00:30'
,
},
];
const
selectedVideoIds
=
ref
<
string
[]
>
([
'video-1'
]);
const
isAllSelected
=
computed
({
get
:
()
=>
selectedVideoIds
.
value
.
length
===
videos
.
length
,
set
:
(
value
:
boolean
)
=>
{
selectedVideoIds
.
value
=
value
?
videos
.
map
((
item
)
=>
item
.
id
)
:
[];
},
});
const
isIndeterminate
=
computed
(()
=>
selectedVideoIds
.
value
.
length
>
0
&&
selectedVideoIds
.
value
.
length
<
videos
.
length
);
const
toggleVideo
=
(
id
:
string
)
=>
{
if
(
selectedVideoIds
.
value
.
includes
(
id
))
{
selectedVideoIds
.
value
=
selectedVideoIds
.
value
.
filter
((
item
)
=>
item
!==
id
);
return
;
}
selectedVideoIds
.
value
=
[...
selectedVideoIds
.
value
,
id
];
};
</
script
>
<
style
scoped
lang=
"scss"
>
.step4-main
{
min-width
:
0
;
}
.video-list
{
align-content
:
flex-start
;
}
.video-card
{
flex
:
0
0
260px
;
border
:
1px
solid
#dce6f2
;
transition
:
border-color
.2s
,
box-shadow
.2s
;
&
.active
{
border-color
:
rgba
(
var
(
--
main-color
)
,
1
);
box-shadow
:
0
0
0
1px
rgba
(
var
(
--
main-color
)
,
.35
);
}
}
.video-cover
{
height
:
146px
;
background
:
#f3f6fb
;
}
.recommend-tag
,
.create-btn
{
background
:
#7d28ff
;
}
.duration-tag
{
background
:
rgba
(
18
,
24
,
38
,
.78
);
}
.detail-btn
,
.icon-btn
{
border-color
:
#dce6f2
;
}
:deep
(
.select-check
.el-checkbox__label
)
{
display
:
none
;
}
:deep
(
.select-check
.el-checkbox__inner
)
{
width
:
18px
;
height
:
18px
;
border-radius
:
4px
;
}
:deep
(
.select-check
.el-checkbox__inner
::after
)
{
left
:
8px
;
top
:
7px
;
}
</
style
>
apps/web-vue/src/views/agent/index.vue
View file @
048729dc
...
...
@@ -6,6 +6,14 @@
</el-icon>
<span
class=
"fs-12 fw-600"
>
返回
</span>
</div>
<div
v-else
class=
"fixed top-20 px-10 right-10 flex-items-center gap-6 pointer"
@
click=
"historyDrawerVisible = true"
>
<el-button>
<el-icon
class=
"fs-16"
>
<AlarmClock
/>
</el-icon>
<span
class=
"fs-12 fw-600"
>
历史任务
</span>
</el-button>
</div>
<section
v-if=
"!hasMessages"
>
<div
class=
"mt-60 flex-col items-center"
>
<div
class=
"flex-center wh-44 round-8 color-fff bg-jb"
>
...
...
@@ -19,7 +27,8 @@
<el-input
v-model=
"prompt"
:rows=
"10"
type=
"textarea"
resize=
"none"
placeholder=
"发送给 Agent"
/>
<div
class=
"flex-between pt-16"
>
<AgentPromptTools
/>
<div
class=
"border-eee flex bg-fff round-100 p-6 gap-10 pl-16 minw-110 pointer hoverbth"
@
click=
"hasMessages = true"
>
<div
class=
"border-eee flex bg-fff round-100 p-6 gap-10 pl-16 minw-110 pointer hoverbth"
@
click=
"hasMessages = true"
>
开始创作
<div
class=
"wh-24 color-fff round flex-center bg-jb"
>
<el-icon>
...
...
@@ -31,9 +40,12 @@
</div>
<div
class=
"flex-center mt-16"
>
<div
class=
"flex-center gap-10"
>
<el-button
v-for=
"item in suggestions"
:key=
"item"
class=
"flex-center h-40 px-20 round-100 border-none boxshaw"
@
click=
"applySuggestion(item)"
>
{{
item
}}
<el-button
class=
"flex-center h-40 px-20 round-100 border-none boxshaw"
@
click=
"goProductVideo"
>
用商品拍一条营销视频
</el-button>
<el-button
class=
"flex-center h-40 px-20 round-100 border-none boxshaw"
@
click=
"applySuggestion('参考样片写分镜脚本')"
>
参考样片写分镜脚本
</el-button>
</div>
</div>
...
...
@@ -104,26 +116,25 @@
</div>
</div>
</section>
<AgentHistoryDrawer
v-model=
"historyDrawerVisible"
/>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
nextTick
,
onBeforeUnmount
,
onMounted
,
ref
}
from
'vue'
;
import
type
{
Component
}
from
'vue
'
;
import
{
A
rrowDown
,
Back
,
Box
,
Coin
,
CopyDocument
,
Link
,
MagicStick
,
Position
,
Top
}
from
'@element-plus/icons-vue'
;
import
{
useRouter
}
from
'vue-router
'
;
import
{
A
larmClock
,
ArrowDown
,
Back
,
CopyDocument
,
MagicStick
,
Top
}
from
'@element-plus/icons-vue'
;
import
UploadFile
from
'@/components/Upload/index.vue'
import
AgentHistoryDrawer
from
'./components/AgentHistoryDrawer.vue'
;
import
AgentPromptTools
from
'./components/AgentPromptTools.vue'
;
type
ToolItem
=
{
label
:
string
;
icon
:
Component
;
hasArrow
?:
boolean
;
};
const
prompt
=
ref
(
''
);
const
router
=
useRouter
();
const
submittedTopic
=
ref
(
'美颜'
);
const
messagesCount
=
ref
(
0
);
const
hasMessages
=
ref
(
false
)
const
historyDrawerVisible
=
ref
(
false
);
const
chatScrollRef
=
ref
<
HTMLElement
>
();
const
composerBoxRef
=
ref
<
HTMLElement
>
();
const
isInputFocused
=
ref
(
false
);
...
...
@@ -131,17 +142,6 @@ const isComposerActive = ref(false);
const
isNearBottom
=
ref
(
true
);
const
isComposerCompact
=
computed
(()
=>
!
isNearBottom
.
value
&&
!
isInputFocused
.
value
&&
!
isComposerActive
.
value
);
const
agentControls
:
ToolItem
[]
=
[
{
label
:
'Agent 模式'
,
icon
:
Position
,
hasArrow
:
true
},
{
label
:
'智能模型'
,
icon
:
Coin
},
{
label
:
'生成参数'
,
icon
:
MagicStick
,
hasArrow
:
true
},
{
label
:
'引用'
,
icon
:
Link
},
{
label
:
'使用 Skill'
,
icon
:
Box
},
{
label
:
'优化'
,
icon
:
MagicStick
},
];
const
suggestions
=
[
'用商品拍一条营销视频'
,
'参考样片写分镜脚本'
];
const
sendMessage
=
()
=>
{
const
value
=
prompt
.
value
.
trim
();
submittedTopic
.
value
=
value
||
submittedTopic
.
value
;
...
...
@@ -155,6 +155,10 @@ const applySuggestion = (value: string) => {
sendMessage
();
};
const
goProductVideo
=
()
=>
{
router
.
push
(
'/agent/product-video'
);
};
const
handleChatScroll
=
()
=>
{
if
(
!
chatScrollRef
.
value
)
{
return
;
...
...
@@ -339,4 +343,5 @@ onBeforeUnmount(() => {
opacity
:
1
;
}
}
</
style
>
apps/web-vue/src/views/agent/product-video.vue
0 → 100644
View file @
048729dc
<
template
>
<div
class=
"p-20 vh100 hidden"
>
<el-card
class=
"h-full round-10 content"
shadow=
"never"
>
<template
#
header
>
<div
class=
"flex-items-center"
>
<div
class=
""
>
<span
class=
"fw-600"
>
{{
title
}}
</span>
</div>
<div
class=
"flex-1 flex-center gap-10 mr-100"
>
<div
v-for=
"(item, index) in steps"
:key=
"index"
class=
"flex-items-center gap-10 default"
:class=
"
{ finish: item.stepn
<
currentStep
,
active:
item
.
stepn =
==
currentStep
,
select:
selectStep =
==
item
.
stepn
}"
@
click=
"lookStep(item)"
>
<div
class=
"flex-items-center px-10 py-6 gap-6 round-6 pointer color-888 name"
>
<el-icon>
<component
:is=
"item.icon"
/>
</el-icon>
<span>
{{
item
.
name
}}
</span>
</div>
<div
v-if=
"index
<
steps
.
length-1
"
class=
"w-40 line"
style=
"height: 1px;"
></div>
</div>
</div>
</div>
</
template
>
<div
class=
"flex h-full"
>
<Step1
v-if=
"selectStep === 1"
@
create-record=
"addCreateRecord"
/>
<Step2
v-else-if=
"selectStep === 2"
@
create-preview=
"addPreviewRecord"
/>
<Step3
v-else-if=
"selectStep === 3"
@
create-video=
"addVideoRecord"
/>
<Step4
v-else-if=
"selectStep === 4"
@
upload-resource=
"addUploadRecord"
/>
<div
v-else
class=
"flex-1 flex-center color-888 fs-14"
>
当前步骤内容待生成
</div>
<aside
class=
"record-side flex-col bg-fff"
>
<header
class=
"record-header flex-items-center gap-8 h-48 px-16"
>
<el-icon
class=
"color-main"
>
<ChatDotSquare
/>
</el-icon>
<span
class=
"fs-14 fw-700 color-000"
>
创作记录
</span>
</header>
<div
class=
"flex-1 over-y-auto px-18 py-16"
>
<div
class=
"flex justify-end mb-16"
>
<div
class=
"user-message color-fff fs-12 lh-20 px-16 py-10 round-8"
>
用我的「商品」拍一条营销视频
</div>
</div>
<div
class=
"product-mini flex-items-center gap-12 p-12 round-8 mb-20"
>
<img
:src=
"productImg"
alt=
"看看卡萨斯"
class=
"mini-cover wh-58 round-4 cover"
/>
<div>
<div
class=
"fs-12 fw-700 color-000 mb-6"
>
看看卡萨斯
</div>
<div
class=
"fs-12 color-888"
>
商品 · 共 1 张参考图
</div>
</div>
</div>
<div
class=
"assistant-text fs-12 color-333 lh-22 mb-18"
>
为了帮您制作合适的电商营销视频,请补充具体商品信息,例如商品名称、所属品类、品牌或款式。
</div>
<div
class=
"flex justify-end mb-18"
>
<div
class=
"user-message color-fff fs-12 lh-20 px-16 py-10 round-8"
>
看看卡萨斯
</div>
</div>
<div
class=
"assistant-text fs-12 color-333 lh-22 mb-14"
>
商品信息已确认,正在为您进行需求分析。
</div>
<div
class=
"record-card flex-items-center gap-12 p-12 round-10 mb-20"
>
<el-icon
class=
"color-main fs-18"
>
<Document
/>
</el-icon>
<div>
<div
class=
"fs-12 fw-700 color-000 mb-4"
>
看看卡萨斯
</div>
<div
class=
"fs-10 color-999"
>
查看详情 | 09:12
</div>
</div>
</div>
<
template
v-for=
"item in chatMessages"
:key=
"item.id"
>
<div
class=
"assistant-text fs-12 color-333 lh-22 mb-12"
>
已根据您的要求更新需求分析内容。
</div>
<div
class=
"flex justify-end mb-18"
>
<div
class=
"user-message color-fff fs-12 lh-20 px-16 py-10 round-8"
>
{{
item
.
content
}}
</div>
</div>
</
template
>
</div>
<div
class=
"chat-input-wrap p-12"
>
<div
class=
"chat-input flex-items-center gap-10 p-8 round-8"
>
<el-input
v-model=
"chatInput"
class=
"chat-text flex-1"
type=
"textarea"
resize=
"none"
:rows=
"2"
placeholder=
"卡萨丁卡上课的"
/>
<el-button
type=
"primary"
class=
"send-btn wh-36 p-0 border-none"
@
click=
"sendChatMessage"
>
<el-icon>
<Top
/>
</el-icon>
</el-button>
</div>
</div>
</aside>
</div>
</el-card>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
'vue'
;
import
{
ChatDotSquare
,
Document
,
Edit
,
Top
}
from
'@element-plus/icons-vue'
;
import
productImg
from
'@/static/image/huaban.png'
;
import
Step1
from
'./components/Step1.vue'
;
import
Step2
from
'./components/Step2.vue'
;
import
Step3
from
'./components/Step3.vue'
;
import
Step4
from
'./components/Step4.vue'
;
type
ChatMessage
=
{
id
:
number
;
content
:
string
;
};
const
title
=
ref
(
'商品分析信息'
)
const
currentStep
=
ref
(
4
)
const
selectStep
=
ref
(
1
)
const
steps
=
ref
([
{
name
:
'需求分析'
,
icon
:
Edit
,
stepn
:
1
,
desc
:
'商品分析信息'
},
{
name
:
'创意与分镜'
,
icon
:
Edit
,
stepn
:
2
,
desc
:
'创意与分镜'
},
{
name
:
'视频预览'
,
icon
:
Edit
,
stepn
:
3
,
desc
:
'视频预览'
},
{
name
:
'视频成片'
,
icon
:
Edit
,
stepn
:
4
,
desc
:
'视频成片'
},
])
const
lookStep
=
(
item
:
any
)
=>
{
if
(
currentStep
.
value
<
item
.
stepn
)
return
selectStep
.
value
=
item
.
stepn
title
.
value
=
item
.
desc
}
const
chatMessages
=
ref
<
ChatMessage
[]
>
([
{
id
:
1
,
content
:
'大活动哈师大'
},
{
id
:
2
,
content
:
'大萨达搬还打算大萨达'
},
{
id
:
3
,
content
:
'大萨达马上到凯撒'
},
{
id
:
4
,
content
:
'大萨达久啊圣诞节啊十八大手机登记登记啊萨'
},
{
id
:
5
,
content
:
'流量卡的角度讲撒娇大萨达'
},
]);
const
chatInput
=
ref
(
''
);
const
sendChatMessage
=
()
=>
{
const
value
=
chatInput
.
value
.
trim
();
if
(
!
value
)
{
return
;
}
chatMessages
.
value
.
push
({
id
:
Date
.
now
(),
content
:
value
,
});
chatInput
.
value
=
''
;
};
const
addCreateRecord
=
()
=>
{
currentStep
.
value
=
Math
.
max
(
currentStep
.
value
,
2
);
selectStep
.
value
=
2
;
title
.
value
=
'创意与分镜'
;
chatMessages
.
value
.
push
({
id
:
Date
.
now
(),
content
:
'生成创意与分镜'
,
});
};
const
addPreviewRecord
=
()
=>
{
currentStep
.
value
=
Math
.
max
(
currentStep
.
value
,
3
);
selectStep
.
value
=
3
;
title
.
value
=
'视频预览'
;
chatMessages
.
value
.
push
({
id
:
Date
.
now
(),
content
:
'生成视频预览'
,
});
};
const
addVideoRecord
=
()
=>
{
currentStep
.
value
=
Math
.
max
(
currentStep
.
value
,
4
);
selectStep
.
value
=
4
;
title
.
value
=
'视频成片'
;
chatMessages
.
value
.
push
({
id
:
Date
.
now
(),
content
:
'生成视频成片'
,
});
};
const
addUploadRecord
=
()
=>
{
chatMessages
.
value
.
push
({
id
:
Date
.
now
(),
content
:
'上传资源库'
,
});
};
</
script
>
<
style
scoped
lang=
"scss"
>
.content
{
:deep
(
.el-card__body
)
{
padding
:
0
;
}
}
.default
{
.name
{
&
:hover
{
background-color
:
#eee
;
}
}
.line
{
background
:
#ddd
;
}
&
.finish
{
.name
{
color
:
#01b95d
;
}
.line
{
background
:
#01b95d
;
}
}
&
.active
{
.name
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
.line
{
background
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
&
.select
{
.name
{
color
:
#fff
;
background-color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
.line
{
background
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
}
.backhover
{
&
:hover
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
.record-card
,
.product-mini
{
border
:
1px
solid
#dce6f2
;
}
.send-btn
,
.user-message
{
background
:
#7d28ff
;
}
.record-side
{
flex
:
0
0
30%
;
border-left
:
1px
solid
#dce6f2
;
}
.record-header
{
border-bottom
:
1px
solid
#dce6f2
;
}
.product-mini
{
width
:
250px
;
margin-left
:
auto
;
background
:
#f4f0ff
;
}
.mini-cover
{
background
:
#f8fafc
;
}
.record-card
{
width
:
280px
;
background
:
#fbfdff
;
}
.chat-input-wrap
{
border-top
:
1px
solid
#dce6f2
;
}
.chat-input
{
border
:
1px
solid
#dce6f2
;
background
:
#fbfdff
;
}
:deep
(
.chat-text
.el-textarea__inner
)
{
padding
:
0
;
box-shadow
:
none
;
background
:
transparent
;
}
:deep
(
.chat-text
.el-textarea__inner
)
{
font-size
:
12px
;
}
</
style
>
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