feat(agent): 重构智能体页面样式和路由配置,优化历史对话组件

This commit is contained in:
林志军
2025-07-25 13:48:49 +08:00
parent 149831ebc9
commit 11579a647a
11 changed files with 607 additions and 218 deletions

View File

@ -1,45 +1,58 @@
<template>
<div>
<div class="logo">
<img :src="cozeInfo?.icon_url" class="agent-img" />
</div>
<a-menu mode="inline" theme="light">
<a-menu-item key="1">
<span class="menu-title">{{ cozeInfo.name }}</span>
<span style="color: #8492ff; font-size: 12px">{{ cozeInfo.type == 1 ? '智能体' : '对话式' }}</span>
<span style="float: right">{{ cozeInfo.views }}次使用</span>
<p>{{ cozeInfo.description }}</p>
</a-menu-item>
<div v-for="(item, index) in conversations" :key="index">
<a-dropdown-button>
<span> {{ item.content }} </span>
<template #content>
<a-doption>重命名</a-doption>
<a-popconfirm
content="确认删除对话吗?删除后,聊天记录将不可恢复。"
@ok="delMessage(item.chat_id, item.conversation_id)"
type="error"
>
<a-button>删除</a-button>
</a-popconfirm>
</template>
</a-dropdown-button>
<div class="agent-card">
<div class="header-section">
<div class="image-container">
<img :src="cozeInfo.icon_url" alt="" />
</div>
</a-menu>
</div>
<div class="info-section">
<div class="title-group">
<div class="title">{{cozeInfo.name}}</div>
<div class="tag">
<div class="">
<img
class="status-icon"
:src="chatbotIcon"
/>
</div>
<div class="text">对话式</div>
</div>
</div>
<div class="usage-info">
<div class="count">{{cozeInfo.views}}</div>
<div class="label">次使用</div>
</div>
</div>
<div class="description-section">
<div class="description">
{{cozeInfo.description}}
</div>
</div>
<div class="divider"></div>
<div class="history-section">
<div class="history-title">
<div class="text">历史对话</div>
</div>
<!-- <div class="history-list">-->
<!-- <div class="history-item">-->
<!-- <div class="item-text">梳理这次舆情的时间线和关键节点</div>-->
<!-- </div>-->
<!-- -->
<!-- </div>-->
</div>
</div>
</template>
<script lang="ts" setup>
import { defineProps } from 'vue';
import { delAgentMessage, getHistoryChat } from '@/api/all/agent';
import chatbotIcon from '@/assets/svg/chatbot.svg';
const props = defineProps({
cozeInfo: {
type: Object as () => any,
default: () => ({}),
}
},
});
const delMessage = async (chatId, conversationId) => {
@ -63,27 +76,9 @@ const truncateText = (text: string, maxLength = 30) => {
};
onMounted(() => {
getHistoryChatData(props.cozeInfo.bot_id);
});
</script>
<style scoped>
.logo {
margin-bottom: 20px;
}
.menu-title {
color: var(--Text-1, #211f24);
font-size: 18px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 26px;
word-wrap: break-word;
}
.agent-img {
width: 100%;
height: 230px;
border-radius: 4px;
}
@import './history.scss';
</style>

View File

@ -0,0 +1,227 @@
.agent-card {
width: 100%;
height: 100%;
background: var(--BG-100, #F7F8FA);
overflow: hidden;
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
.header-section {
align-self: stretch;
height: 160px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
.image-container {
align-self: stretch;
flex: 1 1 0;
position: relative;
background: #FFEDED;
overflow: hidden;
border-radius: 8px;
img {
width: 408.14px;
height: 219px;
left: -24.07px;
top: -29px;
position: absolute;
}
}
}
.info-section {
align-self: stretch;
padding-top: 15px;
padding-bottom: 15px;
display: flex;
justify-content: space-between;
align-items: flex-start;
.title-group {
display: flex;
justify-content: flex-start;
align-items: center;
gap: 4px;
.title {
color: var(--Text-1, #211F24);
font-size: 18px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 26px;
}
.tag {
height: 20px;
padding: 0 8px;
background: var(--Brand-1, #F0EDFF);
border-radius: 2px;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 4px;
.icon {
width: 12px;
height: 12px;
position: relative;
&::before {
content: '';
width: 10.74px;
height: 10.50px;
left: 0.63px;
top: 0.75px;
position: absolute;
background: var(--Brand-6, #6D4CFE);
}
}
.text {
color: var(--Brand-6, #6D4CFE);
font-size: 12px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 20px;
}
}
}
.usage-info {
width: 79px;
height: 24px;
position: relative;
.count {
left: 0px;
top: 0px;
position: absolute;
color: var(--Text-2, #3C4043);
font-size: 16px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 24px;
}
.label {
left: 43px;
top: 3px;
position: absolute;
color: var(--Text-3, #737478);
font-size: 12px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 20px;
}
}
}
.description-section {
align-self: stretch;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
gap: 10px;
.description {
align-self: stretch;
color: var(--Text-2, #3C4043);
font-size: 14px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 22px;
}
}
.divider {
align-self: stretch;
height: 0px;
outline: 1px var(--Border-2, #E6E6E8) solid;
outline-offset: -0.50px;
}
.history-section {
align-self: stretch;
flex: 1 1 0;
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
.history-title {
align-self: stretch;
height: 40px;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 10px;
.text {
color: var(--Text-3, #737478);
font-size: 14px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 22px;
}
}
.history-list {
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
.history-item {
align-self: stretch;
height: 40px;
padding: 8px;
border-radius: 8px;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 10px;
.item-text {
flex: 1 1 0;
color: var(--Text-1, #211F24);
font-size: 14px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 22px;
}
}
}
.scroll-indicator {
width: 8px;
height: 240px;
padding: 8px 1px;
position: absolute;
left: 362px;
top: 40px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
gap: 10px;
.indicator-bar {
flex: 1 1 0;
height: 80px;
background: var(--BG-600, #939499);
border-radius: 4px;
}
}
}
}

View File

@ -24,15 +24,23 @@
<div class="card-title">{{ product?.name }}</div>
<div class="card-description">{{ product?.description }}</div>
</div>
<div class="card-footer">
<div :class="['tag', { red: product?.type === 1, blue: product?.type === 2 }]">
<div :class="['tag-text', { red: product?.type === 1, blue: product?.type === 2 }]">
{{ product?.type == 1 ? '对话式' : '工作流' }}
</div>
<div
:class="['status-tag', product.type === 1 ? 'blue-tag' : 'red-tag']"
:style="{ background: product.type === 1 ? 'var(--Functional-Blue-1, #E6F3FF)' : 'var(--Functional-Red-1, #FFE9E7)' }"
data-size="mini-20px"
>
<img
class="status-icon"
:src="product.type === 2 ? workflowIcon : chatbotIcon"
alt="状态图标"
/>
<div class="status-text">{{ product.type === 1 ? '对话式' : '工作流' }}</div>
</div>
<div class="usage-info">
<span class="usage-count">{{ product?.views }}</span>
<span class="usage-label">次使用</span>
<div class="usage-count">{{ product.views }}</div>
<div class="usage-label">次使用</div>
</div>
</div>
</div>
@ -47,7 +55,8 @@
<script setup lang="ts">
import { useRouter } from 'vue-router';
import { getAgentList } from '@/api/all/agent';
import workflowIcon from '@/assets/svg/workflow.svg';
import chatbotIcon from '@/assets/svg/chatbot.svg';
const router = useRouter();
const list = ref([]);

View File

@ -77,76 +77,6 @@
line-height: 22px;
word-wrap: break-word;
}
.card-footer {
align-self: stretch;
display: inline-flex;
justify-content: space-between;
align-items: center;
}
.tag {
display: flex;
align-items: center;
gap: 4px;
height: 20px;
padding: 0 8px;
border-radius: 2px;
&.red {
color: var(--Functional-Red-6, #f64b31);
}
&.blue {
color: var(--Functional-Blue-6, #3366ff);
}
}
.tag-icon {
width: 12px;
height: 12px;
position: relative;
&::before {
content: '';
position: absolute;
width: 11.5px;
height: 10.75px;
left: 0.25px;
top: 0.63px;
background: var(--Functional-Red-6, #f64b31);
}
}
.tag-text {
font-size: 12px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 20px;
word-wrap: break-word;
&.red {
color: var(--Functional-Red-6, #f64b31);
}
&.blue {
color: var(--Functional-Blue-6, #3366ff);
}
}
.usage-info {
display: flex;
align-items: center;
gap: 2px;
color: var(--Text-3, #737478);
font-size: 12px;
font-family: HarmonyOS Sans SC, Alibaba PuHuiTi;
font-weight: 400;
line-height: 20px;
}
:deep(.arco-input-wrapper) {
border-radius: 4px;
border-color: #d7d7d9;
@ -166,4 +96,62 @@
}
}
.card-footer {
width: 100%;
height: 100%;
display: inline-flex;
justify-content: space-between;
align-items: center;
.status-tag {
height: 20px;
padding: 0 8px;
border-radius: 2px;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 4px;
.status-icon {
width: 12px;
height: 12px;
}
.status-text {
font-size: 12px;
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 400;
line-height: 20px;
}
}
.blue-tag {
.status-text {
color: var(--Functional-Blue-6, #007BFF);
}
}
.red-tag {
.status-text {
color: var(--Functional-Red-6, #F64B31);
}
}
.usage-info {
display: flex;
justify-content: flex-start;
align-items: center;
gap: 2px;
.usage-count,
.usage-label {
color: var(--Text-3, #737478);
font-size: 12px;
font-family: 'HarmonyOS Sans SC', sans-serif;
font-weight: 400;
line-height: 20px;
}
}
}
}

View File

@ -1,21 +1,35 @@
<template>
<a-layout-sider width="250" style="background: #fff">
<div class="logo">
<img :src="cozeInfo?.icon_url" class="agent-img" />
<div class="container">
<div class="header-image-container">
<div class="header-image">
<img :src="cozeInfo?.icon_url" alt="Header Image" />
</div>
</div>
<div class="title-container">
<div class="title">{{cozeInfo?.name}}</div>
<div class="tag">
<div class="">
<img
class="status-icon"
:src="workflow"
/>
</div>
<div class="tag-text">工作流</div>
</div>
<div class="usage-stats">
<div class="usage-count">{{cozeInfo?.views}}</div>
<div class="usage-label">次使用</div>
</div>
</div>
<div class="description">
{{cozeInfo?.description}}
</div>
<a-menu mode="inline" theme="light">
<a-menu-item key="1">
<span>{{ cozeInfo.name }}</span>
<span style="color: #8492ff; font-size: 12px">{{ cozeInfo.type == 1 ? '智能体' : '对话式' }}</span>
<span style="float: right">{{ cozeInfo.views }}次使用 </span>
</a-menu-item>
</a-menu>
</a-layout-sider>
</div>
</template>
<script lang="ts" setup>
import { defineProps } from 'vue';
import workflow from '@/assets/svg/workflow.svg';
const props = defineProps({
cozeInfo: {
@ -33,13 +47,5 @@ onMounted(() => {
</script>
<style scoped>
.logo {
margin-bottom: 20px;
}
.agent-img {
width: 100%;
height: 260px;
border-radius: 4px;
}
@import "./history.scss";
</style>

View File

@ -0,0 +1,198 @@
.container {
width: 100%;
height: 100%;
background: var(--BG-100, #F7F8FA);
overflow: hidden;
border-radius: 8px;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
display: inline-flex;
}
.header-image-container {
align-self: stretch;
height: 160px;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
display: flex;
}
.header-image {
align-self: stretch;
flex: 1 1 0;
position: relative;
background: #FFEDED;
overflow: hidden;
border-radius: 8px;
}
.header-image img {
width: 408.90px;
height: 218px;
left: -24.45px;
top: -29px;
position: absolute;
}
.title-container {
align-self: stretch;
padding-top: 15px;
padding-bottom: 15px;
justify-content: space-between;
align-items: flex-start;
display: inline-flex;
}
.title {
justify-content: center;
display: flex;
flex-direction: column;
color: var(--Text-1, #211F24);
font-size: 18px;
padding: 5px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 26px;
word-wrap: break-word;
}
.tag {
height: 20px;
padding-left: 8px;
padding-right: 8px;
background: var(--Functional-Red-1, #FFE9E7);
overflow: hidden;
border-radius: 2px;
justify-content: flex-start;
align-items: center;
gap: 4px;
display: flex;
}
.tag-icon {
width: 12px;
height: 12px;
position: relative;
}
.tag-icon-inner {
width: 11.50px;
height: 10.75px;
left: 0.25px;
top: 0.63px;
position: absolute;
background: var(--Functional-Red-6, #F64B31);
}
.tag-text {
color: var(--Functional-Red-6, #F64B31);
font-size: 12px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 20px;
word-wrap: break-word;
}
.usage-stats {
width: 79px;
height: 24px;
position: relative;
}
.usage-count {
left: 0px;
top: 0px;
position: absolute;
color: var(--Text-2, #3C4043);
font-size: 16px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 24px;
word-wrap: break-word;
}
.usage-label {
left: 43px;
top: 3px;
position: absolute;
color: var(--Text-3, #737478);
font-size: 12px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 20px;
word-wrap: break-word;
}
.description {
align-self: stretch;
color: var(--Text-2, #3C4043);
font-size: 14px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 22px;
word-wrap: break-word;
padding-inline: 5px;
}
.divider {
align-self: stretch;
height: 0px;
outline: 1px var(--Border-2, #E6E6E8) solid;
outline-offset: -0.50px;
}
.history-title {
color: var(--Text-3, #737478);
font-size: 14px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 22px;
word-wrap: break-word;
}
.history-item {
align-self: stretch;
height: 40px;
padding: 8px;
border-radius: 8px;
justify-content: flex-start;
align-items: center;
gap: 10px;
display: inline-flex;
}
.history-item-text {
flex: 1 1 0;
color: var(--Text-1, #211F24);
font-size: 14px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
line-height: 22px;
word-wrap: break-word;
}
.scroll-indicator {
width: 8px;
height: 240px;
padding-left: 1px;
padding-right: 1px;
padding-top: 8px;
padding-bottom: 8px;
left: 362px;
top: 40px;
position: absolute;
justify-content: flex-start;
align-items: flex-start;
gap: 10px;
display: inline-flex;
}
.scroll-indicator-bar {
flex: 1 1 0;
height: 80px;
background: var(--BG-600, #939499);
border-radius: 4px;
}

View File

@ -5,7 +5,7 @@
<div class="chat-contain">
<a-layout>
<a-layout>
<a-layout-sider width="20%">
<a-layout-sider width="15%">
<HistoryChat :cozeInfo="cozeInfo" />
</a-layout-sider>
<a-layout-sider class="layout-sider" width="17%">
@ -24,7 +24,7 @@
<script setup>
import { ref, reactive } from 'vue';
import HistoryChat from './components/historyChat.vue';
import HistoryChat from './components/HistoryChat.vue';
import DynamicForm from './components/DynamicForm.vue';
import { executeWorkFlow, getWorkFlowInfo } from '@/api/all/agent';
import { useRoute, useRouter } from 'vue-router';