feat(style): 优化主题和显示模式
- 新增经典、灰色主题 - 重构主题设置逻辑,支持平滑过渡 - 优化深色模式下的样式 - 调整按钮和图标的颜色设置 - 修复了一些样式相关的问题
This commit is contained in:
parent
995eb85166
commit
d6b06b5242
Binary file not shown.
After Width: | Height: | Size: 2.1 MiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 MiB |
|
@ -93,22 +93,23 @@ const handleDelete = async (conversationId) => {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
border: none;
|
border: none !important;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
outline: none !important;
|
||||||
|
|
||||||
&.icon-only {
|
&.icon-only {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover,
|
||||||
color: #07c160 !important;
|
|
||||||
background: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
color: var(--el-color-primary) !important;
|
||||||
box-shadow: none;
|
background: transparent !important;
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-icon) {
|
:deep(.el-icon) {
|
||||||
|
@ -116,6 +117,24 @@ const handleDelete = async (conversationId) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.el-dropdown__trigger) {
|
||||||
|
.el-button {
|
||||||
|
border: none !important;
|
||||||
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
outline: none !important;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border: none !important;
|
||||||
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
outline: none !important;
|
||||||
|
color: var(--el-color-primary) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.el-dropdown-menu__item) {
|
:deep(.el-dropdown-menu__item) {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
size="small"
|
size="small"
|
||||||
class="display-mode-group"
|
class="display-mode-group"
|
||||||
>
|
>
|
||||||
<el-radio-button label="system">
|
<el-radio-button value="system">
|
||||||
<span class="icon system"></span> 默认
|
<span class="icon system"></span> 默认
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
<el-radio-button label="light">
|
<el-radio-button value="light">
|
||||||
<span class="icon light"></span> 浅色
|
<span class="icon light"></span> 浅色
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
<el-radio-button label="dark">
|
<el-radio-button value="dark">
|
||||||
<span class="icon dark"></span> 深色
|
<span class="icon dark"></span> 深色
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
|
|
|
@ -32,8 +32,10 @@ const filteredThemes = computed(() => {
|
||||||
const themeLabels = {
|
const themeLabels = {
|
||||||
default: '默认',
|
default: '默认',
|
||||||
fresh: '清新',
|
fresh: '清新',
|
||||||
|
classic: '经典',
|
||||||
warm: '暖色',
|
warm: '暖色',
|
||||||
business: '商务',
|
business: '商务',
|
||||||
|
gray: '灰色',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getThemeLabel = (themeName) => {
|
const getThemeLabel = (themeName) => {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Sidebar from '../components/Sidebar.vue'
|
import Sidebar from './Sidebar.vue'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import "@/styles/style.css";
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||||
// 使用自定义主题
|
|
||||||
import '@/styles/element-variables.scss'
|
import '@/styles/element-variables.scss'
|
||||||
|
import "@/styles/style.css";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import {router} from "@/router/index";
|
import {router} from "@/router/index";
|
||||||
import { createPinia } from "pinia";
|
import { createPinia } from "pinia";
|
||||||
|
|
|
@ -62,7 +62,14 @@ export const useSettingsStore = defineStore('settings', {
|
||||||
updateDisplayMode(newMode) {
|
updateDisplayMode(newMode) {
|
||||||
if (['light', 'dark', 'system'].includes(newMode)) {
|
if (['light', 'dark', 'system'].includes(newMode)) {
|
||||||
this.displayMode = newMode;
|
this.displayMode = newMode;
|
||||||
applyDisplayMode(newMode); // Apply the change immediately
|
// Apply with transition if available
|
||||||
|
if (document.startViewTransition) {
|
||||||
|
document.startViewTransition(() => {
|
||||||
|
applyDisplayMode(newMode);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
applyDisplayMode(newMode); // Fallback
|
||||||
|
}
|
||||||
// Optional: Re-apply theme colors if they differ significantly in dark mode
|
// Optional: Re-apply theme colors if they differ significantly in dark mode
|
||||||
// setTheme(this.theme); // Uncomment if needed
|
// setTheme(this.theme); // Uncomment if needed
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,7 +81,14 @@ export const useSettingsStore = defineStore('settings', {
|
||||||
updateTheme(newTheme) {
|
updateTheme(newTheme) {
|
||||||
if (themes.hasOwnProperty(newTheme)) { // Check if the theme exists
|
if (themes.hasOwnProperty(newTheme)) { // Check if the theme exists
|
||||||
this.theme = newTheme;
|
this.theme = newTheme;
|
||||||
setTheme(newTheme); // Apply the theme colors
|
// Apply with transition if available
|
||||||
|
if (document.startViewTransition) {
|
||||||
|
document.startViewTransition(() => {
|
||||||
|
setTheme(newTheme);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setTheme(newTheme); // Fallback
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn(`Invalid theme: ${newTheme}`);
|
console.warn(`Invalid theme: ${newTheme}`);
|
||||||
}
|
}
|
||||||
|
@ -83,14 +97,53 @@ export const useSettingsStore = defineStore('settings', {
|
||||||
// 重置所有设置
|
// 重置所有设置
|
||||||
resetSettings() {
|
resetSettings() {
|
||||||
this.$reset()
|
this.$reset()
|
||||||
// Re-apply settings after reset
|
// Re-apply settings after reset, potentially with transition
|
||||||
setTheme(this.theme);
|
if (document.startViewTransition) {
|
||||||
applyDisplayMode(this.displayMode);
|
document.startViewTransition(() => {
|
||||||
this.toggleAnimations(this.animationsEnabled); // Re-apply animation class
|
setTheme(this.theme);
|
||||||
|
applyDisplayMode(this.displayMode);
|
||||||
|
this.toggleAnimations(this.animationsEnabled); // Include animation class update
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setTheme(this.theme);
|
||||||
|
applyDisplayMode(this.displayMode);
|
||||||
|
this.toggleAnimations(this.animationsEnabled); // Fallback
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// --- Helper Function to apply animation class ---
|
// --- Helper Function to apply animation class ---
|
||||||
// Moved applying logic into the toggleAnimations action directly
|
// Moved applying logic into the toggleAnimations action directly
|
||||||
// export function applyAnimationSetting(enabled) { ... }
|
// export function applyAnimationSetting(enabled) { ... }
|
||||||
|
|
||||||
|
// --- Watch for system theme changes ---
|
||||||
|
// Ensure this runs after Pinia is initialized if useSettingsStore is called immediately
|
||||||
|
// Placing it here runs it once when the module is imported.
|
||||||
|
if (window.matchMedia) {
|
||||||
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
|
||||||
|
const handleSystemThemeChange = () => {
|
||||||
|
// Need to get the store instance inside the handler
|
||||||
|
// Ensure Pinia is active before calling this
|
||||||
|
try {
|
||||||
|
const settingsStore = useSettingsStore();
|
||||||
|
if (settingsStore.displayMode === 'system') {
|
||||||
|
console.log('System theme changed, re-applying display mode.');
|
||||||
|
applyDisplayMode('system');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Pinia store not available yet for system theme change handler", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the listener
|
||||||
|
mediaQuery.addEventListener('change', handleSystemThemeChange);
|
||||||
|
|
||||||
|
// Optional: Cleanup listener if the store or app unmounts,
|
||||||
|
// though usually not strictly necessary for a global listener like this.
|
||||||
|
// Example (would need proper context, e.g., within app setup):
|
||||||
|
// onUnmounted(() => {
|
||||||
|
// mediaQuery.removeEventListener('change', handleSystemThemeChange);
|
||||||
|
// });
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
/* 自定义主题变量 */
|
/* 自定义主题变量 */
|
||||||
$--color-primary: #07c160;
|
|
||||||
|
|
||||||
/* 导入 Element Plus 样式 */
|
/* 导入 Element Plus 样式 */
|
||||||
@use "element-plus/theme-chalk/src/index.scss" as *;
|
@use "element-plus/theme-chalk/src/index.scss" as *;
|
|
@ -1,10 +1,14 @@
|
||||||
/* 基础样式 */
|
/* 基础样式 */
|
||||||
:root {
|
:root {
|
||||||
--primary-color: #409eff;
|
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
--success-color: #67c23a;
|
line-height: 1.5;
|
||||||
--warning-color: #e6a23c;
|
font-weight: 400;
|
||||||
--danger-color: #f56c6c;
|
|
||||||
--info-color: #909399;
|
color-scheme: light dark;
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 全局样式 */
|
/* 全局样式 */
|
||||||
|
@ -17,30 +21,6 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
:root {
|
|
||||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light only;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -53,30 +33,6 @@ body {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
/* max-width: 100vh; */
|
/* max-width: 100vh; */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -2,18 +2,82 @@
|
||||||
// { eager: true } 表示同步导入,立即获取模块内容
|
// { eager: true } 表示同步导入,立即获取模块内容
|
||||||
const themeModules = import.meta.glob('./themes/*.js', { eager: true });
|
const themeModules = import.meta.glob('./themes/*.js', { eager: true });
|
||||||
|
|
||||||
// 构建 themes 对象
|
// 构建 themes 对象,确保 default 优先
|
||||||
export const themes = {};
|
export const themes = {};
|
||||||
|
const defaultPath = './themes/default.js';
|
||||||
|
|
||||||
|
// 1. 首先处理 default 主题
|
||||||
|
if (themeModules[defaultPath] && themeModules[defaultPath].default) {
|
||||||
|
themes['default'] = themeModules[defaultPath].default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 处理其他主题
|
||||||
for (const path in themeModules) {
|
for (const path in themeModules) {
|
||||||
// 从路径中提取主题名称 (e.g., './themes/default.js' -> 'default')
|
// 跳过已经处理过的 default 主题
|
||||||
const themeName = path.replace('./themes/', '').replace('.js', '');
|
if (path === defaultPath) continue;
|
||||||
// 获取模块的默认导出 (即主题配置对象)
|
|
||||||
if (themeModules[path].default) {
|
// 从路径中提取主题名称 (e.g., './themes/default.js' -> 'default')
|
||||||
themes[themeName] = themeModules[path].default;
|
const themeName = path.replace('./themes/', '').replace('.js', '');
|
||||||
|
// 获取模块的默认导出 (即主题配置对象)
|
||||||
|
if (themeModules[path].default) {
|
||||||
|
themes[themeName] = themeModules[path].default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Color Manipulation Helpers ---
|
||||||
|
|
||||||
|
/** Converts HEX color to RGB object */
|
||||||
|
function hexToRgb(hex) {
|
||||||
|
let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||||
|
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
|
||||||
|
return r + r + g + g + b + b;
|
||||||
|
});
|
||||||
|
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
return result ? {
|
||||||
|
r: parseInt(result[1], 16),
|
||||||
|
g: parseInt(result[2], 16),
|
||||||
|
b: parseInt(result[3], 16)
|
||||||
|
} : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts RGB object to HEX color */
|
||||||
|
function rgbToHex(r, g, b) {
|
||||||
|
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mixes two colors (RGB objects) */
|
||||||
|
function mixColors(rgb1, rgb2, weight) {
|
||||||
|
weight = Math.max(0, Math.min(1, weight));
|
||||||
|
let w1 = weight;
|
||||||
|
let w2 = 1 - weight;
|
||||||
|
return {
|
||||||
|
r: Math.round(rgb1.r * w1 + rgb2.r * w2),
|
||||||
|
g: Math.round(rgb1.g * w1 + rgb2.g * w2),
|
||||||
|
b: Math.round(rgb1.b * w1 + rgb2.b * w2)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- End Color Helpers ---
|
||||||
|
|
||||||
|
// Helper function to apply display mode
|
||||||
|
export function applyDisplayMode(mode) {
|
||||||
|
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
let darkModeEnabled = false;
|
||||||
|
|
||||||
|
if (mode === 'dark') {
|
||||||
|
darkModeEnabled = true;
|
||||||
|
} else if (mode === 'system') {
|
||||||
|
darkModeEnabled = prefersDark;
|
||||||
|
} // else mode === 'light', darkModeEnabled remains false
|
||||||
|
|
||||||
|
if (darkModeEnabled) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主题切换函数
|
// --- Modified setTheme Function ---
|
||||||
export function setTheme(themeName) {
|
export function setTheme(themeName) {
|
||||||
const theme = themes[themeName] || themes.default // Fallback to default
|
const theme = themes[themeName] || themes.default // Fallback to default
|
||||||
if (!theme) {
|
if (!theme) {
|
||||||
|
@ -22,14 +86,61 @@ export function setTheme(themeName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
|
const white = { r: 255, g: 255, b: 255 }; // RGB for white
|
||||||
// 设置主题色变量
|
const black = { r: 0, g: 0, b: 0 }; // RGB for black
|
||||||
|
|
||||||
|
// 设置主题色变量 (包括 primary 的派生色)
|
||||||
Object.keys(theme).forEach(key => {
|
Object.keys(theme).forEach(key => {
|
||||||
root.style.setProperty(`--el-color-${key}`, theme[key])
|
const colorHex = theme[key];
|
||||||
})
|
if (!colorHex) return; // Skip if color is undefined
|
||||||
|
|
||||||
|
root.style.setProperty(`--el-color-${key}`, colorHex);
|
||||||
|
|
||||||
|
// Calculate and set shades/darken for primary color
|
||||||
|
if (key === 'primary') {
|
||||||
|
try {
|
||||||
|
const primaryRgb = hexToRgb(colorHex);
|
||||||
|
if (!primaryRgb) throw new Error('Invalid primary hex color');
|
||||||
|
|
||||||
|
// Set light shades (mix with white)
|
||||||
|
for (let i = 1; i <= 9; i++) {
|
||||||
|
const mixedRgb = mixColors(white, primaryRgb, i / 10);
|
||||||
|
root.style.setProperty(`--el-color-primary-light-${i}`, rgbToHex(mixedRgb.r, mixedRgb.g, mixedRgb.b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set dark shade - dark-2 (mix with black, 20%)
|
||||||
|
const dark2Rgb = mixColors(black, primaryRgb, 0.2);
|
||||||
|
root.style.setProperty(`--el-color-primary-dark-2`, rgbToHex(dark2Rgb.r, dark2Rgb.g, dark2Rgb.b));
|
||||||
|
|
||||||
|
// Set dark shade - dark-1 (mix with black, 10%) - NEW
|
||||||
|
const dark1Rgb = mixColors(black, primaryRgb, 0.1);
|
||||||
|
root.style.setProperty(`--el-color-primary-dark-1`, rgbToHex(dark1Rgb.r, dark1Rgb.g, dark1Rgb.b));
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to generate shades for primary color ${colorHex}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// --- TODO: Optionally add shade generation for success, warning, danger, info here ---
|
||||||
|
// Example for success:
|
||||||
|
/*
|
||||||
|
else if (key === 'success') {
|
||||||
|
try {
|
||||||
|
const successRgb = hexToRgb(colorHex);
|
||||||
|
if (!successRgb) throw new Error('Invalid success hex color');
|
||||||
|
for (let i = 1; i <= 9; i++) {
|
||||||
|
const mixedRgb = mixColors(white, successRgb, i / 10);
|
||||||
|
root.style.setProperty(`--el-color-success-light-${i}`, rgbToHex(mixedRgb.r, mixedRgb.g, mixedRgb.b));
|
||||||
|
}
|
||||||
|
// Add dark-2 if needed
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to generate shades for success color ${colorHex}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// Repeat for warning, danger, info if necessary based on your themes
|
||||||
|
});
|
||||||
|
|
||||||
// 设置主题类名
|
// 设置主题类名
|
||||||
// 查找 body 上是否已有 theme- 开头的类
|
|
||||||
const currentThemeClass = Array.from(document.body.classList).find(cls => cls.startsWith('theme-'));
|
const currentThemeClass = Array.from(document.body.classList).find(cls => cls.startsWith('theme-'));
|
||||||
if (currentThemeClass) {
|
if (currentThemeClass) {
|
||||||
document.body.classList.remove(currentThemeClass);
|
document.body.classList.remove(currentThemeClass);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
export default {
|
||||||
|
primary: '#409EFF',
|
||||||
|
success: '#67C23A',
|
||||||
|
warning: '#E6A23C',
|
||||||
|
danger: '#F56C6C',
|
||||||
|
info: '#909399'
|
||||||
|
};
|
|
@ -1,7 +0,0 @@
|
||||||
export default {
|
|
||||||
primary: '#5CACEE',
|
|
||||||
success: '#85CE61',
|
|
||||||
warning: '#E6A23C',
|
|
||||||
danger: '#F78989',
|
|
||||||
info: '#A6A9AD'
|
|
||||||
};
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
primary: '#409EFF',
|
primary: '#368F7C',
|
||||||
success: '#67C23A',
|
success: '#67C23A',
|
||||||
warning: '#E6A23C',
|
warning: '#E6A23C',
|
||||||
danger: '#F56C6C',
|
danger: '#F56C6C',
|
||||||
info: '#909399'
|
info: '#909399'
|
||||||
};
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
export default {
|
||||||
|
primary: '#606266', // Use Regular Text grey as primary for White theme
|
||||||
|
success: '#67C23A', // 标准成功绿
|
||||||
|
warning: '#E6A23C', // 标准警告橙
|
||||||
|
danger: '#F56C6C', // 标准危险红
|
||||||
|
info: '#909399' // 标准信息灰
|
||||||
|
};
|
|
@ -126,8 +126,8 @@ onUnmounted(() => {
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.chat-header {
|
.chat-header {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-bottom: 1px solid #e5e5e5;
|
border-bottom: 1px solid var(--el-border-color-light);
|
||||||
background: #FFF;
|
background: var(--el-color-primary-light-8);
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ onUnmounted(() => {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: #666;
|
color: var(--el-text-color-secondary);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
@ -159,7 +159,7 @@ onUnmounted(() => {
|
||||||
margin-left: -4px;
|
margin-left: -4px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #07c160;
|
color: var(--el-color-primary);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ onUnmounted(() => {
|
||||||
.title-text {
|
.title-text {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #333;
|
color: var(--el-text-color-primary);
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -190,7 +190,7 @@ onUnmounted(() => {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: #666;
|
color: var(--el-text-color-secondary);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
@ -199,7 +199,7 @@ onUnmounted(() => {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #07c160;
|
color: var(--el-color-primary);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,12 +223,13 @@ onUnmounted(() => {
|
||||||
:deep(.history-btn) {
|
:deep(.history-btn) {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
color: #666;
|
color: var(--el-text-color-secondary);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #07c160 !important;
|
color: var(--el-color-primary);
|
||||||
|
background-color: var(--el-color-primary-light-9);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-icon) {
|
:deep(.el-icon) {
|
||||||
|
@ -248,20 +249,21 @@ onUnmounted(() => {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: #666;
|
color: var(--el-text-color-secondary);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #07c160;
|
color: var(--el-color-primary);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.delete-btn {
|
&.delete-btn {
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--el-color-danger) !important;
|
color: var(--el-color-danger) !important;
|
||||||
|
background-color: var(--el-color-danger-light-9) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +279,12 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dark mode override
|
||||||
|
html.dark .chat-header {
|
||||||
|
background: var(--el-color-primary-dark-1);
|
||||||
|
border-bottom-color: var(--el-border-color-dark);
|
||||||
|
}
|
||||||
|
|
||||||
.user-info-content {
|
.user-info-content {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<!-- 用户消息 -->
|
<!-- 用户消息 -->
|
||||||
<div class="message">
|
<div class="message">
|
||||||
<div class="message-wrapper user">
|
<div class="message-wrapper user">
|
||||||
<div class="avatar"><span class="emoji">👤</span></div>
|
<el-avatar :src="userAvatarUrl" :size="40" class="avatar" />
|
||||||
<div class="message-content">
|
<div class="message-content">
|
||||||
<div class="message-text-wrapper">
|
<div class="message-text-wrapper">
|
||||||
<!-- <div v-if="message.createdAt" class="message-timestamp">
|
<!-- <div v-if="message.createdAt" class="message-timestamp">
|
||||||
|
@ -27,13 +27,15 @@
|
||||||
<div class="message-text">{{ message.question }}</div>
|
<div class="message-text">{{ message.question }}</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 改进建议部分 -->
|
<!-- 改进建议部分 -->
|
||||||
<div class="evaluation-toggle" @click="chatStore.toggleEvaluation(message.messageId)">
|
<el-button type="primary" link @click="chatStore.toggleEvaluation(message.messageId)" class="evaluation-toggle-btn">
|
||||||
<span class="evaluation-btn">改进建议</span>
|
改进建议
|
||||||
<span v-if="['pingfen', 'zongjie'].includes(message?.respondingType)" class="typing-indicator evaluation-icon">
|
<el-icon v-if="!['pingfen', 'zongjie'].includes(message?.respondingType)">
|
||||||
|
<component :is="message.showEvaluation ? CaretBottom : CaretRight" />
|
||||||
|
</el-icon>
|
||||||
|
<span v-else class="typing-indicator evaluation-icon">
|
||||||
<span></span><span></span><span></span>
|
<span></span><span></span><span></span>
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="evaluation-icon">{{ message.showEvaluation ? '▼' : '▶' }}</span>
|
</el-button>
|
||||||
</div>
|
|
||||||
<!-- 评价总结内容 -->
|
<!-- 评价总结内容 -->
|
||||||
<div v-if="message.showEvaluation && (message.pingfen || message.zongjie)" class="evaluation-section">
|
<div v-if="message.showEvaluation && (message.pingfen || message.zongjie)" class="evaluation-section">
|
||||||
<div class="evaluation-content">
|
<div class="evaluation-content">
|
||||||
|
@ -50,7 +52,7 @@
|
||||||
<!-- 回答 -->
|
<!-- 回答 -->
|
||||||
<div class="message">
|
<div class="message">
|
||||||
<div class="message-wrapper assistant">
|
<div class="message-wrapper assistant">
|
||||||
<div class="avatar"><span class="emoji">🤖</span></div>
|
<el-avatar :src="customAvatarUrl" :size="40" class="avatar" />
|
||||||
<div class="message-content">
|
<div class="message-content">
|
||||||
<div class="message-text-wrapper">
|
<div class="message-text-wrapper">
|
||||||
<!-- <div v-if="message.createdAt" class="message-timestamp">
|
<!-- <div v-if="message.createdAt" class="message-timestamp">
|
||||||
|
@ -102,7 +104,7 @@
|
||||||
<div v-if="lastMessageWithDafen" class="summary-panel" :class="{ 'summary-panel-collapsed': isSummaryCollapsed }">
|
<div v-if="lastMessageWithDafen" class="summary-panel" :class="{ 'summary-panel-collapsed': isSummaryCollapsed }">
|
||||||
<div class="summary-header" @click="toggleSummary">
|
<div class="summary-header" @click="toggleSummary">
|
||||||
<span class="summary-title">会话总结</span>
|
<span class="summary-title">会话总结</span>
|
||||||
<span v-if="['dafen'].includes(message?.respondingType)" class="typing-indicator evaluation-icon">
|
<span v-if="['dafen'].includes(lastMessageWithDafen?.respondingType)" class="typing-indicator evaluation-icon">
|
||||||
<span></span><span></span><span></span>
|
<span></span><span></span><span></span>
|
||||||
</span>
|
</span>
|
||||||
<span class="summary-toggle-icon">{{ isSummaryCollapsed ? '▼' : '▲' }}</span>
|
<span class="summary-toggle-icon">{{ isSummaryCollapsed ? '▼' : '▲' }}</span>
|
||||||
|
@ -118,8 +120,10 @@ import { marked } from 'marked'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { useChatStore } from '@/store/chat'
|
import { useChatStore } from '@/store/chat'
|
||||||
import ChatHeader from '@/views/chat/ChatHeader.vue'
|
import ChatHeader from '@/views/chat/ChatHeader.vue'
|
||||||
import { ElTag, ElButton, ElInput } from 'element-plus'
|
import { ElTag, ElButton, ElInput, ElAvatar } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { Plus, CaretBottom, CaretRight } from '@element-plus/icons-vue'
|
||||||
|
import userAvatarUrl from '@/assets/user.png';
|
||||||
|
import customAvatarUrl from '@/assets/custom.png';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ChatInterface'
|
name: 'ChatInterface'
|
||||||
|
@ -323,11 +327,16 @@ onUnmounted(() => {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #f5f5f5;
|
background-color: var(--el-bg-color-page);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dark mode override for chat container
|
||||||
|
html.dark .chat-container {
|
||||||
|
background-color: var(--el-color-primary-dark-1); // Use the new lighter dark shade
|
||||||
|
}
|
||||||
|
|
||||||
.chat-background {
|
.chat-background {
|
||||||
margin: 0 0 20px 0;
|
margin: 0 0 20px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -345,14 +354,14 @@ onUnmounted(() => {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background-color: #f4f4f5;
|
background-color: var(--el-fill-color-light);
|
||||||
border: 1px solid #e9e9eb;
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
color: #909399;
|
color: var(--el-text-color-secondary);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #e9e9eb;
|
background-color: var(--el-fill-color);
|
||||||
color: #606266;
|
color: var(--el-text-color-regular);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,10 +370,10 @@ onUnmounted(() => {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
background: #fff;
|
background: var(--el-bg-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
box-shadow: var(--el-box-shadow-light);
|
||||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
|
|
||||||
.background-content {
|
.background-content {
|
||||||
padding: 16px 24px 16px 16px;
|
padding: 16px 24px 16px 16px;
|
||||||
|
@ -385,19 +394,19 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: var(--el-border-color-darker);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: var(--el-border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.background-text {
|
.background-text {
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
color: #495057;
|
color: var(--el-text-color-regular);
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
|
|
||||||
:deep(p) {
|
:deep(p) {
|
||||||
|
@ -414,7 +423,7 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(strong) {
|
:deep(strong) {
|
||||||
color: #2c3e50;
|
color: var(--el-text-color-primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,26 +431,31 @@ onUnmounted(() => {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 0 0 16px 0;
|
margin: 0 0 16px 0;
|
||||||
color: #333;
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(h2) {
|
:deep(h2) {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 20px 0 12px 0;
|
margin: 20px 0 12px 0;
|
||||||
color: #333;
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(h3) {
|
:deep(h3) {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 16px 0 8px 0;
|
margin: 16px 0 8px 0;
|
||||||
color: #333;
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dark mode override for background content
|
||||||
|
html.dark .background-section .background-content {
|
||||||
|
background: var(--el-fill-color-light); // Use a neutral dark fill color
|
||||||
|
}
|
||||||
|
|
||||||
.chat-messages {
|
.chat-messages {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
@ -464,13 +478,13 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: var(--el-border-color-darker);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: var(--el-border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,7 +505,9 @@ onUnmounted(() => {
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
.message-text {
|
.message-text {
|
||||||
background-color: #95ec69;
|
background-color: var(--el-color-primary);
|
||||||
|
color: var(--el-color-white);
|
||||||
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
.message-content {
|
.message-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -504,8 +520,8 @@ onUnmounted(() => {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
.message-text {
|
.message-text {
|
||||||
background-color: #ffffff;
|
background-color: var(--el-bg-color);
|
||||||
color: #333333;
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
.message-content {
|
.message-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -518,18 +534,6 @@ onUnmounted(() => {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border-radius: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
||||||
|
|
||||||
.emoji {
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,16 +551,15 @@ onUnmounted(() => {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
.message-text {
|
.message-text {
|
||||||
min-height: 36px;
|
// min-width: 60px;
|
||||||
min-width: 60px;
|
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
box-shadow: var(--el-box-shadow-light);
|
||||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
|
@ -571,45 +574,28 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.evaluation-toggle {
|
.evaluation-toggle-btn {
|
||||||
display: flex!important;
|
padding: 6px 0; // Adjust padding for link button
|
||||||
cursor: pointer;
|
|
||||||
color: #576b95;
|
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
margin-top: 8px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
display: block;
|
|
||||||
width: fit-content;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: rgba(87, 107, 149, 0.08);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
border: 1px solid rgba(87, 107, 149, 0.1);
|
|
||||||
|
|
||||||
&:hover {
|
.el-icon {
|
||||||
background: rgba(87, 107, 149, 0.15);
|
margin-left: 4px;
|
||||||
border-color: rgba(87, 107, 149, 0.2);
|
vertical-align: middle;
|
||||||
}
|
|
||||||
|
|
||||||
.evaluation-btn {
|
|
||||||
padding-right: 4px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.evaluation-icon {
|
.evaluation-icon {
|
||||||
font-size: 12px;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
|
|
||||||
&.typing-indicator {
|
&.typing-indicator {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
|
margin-left: 4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
width: 4px;
|
width: 4px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: #576b95;
|
background: var(--el-color-primary);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: bounce 1.4s infinite ease-in-out;
|
animation: bounce 1.4s infinite ease-in-out;
|
||||||
|
|
||||||
|
@ -624,18 +610,17 @@ onUnmounted(() => {
|
||||||
.evaluation-section {
|
.evaluation-section {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: #fff;
|
background: var(--el-bg-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
box-shadow: var(--el-box-shadow-light);
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.evaluation-content {
|
.evaluation-content {
|
||||||
padding: 16px 24px 16px 16px;
|
padding: 16px 24px 16px 16px;
|
||||||
background: #f8f9fa;
|
background: var(--el-fill-color-light);
|
||||||
// max-height: 480px;
|
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -651,19 +636,19 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: var(--el-border-color-darker);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: var(--el-border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.evaluation-text {
|
.evaluation-text {
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
color: #495057;
|
color: var(--el-text-color-regular);
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -686,12 +671,12 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(strong) {
|
:deep(strong) {
|
||||||
color: #2c3e50;
|
color: var(--el-text-color-primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(em) {
|
:deep(em) {
|
||||||
color: #6c757d;
|
color: var(--el-text-color-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,9 +692,9 @@ onUnmounted(() => {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: #f5f5f5;
|
background: var(--el-color-primary-light-8);
|
||||||
border-top: 1px solid #e5e5e5;
|
border-top: 1px solid var(--el-border-color-light);
|
||||||
|
z-index: 3;
|
||||||
:deep(.el-textarea) {
|
:deep(.el-textarea) {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
|
@ -719,34 +704,40 @@ onUnmounted(() => {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border-color: #dcdfe6;
|
border-color: var(--el-border-color);
|
||||||
background-color: #fff;
|
background-color: var(--el-bg-color);
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #c0c4cc;
|
border-color: var(--el-border-color-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: var(--el-color-primary);
|
border-color: var(--el-color-primary);
|
||||||
box-shadow: 0 0 0 2px rgba(7, 193, 96, 0.1);
|
box-shadow: 0 0 0 2px var(--el-color-primary-light-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background-color: #f5f5f5;
|
background-color: var(--el-fill-color-light);
|
||||||
border-color: #e0e0e0;
|
border-color: var(--el-border-color-lighter);
|
||||||
color: #999;
|
color: var(--el-text-color-placeholder);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: #999;
|
color: var(--el-text-color-placeholder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dark mode override for input area
|
||||||
|
html.dark .input-area {
|
||||||
|
background: var(--el-color-primary-dark-1); // Dark 1 (Lighter dark)
|
||||||
|
border-top-color: var(--el-border-color-dark); // Use standard dark border
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.el-button) {
|
:deep(.el-button) {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
@ -755,22 +746,22 @@ onUnmounted(() => {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
&.is-disabled {
|
&.is-disabled {
|
||||||
background-color: #f5f5f5 !important;
|
background-color: var(--el-fill-color-light) !important;
|
||||||
border-color: #dcdfe6 !important;
|
border-color: var(--el-border-color) !important;
|
||||||
color: #999 !important;
|
color: var(--el-text-color-placeholder) !important;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.new-chat-btn {
|
&.new-chat-btn {
|
||||||
--el-button-bg-color: #f2f3f5;
|
--el-button-bg-color: var(--el-fill-color-light);
|
||||||
--el-button-border-color: #dcdfe6;
|
--el-button-border-color: var(--el-border-color);
|
||||||
--el-button-text-color: #606266;
|
--el-button-text-color: var(--el-text-color-regular);
|
||||||
--el-button-hover-bg-color: #e9ecef;
|
--el-button-hover-bg-color: var(--el-fill-color);
|
||||||
--el-button-hover-border-color: #c0c4cc;
|
--el-button-hover-border-color: var(--el-border-color-hover);
|
||||||
--el-button-hover-text-color: #303133;
|
--el-button-hover-text-color: var(--el-text-color-primary);
|
||||||
--el-button-active-bg-color: #e9ecef;
|
--el-button-active-bg-color: var(--el-fill-color);
|
||||||
--el-button-active-border-color: #c0c4cc;
|
--el-button-active-border-color: var(--el-border-color-hover);
|
||||||
--el-button-active-text-color: #303133;
|
--el-button-active-text-color: var(--el-text-color-primary);
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -792,9 +783,9 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-disabled {
|
&.is-disabled {
|
||||||
background-color: #f5f5f5 !important;
|
background-color: var(--el-fill-color-light) !important;
|
||||||
border-color: #dcdfe6 !important;
|
border-color: var(--el-border-color) !important;
|
||||||
color: #999 !important;
|
color: var(--el-text-color-placeholder) !important;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -805,12 +796,12 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-button--primary) {
|
:deep(.el-button--primary) {
|
||||||
--el-button-bg-color: #07c160;
|
--el-button-bg-color: var(--el-color-primary);
|
||||||
--el-button-border-color: #07c160;
|
--el-button-border-color: var(--el-color-primary);
|
||||||
--el-button-hover-bg-color: #06ae56;
|
--el-button-hover-bg-color: var(--el-color-primary-light-3);
|
||||||
--el-button-hover-border-color: #06ae56;
|
--el-button-hover-border-color: var(--el-color-primary-light-3);
|
||||||
--el-button-active-bg-color: #06ae56;
|
--el-button-active-bg-color: var(--el-color-primary-light-3);
|
||||||
--el-button-active-border-color: #06ae56;
|
--el-button-active-border-color: var(--el-color-primary-light-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-chat-btn {
|
.new-chat-btn {
|
||||||
|
@ -858,7 +849,8 @@ onUnmounted(() => {
|
||||||
/* 统一的滚动条样式 */
|
/* 统一的滚动条样式 */
|
||||||
.chat-messages,
|
.chat-messages,
|
||||||
.summary-content,
|
.summary-content,
|
||||||
.evaluation-content {
|
.evaluation-content,
|
||||||
|
.background-content {
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
|
@ -871,13 +863,13 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: var(--el-border-color-darker);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: var(--el-border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -905,11 +897,10 @@ onUnmounted(() => {
|
||||||
|
|
||||||
.user {
|
.user {
|
||||||
.message-text {
|
.message-text {
|
||||||
background-color: #95ec69;
|
border-color: transparent;
|
||||||
border-color: rgba(0, 0, 0, 0.08);
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
border-right-color: #95ec69;
|
border-right-color: var(--el-color-primary);
|
||||||
right: 100%;
|
right: 100%;
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
@ -918,11 +909,11 @@ onUnmounted(() => {
|
||||||
|
|
||||||
.assistant {
|
.assistant {
|
||||||
.message-text {
|
.message-text {
|
||||||
background-color: #ffffff;
|
background-color: var(--el-bg-color);
|
||||||
border-color: rgba(0, 0, 0, 0.08);
|
border-color: var(--el-border-color-lighter);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
border-right-color: #ffffff;
|
border-right-color: var(--el-bg-color);
|
||||||
right: 100%;
|
right: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -944,7 +935,7 @@ onUnmounted(() => {
|
||||||
span {
|
span {
|
||||||
width: 4px;
|
width: 4px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: #999;
|
background: var(--el-text-color-placeholder);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: bounce 1.4s infinite ease-in-out;
|
animation: bounce 1.4s infinite ease-in-out;
|
||||||
|
|
||||||
|
@ -958,36 +949,23 @@ onUnmounted(() => {
|
||||||
40% { transform: scale(1); }
|
40% { transform: scale(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.evaluation-toggle {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.evaluation-text {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-panel {
|
.summary-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 80px;
|
bottom: 80px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
background: #fff;
|
background: var(--el-bg-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: var(--el-box-shadow-light);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
z-index: 100;
|
z-index: 2;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
|
|
||||||
&.summary-panel-collapsed {
|
&.summary-panel-collapsed {
|
||||||
max-height: 42px; // 标题栏的高度
|
max-height: 42px;
|
||||||
|
|
||||||
.summary-content {
|
.summary-content {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -1005,21 +983,21 @@ onUnmounted(() => {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
background: #f8f9fa;
|
background: var(--el-fill-color-light);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-bottom: 1px solid #e9ecef;
|
border-bottom: 1px solid var(--el-border-color-light);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 42px;
|
height: 24px;
|
||||||
|
|
||||||
.summary-title {
|
.summary-title {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #2c3e50;
|
color: var(--el-text-color-primary);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-toggle-icon {
|
.summary-toggle-icon {
|
||||||
color: #6c757d;
|
color: var(--el-text-color-secondary);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
@ -1031,8 +1009,8 @@ onUnmounted(() => {
|
||||||
max-height: 250px;
|
max-height: 250px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: #fff;
|
background: var(--el-bg-color);
|
||||||
color: #495057;
|
color: var(--el-text-color-regular);
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
@ -1056,20 +1034,20 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(strong) {
|
:deep(strong) {
|
||||||
color: #2c3e50;
|
color: var(--el-text-color-primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(em) {
|
:deep(em) {
|
||||||
color: #6c757d;
|
color: var(--el-text-color-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(code) {
|
:deep(code) {
|
||||||
background: #f8f9fa;
|
background: var(--el-fill-color-light);
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #e83e8c;
|
color: var(--el-color-primary);
|
||||||
font-family: 'Courier New', Courier, monospace;
|
font-family: 'Courier New', Courier, monospace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1055,7 @@ onUnmounted(() => {
|
||||||
|
|
||||||
.message-timestamp {
|
.message-timestamp {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #999;
|
color: var(--el-text-color-secondary);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -20px;
|
top: -20px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -1096,15 +1074,15 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-text {
|
.message-text {
|
||||||
min-height: 36px;
|
// min-width: 60px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
box-shadow: var(--el-box-shadow-light);
|
||||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
|
@ -1128,9 +1106,9 @@ onUnmounted(() => {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background-color: #f4f4f5;
|
background-color: var(--el-fill-color-light);
|
||||||
border-color: #e9e9eb;
|
border-color: var(--el-border-color-lighter);
|
||||||
color: #909399;
|
color: var(--el-text-color-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -8,9 +8,14 @@
|
||||||
></div>
|
></div>
|
||||||
<div class="mode-selector" :class="{ 'collapsed': settingsStore.sidebarCollapsed }">
|
<div class="mode-selector" :class="{ 'collapsed': settingsStore.sidebarCollapsed }">
|
||||||
<div class="mode-header">
|
<div class="mode-header">
|
||||||
|
<!-- Expanded Logo -->
|
||||||
<div class="mode-header-title" v-if="!settingsStore.sidebarCollapsed">
|
<div class="mode-header-title" v-if="!settingsStore.sidebarCollapsed">
|
||||||
<img src="/lgogo.svg" alt="Logo" class="mode-header-icon" />
|
<img src="/lgogo.svg" alt="Logo" class="mode-header-icon" />
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Collapsed Logo -->
|
||||||
|
<div class="mode-header-collapsed-logo" v-if="settingsStore.sidebarCollapsed">
|
||||||
|
<img src="/logo.svg" alt="Logo" class="mode-header-icon collapsed" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-menu
|
<el-menu
|
||||||
:default-active="chatStore.currentMode"
|
:default-active="chatStore.currentMode"
|
||||||
|
@ -34,7 +39,7 @@
|
||||||
<div class="sidebar-footer">
|
<div class="sidebar-footer">
|
||||||
<div class="settings-button" title="设置">
|
<div class="settings-button" title="设置">
|
||||||
<el-icon><Setting /></el-icon>
|
<el-icon><Setting /></el-icon>
|
||||||
<span class="button-text">设置</span>
|
<span v-if="!settingsStore.sidebarCollapsed" class="button-text">设置</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -101,7 +106,7 @@ onUnmounted(() => {
|
||||||
.mode-selector {
|
.mode-selector {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--el-bg-color);
|
background-color: var(--el-color-primary-light-7);
|
||||||
border-right: 1px solid var(--el-border-color-light);
|
border-right: 1px solid var(--el-border-color-light);
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
@ -165,12 +170,12 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-active {
|
&.is-active {
|
||||||
background-image: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%);
|
background-image: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%);
|
||||||
color: white;
|
color: var(--el-color-white);
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
.el-icon {
|
.el-icon {
|
||||||
color: white;
|
color: var(--el-color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,6 +239,26 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-selector.collapsed {
|
.mode-selector.collapsed {
|
||||||
|
.mode-header {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 60px;
|
||||||
|
|
||||||
|
.mode-header-collapsed-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-header-icon.collapsed {
|
||||||
|
height: 32px;
|
||||||
|
filter: drop-shadow(0 0 0.75em rgba(var(--el-color-primary-rgb), 0.6));
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mode-menu {
|
.mode-menu {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
|
@ -267,66 +292,236 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-footer {
|
.sidebar-footer {
|
||||||
padding: 8px;
|
height: 48px;
|
||||||
margin-top: auto;
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-button {
|
.settings-button {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 44px;
|
height: 40px;
|
||||||
line-height: 44px;
|
width: 100%;
|
||||||
|
padding: 0 12px;
|
||||||
color: var(--el-text-color-regular);
|
color: var(--el-text-color-regular);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 0 12px !important;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||||
|
|
||||||
body:not(.no-animations) & {
|
|
||||||
transition: background-color 0.3s, color 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-icon {
|
.el-icon {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
color: var(--el-text-color-regular);
|
}
|
||||||
body:not(.no-animations) & {
|
|
||||||
transition: color 0.3s;
|
&:hover {
|
||||||
}
|
background-color: var(--el-fill-color-light);
|
||||||
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-text {
|
.button-text {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-left: 12px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0);
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
|
||||||
body:not(.no-animations) & {
|
|
||||||
transition: opacity 0.3s ease-in-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--el-color-primary-light-9);
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-selector.collapsed {
|
.mode-selector.collapsed {
|
||||||
.sidebar-footer {
|
.sidebar-footer {
|
||||||
padding: 8px 12px;
|
padding: 0;
|
||||||
.settings-button {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-button {
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-text {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.settings-popover-popper {
|
||||||
|
min-width: 350px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: var(--el-box-shadow-light);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.mode-selector {
|
||||||
|
width: 240px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--el-color-primary-light-7);
|
||||||
|
border-right: 1px solid var(--el-border-color-light);
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
body:not(.no-animations) & {
|
||||||
|
transition: width 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
width: 64px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-header {
|
||||||
|
height: 60px;
|
||||||
|
padding: 0 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.mode-header-icon {
|
||||||
|
height: 32px;
|
||||||
|
will-change: filter;
|
||||||
|
|
||||||
|
body:not(.no-animations) & {
|
||||||
|
transition: filter 300ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: drop-shadow(0 0 0.75em rgba(var(--el-color-primary-rgb), 0.6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-menu {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 8px;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
:deep(.el-menu-item) {
|
||||||
|
height: 44px;
|
||||||
|
line-height: 44px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
padding: 0 12px !important;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-image: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%);
|
||||||
|
color: var(--el-color-white);
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
color: var(--el-color-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.is-active):hover {
|
||||||
|
background-color: var(--el-color-primary-light-9);
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-name {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
|
||||||
|
body:not(.no-animations) & {
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-setting-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端样式 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.mode-selector-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: var(--el-overlay-color-lighter);
|
||||||
|
z-index: 9;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-selector {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-selector.collapsed {
|
||||||
|
.mode-header {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 60px;
|
||||||
|
|
||||||
|
.mode-header-collapsed-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-header-icon.collapsed {
|
||||||
|
height: 32px;
|
||||||
|
filter: drop-shadow(0 0 0.75em rgba(var(--el-color-primary-rgb), 0.6));
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mode-menu {
|
.mode-menu {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
|
@ -350,18 +545,99 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-button {
|
.settings-button {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
.mode-name,
|
.mode-name,
|
||||||
.button-text {
|
.button-text {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-footer {
|
||||||
|
height: 48px;
|
||||||
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 40px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 12px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-text {
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-selector.collapsed {
|
||||||
|
.sidebar-footer {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-button {
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-text {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.settings-popover-popper {
|
.settings-popover-popper {
|
||||||
|
min-width: 350px !important;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
min-width: 240px !important;
|
border: none !important;
|
||||||
width: auto !important;
|
box-shadow: var(--el-box-shadow-light);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
/* Dark mode override */
|
||||||
|
html.dark .mode-selector {
|
||||||
|
background-color: var(--el-color-primary-dark-2);
|
||||||
|
border-right-color: var(--el-border-color-dark);
|
||||||
|
|
||||||
|
/* Dark mode hover */
|
||||||
|
.mode-menu :deep(.el-menu-item):not(.is-active):hover {
|
||||||
|
background-color: var(--el-fill-color);
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -39,7 +39,7 @@ const handleModeChange = (mode) => {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #f5f5f5;
|
background-color: var(--el-bg-color-page);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-container {
|
.chat-container {
|
||||||
|
@ -52,7 +52,7 @@ const handleModeChange = (mode) => {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #f5f5f5;
|
background-color: var(--el-bg-color-page);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ import mkcert from "vite-plugin-mkcert";
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig(({ command, mode }) => {
|
export default defineConfig(({ command, mode }) => {
|
||||||
const env = loadEnv(mode, process.cwd())
|
const env = loadEnv(mode, process.cwd())
|
||||||
console.log('env', env)
|
console.log('\x1b[36m%s\x1b[0m', '[VITE_APP_ENV]', env.VITE_APP_ENV)
|
||||||
|
console.log('\x1b[33m%s\x1b[0m', '[VITE_APP_BASE_API]', env.VITE_APP_BASE_API)
|
||||||
|
|
||||||
// 将环境变量转换为 process.env 格式
|
// 将环境变量转换为 process.env 格式
|
||||||
const processEnv = {}
|
const processEnv = {}
|
||||||
Object.keys(env).forEach(key => {
|
Object.keys(env).forEach(key => {
|
||||||
|
@ -37,7 +39,7 @@ export default defineConfig(({ command, mode }) => {
|
||||||
css: {
|
css: {
|
||||||
preprocessorOptions: {
|
preprocessorOptions: {
|
||||||
scss: {
|
scss: {
|
||||||
additionalData: ``
|
api: 'modern-compiler'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue