feature/zoujing #4
@@ -2,6 +2,14 @@
|
||||
<!-- 页面根 -->
|
||||
<div class="h-full overflow-hidden flex flex-col">
|
||||
|
||||
<div class="border-box px-6 pt-40 pb-6 ">
|
||||
<h1 class="text-[28px] font-bold mb-7 leading-tight">
|
||||
你好,<br />
|
||||
我今天能帮你什么?
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 消息列表(唯一滚动区) -->
|
||||
<div ref="listRef" class="flex-1 overflow-y-auto px-6 py-6 space-y-6">
|
||||
<div v-for="msg in chatMsgList" :key="msg.messageId" class="flex items-start gap-3"
|
||||
@@ -50,31 +58,18 @@
|
||||
智能问数
|
||||
</div>
|
||||
|
||||
<div class="h-[174px] bg-white rounded-lg border border-[#eef2f6]
|
||||
shadow-[0_1px_0_rgba(0,0,0,0.03)]
|
||||
p-[18px] mt-[8px] flex flex-col justify-between">
|
||||
<textarea rows="2" placeholder="给我发布或者布置任务" class="flex-1 resize-none outline-none text-sm"
|
||||
v-model="inputMessage" @keydown.enter="handleKeydownEnter" />
|
||||
<ChatInputArea v-model="inputMessage" :isSendingMessage="isSendingMessage" @send="sendMessageAction"
|
||||
@attach="addAttachmentAction" />
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-end">
|
||||
<button @click="addAttachmentAction()">
|
||||
<RiLink />
|
||||
</button>
|
||||
<button class="w-[48px] h-[48px] bg-[#F5F7FA] px-2.5 py-1.5 rounded-md flex items-center justify-center"
|
||||
@click="sendMessageAction()">
|
||||
<RiStopFill v-if="isSendingMessage" />
|
||||
<RiSendPlaneFill v-else />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 任务中心 -->
|
||||
<TaskCenter />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { RiLink, RiSendPlaneFill, RiStopFill } from '@remixicon/vue'
|
||||
import { onMounted, nextTick, onUnmounted } from "vue";
|
||||
import { WebSocketManager } from "@common/WebSocketManager";
|
||||
import { MessageRole, ChatMessage } from "./model/ChatModel";
|
||||
@@ -86,12 +81,17 @@ import ChatRoleMe from './components/ChatRoleMe.vue';
|
||||
import ChatAIMark from './components/ChatAIMark.vue';
|
||||
import ChatNameTime from './components/ChatNameTime.vue';
|
||||
import ChatAttach from './components/ChatAttach.vue';
|
||||
import ChatInputArea from './components/ChatInputArea.vue';
|
||||
import TaskCenter from './TaskCenter.vue';
|
||||
|
||||
import { Session } from '../../utils/storage';
|
||||
|
||||
import userAvatar from '@assets/images/login/user_icon.png';
|
||||
import aiAvatar from '@assets/images/login/blue_logo.png';
|
||||
|
||||
/// 是否是引导页
|
||||
const isGuidePage = ref(true);
|
||||
|
||||
// 列表滚动容器引用
|
||||
const listRef = ref<HTMLElement | null>(null);
|
||||
|
||||
@@ -217,16 +217,6 @@ const sendMessageAction = () => {
|
||||
setTimeoutScrollToBottom();
|
||||
};
|
||||
|
||||
// 处理在 textarea 中按 Enter:Shift+Enter 保留换行,单按 Enter 发送并阻止默认换行行为
|
||||
const handleKeydownEnter = (e: KeyboardEvent) => {
|
||||
if ((e as KeyboardEvent).shiftKey) {
|
||||
// 允许插入换行
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
sendMessageAction();
|
||||
};
|
||||
|
||||
// 停止发送消息事件
|
||||
const sendStopAction = () => {
|
||||
console.log("停止发送消息");
|
||||
|
||||
@@ -3,71 +3,41 @@
|
||||
<div class="h-full overflow-y-auto">
|
||||
|
||||
<!-- Hero:吸顶 -->
|
||||
<div class="bg-white border-box px-12 pt-10 pb-6 max-[800px]:px-5">
|
||||
<div class="bg-white border-box px-6 pt-40 pb-6 max-[800px]:px-5">
|
||||
<h1 class="text-[28px] font-bold mb-7 leading-tight">
|
||||
你好,<br />
|
||||
我今天能帮你什么?
|
||||
</h1>
|
||||
|
||||
<!-- input -->
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-col mt-20 gap-3">
|
||||
<div class="inline-flex items-center justify-center w-[108px]
|
||||
px-3 py-1.5 rounded-2xl border border-[#E5E8EE]
|
||||
text-[13px] text-[#333]">
|
||||
智能问数
|
||||
</div>
|
||||
|
||||
<div class="h-[174px] bg-white rounded-lg border border-[#eef2f6]
|
||||
shadow-[0_1px_0_rgba(0,0,0,0.03)]
|
||||
p-[18px] flex flex-col justify-between">
|
||||
<div class="text-[#bfc9d4]">
|
||||
给我发布或者布置任务
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<button class="text-[#9fb0c4]">🔗</button>
|
||||
<button class="bg-[#f1f6fb] px-2.5 py-1.5 rounded-md">
|
||||
✈
|
||||
</button>
|
||||
<ChatInputArea v-model="inputMessage" @send="sendMessageAction" @attach="addAttachmentAction" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- header -->
|
||||
<div class="flex justify-between items-center mt-4">
|
||||
<h3 class="text-base font-semibold">任务中心</h3>
|
||||
<a class="text-[#3b82f6] text-[13px] cursor-pointer">
|
||||
编辑
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区 -->
|
||||
<div class="flex-1 px-12 pb-10 pt-4 max-[800px]:px-5">
|
||||
<div class="grid grid-cols-2 gap-4 max-[800px]:grid-cols-1">
|
||||
<div v-for="n in 14" :key="n" class="flex gap-3 items-start p-3.5
|
||||
rounded-[10px] border border-[#dfeaf6] bg-white">
|
||||
<div class="w-11 h-11 bg-[#EFF6FF] rounded-lg
|
||||
border border-dashed border-[#9fc0e8]
|
||||
flex items-center justify-center
|
||||
text-[#3b82f6] text-[23px]">
|
||||
销
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="font-semibold">
|
||||
每日销售数据
|
||||
</div>
|
||||
<div class="text-[#9aa5b1] text-[13px] mt-1.5">
|
||||
分析用于销售渠道每日数据汇总及简要展示
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<TaskCenter />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ChatInputArea from './components/ChatInputArea.vue';
|
||||
import TaskCenter from './TaskCenter.vue';
|
||||
import { ref } from 'vue';
|
||||
const inputMessage = ref<string>('');
|
||||
const sendMessageAction = () => {
|
||||
console.log('发送消息:', inputMessage.value);
|
||||
// 这里可以添加发送消息的逻辑
|
||||
};
|
||||
const addAttachmentAction = () => {
|
||||
console.log('添加附件');
|
||||
// 这里可以添加附件的逻辑
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
31
src/renderer/views/home/TaskCenter.vue
Normal file
31
src/renderer/views/home/TaskCenter.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="flex-1 px-6 pb-6">
|
||||
<div class="flex justify-between items-center py-4">
|
||||
<h3 class="text-base font-semibold">任务中心</h3>
|
||||
<a class="text-[#3b82f6] text-[13px] cursor-pointer">
|
||||
编辑
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 max-[800px]:grid-cols-1">
|
||||
<div v-for="n in 14" :key="n" class="flex gap-3 items-start p-3.5
|
||||
rounded-[10px] border border-[#dfeaf6] bg-white">
|
||||
<div class="w-11 h-11 bg-[#EFF6FF] rounded-lg
|
||||
border border-dashed border-[#9fc0e8]
|
||||
flex items-center justify-center
|
||||
text-[#3b82f6] text-[23px]">
|
||||
销
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="font-semibold">
|
||||
每日销售数据
|
||||
</div>
|
||||
<div class="text-[#9aa5b1] text-[13px] mt-1.5">
|
||||
分析用于销售渠道每日数据汇总及简要展示
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
48
src/renderer/views/home/components/ChatInputArea.vue
Normal file
48
src/renderer/views/home/components/ChatInputArea.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="h-[174px] bg-white rounded-lg border border-[#eef2f6] shadow-[0_1px_0_rgba(0,0,0,0.03)] p-[18px] mt-[8px] flex flex-col justify-between">
|
||||
<textarea
|
||||
rows="2"
|
||||
placeholder="给我发布或者布置任务xx"
|
||||
class="flex-1 resize-none outline-none text-sm"
|
||||
:value="modelValue"
|
||||
@input="onInput"
|
||||
@keydown.enter="onKeydownEnter"
|
||||
/>
|
||||
|
||||
<div class="flex justify-between items-end">
|
||||
<button @click="onAttach">
|
||||
<RiLink />
|
||||
</button>
|
||||
<button class="w-[48px] h-[48px] bg-[#F5F7FA] px-2.5 py-1.5 rounded-md flex items-center justify-center" @click="onSend">
|
||||
<RiStopFill v-if="isSendingMessage" />
|
||||
<RiSendPlaneFill v-else />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits } from 'vue'
|
||||
import { RiLink, RiSendPlaneFill, RiStopFill } from '@remixicon/vue'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: String, default: '' },
|
||||
isSendingMessage: { type: Boolean, default: false },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'send', 'attach'])
|
||||
|
||||
const onInput = (e: Event) => {
|
||||
const v = (e.target as HTMLTextAreaElement).value
|
||||
emit('update:modelValue', v)
|
||||
}
|
||||
|
||||
const onKeydownEnter = (e: KeyboardEvent) => {
|
||||
if ((e as KeyboardEvent).shiftKey) return
|
||||
e.preventDefault()
|
||||
emit('send')
|
||||
}
|
||||
|
||||
const onAttach = () => emit('attach')
|
||||
const onSend = () => emit('send')
|
||||
</script>
|
||||
@@ -16,7 +16,6 @@ import MarkdownIt from 'markdown-it'
|
||||
import hljs from 'highlight.js'
|
||||
import 'highlight.js/styles/github.css'
|
||||
import ChatLoading from './ChatLoading.vue';
|
||||
import { sl } from 'element-plus/es/locale/index.mjs';
|
||||
|
||||
interface Props {
|
||||
msg: ChatMessage
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<layout>
|
||||
<div class="flex h-full w-full flex-col md:flex-row ">
|
||||
<chat-history class="flex-none w-64" />
|
||||
<chat-history class="flex-none w-50" />
|
||||
<div class="flex-1 mr-2 overflow-hidden bg-white rounded-xl">
|
||||
<!-- <chat-guide /> -->
|
||||
<chat-box />
|
||||
|
||||
Reference in New Issue
Block a user