208 lines
3.9 KiB
Vue
208 lines
3.9 KiB
Vue
<template>
|
|
<div class="message-input-container">
|
|
<div class="input-wrapper">
|
|
<n-input
|
|
v-model:value="messageText"
|
|
type="textarea"
|
|
:placeholder="placeholder"
|
|
:autosize="{ minRows: 1, maxRows: 4 }"
|
|
:bordered="false"
|
|
class="message-input"
|
|
@keydown="handleKeyDown"
|
|
@input="handleInput"
|
|
/>
|
|
<div class="input-actions">
|
|
<n-button
|
|
type="primary"
|
|
size="medium"
|
|
:disabled="!canSend"
|
|
class="send-button"
|
|
@click="handleSend"
|
|
>
|
|
发送
|
|
</n-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed } from 'vue'
|
|
import { NInput, NButton } from 'naive-ui'
|
|
|
|
// Props
|
|
interface Props {
|
|
placeholder?: string
|
|
maxLength?: number
|
|
disabled?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
placeholder: '请输入消息内容...',
|
|
maxLength: 500,
|
|
disabled: false
|
|
})
|
|
|
|
// Emits
|
|
const emit = defineEmits<{
|
|
send: [message: string]
|
|
input: [value: string]
|
|
}>()
|
|
|
|
// 响应式数据
|
|
const messageText = ref('')
|
|
|
|
// 计算属性
|
|
const canSend = computed(() => {
|
|
return messageText.value.trim().length > 0 && !props.disabled
|
|
})
|
|
|
|
// 方法
|
|
const handleSend = () => {
|
|
if (canSend.value) {
|
|
emit('send', messageText.value.trim())
|
|
messageText.value = ''
|
|
}
|
|
}
|
|
|
|
const handleInput = (value: string) => {
|
|
emit('input', value)
|
|
}
|
|
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
// Ctrl/Cmd + Enter 发送消息
|
|
if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') {
|
|
event.preventDefault()
|
|
handleSend()
|
|
}
|
|
}
|
|
|
|
// 暴露方法供父组件调用
|
|
defineExpose({
|
|
focus: () => {
|
|
// 可以在这里添加聚焦逻辑
|
|
},
|
|
clear: () => {
|
|
messageText.value = ''
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.message-input-container {
|
|
position: sticky;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: #ffffff;
|
|
border-top: 1px solid #e8e8e8;
|
|
padding: 16px 20px;
|
|
z-index: 100;
|
|
}
|
|
|
|
.input-wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.message-input {
|
|
flex: 1;
|
|
background: #f8f9fa;
|
|
border-radius: 12px;
|
|
padding: 12px 16px;
|
|
min-height: 44px;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.message-input:hover {
|
|
background: #f0f2f5;
|
|
}
|
|
|
|
.message-input:focus-within {
|
|
background: #ffffff;
|
|
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
|
}
|
|
|
|
.input-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.send-button {
|
|
height: 44px;
|
|
padding: 0 24px;
|
|
border-radius: 12px;
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
white-space: nowrap;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.send-button:not(:disabled):hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
|
|
}
|
|
|
|
/* 自定义Naive UI样式 */
|
|
:deep(.n-input .n-input__textarea) {
|
|
background: transparent !important;
|
|
border: none !important;
|
|
padding: 0 !important;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
resize: none;
|
|
}
|
|
|
|
:deep(.n-input .n-input__textarea::placeholder) {
|
|
color: #999;
|
|
font-size: 14px;
|
|
}
|
|
|
|
:deep(.n-input.n-input--focus .n-input__textarea) {
|
|
background: transparent !important;
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
:deep(.n-button.n-button--primary-type) {
|
|
background: linear-gradient(135deg, #1890ff 0%, #40a9ff 100%);
|
|
border: none;
|
|
}
|
|
|
|
:deep(.n-button.n-button--primary-type:not(.n-button--disabled):hover) {
|
|
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
}
|
|
|
|
:deep(.n-button.n-button--primary-type.n-button--disabled) {
|
|
background: #d9d9d9;
|
|
color: #fff;
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 768px) {
|
|
.message-input-container {
|
|
padding: 12px 16px;
|
|
}
|
|
|
|
.input-wrapper {
|
|
gap: 8px;
|
|
}
|
|
|
|
.send-button {
|
|
height: 40px;
|
|
padding: 0 16px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.message-input {
|
|
padding: 10px 14px;
|
|
min-height: 40px;
|
|
font-size: 13px;
|
|
}
|
|
}
|
|
</style> |