feat: update UI components and settings structure, remove unused icons
This commit is contained in:
@@ -7,4 +7,5 @@
|
|||||||
5、一键打开渠道可以新增渠道 - 完成
|
5、一键打开渠道可以新增渠道 - 完成
|
||||||
6、把龙虾包装到对话
|
6、把龙虾包装到对话
|
||||||
7、迁移频道功能
|
7、迁移频道功能
|
||||||
8、迁移agent功能
|
8、迁移agent功能
|
||||||
|
9、知识库调整成上传文件,查看文件列表
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
import { SendHorizontal, Square, X, Paperclip, FileText, Film, Music, FileArchive, File, Loader2, AtSign } from 'lucide-react';
|
||||||
import type { AttachedFileMeta } from '../../shared/chat-model';
|
import type { AttachedFileMeta } from '../../shared/chat-model';
|
||||||
|
|
||||||
type ChatComposerProps = {
|
type ChatComposerProps = {
|
||||||
@@ -32,9 +33,6 @@ export default function ChatComposer({
|
|||||||
<div className="border-t border-[#edf2f7] px-6 py-4 dark:border-[#2a2a2d]">
|
<div className="border-t border-[#edf2f7] px-6 py-4 dark:border-[#2a2a2d]">
|
||||||
<div className="rounded-[18px] border border-[#dfeaf6] bg-white p-4 shadow-[0_10px_30px_rgba(15,23,42,0.04)] dark:border-[#2a2a2d] dark:bg-[#1f1f22]">
|
<div className="rounded-[18px] border border-[#dfeaf6] bg-white p-4 shadow-[0_10px_30px_rgba(15,23,42,0.04)] dark:border-[#2a2a2d] dark:bg-[#1f1f22]">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<div className="mt-1 flex h-9 w-9 flex-none items-center justify-center rounded-full bg-[#eff6ff] text-xs font-bold text-[#2B7FFF] dark:bg-[#222225]">
|
|
||||||
AI
|
|
||||||
</div>
|
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
{error ? (
|
{error ? (
|
||||||
<div className="mb-3 flex items-center justify-between gap-3 rounded-[14px] border border-[#fecaca] bg-[#fff1f2] px-4 py-3 text-sm text-[#b91c1c] dark:border-[#7f1d1d] dark:bg-[#2d1618] dark:text-[#fca5a5]">
|
<div className="mb-3 flex items-center justify-between gap-3 rounded-[14px] border border-[#fecaca] bg-[#fff1f2] px-4 py-3 text-sm text-[#b91c1c] dark:border-[#7f1d1d] dark:bg-[#2d1618] dark:text-[#fca5a5]">
|
||||||
@@ -100,21 +98,14 @@ export default function ChatComposer({
|
|||||||
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
||||||
onClick={() => fileInputRef.current?.click()}
|
onClick={() => fileInputRef.current?.click()}
|
||||||
>
|
>
|
||||||
添加附件
|
<Paperclip className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
||||||
onClick={isSending ? onStop : onSend}
|
onClick={isSending ? onStop : onSend}
|
||||||
>
|
>
|
||||||
{isSending ? '停止生成' : '发送消息'}
|
{isSending ? <Square className="h-4 w-4" /> : <SendHorizontal className="h-4 w-4" />}
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
|
||||||
onClick={() => onChange('')}
|
|
||||||
>
|
|
||||||
清空输入
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ function ChatHistoryPanel({
|
|||||||
|
|
||||||
{!isCompact ? (
|
{!isCompact ? (
|
||||||
<div className={cx('flex min-w-0 items-center gap-3', isCompact && 'flex-col gap-2')}>
|
<div className={cx('flex min-w-0 items-center gap-3', isCompact && 'flex-col gap-2')}>
|
||||||
<div className="flex h-12 w-12 flex-none items-center justify-center overflow-hidden rounded-[16px] border border-white bg-white shadow-[0_6px_16px_rgba(15,23,42,0.08)]">
|
<div className="flex h-12 w-12 flex-none items-center justify-center overflow-hidden rounded-2xl border border-white bg-white shadow-[0_6px_16px_rgba(15,23,42,0.08)]">
|
||||||
<img className="h-full w-full object-cover" src={blueLogo} alt="YINIAN" />
|
<img className="h-full w-full object-cover" src={blueLogo} alt="YINIAN" />
|
||||||
</div>
|
</div>
|
||||||
<div className="truncate text-[20px] font-semibold whitespace-nowrap tracking-[0.06em] text-[#111827] dark:text-gray-50">
|
<div className="truncate text-[20px] font-semibold whitespace-nowrap tracking-[0.06em] text-[#111827] dark:text-gray-50">
|
||||||
@@ -132,7 +132,7 @@ function ChatHistoryPanel({
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="inline-flex h-12 w-12 items-center justify-center text-[#64748b] transition-colors border border-white hover:text-[#111827] rounded-[14px] dark:border-[#2a2a2d] dark:text-gray-300 dark:hover:border-[#3a3a3f] dark:hover:text-gray-100"
|
className={cx('inline-flex h-12 w-12 items-center justify-center text-[#64748b] transition-colors border hover:text-[#111827] rounded-lg dark:border-[#2a2a2d] dark:text-gray-300 dark:hover:border-[#3a3a3f] dark:hover:text-gray-100', isCompact ? 'border-[#e3eaf3]' : 'border-transparent')}
|
||||||
title={isCompact ? '展开侧栏' : '收起侧栏'}
|
title={isCompact ? '展开侧栏' : '收起侧栏'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMenuState(null);
|
setMenuState(null);
|
||||||
@@ -153,7 +153,7 @@ function ChatHistoryPanel({
|
|||||||
onClick={onNewChat}
|
onClick={onNewChat}
|
||||||
>
|
>
|
||||||
<Plus className="h-5 w-5 flex-none" />
|
<Plus className="h-5 w-5 flex-none" />
|
||||||
{!isCompact ? <span>新对话</span> : null}
|
{!isCompact ? <span className='whitespace-nowrap'>新对话</span> : null}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="min-h-0 flex-1 overflow-y-auto pt-4">
|
<div className="min-h-0 flex-1 overflow-y-auto pt-4">
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const MENU_MARKS: Record<string, typeof House> = {
|
|||||||
'/models': Cpu,
|
'/models': Cpu,
|
||||||
'/skills': Puzzle,
|
'/skills': Puzzle,
|
||||||
'/cron': Clock,
|
'/cron': Clock,
|
||||||
'/scripts': Code,
|
// '/scripts': Code,
|
||||||
'/setting': Settings,
|
'/setting': Settings,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { RefreshCw
|
||||||
|
} from 'lucide-react';
|
||||||
import type { RawMessage } from '../../shared/chat-model';
|
import type { RawMessage } from '../../shared/chat-model';
|
||||||
import { extractText, isInternalMessage } from '../../shared/chat-model';
|
import { extractText, isInternalMessage } from '../../shared/chat-model';
|
||||||
import { taskCenterList, type TaskCenterItem } from '../../constants/taskCenterList';
|
import { taskCenterList, type TaskCenterItem } from '../../constants/taskCenterList';
|
||||||
@@ -391,7 +393,7 @@ export default function HomePage() {
|
|||||||
onDeleteConversation={handleDeleteConversation}
|
onDeleteConversation={handleDeleteConversation}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
<div className="flex min-h-0 min-w-0 flex-1 flex-col border-l border-[#edf2f7] dark:border-[#2a2a2d] overflow-hidden">
|
||||||
<div className="flex items-center justify-between border-b border-[#edf2f7] px-6 py-4 dark:border-[#2a2a2d]">
|
<div className="flex items-center justify-between border-b border-[#edf2f7] px-6 py-4 dark:border-[#2a2a2d]">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-base font-semibold text-[#171717] dark:text-gray-100">智能对话</h2>
|
<h2 className="text-base font-semibold text-[#171717] dark:text-gray-100">智能对话</h2>
|
||||||
@@ -424,7 +426,7 @@ export default function HomePage() {
|
|||||||
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
|
||||||
onClick={handleRefreshConversationData}
|
onClick={handleRefreshConversationData}
|
||||||
>
|
>
|
||||||
刷新会话
|
<RefreshCw className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -434,7 +436,7 @@ export default function HomePage() {
|
|||||||
<HomeChatComposerSection />
|
<HomeChatComposerSection />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-t border-[#edf2f7] dark:border-[#2a2a2d]">
|
{/* <div className="border-t border-[#edf2f7] dark:border-[#2a2a2d]">
|
||||||
<div className="px-4 py-3">
|
<div className="px-4 py-3">
|
||||||
<div className="flex items-center justify-between pb-3">
|
<div className="flex items-center justify-between pb-3">
|
||||||
<h3 className="text-base font-semibold text-[#171717] dark:text-gray-100">任务中心</h3>
|
<h3 className="text-base font-semibold text-[#171717] dark:text-gray-100">任务中心</h3>
|
||||||
@@ -499,7 +501,7 @@ export default function HomePage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import { Moon, Sun, Monitor, RefreshCw } from 'lucide-react';
|
||||||
import { useI18n } from '../../../i18n';
|
import { useI18n } from '../../../i18n';
|
||||||
import { SUPPORTED_LANGUAGE_CODES } from '../../../i18n/constants';
|
import { SUPPORTED_LANGUAGE_CODES } from '../../../i18n/constants';
|
||||||
import type { LanguageCode, ThemeMode } from '../../../types/runtime';
|
import type { LanguageCode, ThemeMode } from '../../../types/runtime';
|
||||||
import type { SettingUpdateState } from '../useSettingUpdateState';
|
import type { SettingUpdateState } from '../useSettingUpdateState';
|
||||||
import SectionHeader from './SectionHeader';
|
import SectionHeader from './SectionHeader';
|
||||||
import { ComputerIcon, MoonIcon, RefreshIcon, SunIcon } from './SettingIcons';
|
|
||||||
import ToggleSwitch from './ToggleSwitch';
|
import ToggleSwitch from './ToggleSwitch';
|
||||||
|
|
||||||
type GeneralSettingsPanelProps = {
|
type GeneralSettingsPanelProps = {
|
||||||
@@ -16,12 +16,12 @@ type GeneralSettingsPanelProps = {
|
|||||||
|
|
||||||
const THEME_OPTIONS: Array<{
|
const THEME_OPTIONS: Array<{
|
||||||
value: ThemeMode;
|
value: ThemeMode;
|
||||||
icon: typeof SunIcon;
|
icon: typeof Sun | typeof Moon | typeof Monitor;
|
||||||
labelPath: 'theme.light' | 'theme.dark' | 'theme.system';
|
labelPath: 'theme.light' | 'theme.dark' | 'theme.system';
|
||||||
}> = [
|
}> = [
|
||||||
{ value: 'light', icon: SunIcon, labelPath: 'theme.light' },
|
{ value: 'light', icon: Sun, labelPath: 'theme.light' },
|
||||||
{ value: 'dark', icon: MoonIcon, labelPath: 'theme.dark' },
|
{ value: 'dark', icon: Moon, labelPath: 'theme.dark' },
|
||||||
{ value: 'system', icon: ComputerIcon, labelPath: 'theme.system' },
|
{ value: 'system', icon: Monitor, labelPath: 'theme.system' },
|
||||||
];
|
];
|
||||||
|
|
||||||
function getUpdateStatusText(t: ReturnType<typeof useI18n>['t'], updateState: SettingUpdateState) {
|
function getUpdateStatusText(t: ReturnType<typeof useI18n>['t'], updateState: SettingUpdateState) {
|
||||||
@@ -59,14 +59,14 @@ export default function GeneralSettingsPanel({
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex-1 h-full p-[20px] select-none">
|
<section className="flex-1 h-full p-5 select-none">
|
||||||
<SectionHeader
|
<SectionHeader
|
||||||
title={t('settings.general.title')}
|
title={t('settings.general.title')}
|
||||||
description={t('settings.general.description')}
|
description={t('settings.general.description')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="mt-[20px] box-border flex w-full items-center border-b border-dashed border-[#E5E8EE] py-[20px] dark:border-gray-700">
|
<div className="mt-5 box-border flex w-full items-center border-b border-dashed border-[#E5E8EE] py-5 dark:border-gray-700">
|
||||||
<div className="mr-[24px] whitespace-nowrap text-[16px] font-medium text-[#171717] dark:text-gray-100">
|
<div className="mr-6 whitespace-nowrap text-[16px] font-medium text-[#171717] dark:text-gray-100">
|
||||||
{t('settings.general.themeSection')}
|
{t('settings.general.themeSection')}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
@@ -97,8 +97,8 @@ export default function GeneralSettingsPanel({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-[20px] box-border flex w-full items-center border-b border-dashed border-[#E5E8EE] py-[20px] dark:border-gray-700">
|
<div className="mt-5 box-border flex w-full items-center border-b border-dashed border-[#E5E8EE] py-5 dark:border-gray-700">
|
||||||
<div className="mr-[24px] whitespace-nowrap text-[16px] font-medium text-[#171717] dark:text-gray-100">
|
<div className="mr-6 whitespace-nowrap text-[16px] font-medium text-[#171717] dark:text-gray-100">
|
||||||
{t('settings.general.languageSection')}
|
{t('settings.general.languageSection')}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
@@ -126,14 +126,14 @@ export default function GeneralSettingsPanel({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-[40px]">
|
<div className="mt-10">
|
||||||
<div className="mb-[24px] text-[24px] font-medium text-[#171717] dark:text-gray-100">
|
<div className="mb-6 text-[24px] font-medium text-[#171717] dark:text-gray-100">
|
||||||
{t('settings.general.updatesTitle')}
|
{t('settings.general.updatesTitle')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-[16px] flex items-center justify-between gap-4">
|
<div className="mb-4 flex items-center justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-[4px] text-[14px] text-[#525866] dark:text-gray-400">
|
<div className="mb-1 text-[14px] text-[#525866] dark:text-gray-400">
|
||||||
{t('settings.general.currentVersion')}
|
{t('settings.general.currentVersion')}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[28px] font-bold text-[#171717] dark:text-gray-100">
|
<div className="text-[28px] font-bold text-[#171717] dark:text-gray-100">
|
||||||
@@ -143,13 +143,13 @@ export default function GeneralSettingsPanel({
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="rounded-full p-[8px] transition-colors hover:bg-gray-100 dark:hover:bg-gray-800"
|
className="rounded-full p-2 transition-colors hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
void updateState.checkUpdate();
|
void updateState.checkUpdate();
|
||||||
}}
|
}}
|
||||||
aria-label={t('settings.general.checkForUpdates')}
|
aria-label={t('settings.general.checkForUpdates')}
|
||||||
>
|
>
|
||||||
<RefreshIcon
|
<RefreshCw
|
||||||
className={[
|
className={[
|
||||||
'h-5 w-5 text-[#525866] dark:text-gray-400',
|
'h-5 w-5 text-[#525866] dark:text-gray-400',
|
||||||
updateState.status === 'checking' ? 'animate-spin' : '',
|
updateState.status === 'checking' ? 'animate-spin' : '',
|
||||||
@@ -158,7 +158,7 @@ export default function GeneralSettingsPanel({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-[16px] flex items-center justify-between gap-4 rounded-[8px] bg-[#F5F7FA] p-[16px] dark:bg-gray-800">
|
<div className="mb-4 flex items-center justify-between gap-4 rounded-lg bg-[#F5F7FA] p-4 dark:bg-gray-800">
|
||||||
<div
|
<div
|
||||||
className={[
|
className={[
|
||||||
'text-[14px]',
|
'text-[14px]',
|
||||||
@@ -175,7 +175,7 @@ export default function GeneralSettingsPanel({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
void updateState.downloadUpdate();
|
void updateState.downloadUpdate();
|
||||||
}}
|
}}
|
||||||
className="rounded-[8px] bg-[#2B7FFF] px-[14px] py-[8px] text-[14px] font-medium text-white transition-colors hover:bg-[#1F6AE5]"
|
className="rounded-lg bg-[#2B7FFF] px-3.5 py-2 text-[14px] font-medium text-white transition-colors hover:bg-[#1F6AE5]"
|
||||||
>
|
>
|
||||||
{t('settings.general.downloadUpdate')}
|
{t('settings.general.downloadUpdate')}
|
||||||
</button>
|
</button>
|
||||||
@@ -185,7 +185,7 @@ export default function GeneralSettingsPanel({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
void updateState.installUpdate();
|
void updateState.installUpdate();
|
||||||
}}
|
}}
|
||||||
className="rounded-[8px] bg-[#1FC16B] px-[14px] py-[8px] text-[14px] font-medium text-white transition-colors hover:bg-[#17A95C]"
|
className="rounded-lg bg-[#1FC16B] px-3.5 py-2 text-[14px] font-medium text-white transition-colors hover:bg-[#17A95C]"
|
||||||
>
|
>
|
||||||
{t('settings.general.restartAndInstall')}
|
{t('settings.general.restartAndInstall')}
|
||||||
</button>
|
</button>
|
||||||
@@ -195,9 +195,9 @@ export default function GeneralSettingsPanel({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
void updateState.checkUpdate();
|
void updateState.checkUpdate();
|
||||||
}}
|
}}
|
||||||
className="inline-flex items-center gap-2 rounded-[8px] border border-[#E5E8EE] bg-white px-[14px] py-[8px] text-[14px] font-medium text-[#171717] transition-colors hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600"
|
className="inline-flex items-center gap-2 rounded-lg border border-[#E5E8EE] bg-white px-3.5 py-2 text-[14px] font-medium text-[#171717] transition-colors hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600"
|
||||||
>
|
>
|
||||||
<RefreshIcon
|
<RefreshCw
|
||||||
className={[
|
className={[
|
||||||
'h-4 w-4',
|
'h-4 w-4',
|
||||||
updateState.status === 'checking' ? 'animate-spin' : '',
|
updateState.status === 'checking' ? 'animate-spin' : '',
|
||||||
@@ -209,13 +209,13 @@ export default function GeneralSettingsPanel({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-[32px] text-[12px] text-[#99A0AE] dark:text-gray-500">
|
<div className="mb-8 text-[12px] text-[#99A0AE] dark:text-gray-500">
|
||||||
{t('settings.general.autoUpdateHint')}
|
{t('settings.general.autoUpdateHint')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between gap-4 border-b border-[#E5E8EE] py-[16px] dark:border-gray-800">
|
<div className="flex items-center justify-between gap-4 border-b border-[#E5E8EE] py-4 dark:border-gray-800">
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-[4px] text-[16px] text-[#171717] dark:text-gray-100">
|
<div className="mb-1 text-[16px] text-[#171717] dark:text-gray-100">
|
||||||
{t('settings.general.autoCheckTitle')}
|
{t('settings.general.autoCheckTitle')}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[14px] text-[#99A0AE] dark:text-gray-500">
|
<div className="text-[14px] text-[#99A0AE] dark:text-gray-500">
|
||||||
@@ -229,9 +229,9 @@ export default function GeneralSettingsPanel({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between gap-4 py-[16px]">
|
<div className="flex items-center justify-between gap-4 py-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-[4px] text-[16px] text-[#171717] dark:text-gray-100">
|
<div className="mb-1 text-[16px] text-[#171717] dark:text-gray-100">
|
||||||
{t('settings.general.autoDownloadTitle')}
|
{t('settings.general.autoDownloadTitle')}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[14px] text-[#99A0AE] dark:text-gray-500">
|
<div className="text-[14px] text-[#99A0AE] dark:text-gray-500">
|
||||||
|
|||||||
@@ -1,155 +0,0 @@
|
|||||||
import type { CSSProperties, ReactNode } from 'react';
|
|
||||||
|
|
||||||
type IconProps = {
|
|
||||||
className?: string;
|
|
||||||
style?: CSSProperties;
|
|
||||||
};
|
|
||||||
|
|
||||||
function BaseIcon({
|
|
||||||
className,
|
|
||||||
style,
|
|
||||||
children,
|
|
||||||
viewBox = '0 0 24 24',
|
|
||||||
}: IconProps & { children: ReactNode; viewBox?: string }) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
viewBox={viewBox}
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
className={className}
|
|
||||||
style={style}
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function UserIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<BaseIcon className={className} style={style}>
|
|
||||||
<path
|
|
||||||
d="M12 12C14.7614 12 17 9.76142 17 7C17 4.23858 14.7614 2 12 2C9.23858 2 7 4.23858 7 7C7 9.76142 9.23858 12 12 12Z"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M4.5 20.5C4.5 16.9101 7.41015 14 11 14H13C16.5899 14 19.5 16.9101 19.5 20.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
</BaseIcon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SettingsIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<BaseIcon className={className} style={style}>
|
|
||||||
<path
|
|
||||||
d="M12 8.5C10.067 8.5 8.5 10.067 8.5 12C8.5 13.933 10.067 15.5 12 15.5C13.933 15.5 15.5 13.933 15.5 12C15.5 10.067 13.933 8.5 12 8.5Z"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M19.4 15C19.557 14.6454 19.8 14.3303 20.109 14.089L21 13.4V10.6L20.109 9.911C19.8001 9.66973 19.557 9.35459 19.4 9L19.211 8.554C19.104 8.18336 19.1123 7.78916 19.235 7.423L19.59 6.365L17.635 4.41L16.577 4.765C16.2108 4.88772 15.8166 4.89604 15.446 4.789L15 4.6C14.6454 4.44304 14.3303 4.1999 14.089 3.891L13.4 3H10.6L9.911 3.891C9.66973 4.19991 9.35459 4.44304 9 4.6L8.554 4.789C8.18336 4.89605 7.78916 4.88773 7.423 4.765L6.365 4.41L4.41 6.365L4.765 7.423C4.88772 7.78916 4.89604 8.18336 4.789 8.554L4.6 9C4.44304 9.35459 4.19991 9.66973 3.891 9.911L3 10.6V13.4L3.891 14.089C4.1999 14.3303 4.44304 14.6454 4.6 15L4.789 15.446C4.89605 15.8166 4.88773 16.2108 4.765 16.577L4.41 17.635L6.365 19.59L7.423 19.235C7.78916 19.1123 8.18336 19.104 8.554 19.211L9 19.4C9.35459 19.557 9.66973 19.8001 9.911 20.109L10.6 21H13.4L14.089 20.109C14.3303 19.8001 14.6454 19.557 15 19.4L15.446 19.211C15.8166 19.104 16.2108 19.1123 16.577 19.235L17.635 19.59L19.59 17.635L19.235 16.577C19.1123 16.2108 19.104 15.8166 19.211 15.446L19.4 15Z"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.4"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</BaseIcon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SunIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<BaseIcon className={className} style={style}>
|
|
||||||
<circle cx="12" cy="12" r="4" stroke="currentColor" strokeWidth="1.8" />
|
|
||||||
<path d="M12 2.5V5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M12 19V21.5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M4.93 4.93L6.7 6.7" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M17.3 17.3L19.07 19.07" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M2.5 12H5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M19 12H21.5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M4.93 19.07L6.7 17.3" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M17.3 6.7L19.07 4.93" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
</BaseIcon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function MoonIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<BaseIcon className={className} style={style}>
|
|
||||||
<path
|
|
||||||
d="M18.5 14.5C17.3699 14.8222 16.1781 14.8095 15.0551 14.4635C13.9321 14.1175 12.9494 13.4537 12.2249 12.5501C11.5005 11.6466 11.0671 10.5442 10.9802 9.39101C10.8932 8.2378 11.1568 7.08346 11.737 6.08301C12.3172 5.08256 13.1872 4.28144 14.2325 3.78474C15.2778 3.28805 16.4494 3.11965 17.5932 3.30198C16.7789 2.71195 15.8164 2.36011 14.8131 2.28479C13.8099 2.20947 12.8056 2.41357 11.9101 2.87455C11.0145 3.33554 10.2617 4.0355 9.73336 4.89719C9.205 5.75888 8.92124 6.74985 8.91315 7.76257C8.90507 8.77529 9.17299 9.77067 9.68754 10.6407C10.2021 11.5108 10.9437 12.2227 11.8338 12.6978C12.724 13.1729 13.7249 13.393 14.7287 13.334C15.7324 13.2751 16.7002 12.9391 17.5 12.363"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</BaseIcon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ComputerIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<BaseIcon className={className} style={style}>
|
|
||||||
<rect x="3" y="4" width="18" height="12" rx="2.5" stroke="currentColor" strokeWidth="1.8" />
|
|
||||||
<path d="M8 20H16" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M10 16.5L9 20" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<path d="M14 16.5L15 20" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
</BaseIcon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function RefreshIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<BaseIcon className={className} style={style}>
|
|
||||||
<path
|
|
||||||
d="M20 11.5C19.8793 9.66472 19.068 7.94337 17.7311 6.67979C16.3942 5.41622 14.6298 4.70285 12.7908 4.68508C10.9518 4.66731 9.174 5.34644 7.81297 6.584C6.45194 7.82156 5.60751 9.52693 5.45142 11.36"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M4.5 7.5V11.5H8.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M4 12.5C4.12066 14.3353 4.93201 16.0566 6.26889 17.3202C7.60578 18.5838 9.37021 19.2971 11.2092 19.3149C13.0482 19.3327 14.826 18.6536 16.187 17.416C17.5481 16.1784 18.3925 14.4731 18.5486 12.64"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M19.5 16.5V12.5H15.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</BaseIcon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function CheckCircleIcon({ className, style }: IconProps) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
className={className}
|
|
||||||
style={style}
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
d="M10 18.5C14.6944 18.5 18.5 14.6944 18.5 10C18.5 5.30558 14.6944 1.5 10 1.5C5.30558 1.5 1.5 5.30558 1.5 10C1.5 14.6944 5.30558 18.5 10 18.5ZM13.7803 7.78033C14.0732 7.48744 14.0732 7.01256 13.7803 6.71967C13.4874 6.42678 13.0126 6.42678 12.7197 6.71967L8.75 10.6893L7.28033 9.21967C6.98744 8.92678 6.51256 8.92678 6.21967 9.21967C5.92678 9.51256 5.92678 9.98744 6.21967 10.2803L8.21967 12.2803C8.51256 12.5732 8.98744 12.5732 9.28033 12.2803L13.7803 7.78033Z"
|
|
||||||
clipRule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -13,24 +13,24 @@ const MENU_ITEMS: Array<{
|
|||||||
labelKey: 'settings.menu.account' | 'settings.menu.general';
|
labelKey: 'settings.menu.account' | 'settings.menu.general';
|
||||||
Icon: typeof UserIcon;
|
Icon: typeof UserIcon;
|
||||||
}> = [
|
}> = [
|
||||||
{
|
|
||||||
id: 'account',
|
|
||||||
labelKey: 'settings.menu.account',
|
|
||||||
Icon: UserIcon,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'general',
|
id: 'general',
|
||||||
labelKey: 'settings.menu.general',
|
labelKey: 'settings.menu.general',
|
||||||
Icon: SettingsIcon,
|
Icon: SettingsIcon,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'account',
|
||||||
|
labelKey: 'settings.menu.account',
|
||||||
|
Icon: UserIcon,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function SettingMenu({ currentView, onChange }: SettingMenuProps) {
|
export default function SettingMenu({ currentView, onChange }: SettingMenuProps) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="box-border flex h-full w-[160px] shrink-0 flex-col gap-[4px] border-r border-[#E5E8EE] px-[8px] py-[12px] select-none dark:border-gray-700">
|
<aside className="box-border flex h-full w-40 shrink-0 flex-col gap-1 border-r border-[#E5E8EE] px-2 py-3 select-none dark:border-gray-700">
|
||||||
<div className="p-[4px] text-[12px] text-[#99A0AE] dark:text-gray-500">
|
<div className="p-1 text-[12px] text-[#99A0AE] dark:text-gray-500">
|
||||||
{t('settings.menu.systemSettings')}
|
{t('settings.menu.systemSettings')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function SettingPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-[#1b1b1d] box-border w-full h-full min-w-0 min-h-0 flex rounded-[16px] overflow-hidden">
|
<div className="bg-white dark:bg-[#1b1b1d] box-border w-full h-full min-w-0 min-h-0 flex rounded-2xl overflow-hidden">
|
||||||
<SettingMenu currentView={currentView} onChange={setCurrentView} />
|
<SettingMenu currentView={currentView} onChange={setCurrentView} />
|
||||||
|
|
||||||
<div className="flex-1 min-w-0 min-h-0 overflow-y-auto">
|
<div className="flex-1 min-w-0 min-h-0 overflow-y-auto">
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export const NAV_ITEMS: NavItem[] = [
|
|||||||
{ path: '/models', labelKey: 'sidebar.models' },
|
{ path: '/models', labelKey: 'sidebar.models' },
|
||||||
{ path: '/skills', labelKey: 'sidebar.skills' },
|
{ path: '/skills', labelKey: 'sidebar.skills' },
|
||||||
{ path: '/cron', labelKey: 'sidebar.cron' },
|
{ path: '/cron', labelKey: 'sidebar.cron' },
|
||||||
{ path: '/scripts', labelKey: 'sidebar.scripts' },
|
// { path: '/scripts', labelKey: 'sidebar.scripts' },
|
||||||
{ path: '/setting', labelKey: 'sidebar.settings' },
|
{ path: '/setting', labelKey: 'sidebar.settings' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user