优化移动端体验
This commit is contained in:
parent
d5f1e0dd31
commit
2de7b13e87
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chat" ref="chatContainer">
|
<div class="chat" ref="chatContainer">
|
||||||
<div class="header">
|
<div class="chat-header">
|
||||||
<div class="header__left">
|
<div class="header__left">
|
||||||
<div
|
<div
|
||||||
v-if="!state.isSidebarOpen"
|
v-if="!state.isSidebarOpen"
|
||||||
@ -593,7 +593,7 @@ watch(
|
|||||||
flex: 5 5 200px;
|
flex: 5 5 200px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
|
||||||
.header {
|
.chat-header {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -1008,14 +1008,14 @@ watch(
|
|||||||
height: calc(100vh - 60px);
|
height: calc(100vh - 60px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-container .chat .header {
|
.chat-container .chat .chat-header {
|
||||||
background: var(--main-light-4);
|
background: var(--main-light-4);
|
||||||
.header__left, .header__right {
|
.header__left, .header__right {
|
||||||
gap: 20px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-btn {
|
.nav-btn {
|
||||||
font-size: 1.5rem;
|
font-size: 1.3rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
@ -337,8 +337,12 @@ div.header, #app-router-view {
|
|||||||
div.header {
|
div.header {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
.debug-panel {
|
||||||
|
bottom: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
.app-layout div.header-mobile {
|
.app-layout div.header-mobile {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -348,6 +352,7 @@ div.header, #app-router-view {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 0 0 60px;
|
flex: 0 0 60px;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|||||||
@ -256,10 +256,11 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 520px) {
|
@media (max-width: 520px) {
|
||||||
.conversation {
|
.conversations {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 101;
|
z-index: 101;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
height: 100%;
|
||||||
border-radius: 0 16px 16px 0;
|
border-radius: 0 16px 16px 0;
|
||||||
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,15 +14,15 @@
|
|||||||
</template>
|
</template>
|
||||||
</HeaderComponent>
|
</HeaderComponent>
|
||||||
<div class="setting-container layout-container">
|
<div class="setting-container layout-container">
|
||||||
<div class="sider">
|
<div class="sider" v-if="state.windowWidth > 520">
|
||||||
<a-button type="text" :class="{ activesec: state.section === 'base'}" @click="state.section='base'" :icon="h(SettingOutlined)"> 基本设置 </a-button>
|
<a-button type="text" :class="{ activesec: state.section === 'base'}" @click="state.section='base'" :icon="h(SettingOutlined)"> 基本设置 </a-button>
|
||||||
<a-button type="text" :class="{ activesec: state.section === 'model'}" @click="state.section='model'" :icon="h(CodeOutlined)"> 模型配置 </a-button>
|
<a-button type="text" :class="{ activesec: state.section === 'model'}" @click="state.section='model'" :icon="h(CodeOutlined)"> 模型配置 </a-button>
|
||||||
<a-button type="text" :class="{ activesec: state.section === 'path'}" @click="state.section='path'" :icon="h(FolderOutlined)"> 路径配置 </a-button>
|
<a-button type="text" :class="{ activesec: state.section === 'path'}" @click="state.section='path'" :icon="h(FolderOutlined)"> 路径配置 </a-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting" v-if="state.section === 'base'">
|
<div class="setting" v-if="state.windowWidth <= 520 || state.section === 'base'">
|
||||||
<h3>基础模型配置</h3>
|
<h3>基础模型配置</h3>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="card">
|
<div class="card card-select">
|
||||||
<span class="label">{{ items?.embed_model.des }}</span>
|
<span class="label">{{ items?.embed_model.des }}</span>
|
||||||
<a-select style="width: 300px"
|
<a-select style="width: 300px"
|
||||||
:value="configStore.config?.embed_model"
|
:value="configStore.config?.embed_model"
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card card-select">
|
||||||
<span class="label">{{ items?.reranker.des }}</span>
|
<span class="label">{{ items?.reranker.des }}</span>
|
||||||
<a-select style="width: 300px"
|
<a-select style="width: 300px"
|
||||||
:value="configStore.config?.reranker"
|
:value="configStore.config?.reranker"
|
||||||
@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<h3>检索配置</h3>
|
<h3>检索配置</h3>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="card">
|
<div class="card card-select">
|
||||||
<span class="label">{{ items?.use_rewrite_query.des }}</span>
|
<span class="label">{{ items?.use_rewrite_query.des }}</span>
|
||||||
<a-select style="width: 200px"
|
<a-select style="width: 200px"
|
||||||
:value="configStore.config?.use_rewrite_query"
|
:value="configStore.config?.use_rewrite_query"
|
||||||
@ -95,7 +95,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting" v-if="state.section === 'model'">
|
<div class="setting" v-if="state.windowWidth <= 520 || state.section === 'model'">
|
||||||
<h3>模型配置</h3>
|
<h3>模型配置</h3>
|
||||||
<p>请在 <code>src/.env</code> 文件中配置对应的 APIKEY</p>
|
<p>请在 <code>src/.env</code> 文件中配置对应的 APIKEY</p>
|
||||||
<div class="model-provider-card">
|
<div class="model-provider-card">
|
||||||
@ -184,7 +184,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting" v-if="state.section ==='path'">
|
<div class="setting" v-if="state.windowWidth <= 520 || state.section ==='path'">
|
||||||
<h3>本地模型配置</h3>
|
<h3>本地模型配置</h3>
|
||||||
<p>如果是 Docker 启动,务必确保在环境变量中设置了 MODEL_DIR,或者设置了 volumes 映射</p>
|
<p>如果是 Docker 启动,务必确保在环境变量中设置了 MODEL_DIR,或者设置了 volumes 映射</p>
|
||||||
<TableConfigComponent
|
<TableConfigComponent
|
||||||
@ -198,7 +198,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { computed, reactive, ref, h, watch } from 'vue'
|
import { computed, reactive, ref, h, watch, onMounted, onUnmounted } from 'vue'
|
||||||
import { useConfigStore } from '@/stores/config';
|
import { useConfigStore } from '@/stores/config';
|
||||||
import {
|
import {
|
||||||
ReloadOutlined,
|
ReloadOutlined,
|
||||||
@ -231,16 +231,17 @@ const customModel = reactive({
|
|||||||
})
|
})
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
section: 'base'
|
section: 'base',
|
||||||
|
windowWidth: window?.innerWidth || 0
|
||||||
})
|
})
|
||||||
|
|
||||||
// 筛选 modelStatus 中为真的key
|
// 筛选 modelStatus 中为真的key
|
||||||
const modelKeys = computed(() => {
|
const modelKeys = computed(() => {
|
||||||
return Object.keys(modelStatus.value).filter(key => modelStatus.value[key])
|
return Object.keys(modelStatus.value || {}).filter(key => modelStatus.value?.[key])
|
||||||
})
|
})
|
||||||
|
|
||||||
const notModelKeys = computed(() => {
|
const notModelKeys = computed(() => {
|
||||||
return Object.keys(modelStatus.value).filter(key => !modelStatus.value[key])
|
return Object.keys(modelStatus.value || {}).filter(key => !modelStatus.value?.[key])
|
||||||
})
|
})
|
||||||
|
|
||||||
const generateRandomHash = (length) => {
|
const generateRandomHash = (length) => {
|
||||||
@ -360,6 +361,19 @@ const handleCancelCustomModel = () => {
|
|||||||
customModel.visible = false
|
customModel.visible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateWindowWidth = () => {
|
||||||
|
state.windowWidth = window?.innerWidth || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateWindowWidth()
|
||||||
|
window.addEventListener('resize', updateWindowWidth)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', updateWindowWidth)
|
||||||
|
})
|
||||||
|
|
||||||
const sendRestart = () => {
|
const sendRestart = () => {
|
||||||
console.log('Restarting...')
|
console.log('Restarting...')
|
||||||
message.loading({ content: '重新加载模型中', key: "restart", duration: 0 });
|
message.loading({ content: '重新加载模型中', key: "restart", duration: 0 });
|
||||||
@ -618,7 +632,18 @@ const sendRestart = () => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 520px) {
|
||||||
|
.setting-container {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.card-select {
|
||||||
|
gap: 0.75rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user