update: Enhance mobile responsiveness and sidebar functionality across chat components
This commit is contained in:
parent
f0ee5102af
commit
0d3d30952d
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="main-layout">
|
||||
<Sidebar />
|
||||
<Sidebar class="sidebar" />
|
||||
<main class="content-area">
|
||||
<!-- 路由视图将渲染在这里 -->
|
||||
<router-view />
|
||||
|
@ -28,6 +28,21 @@ import Sidebar from '../components/Sidebar.vue'
|
|||
background-color: #ffffff; /* 示例背景色 */
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 移动端样式 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 简单的侧边栏列表样式 */
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
<div class="chat-header">
|
||||
<div class="header-content">
|
||||
<div class="title">
|
||||
<el-button
|
||||
class="mobile-sidebar-toggle"
|
||||
:icon="Expand"
|
||||
@click="settingsStore.toggleSidebar"
|
||||
text
|
||||
v-if="isMobile"
|
||||
/>
|
||||
<span class="title-text">{{ title }}</span>
|
||||
<el-tag v-if="chatStore.currentConversation?.conversationStatus === 'typing'"
|
||||
size="small"
|
||||
|
@ -49,10 +56,10 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useChatStore } from '@/store/chat'
|
||||
import { useSettingsStore } from '@/store/settings'
|
||||
import { Delete, Setting, User } from '@element-plus/icons-vue'
|
||||
import { Delete, Setting, User, Expand } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import HistoryButton from '@/components/chat/HistoryButton.vue'
|
||||
import CustomerBackground from '@/components/chat/CustomerBackground.vue'
|
||||
|
@ -61,6 +68,7 @@ const chatStore = useChatStore()
|
|||
const settingsStore = useSettingsStore()
|
||||
const showUserInfo = ref(false)
|
||||
const customerBackgroundRef = ref(null)
|
||||
const isMobile = ref(false)
|
||||
|
||||
const title = computed(() => {
|
||||
const conversation = chatStore.currentConversation
|
||||
|
@ -101,6 +109,19 @@ const handleSettings = () => {
|
|||
// TODO: 实现设置功能
|
||||
console.log('打开设置')
|
||||
}
|
||||
|
||||
const checkMobile = () => {
|
||||
isMobile.value = window.innerWidth <= 768
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
checkMobile()
|
||||
window.addEventListener('resize', checkMobile)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', checkMobile)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -121,7 +142,38 @@ const handleSettings = () => {
|
|||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
gap: 4px;
|
||||
height: 100%;
|
||||
|
||||
.mobile-sidebar-toggle {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
padding: 0;
|
||||
color: #666;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
background: transparent !important;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: -4px;
|
||||
|
||||
&:hover {
|
||||
color: #07c160;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:deep(.el-icon) {
|
||||
font-size: 18px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 16px;
|
||||
|
@ -131,6 +183,8 @@ const handleSettings = () => {
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 24px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
|
|
|
@ -1,41 +1,49 @@
|
|||
<template>
|
||||
<div class="mode-selector" :class="{ 'collapsed': settingsStore.sidebarCollapsed }">
|
||||
<div class="mode-header">
|
||||
<h3 class="mode-title">对话场景</h3>
|
||||
<div class="header-actions">
|
||||
<HistoryButton v-if="!settingsStore.sidebarCollapsed" :icon-only="true" />
|
||||
<el-button
|
||||
class="collapse-btn"
|
||||
:icon="settingsStore.sidebarCollapsed ? Expand : Fold"
|
||||
text
|
||||
bg
|
||||
@click="settingsStore.toggleSidebar"
|
||||
/>
|
||||
<div>
|
||||
<div
|
||||
class="mode-selector-backdrop"
|
||||
:class="{ visible: !settingsStore.sidebarCollapsed }"
|
||||
@click="settingsStore.toggleSidebar"
|
||||
v-if="isMobile"
|
||||
></div>
|
||||
<div class="mode-selector" :class="{ 'collapsed': settingsStore.sidebarCollapsed }">
|
||||
<div class="mode-header">
|
||||
<h3 class="mode-title">对话场景</h3>
|
||||
<div class="header-actions">
|
||||
<HistoryButton v-if="!settingsStore.sidebarCollapsed" :icon-only="true" />
|
||||
<el-button
|
||||
class="collapse-btn"
|
||||
:icon="settingsStore.sidebarCollapsed ? Expand : Fold"
|
||||
text
|
||||
bg
|
||||
@click="settingsStore.toggleSidebar"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mode-list">
|
||||
<div
|
||||
v-for="mode in chatModes"
|
||||
:key="mode.id"
|
||||
:class="['mode-item', { active: chatStore.currentMode === mode.id }]"
|
||||
@click="selectMode(mode.id)"
|
||||
>
|
||||
<span class="emoji-icon">{{ mode.icon }}</span>
|
||||
<span v-if="!settingsStore.sidebarCollapsed" class="mode-name">{{ mode.name }}</span>
|
||||
<ModeSetting v-if="!settingsStore.sidebarCollapsed" @command="(cmd) => handleModeSettings(cmd, mode.id)">
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
编辑设置
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="reset">
|
||||
<el-icon><RefreshRight /></el-icon>
|
||||
重置设置
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除场景
|
||||
</el-dropdown-item>
|
||||
</ModeSetting>
|
||||
<div class="mode-list">
|
||||
<div
|
||||
v-for="mode in chatModes"
|
||||
:key="mode.id"
|
||||
:class="['mode-item', { active: chatStore.currentMode === mode.id }]"
|
||||
@click="selectMode(mode.id)"
|
||||
>
|
||||
<span class="emoji-icon">{{ mode.icon }}</span>
|
||||
<span v-if="!settingsStore.sidebarCollapsed" class="mode-name">{{ mode.name }}</span>
|
||||
<ModeSetting v-if="!settingsStore.sidebarCollapsed" @command="(cmd) => handleModeSettings(cmd, mode.id)">
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
编辑设置
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="reset">
|
||||
<el-icon><RefreshRight /></el-icon>
|
||||
重置设置
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除场景
|
||||
</el-dropdown-item>
|
||||
</ModeSetting>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -44,7 +52,7 @@
|
|||
<script setup>
|
||||
import { useChatStore } from '@/store/chat'
|
||||
import { useSettingsStore } from '@/store/settings'
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref, onMounted, onUnmounted } from 'vue'
|
||||
import { Delete, EditPen, RefreshRight, Expand, Fold } from '@element-plus/icons-vue'
|
||||
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElButton, ElMessageBox } from 'element-plus'
|
||||
import ModeSetting from '@/components/chat/ModeSetting.vue'
|
||||
|
@ -117,6 +125,21 @@ const handleModeSettings = (command, modeId) => {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
const isMobile = ref(false)
|
||||
|
||||
const checkMobile = () => {
|
||||
isMobile.value = window.innerWidth <= 768
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
checkMobile()
|
||||
window.addEventListener('resize', checkMobile)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', checkMobile)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -139,6 +162,8 @@ $hover-color-dark: #2d2d2d;
|
|||
padding: 0;
|
||||
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
|
||||
&.collapsed {
|
||||
width: 64px;
|
||||
|
@ -349,6 +374,44 @@ $hover-color-dark: #2d2d2d;
|
|||
}
|
||||
}
|
||||
|
||||
/* 移动端样式 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.mode-selector {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transform: translateX(-100%);
|
||||
z-index: 1000;
|
||||
|
||||
&.collapsed {
|
||||
transform: translateX(-240px);
|
||||
}
|
||||
|
||||
&:not(.collapsed) {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.mode-selector-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @media (prefers-color-scheme: dark) {
|
||||
// .mode-selector {
|
||||
// background: $background-color-dark;
|
||||
|
|
|
@ -55,4 +55,20 @@ const handleModeChange = (mode) => {
|
|||
background-color: #f5f5f5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 移动端样式 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.chat-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chat-wrapper {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue