217 lines
5.2 KiB
Vue
217 lines
5.2 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="input-shell">
|
|||
|
|
<div class="input-card">
|
|||
|
|
<el-input
|
|||
|
|
v-model="message"
|
|||
|
|
type="textarea"
|
|||
|
|
:rows="1"
|
|||
|
|
:autosize="{ minRows: 2, maxRows: 5 }"
|
|||
|
|
placeholder="多说说你的偏好和要求,我会越用越懂你"
|
|||
|
|
class="message-input"
|
|||
|
|
@keydown.enter.exact="handleSend"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<div class="input-toolbar">
|
|||
|
|
<div class="toolbar-left">
|
|||
|
|
<el-button circle class="tool-btn" @click="handleAttachment">
|
|||
|
|
<el-icon><Plus /></el-icon>
|
|||
|
|
</el-button>
|
|||
|
|
<el-dropdown trigger="click" @command="handleCommandSelect">
|
|||
|
|
<el-button class="pill-btn">快捷指令</el-button>
|
|||
|
|
<template #dropdown>
|
|||
|
|
<el-dropdown-menu>
|
|||
|
|
<el-dropdown-item command="rewrite">帮我润色这段文案</el-dropdown-item>
|
|||
|
|
<el-dropdown-item command="summary">总结当前对话重点</el-dropdown-item>
|
|||
|
|
<el-dropdown-item command="todo">整理下一步 TODO</el-dropdown-item>
|
|||
|
|
</el-dropdown-menu>
|
|||
|
|
</template>
|
|||
|
|
</el-dropdown>
|
|||
|
|
|
|||
|
|
<el-dropdown trigger="click" @command="handleReplySelect">
|
|||
|
|
<el-button class="pill-btn">快捷回复</el-button>
|
|||
|
|
<template #dropdown>
|
|||
|
|
<el-dropdown-menu>
|
|||
|
|
<el-dropdown-item command="ok">收到,我马上处理</el-dropdown-item>
|
|||
|
|
<el-dropdown-item command="confirm">这个方向可以,继续</el-dropdown-item>
|
|||
|
|
<el-dropdown-item command="adjust">这个比例还要再调一下</el-dropdown-item>
|
|||
|
|
</el-dropdown-menu>
|
|||
|
|
</template>
|
|||
|
|
</el-dropdown>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="toolbar-right">
|
|||
|
|
<el-button class="mode-btn">启动</el-button>
|
|||
|
|
<el-button circle class="send-btn" :disabled="!message.trim()" @click="handleSend">
|
|||
|
|
<el-icon><Top /></el-icon>
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import { ref } from 'vue';
|
|||
|
|
import { Top, Plus } from '@element-plus/icons-vue';
|
|||
|
|
import { ElMessage } from 'element-plus';
|
|||
|
|
|
|||
|
|
interface Emits {
|
|||
|
|
(e: 'send', message: string): void;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const emit = defineEmits<Emits>();
|
|||
|
|
const message = ref('');
|
|||
|
|
|
|||
|
|
const quickCommands: Record<string, string> = {
|
|||
|
|
rewrite: '请帮我润色下面这段内容,保持原意并提升表达质感:',
|
|||
|
|
summary: '请总结我们当前对话的重点,并给出 3 条执行建议。',
|
|||
|
|
todo: '请把当前需求拆解成可执行的 TODO 列表。',
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const quickReplies: Record<string, string> = {
|
|||
|
|
ok: '收到,我马上处理。',
|
|||
|
|
confirm: '这个方向可以,继续。',
|
|||
|
|
adjust: '这个比例还要再调一下。',
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleSend = (event?: KeyboardEvent) => {
|
|||
|
|
if (event) event.preventDefault();
|
|||
|
|
const msg = message.value.trim();
|
|||
|
|
if (!msg) return;
|
|||
|
|
emit('send', msg);
|
|||
|
|
message.value = '';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleAttachment = () => {
|
|||
|
|
ElMessage.info('附件上传功能开发中...');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleCommandSelect = (key: string | number | object) => {
|
|||
|
|
const k = String(key);
|
|||
|
|
message.value = quickCommands[k] || message.value;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleReplySelect = (key: string | number | object) => {
|
|||
|
|
const k = String(key);
|
|||
|
|
message.value = quickReplies[k] || message.value;
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.input-shell {
|
|||
|
|
position: relative;
|
|||
|
|
z-index: 12;
|
|||
|
|
margin-top: -20px;
|
|||
|
|
padding: 0 0 50px;
|
|||
|
|
background: transparent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.input-card {
|
|||
|
|
width: min(1060px, 82%);
|
|||
|
|
margin: 0 auto;
|
|||
|
|
background:
|
|||
|
|
linear-gradient(180deg, rgba(255, 255, 255, 0.97) 0%, rgba(255, 255, 255, 0.92) 100%),
|
|||
|
|
radial-gradient(120% 180% at 0% 0%, rgba(59, 130, 246, 0.12) 0%, rgba(59, 130, 246, 0) 38%);
|
|||
|
|
border: 1px solid rgba(191, 219, 254, 0.62);
|
|||
|
|
border-radius: 18px;
|
|||
|
|
box-shadow:
|
|||
|
|
0 20px 44px rgba(15, 23, 42, 0.14),
|
|||
|
|
0 0 0 1px rgba(59, 130, 246, 0.09) inset,
|
|||
|
|
0 10px 24px rgba(37, 99, 235, 0.16);
|
|||
|
|
padding: 14px 16px 12px;
|
|||
|
|
backdrop-filter: blur(14px);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.message-input {
|
|||
|
|
:deep(.el-textarea__inner) {
|
|||
|
|
border: none;
|
|||
|
|
box-shadow: none;
|
|||
|
|
resize: none;
|
|||
|
|
padding: 8px 6px 14px;
|
|||
|
|
font-size: 15px;
|
|||
|
|
line-height: 1.65;
|
|||
|
|
color: #0f172a;
|
|||
|
|
background: transparent;
|
|||
|
|
min-height: 50px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
|
|||
|
|
&::placeholder {
|
|||
|
|
color: #90a1b7;
|
|||
|
|
font-weight: 400;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.input-toolbar {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 10px;
|
|||
|
|
padding-top: 2px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.toolbar-left,
|
|||
|
|
.toolbar-right {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tool-btn {
|
|||
|
|
width: 30px;
|
|||
|
|
height: 30px;
|
|||
|
|
border: 1px solid #d9e4f5;
|
|||
|
|
color: #5b6b84;
|
|||
|
|
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
|
|||
|
|
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08);
|
|||
|
|
|
|||
|
|
&:hover {
|
|||
|
|
color: #2b4d8f;
|
|||
|
|
background: #f3f8ff;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pill-btn {
|
|||
|
|
height: 30px;
|
|||
|
|
padding: 0 12px;
|
|||
|
|
border-radius: 999px;
|
|||
|
|
border: 1px solid #dbe7f7;
|
|||
|
|
color: #30435f;
|
|||
|
|
background: linear-gradient(180deg, #ffffff 0%, #f6f9ff 100%);
|
|||
|
|
font-size: 12px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-btn {
|
|||
|
|
height: 30px;
|
|||
|
|
padding: 0 13px;
|
|||
|
|
border-radius: 999px;
|
|||
|
|
border: 1px solid #dbe7f7;
|
|||
|
|
color: #30435f;
|
|||
|
|
background: linear-gradient(180deg, #ffffff 0%, #f6f9ff 100%);
|
|||
|
|
font-size: 12px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
letter-spacing: 0.2px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.send-btn {
|
|||
|
|
width: 30px;
|
|||
|
|
height: 30px;
|
|||
|
|
border: none;
|
|||
|
|
background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 55%, #2563eb 100%);
|
|||
|
|
color: #fff;
|
|||
|
|
box-shadow: 0 6px 14px rgba(59, 130, 246, 0.4);
|
|||
|
|
|
|||
|
|
&:hover:not(:disabled) {
|
|||
|
|
filter: brightness(1.06);
|
|||
|
|
transform: translateY(-1px);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&:disabled {
|
|||
|
|
opacity: 0.55;
|
|||
|
|
box-shadow: none;
|
|||
|
|
background: #cbd5e1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|