|
|
@@ -13,6 +13,35 @@
|
|
|
placeholder=""
|
|
|
@keyup.enter.exact="doSendMessage(prompt.trim())"
|
|
|
></textarea>
|
|
|
+ <div class="dropdowns-container">
|
|
|
+ <el-dropdown
|
|
|
+ v-for="dropdown in dropdowns"
|
|
|
+ :key="dropdown.key"
|
|
|
+ v-model="dropdown.value"
|
|
|
+ @command="(command) => handleSelect(dropdown.key, command)"
|
|
|
+ @visible-change="(visible) => handleVisibleChange(dropdown.key, visible)"
|
|
|
+ >
|
|
|
+ <el-button type="primary">
|
|
|
+ <el-icon class="el-icon--left"><component :is="dropdown.icon" /></el-icon>
|
|
|
+ {{ dropdown.value }}
|
|
|
+ <el-icon class="el-icon--right" v-if="!dropdown.visible"><ArrowDownBold /></el-icon>
|
|
|
+ <el-icon class="el-icon--right" v-else><ArrowUpBold /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ <template #dropdown>
|
|
|
+ <el-dropdown-menu class="dropdown-menu">
|
|
|
+ <el-dropdown-item
|
|
|
+ v-for="item in dropdown.options"
|
|
|
+ :key="item.value"
|
|
|
+ :command="item.value"
|
|
|
+ >{{ item.label }}</el-dropdown-item
|
|
|
+ >
|
|
|
+ </el-dropdown-menu>
|
|
|
+ </template>
|
|
|
+ </el-dropdown>
|
|
|
+ </div>
|
|
|
+ <button class="send-button" :class="{ 'active': prompt.trim().length > 0 }" @click="doSendMessage(prompt.trim())" :disabled="!prompt.trim().length">
|
|
|
+ <Top />
|
|
|
+ </button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -21,10 +50,106 @@
|
|
|
|
|
|
<script setup>
|
|
|
import {ref} from "vue";
|
|
|
+import { Top, Search, User,Memo,ArrowUpBold,ArrowDownBold } from '@element-plus/icons-vue'
|
|
|
|
|
|
// 发送消息输入框
|
|
|
const prompt = ref(""); // prompt
|
|
|
|
|
|
+// 下拉框配置
|
|
|
+const dropdowns = ref([
|
|
|
+ {
|
|
|
+ key: 'course',
|
|
|
+ value: '诗词课',
|
|
|
+ visible: false,
|
|
|
+ icon: Search,
|
|
|
+ options: [
|
|
|
+ { label: '数学课', value: '数学课' },
|
|
|
+ { label: '英语课', value: '英语课' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'teacher',
|
|
|
+ value: '主讲',
|
|
|
+ visible: false,
|
|
|
+ icon: User,
|
|
|
+ options: [
|
|
|
+ { label: '张老师', value: '张老师' },
|
|
|
+ { label: '李老师', value: '李老师' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'assistant',
|
|
|
+ value: '助教',
|
|
|
+ visible: false,
|
|
|
+ icon: Memo,
|
|
|
+ options: [
|
|
|
+ { label: '小王', value: '小王' },
|
|
|
+ { label: '小李', value: '小李' },
|
|
|
+ { label: '小王', value: '小王' },
|
|
|
+ { label: '小李', value: '小李' },
|
|
|
+ { label: '小王', value: '小王' },
|
|
|
+ { label: '小李', value: '小李' },
|
|
|
+ { label: '小王', value: '小王' },
|
|
|
+ { label: '小李', value: '小李' },
|
|
|
+ { label: '小王', value: '小王' },
|
|
|
+ { label: '小李', value: '小李' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+]);
|
|
|
+
|
|
|
+// 下拉框配置映射,用于生成内容和正则表达式
|
|
|
+const dropdownConfig = {
|
|
|
+ course: {
|
|
|
+ prefix: '诗词课',
|
|
|
+ default: '诗词课',
|
|
|
+ regex: /诗词课[^,]+/g
|
|
|
+ },
|
|
|
+ teacher: {
|
|
|
+ prefix: '主讲为',
|
|
|
+ default: '主讲',
|
|
|
+ regex: /主讲为[^,]+/g
|
|
|
+ },
|
|
|
+ assistant: {
|
|
|
+ prefix: '助教为',
|
|
|
+ default: '助教',
|
|
|
+ regex: /助教为[^,]+/g
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 处理下拉框选择
|
|
|
+const handleSelect = (key, command) => {
|
|
|
+ const dropdown = dropdowns.value.find(item => item.key === key);
|
|
|
+ if (dropdown && dropdownConfig[key]) {
|
|
|
+ const config = dropdownConfig[key];
|
|
|
+
|
|
|
+ // 生成新内容,仅当选择的值与默认值不同时添加
|
|
|
+ const newContent = command === config.default
|
|
|
+ ? config.prefix
|
|
|
+ : `${config.prefix}${command}`;
|
|
|
+
|
|
|
+ // 检查输入框中是否已存在该类型的内容
|
|
|
+ if (config.regex.test(prompt.value)) {
|
|
|
+ // 替换已存在的内容
|
|
|
+ prompt.value = prompt.value.replace(config.regex, newContent);
|
|
|
+ } else {
|
|
|
+ // 添加到输入框,用逗号隔开
|
|
|
+ if (prompt.value.trim()) {
|
|
|
+ prompt.value += `, ${newContent}`;
|
|
|
+ } else {
|
|
|
+ prompt.value = newContent;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 处理下拉框可见性变化
|
|
|
+const handleVisibleChange = (key, visible) => {
|
|
|
+ const dropdown = dropdowns.value.find(item => item.key === key);
|
|
|
+ if (dropdown) {
|
|
|
+ dropdown.visible = visible;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
/** 处理来自 keydown 的发送消息 */
|
|
|
const handleSendByKeydown = async (event) => {
|
|
|
const content = prompt.value?.trim();
|
|
|
@@ -52,8 +177,6 @@ const doSendMessage = async (content) => {
|
|
|
// 清空输入框
|
|
|
prompt.value = "";
|
|
|
|
|
|
- // 这里可以添加发送消息的逻辑
|
|
|
- console.log("发送消息:", content);
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
@@ -76,7 +199,6 @@ const doSendMessage = async (content) => {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
- margin: rpx(0) 0;
|
|
|
|
|
|
h3 {
|
|
|
font-size: rpx(12);
|
|
|
@@ -87,8 +209,9 @@ const doSendMessage = async (content) => {
|
|
|
|
|
|
.input-section {
|
|
|
display: flex;
|
|
|
- justify-content: center;
|
|
|
- padding: rpx(10);
|
|
|
+ justify-content: flex-start;
|
|
|
+ margin-left: rpx(10);
|
|
|
+ width: calc(100% - rpx(10));
|
|
|
}
|
|
|
|
|
|
.dialogue-card {
|
|
|
@@ -105,7 +228,9 @@ const doSendMessage = async (content) => {
|
|
|
}
|
|
|
|
|
|
.user-input-card {
|
|
|
- max-width: 80%;
|
|
|
+ width: 90%;
|
|
|
+ margin-left: rpx(20);
|
|
|
+ max-width: none;
|
|
|
animation: dialogueEnterCenter 0.6s ease forwards;
|
|
|
}
|
|
|
|
|
|
@@ -131,26 +256,109 @@ const doSendMessage = async (content) => {
|
|
|
text-align: left;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
+ position: relative;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.user-input-textarea {
|
|
|
- width: 95%;
|
|
|
- min-height: rpx(50);
|
|
|
+ width: 100%;
|
|
|
+ min-height: rpx(70);
|
|
|
max-height: rpx(150);
|
|
|
border: none;
|
|
|
outline: none;
|
|
|
background: transparent;
|
|
|
- font-size: rpx(10);
|
|
|
+ font-size: rpx(8);
|
|
|
line-height: 1.2;
|
|
|
color: #333;
|
|
|
resize: none;
|
|
|
font-family: inherit;
|
|
|
overflow-y: auto;
|
|
|
text-align: left;
|
|
|
- padding: rpx(5) 0;
|
|
|
+ padding: rpx(5) rpx(0);
|
|
|
+}
|
|
|
+
|
|
|
+.dropdowns-container {
|
|
|
+ display: flex;
|
|
|
+ gap: rpx(5);
|
|
|
+ margin-top: rpx(5);
|
|
|
+ align-self: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+.dropdowns-container .el-button {
|
|
|
+ width: rpx(50);
|
|
|
+ height: rpx(18);
|
|
|
+ background-color: #f1f0ff;
|
|
|
+ border: rpx(1) solid #a7a4ed;
|
|
|
+ color: black;
|
|
|
+ border-radius: rpx(4);
|
|
|
+ font-size: rpx(8);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+.dropdown-menu {
|
|
|
+ min-width: rpx(50);
|
|
|
+ width: auto;
|
|
|
+ max-height: rpx(160);
|
|
|
+ overflow-y: auto;
|
|
|
+ border-radius: rpx(3);
|
|
|
+ border: 1px white solid;
|
|
|
+ background-color: rgb(255, 255, 255, 0.5);
|
|
|
+ backdrop-filter: blur(rpx(5));
|
|
|
+ box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-menu ::v-deep::-webkit-scrollbar {
|
|
|
+ width: rpx(2);
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-menu ::v-deep::-webkit-scrollbar-track {
|
|
|
+ background: #f1f1f1;
|
|
|
+ border-radius: rpx(2);
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-menu ::v-deep::-webkit-scrollbar-thumb {
|
|
|
+ background: #c1c1c1;
|
|
|
+ border-radius: rpx(2);
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-menu ::v-deep::-webkit-scrollbar-thumb:hover {
|
|
|
+ background: #a8a8a8;
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-menu ::v-deep(.el-dropdown-menu__item) {
|
|
|
+ font-size: rpx(8);
|
|
|
+ color: black;
|
|
|
+ border-radius: rpx(5);
|
|
|
+ width: auto;
|
|
|
+ min-width: rpx(35);
|
|
|
+ height: rpx(20);
|
|
|
+ margin-bottom: rpx(8);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 0 rpx(8);
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-menu ::v-deep(.el-dropdown-menu__item:hover),
|
|
|
+.dropdown-menu ::v-deep(.el-dropdown-menu__item:focus),
|
|
|
+.dropdown-menu ::v-deep(.el-dropdown-menu__item:active) {
|
|
|
+ background: linear-gradient(
|
|
|
+ to bottom,
|
|
|
+ #fee78a,
|
|
|
+ #ffce1b
|
|
|
+ );
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+}
|
|
|
+
|
|
|
+/* 确保下拉按钮点击时也没有边框 */
|
|
|
+.dropdowns-container .el-button:focus,
|
|
|
+.dropdowns-container .el-button:active {
|
|
|
+ outline: none;
|
|
|
+ box-shadow: none;
|
|
|
}
|
|
|
|
|
|
/* 滚动条样式 */
|
|
|
@@ -172,5 +380,67 @@ const doSendMessage = async (content) => {
|
|
|
background: rgba(64, 158, 255, 0.8);
|
|
|
}
|
|
|
|
|
|
+.send-button {
|
|
|
+ position: absolute;
|
|
|
+ bottom: rpx(0);
|
|
|
+ right: rpx(0);
|
|
|
+ width: rpx(20);
|
|
|
+ height: rpx(20);
|
|
|
+ border-radius: 50%;
|
|
|
+ background: transparent;
|
|
|
+ color: #a7a4ed;
|
|
|
+ border: rpx(1) solid #a7a4ed;
|
|
|
+ font-size: rpx(3);
|
|
|
+ font-weight: bold;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ cursor: not-allowed;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ outline: none;
|
|
|
+ box-shadow: none;
|
|
|
+ opacity: 0.6;
|
|
|
+}
|
|
|
+
|
|
|
+.send-button.active {
|
|
|
+ background: linear-gradient(
|
|
|
+ to bottom,
|
|
|
+ #ffefb0,
|
|
|
+ #ffcc00
|
|
|
+ );
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ cursor: pointer;
|
|
|
+ opacity: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.send-button:hover:not(.active) {
|
|
|
+ border-color: #a7a4ed;
|
|
|
+ color: #a7a4ed;
|
|
|
+ transform: none;
|
|
|
+ outline: none;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+
|
|
|
+.send-button:hover.active {
|
|
|
+ transform: scale(1.1);
|
|
|
+ outline: none;
|
|
|
+ box-shadow: 0 rpx(2) rpx(5) rgba(255, 204, 0, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+.send-button:active.active {
|
|
|
+ transform: scale(0.95);
|
|
|
+ outline: none;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+
|
|
|
+.send-button:focus {
|
|
|
+ outline: none;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+
|
|
|
+.send-button span {
|
|
|
+ display: block;
|
|
|
+}
|
|
|
|
|
|
</style>
|