chat对话模块

main
许宏杰 2 months ago
parent 558e9063df
commit 1f202d0efc

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

@ -20,8 +20,8 @@ export enum EditEnum {
export enum PageEnum {
// 登录
BASE_LOGIN = '/login',
BASE_LOGIN_NAME = 'Login',
BASE_LOGIN = '/ai',
BASE_LOGIN_NAME = 'ai',
//重定向
REDIRECT = '/redirect',

@ -8,10 +8,27 @@ import { GoReload } from '@/components/GoReload'
export const LoginRoute: RouteRecordRaw = {
path: PageEnum.BASE_LOGIN,
name: PageEnum.BASE_LOGIN_NAME,
component: () => import('@/views/login/index.vue'),
component: () => import('@/views/AI/index.vue'),
meta: {
title: '登录',
title: 'AI',
},
children: [
{
path: '',
redirect: '/chat'
},
{
path: '/chat',
name: 'chat',
component: () => import('@/views/AI/chat/index.vue'),
},
{
path: '/board',
name: 'board',
component: () => import('@/views/AI/board/index.vue'),
}
]
};
export const HttpErrorPage: RouteRecordRaw[] = [

@ -0,0 +1,12 @@
<template>
<div>
看板
</div>
</template>
<script setup>
</script>
<style scoped>
</style>

@ -0,0 +1,127 @@
<template>
<div class="chat-container">
<div class="chat-list">
<div
v-for="(item, index) in messages"
:key="index"
:class="['chat-item', item.from == 'user' ? 'user-message' : 'ai-message']"
>
<!-- 头像 -->
<img :src="item.from == 'user' ? userIcon : aiIcon" class="user-icon" alt="" />
<!-- 内容 -->
<div class="message-content">
<div class="message-time">{{ item.time }}</div>
<div class="message-text">{{ item.text }}</div>
</div>
</div>
</div>
<n-input
class="chat-input"
round
v-model:value="keyWord"
type="textarea"
placeholder="请输入您的问题"
:autosize="{ minRows: 5 }"
>
<template #suffix>
<div class="chat-suffix">
<span>常用问题</span>
<img src="~@/assets/images/ai/chat-send.png" class="chat-send" alt="" />
</div>
</template>
</n-input>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import userIcon from '@/assets/images/ai/user-icon.png'
import aiIcon from '@/assets/images/ai/ai-icon.png'
let keyWord = ref(null)
let messages = reactive([
{
from: 'user',
text: '根据2024年度系统内所有业务类型签订的合同数据指标生成数据看板根据业务数据生成并且完整展示数据内容用拼图的形式展现图表颜色搭配要协调整体美观',
time: '2025/03/27 14:30:23'
},
{
from: 'ai',
text: '根据用户要求的统计2024年系统每个业务类型产生签订的合同数量并用拼图展示生成的统计图是[此处可插入图表相关展示代码或占位符]',
time: '2025/03/27 14:30:23'
}
])
</script>
<style lang="scss" scoped>
.chat-container {
height: 100%;
gap: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.chat-input {
width: 50%;
}
.chat-suffix {
font-size: 14px;
height: 100%;
display: flex;
align-items: center;
flex-direction: column;
justify-content: space-between;
}
.chat-send {
cursor: pointer;
width: 46px;
height: 30px;
margin-bottom: 10px;
}
.chat-list {
width: 50%;
height: 100%;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 25px;
}
.chat-item {
display: flex;
gap: 6px;
}
.user-icon {
height: 50px;
width: 50px;
}
.user-message {
flex-direction: row-reverse;
.message-content > div {
text-align: right;
}
}
.ai-message {
flex-direction: row;
}
.message-content {
font-size: 14px;
font-weight: 400;
.message-time {
color: #c3cad9;
}
width: calc(100% - 110px);
padding-top: 15px;
.message-text {
color: #ffffff;
font-size: 15px;
margin-top: 10px;
padding: 18px;
background: #282a31;
border-radius: 10px 10px 10px 10px;
}
}
</style>

@ -0,0 +1,12 @@
<template>
<div class="history-list">
</div>
</template>
<script setup>
</script>
<style scoped>
</style>

@ -0,0 +1,27 @@
<template>
<div class="ai-logo">
<img src="~@/assets/images/ai/ai-logo.png" alt="" class="logo-img" />
<span class="logo-title">AI助手</span>
</div>
</template>
<script setup></script>
<style lang="scss" scoped>
.ai-logo {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 50px;
.logo-img {
height: 36px;
width: 36px;
margin-right: 10px;
}
.logo-title {
font-size: 28px;
color: #ffffff;
font-weight: 400;
}
}
</style>

@ -0,0 +1,80 @@
<template>
<div class="ai-container">
<div class="left-menu">
<ai-logo></ai-logo>
<div class="menu-list">
<router-link
class="menu-item flex-box"
active-class="active-link"
:to="item.path"
v-for="(item, index) in menuList"
:key="index"
>
<n-icon size="20">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path
d="M368.5 240H272v-96.5c0-8.8-7.2-16-16-16s-16 7.2-16 16V240h-96.5c-8.8 0-16 7.2-16 16 0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7H240v96.5c0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7 8.8 0 16-7.2 16-16V272h96.5c8.8 0 16-7.2 16-16s-7.2-16-16-16z"
/>
</svg> </n-icon
>新建{{ item.name }}
</router-link>
</div>
<ai-history></ai-history>
</div>
<div class="right-container">
<router-view></router-view>
</div>
</div>
</template>
<script setup>
import AiLogo from '../AI/components/logo/index.vue'
import AiHistory from '../AI/components/history/index.vue'
const menuList = [
{ name: '聊天', path: '/chat' },
{ name: '数据看板', path: '/board' }
]
</script>
<style lang="scss" scoped>
.ai-container {
height: 100vh;
color: #fff;
display: flex;
.left-menu {
width: 12%;
box-sizing: border-box;
padding: 50px 20px;
background: url('../../assets/images/ai/menu-bg.png');
background-size: 100% 100%;
.menu-item {
color: inherit;
text-decoration: none;
cursor: pointer;
height: 38px;
border-radius: 4px 4px 4px 4px;
border: 1px solid #474d59;
margin-bottom: 20px;
letter-spacing: 2px;
font-size: 14px;
}
.active-link , .menu-item:active {
color: #507afc;
border-color: #507afc;
background: rgba(80, 122, 252, 0.2);
}
}
.right-container {
flex: 1;
padding: 20px;
overflow-x: auto;
}
}
.flex-box {
display: flex;
align-items: center;
justify-content: center;
}
</style>
Loading…
Cancel
Save