Commit a1f3aea0 authored by 黄同智's avatar 黄同智

agent页面,发起对话,对话详情

parent 6919af5a
......@@ -86,7 +86,7 @@ const menus = [
},
{
name: 'Agent创作',
path: '/',
path: '/agent',
icon: 'audio',
},
{
......
......@@ -10,6 +10,7 @@ import ThreeD from '@/views/vue-flow/3d.vue'
import Layout from '@/layout/index.vue'
import Task from '@/views/task/index.vue'
import QuickCreation from '@/views/quickCreation/index.vue'
import Agent from '@/views/agent/index.vue'
const routes = [
{
......@@ -73,6 +74,18 @@ const routes = [
]
},
{
path: '/agent',
component: Layout,
children: [
{
path: '',
name: 'Agent',
component: Agent,
meta: { title: 'Agent创作', icon: 'audio', affix: true }
}
]
},
{
path: '/zhibo',
component: Layout,
children: [
......
<template>
<div class="h-full bgmr relative hidden">
<section v-if="hasMessages">
<div class="mt-60 flex-col items-center">
<div class="flex-center wh-44 round-8 color-fff bg-jb">
<el-icon class="fs-24">
<MagicStick />
</el-icon>
</div>
<div class="fs-26 lh-42 fw-700 color-000 mt-18">想做什么视频?</div>
</div>
<div class="flex-col bg-fff round-16 model2 p-20 boxshaw">
<el-input v-model="prompt" :rows="10" type="textarea" resize="none" placeholder="发送给 Agent" />
<div class="flex-between pt-16">
<div class="flex-items-center flex-wrap">
<el-popover placement="top-start" :width="150" trigger="hover">
<template #reference>
<el-button class="m-2 h-30 border-none px-6">
<el-icon>
<component :is="Box" />
</el-icon>
<span>商品</span>
</el-button>
</template>
<div>
<div class="flex-items-center gap-6 h-30 border-none pointer hover">
<el-icon>
<component :is="Link" />
</el-icon>
<span>输入商品信息</span>
</div>
<div class="flex-items-center gap-6 h-30 border-none pointer hover">
<el-icon>
<component :is="Link" />
</el-icon>
<span>添加商品图</span>
</div>
</div>
</el-popover>
<el-popover placement="top-start" :width="150" trigger="hover">
<template #reference>
<el-button class="m-2 h-30 border-none px-6">
<el-icon>
<component :is="VideoCamera" />
</el-icon>
<span>参考</span>
</el-button>
</template>
<div>
<div class="flex-items-center gap-6 h-30 border-none pointer hover">
<el-icon>
<component :is="Clock" />
</el-icon>
<span>历史投放素材</span>
</div>
<div class="flex-items-center gap-6 h-30 border-none pointer hover">
<el-icon>
<component :is="Upload" />
</el-icon>
<span>本地上传</span>
</div>
</div>
</el-popover>
<el-popover placement="top-start" :width="120" trigger="hover" popper-class="xxx">
<template #reference>
<el-button class="m-2 h-30 border-none px-6">
<el-icon>
<component :is="Document" />
</el-icon>
<span>脚本/原料</span>
</el-button>
</template>
<div>
<div class="flex-items-center gap-6 h-30 border-none pointer hover">
<el-icon>
<component :is="Document" />
</el-icon>
<span>添加脚本</span>
</div>
<div class="flex-items-center gap-6 h-30 border-none pointer hover">
<el-icon>
<component :is="Film" />
</el-icon>
<span>添加原料</span>
</div>
</div>
</el-popover>
<el-button class="flex-center gap-6 h-30 border-none px-6">
<el-icon>
<component :is="Setting" />
</el-icon>
<span>45秒 · 9:16</span>
</el-button>
<el-button class="flex-center gap-6 h-30 border-none px-6">
<el-icon>
<component :is="Position" />
</el-icon>
<span>风格</span>
</el-button>
</div>
<div class="border-eee flex bg-fff round-100 p-6 gap-10 pl-16 minw-110 pointer hoverbth">
开始创作
<div class="wh-24 color-fff round flex-center bg-jb">
<el-icon>
<Top />
</el-icon>
</div>
</div>
</div>
</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>
</div>
</div>
</section>
<section v-else class="h-full flex-col">
<div ref="chatScrollRef" class="flex-1 over-y-auto pb-200 hide-scroll" @scroll="handleChatScroll">
<div class="chat-inner">
<div v-for="value in 10">
<div class="flex justify-end mt-20">
<div class="flex-col items-end">
<div class="flex-items-center gap-10">
<div class="user-bubble h-46 px-20 flex-center round-14 fw-700 color-000">
{{ submittedTopic }}
</div>
<span class="avatar flex-center wh-32 round color-fff fs-12 fw-700">AD</span>
</div>
<div class="flex-items-center gap-6 mt-8 fs-12 color-888">
<span>今天 09:27</span>
<el-icon>
<CopyDocument />
</el-icon>
</div>
</div>
</div>
<div class="mt-40 flex-items-center gap-20">
<span class="flex-center wh-46 round border-eee bg-fff">
<el-icon class="status-icon fs-24">
<MagicStick />
</el-icon>
</span>
<span class="color-999">Agent 任务已取消。</span>
</div>
</div>
</div>
</div>
<div class="chat-composer-wrap absolute left-0 right-0 bottom-20"
:class="{ 'is-compact': isComposerCompact }">
<div v-if="isComposerCompact" class="flex-center mb-8">
<el-button class="back-bottom h-34 px-18 round-8 bg-fff fs-12" @click="scrollToBottom">
<el-icon>
<ArrowDown />
</el-icon>
<span>回到底部</span>
</el-button>
</div>
<div class="composer-box flex-col bg-fff round-16 border-eee boxshaw">
<div class="input-row flex gap-20 px-14 pt-14">
<UploadFile :width="isComposerCompact ? 40 : 44" />
<el-input v-model="prompt" class="flex-1 boxno" type="textarea" resize="none" :rows="3"
:placeholder="isComposerCompact ? '输入你的创作想法' : '输入你的创作想法、脚本或画面要求'"
@focus="handleInputFocus" @blur="handleInputBlur" />
</div>
<div class="composer-actions flex-between px-14">
<div class="flex-items-center flex-wrap">
<el-button v-for="item in agentControls" :key="item.label"
class="flex-center gap-6 h-32 px-12 fs-12 round-6">
<el-icon>
<component :is="item.icon" />
</el-icon>
<span>{{ item.label }}</span>
<el-icon v-if="item.hasArrow">
<ArrowDown />
</el-icon>
</el-button>
</div>
<div class="send-btn flex-center wh-40 p-0 color-fff pointer border-none round fs-20 mb-10 bg-jb"
@click="sendMessage">
<el-icon>
<Top />
</el-icon>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import { computed, nextTick, onMounted, ref } from 'vue';
import type { Component } from 'vue';
import { ArrowDown, Box, Coin, CopyDocument, Document, Link, MagicStick, Position, Setting, Top, VideoCamera, Clock, Upload, Film } from '@element-plus/icons-vue';
import UploadFile from '@/components/Upload/index.vue'
type ToolItem = {
label: string;
icon: Component;
hasArrow?: boolean;
};
const prompt = ref('');
const submittedTopic = ref('美颜');
const messagesCount = ref(0);
const hasMessages = computed(() => messagesCount.value > 0);
const chatScrollRef = ref<HTMLElement>();
const isInputFocused = ref(false);
const isNearBottom = ref(true);
const isComposerCompact = computed(() => !isNearBottom.value && !isInputFocused.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;
messagesCount.value = 1;
prompt.value = '';
nextTick(scrollToBottom);
};
const applySuggestion = (value: string) => {
prompt.value = value;
sendMessage();
};
const handleChatScroll = () => {
if (!chatScrollRef.value) {
return;
}
const { scrollHeight, scrollTop, clientHeight } = chatScrollRef.value;
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
isNearBottom.value = distanceToBottom < 60;
};
const scrollToBottom = () => {
if (!chatScrollRef.value) {
return;
}
isNearBottom.value = true;
chatScrollRef.value.scrollTo({
top: chatScrollRef.value.scrollHeight,
behavior: 'smooth',
});
};
const handleInputFocus = () => {
isInputFocused.value = true;
};
const handleInputBlur = () => {
isInputFocused.value = false;
nextTick(handleChatScroll);
};
onMounted(() => {
nextTick(handleChatScroll);
});
</script>
<style scoped lang="scss">
.bg-jb {
background: linear-gradient(135deg, #7b33ff 0%, #9d19ff 100%);
}
.model2 {
margin: 26px 15%;
:deep(.el-textarea__inner) {
border: none;
box-shadow: none;
background-color: #f8f8fa;
border-radius: 12px;
}
}
.hover {
&:hover {
color: rgba(var(--main-color), 0.8);
}
}
.boxshaw {
box-shadow: 0 0 10px #00000009;
&:hover {
box-shadow: 0 0 16px #00000016;
}
}
.hoverbth {
&:hover {
box-shadow: 0 0 0 1px rgba(var(--main-color), 0.6);
}
}
.chat-inner {
max-width: 1100px;
min-height: 520px;
margin: auto;
}
.user-bubble {
background-color: rgba(var(--main-color), 0.1);
}
.avatar {
background-color: #7b33ff;
}
.chat-composer-wrap {
width: 1100px;
margin: auto;
transition: width .24s ease, transform .24s ease;
}
.boxno {
:deep(.el-textarea__inner) {
box-shadow: none;
transition: min-height .24s ease, padding .24s ease;
}
}
.composer-box {
transition: border-radius .24s ease, box-shadow .24s ease;
}
.input-row {
transition: padding .24s ease, gap .24s ease;
}
.composer-actions {
transition: opacity .2s ease, padding .24s ease;
}
.compact-tools {
display: none;
}
.back-bottom {
border-color: #dfe7f2;
box-shadow: 0 2px 10px rgba(20, 38, 70, .1);
}
.chat-composer-wrap.is-compact .composer-box {
flex-direction: row;
align-items: center;
border-radius: 18px;
}
.chat-composer-wrap.is-compact .input-row {
flex: 1;
align-items: center;
gap: 16px;
padding: 8px 0 8px 14px;
}
.chat-composer-wrap.is-compact .boxno {
:deep(.el-textarea__inner) {
min-height: 36px !important;
height: 36px !important;
padding: 8px 0;
overflow: hidden;
}
}
.chat-composer-wrap.is-compact .composer-actions {
flex: 0 0 auto;
padding: 0 8px 0 0;
}
.chat-composer-wrap.is-compact .composer-actions > .flex-items-center:first-child {
display: none;
}
.chat-composer-wrap.is-compact .compact-tools {
display: flex;
}
.chat-composer-wrap.is-compact .send-btn {
width: 44px;
height: 44px;
margin-bottom: 0;
color: #9aaac0;
background: #e8eef6;
}
.chat-composer-wrap.is-compact .send-btn.bg-jb {
background: #e8eef6;
}
.send-btn {
opacity: 0.8;
&:hover {
opacity: 1;
}
}
</style>
<style>
.xxx {
min-width: 120px !important;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment