generated from template/astro-template
	temp
This commit is contained in:
		
							
								
								
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  
 | 
					  "workbench.editorAssociations": {
 | 
				
			||||||
 | 
					    // "*.md": "vscode.markdown.preview.editor" // 预览打开
 | 
				
			||||||
 | 
					    "*.md": "default" // 默认打开
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { DragModal, DragModalTitle, getComputedHeight } from '@/components/a/drag-modal/index.tsx';
 | 
					import { DragModal, DragModalTitle, getComputedHeight, useDragSize } from '@/components/a/drag-modal/index.tsx';
 | 
				
			||||||
import { useChatStore } from '../store';
 | 
					import { useChatStore } from '../store';
 | 
				
			||||||
import { useShallow } from 'zustand/shallow';
 | 
					import { useShallow } from 'zustand/shallow';
 | 
				
			||||||
import { Button } from '@/components/a/button.tsx';
 | 
					import { Button } from '@/components/a/button.tsx';
 | 
				
			||||||
@@ -68,6 +68,7 @@ export const ChatContextDialog = () => {
 | 
				
			|||||||
    setShowContext(false);
 | 
					    setShowContext(false);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  const [role, setRole] = useState<string>('user');
 | 
					  const [role, setRole] = useState<string>('user');
 | 
				
			||||||
 | 
					  const dragSize = useDragSize();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <DragModal
 | 
					    <DragModal
 | 
				
			||||||
      focus={modelId === 'chat-context'}
 | 
					      focus={modelId === 'chat-context'}
 | 
				
			||||||
@@ -111,14 +112,8 @@ export const ChatContextDialog = () => {
 | 
				
			|||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      defaultSize={{
 | 
					      defaultSize={dragSize.defaultSize}
 | 
				
			||||||
        width: 600,
 | 
					      style={dragSize.style}
 | 
				
			||||||
        height: 400,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      style={{
 | 
					 | 
				
			||||||
        left: computedHeight.width / 2 - 300,
 | 
					 | 
				
			||||||
        top: computedHeight.height / 2 - 200,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { DragModal, DragModalTitle, getComputedHeight } from '@/components/a/drag-modal/index.tsx';
 | 
					import { DragModal, DragModalTitle, getComputedHeight, useDragSize } from '@/components/a/drag-modal/index.tsx';
 | 
				
			||||||
import { useChatStore } from '../store';
 | 
					import { useChatStore } from '../store';
 | 
				
			||||||
import { useShallow } from 'zustand/shallow';
 | 
					import { useShallow } from 'zustand/shallow';
 | 
				
			||||||
import { ChatCopyList } from './List';
 | 
					import { ChatCopyList } from './List';
 | 
				
			||||||
@@ -16,6 +16,7 @@ export const ChatCopyDialog = () => {
 | 
				
			|||||||
  if (!store.showCopy) {
 | 
					  if (!store.showCopy) {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  const dragSize = useDragSize();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <DragModal
 | 
					    <DragModal
 | 
				
			||||||
      focus={store.modelId === 'chat-copy'}
 | 
					      focus={store.modelId === 'chat-copy'}
 | 
				
			||||||
@@ -33,14 +34,8 @@ export const ChatCopyDialog = () => {
 | 
				
			|||||||
          <ChatCopyList />
 | 
					          <ChatCopyList />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      defaultSize={{
 | 
					      defaultSize={dragSize.defaultSize}
 | 
				
			||||||
        width: 600,
 | 
					      style={dragSize.style}
 | 
				
			||||||
        height: 400,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      style={{
 | 
					 | 
				
			||||||
        left: computedHeight.width / 2 - 300,
 | 
					 | 
				
			||||||
        top: computedHeight.height / 2 - 200,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,17 @@
 | 
				
			|||||||
import { DragModal, DragModalTitle, getComputedHeight } from '@/components/a/drag-modal/index.tsx';
 | 
					import { DragModal, DragModalTitle, getComputedHeight, useDragSize } from '@/components/a/drag-modal/index.tsx';
 | 
				
			||||||
import { useChatStore } from '../store';
 | 
					import { useChatStore } from '../store';
 | 
				
			||||||
import { useShallow } from 'zustand/shallow';
 | 
					import { useShallow } from 'zustand/shallow';
 | 
				
			||||||
import { ChatHistoryList } from './List';
 | 
					import { ChatHistoryList } from './List';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ChatHistoryDialog = ({ storeId }: { storeId: string }) => {
 | 
					export const ChatHistoryDialog = ({ storeId }: { storeId: string }) => {
 | 
				
			||||||
  const { showList, setShowList, setModelId, modelId } = useChatStore(
 | 
					  const { showList, setShowList, setModelId, modelId } = useChatStore(
 | 
				
			||||||
    useShallow((state) => ({ showList: state.showList, setShowList: state.setShowList, setModelId: state.setModelId, modelId: state.modelId  })),
 | 
					    useShallow((state) => ({ showList: state.showList, setShowList: state.setShowList, setModelId: state.setModelId, modelId: state.modelId })),
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  const computedHeight = getComputedHeight();
 | 
					  const computedHeight = getComputedHeight();
 | 
				
			||||||
  if (!showList) {
 | 
					  if (!showList) {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  const dragSize = useDragSize();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <DragModal
 | 
					    <DragModal
 | 
				
			||||||
      focus={modelId === 'chat-history'}
 | 
					      focus={modelId === 'chat-history'}
 | 
				
			||||||
@@ -28,14 +29,7 @@ export const ChatHistoryDialog = ({ storeId }: { storeId: string }) => {
 | 
				
			|||||||
          <ChatHistoryList storeId={storeId} />
 | 
					          <ChatHistoryList storeId={storeId} />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      defaultSize={{
 | 
					      {...dragSize}
 | 
				
			||||||
        width: 600,
 | 
					 | 
				
			||||||
        height: 400,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      style={{
 | 
					 | 
				
			||||||
        left: computedHeight.width / 2 - 300,
 | 
					 | 
				
			||||||
        top: computedHeight.height / 2 - 200,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { DragModal, DragModalTitle, getComputedHeight } from '@/components/a/drag-modal/index.tsx';
 | 
					import { DragModal, DragModalTitle, getComputedHeight, useDragSize } from '@/components/a/drag-modal/index.tsx';
 | 
				
			||||||
import { useChatStore } from '../store';
 | 
					import { useChatStore } from '../store';
 | 
				
			||||||
import { useShallow } from 'zustand/shallow';
 | 
					import { useShallow } from 'zustand/shallow';
 | 
				
			||||||
import { ChatSettingList } from './List';
 | 
					import { ChatSettingList } from './List';
 | 
				
			||||||
@@ -16,6 +16,7 @@ export const ChatModelSettingDialog = () => {
 | 
				
			|||||||
  if (!showChatSetting) {
 | 
					  if (!showChatSetting) {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  const dragSize = useDragSize();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <DragModal
 | 
					    <DragModal
 | 
				
			||||||
      focus={modelId === 'chat-model-setting'}
 | 
					      focus={modelId === 'chat-model-setting'}
 | 
				
			||||||
@@ -33,14 +34,7 @@ export const ChatModelSettingDialog = () => {
 | 
				
			|||||||
          <ChatSettingList />
 | 
					          <ChatSettingList />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      defaultSize={{
 | 
					      {...dragSize}
 | 
				
			||||||
        width: 600,
 | 
					 | 
				
			||||||
        height: 400,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      style={{
 | 
					 | 
				
			||||||
        left: computedHeight.width / 2 - 300,
 | 
					 | 
				
			||||||
        top: computedHeight.height / 2 - 200,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { DragModal, DragModalTitle, getComputedHeight } from '@/components/a/drag-modal/index.tsx';
 | 
					import { DragModal, DragModalTitle, getComputedHeight, useDragSize } from '@/components/a/drag-modal/index.tsx';
 | 
				
			||||||
import { useChatStore } from '../store';
 | 
					import { useChatStore } from '../store';
 | 
				
			||||||
import { useShallow } from 'zustand/shallow';
 | 
					import { useShallow } from 'zustand/shallow';
 | 
				
			||||||
import { ChatSettingList } from './List';
 | 
					import { ChatSettingList } from './List';
 | 
				
			||||||
@@ -16,6 +16,7 @@ export const ChatSettingDialog = () => {
 | 
				
			|||||||
  if (!showSetting) {
 | 
					  if (!showSetting) {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  const dragSize = useDragSize();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <DragModal
 | 
					    <DragModal
 | 
				
			||||||
      focus={modelId === 'chat-setting'}
 | 
					      focus={modelId === 'chat-setting'}
 | 
				
			||||||
@@ -33,14 +34,7 @@ export const ChatSettingDialog = () => {
 | 
				
			|||||||
          <ChatSettingList />
 | 
					          <ChatSettingList />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      defaultSize={{
 | 
					      {...dragSize}
 | 
				
			||||||
        width: 600,
 | 
					 | 
				
			||||||
        height: 400,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      style={{
 | 
					 | 
				
			||||||
        left: computedHeight.width / 2 - 300,
 | 
					 | 
				
			||||||
        top: computedHeight.height / 2 - 200,
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,7 +75,7 @@ export const Chat = ({ storeId }: { storeId: string }) => {
 | 
				
			|||||||
  }, []);
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className='w-full h-full relative'>
 | 
					    <div className='w-full h-full relative flex flex-col lg:flex-row'>
 | 
				
			||||||
      {!id && (
 | 
					      {!id && (
 | 
				
			||||||
        <div className='w-full h-full flex flex-col justify-center items-center'>
 | 
					        <div className='w-full h-full flex flex-col justify-center items-center'>
 | 
				
			||||||
          <ChatHistoryList storeId={storeId} />
 | 
					          <ChatHistoryList storeId={storeId} />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ export const ModelNav = () => {
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className='flex gap-2 items-center'>
 | 
					    <div className='flex gap-2 items-center'>
 | 
				
			||||||
      <div className='hidden lg:block font-bold text-gray-600'>提示词规划器</div>
 | 
					      <div className='hidden lg:block font-bold text-gray-600'>提示词规划器</div>
 | 
				
			||||||
      <div className='flex gap-2 items-center' onClick={() => setShowChatSetting(true)}>
 | 
					      {/* <div className='flex gap-2 items-center' onClick={() => setShowChatSetting(true)}>
 | 
				
			||||||
        {currentUserModel && (
 | 
					        {currentUserModel && (
 | 
				
			||||||
          <Tooltip
 | 
					          <Tooltip
 | 
				
			||||||
            title={
 | 
					            title={
 | 
				
			||||||
@@ -58,7 +58,7 @@ export const ModelNav = () => {
 | 
				
			|||||||
          </Tooltip>
 | 
					          </Tooltip>
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
        {!currentUserModel && <div className='text-sm text-gray-500 cursor-pointer'>Not Selected Model</div>}
 | 
					        {!currentUserModel && <div className='text-sm text-gray-500 cursor-pointer'>Not Selected Model</div>}
 | 
				
			||||||
      </div>
 | 
					      </div> */}
 | 
				
			||||||
      <div className='flex gap-2 items-center'>
 | 
					      <div className='flex gap-2 items-center'>
 | 
				
			||||||
        {/* <Tooltip title='设置'>
 | 
					        {/* <Tooltip title='设置'>
 | 
				
			||||||
          <IconButton
 | 
					          <IconButton
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								src/apps/ai-editor/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/apps/ai-editor/index.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import { ToastProvider } from '@/modules/toast/Provider';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const App = () => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <ToastProvider>
 | 
				
			||||||
 | 
					      <AIEditor />
 | 
				
			||||||
 | 
					    </ToastProvider>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const AIEditor = () => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className='flex h-full w-full flex-col items-center justify-center'>
 | 
				
			||||||
 | 
					      <div className='text-2xl font-bold'>AI Editor</div>
 | 
				
			||||||
 | 
					      <div className='mt-4 text-gray-500'>This is a placeholder for the AI Editor application.</div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -5,14 +5,35 @@ import { Tooltip } from '@/components/a/tooltip';
 | 
				
			|||||||
export const queryMark = new QueryMark({ query: query, markType: 'md' });
 | 
					export const queryMark = new QueryMark({ query: query, markType: 'md' });
 | 
				
			||||||
import Fuse from 'fuse.js';
 | 
					import Fuse from 'fuse.js';
 | 
				
			||||||
import { debounce } from 'lodash-es';
 | 
					import { debounce } from 'lodash-es';
 | 
				
			||||||
import { SquareArrowOutUpRight } from 'lucide-react';
 | 
					import { Plus, SquareArrowOutUpRight } from 'lucide-react';
 | 
				
			||||||
 | 
					import { Pencil, Trash2 } from 'lucide-react';
 | 
				
			||||||
 | 
					import { Button } from '@/components/a/button';
 | 
				
			||||||
 | 
					import { Confirm } from '@/components/a/confirm';
 | 
				
			||||||
 | 
					import { toast } from 'react-toastify';
 | 
				
			||||||
 | 
					import { ToastProvider } from '@/modules/toast/Provider';
 | 
				
			||||||
 | 
					import { Modal } from '@/components/a/modal';
 | 
				
			||||||
 | 
					import { useForm, Controller } from 'react-hook-form'; // 添加此行
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const App = () => {
 | 
					export const App = () => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <ToastProvider>
 | 
				
			||||||
 | 
					      <AiMark />
 | 
				
			||||||
 | 
					    </ToastProvider>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					const AiMark = () => {
 | 
				
			||||||
  const [list, setList] = useState<Mark[]>([]);
 | 
					  const [list, setList] = useState<Mark[]>([]);
 | 
				
			||||||
  const [searchTerm, setSearchTerm] = useState('');
 | 
					  const [searchTerm, setSearchTerm] = useState('');
 | 
				
			||||||
  const [searchResults, setSearchResults] = useState<Mark[]>([]);
 | 
					  const [searchResults, setSearchResults] = useState<Mark[]>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const fuseRef = useRef<Fuse<Mark>>(null);
 | 
					  const fuseRef = useRef<Fuse<Mark>>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [open, setOpen] = useState(false);
 | 
				
			||||||
 | 
					  const [formData, setFormData] = useState<Mark>();
 | 
				
			||||||
 | 
					  const onOpenEdit = (data: Mark) => {
 | 
				
			||||||
 | 
					    setOpen(true);
 | 
				
			||||||
 | 
					    setFormData(data);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
  // 实际执行搜索的函数
 | 
					  // 实际执行搜索的函数
 | 
				
			||||||
  const performSearch = (term: string) => {
 | 
					  const performSearch = (term: string) => {
 | 
				
			||||||
    if (!term.trim()) {
 | 
					    if (!term.trim()) {
 | 
				
			||||||
@@ -47,6 +68,7 @@ export const App = () => {
 | 
				
			|||||||
    if (res.code === 200) {
 | 
					    if (res.code === 200) {
 | 
				
			||||||
      const list = res.data?.list || [];
 | 
					      const list = res.data?.list || [];
 | 
				
			||||||
      setList(list!);
 | 
					      setList(list!);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const fuse = new Fuse(list, {
 | 
					      const fuse = new Fuse(list, {
 | 
				
			||||||
        keys: ['title', 'description', 'tags', 'summary'],
 | 
					        keys: ['title', 'description', 'tags', 'summary'],
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -65,13 +87,23 @@ export const App = () => {
 | 
				
			|||||||
    const link = item.link;
 | 
					    const link = item.link;
 | 
				
			||||||
    window.open(link);
 | 
					    window.open(link);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					  const refresh = () => {
 | 
				
			||||||
 | 
					    init();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
  // 确定要显示的列表:有搜索内容时显示搜索结果,否则显示全部
 | 
					  // 确定要显示的列表:有搜索内容时显示搜索结果,否则显示全部
 | 
				
			||||||
  const displayList = searchTerm.trim() ? searchResults : list;
 | 
					  const displayList = searchTerm.trim() ? searchResults : list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className='w-full h-full overflow-auto'>
 | 
					    <div className='w-full h-full overflow-auto scrollbar'>
 | 
				
			||||||
      <div className='sticky top-0 p-4 bg-white z-10 shadow-sm'>
 | 
					      <div className='sticky top-0 p-4 bg-white z-10 shadow-sm flex gap-2'>
 | 
				
			||||||
 | 
					        <Button
 | 
				
			||||||
 | 
					          size='icon'
 | 
				
			||||||
 | 
					          onClick={() => {
 | 
				
			||||||
 | 
					            setFormData(undefined);
 | 
				
			||||||
 | 
					            setOpen(true);
 | 
				
			||||||
 | 
					          }}>
 | 
				
			||||||
 | 
					          <Plus />
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
        <input
 | 
					        <input
 | 
				
			||||||
          type='text'
 | 
					          type='text'
 | 
				
			||||||
          value={searchTerm}
 | 
					          value={searchTerm}
 | 
				
			||||||
@@ -102,11 +134,141 @@ export const App = () => {
 | 
				
			|||||||
                    </span>
 | 
					                    </span>
 | 
				
			||||||
                  ))}
 | 
					                  ))}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                <Action data={item} onEdit={onOpenEdit} refresh={refresh} />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					      <Modal open={open} setOpen={setOpen}>
 | 
				
			||||||
 | 
					        <MarkForm
 | 
				
			||||||
 | 
					          data={formData}
 | 
				
			||||||
 | 
					          onCancel={() => setOpen(false)}
 | 
				
			||||||
 | 
					          onSuccess={() => {
 | 
				
			||||||
 | 
					            setOpen(false);
 | 
				
			||||||
 | 
					            init();
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </Modal>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const MarkForm = (props?: { data?: Mark; onSuccess?: () => void; onCancel?: () => void }) => {
 | 
				
			||||||
 | 
					  const {
 | 
				
			||||||
 | 
					    register,
 | 
				
			||||||
 | 
					    handleSubmit,
 | 
				
			||||||
 | 
					    control,
 | 
				
			||||||
 | 
					    formState: { errors },
 | 
				
			||||||
 | 
					  } = useForm<Mark>({
 | 
				
			||||||
 | 
					    defaultValues: props?.data || {
 | 
				
			||||||
 | 
					      title: '',
 | 
				
			||||||
 | 
					      summary: '',
 | 
				
			||||||
 | 
					      link: '',
 | 
				
			||||||
 | 
					      tags: [],
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onSubmit = async (data: Mark) => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const res = await queryMark.updateMark(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (res.code === 200) {
 | 
				
			||||||
 | 
					        toast.success(data.id ? '更新成功' : '创建成功');
 | 
				
			||||||
 | 
					        props?.onSuccess?.();
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        toast.error(res?.message || '操作失败');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      toast.error('操作失败');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <form onSubmit={handleSubmit(onSubmit)} className='space-y-4 p-2'>
 | 
				
			||||||
 | 
					      {props?.data?.id && <input type='hidden' {...register('id')} />}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <label className='block text-sm font-medium mb-1'>标题</label>
 | 
				
			||||||
 | 
					        <input
 | 
				
			||||||
 | 
					          type='text'
 | 
				
			||||||
 | 
					          {...register('title', { required: '标题是必填项' })}
 | 
				
			||||||
 | 
					          className='w-full p-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-300'
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        {errors.title && <p className='text-red-500 text-xs mt-1'>{errors.title.message}</p>}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <label className='block text-sm font-medium mb-1'>链接</label>
 | 
				
			||||||
 | 
					        <input
 | 
				
			||||||
 | 
					          type='text'
 | 
				
			||||||
 | 
					          {...register('link', { required: '链接是必填项' })}
 | 
				
			||||||
 | 
					          className='w-full p-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-300'
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        {errors.link && <p className='text-red-500 text-xs mt-1'>{errors.link.message}</p>}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <label className='block text-sm font-medium mb-1'>摘要</label>
 | 
				
			||||||
 | 
					        <textarea {...register('summary')} rows={3} className='w-full p-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-300' />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <label className='block text-sm font-medium mb-1'>标签</label>
 | 
				
			||||||
 | 
					        <Controller
 | 
				
			||||||
 | 
					          name='tags'
 | 
				
			||||||
 | 
					          control={control}
 | 
				
			||||||
 | 
					          render={({ field }) => (
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					              type='text'
 | 
				
			||||||
 | 
					              value={field.value?.join(', ') || ''}
 | 
				
			||||||
 | 
					              onChange={(e) => {
 | 
				
			||||||
 | 
					                const value = e.target.value;
 | 
				
			||||||
 | 
					                field.onChange(
 | 
				
			||||||
 | 
					                  value
 | 
				
			||||||
 | 
					                    .split(',')
 | 
				
			||||||
 | 
					                    .map((tag) => tag.trim())
 | 
				
			||||||
 | 
					                    .filter((tag) => tag !== ''),
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              className='w-full p-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-300'
 | 
				
			||||||
 | 
					              placeholder='用逗号分隔多个标签'
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div className='flex justify-end space-x-2 mt-4'>
 | 
				
			||||||
 | 
					        <Button onClick={props?.onCancel} type='button'>
 | 
				
			||||||
 | 
					          取消
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					        <Button type='submit'>保存</Button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					export const Action = (props: { data: Mark; onEdit?: (data: Mark) => any; refresh?: any }) => {
 | 
				
			||||||
 | 
					  const onDelete = async () => {
 | 
				
			||||||
 | 
					    const res = await queryMark.deleteMark(props.data.id);
 | 
				
			||||||
 | 
					    if (res.code === 200) {
 | 
				
			||||||
 | 
					      toast.success('删除成功');
 | 
				
			||||||
 | 
					      props?.refresh?.();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      toast.error(res?.message || '请求失败');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className='flex gap-2 mt-2'>
 | 
				
			||||||
 | 
					      <Button className='flex items-center gap-1 transition' onClick={() => props?.onEdit?.(props.data)} title='编辑'>
 | 
				
			||||||
 | 
					        <Pencil className='w-4 h-4' />
 | 
				
			||||||
 | 
					        编辑
 | 
				
			||||||
 | 
					      </Button>
 | 
				
			||||||
 | 
					      <Confirm onOk={onDelete}>
 | 
				
			||||||
 | 
					        <Button className='flex items-center gap-1 text-red-600 transition' title='删除'>
 | 
				
			||||||
 | 
					          <Trash2 className='w-4 h-4' />
 | 
				
			||||||
 | 
					          删除
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					      </Confirm>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								src/apps/kevisual-lib/Layout.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/apps/kevisual-lib/Layout.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					type LayoutProps = {
 | 
				
			||||||
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
 | 
					  className?: string;
 | 
				
			||||||
 | 
					  style?: React.CSSProperties;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					export const Layout = (props: LayoutProps) => {
 | 
				
			||||||
 | 
					  const { children, className, style } = props;
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className={className} style={style}>
 | 
				
			||||||
 | 
					      {children}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -4,9 +4,10 @@ export interface Props {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<html lang='zh'>
 | 
					<html lang='zh-CN'>
 | 
				
			||||||
  <header>
 | 
					  <head>
 | 
				
			||||||
    <meta charset='UTF-8' />
 | 
					    <meta charset='UTF-8' />
 | 
				
			||||||
 | 
					    <meta name='viewport' content='width=device-width, initial-scale=1.0' />
 | 
				
			||||||
    <title>Docs</title>
 | 
					    <title>Docs</title>
 | 
				
			||||||
    <link
 | 
					    <link
 | 
				
			||||||
      rel='stylesheet'
 | 
					      rel='stylesheet'
 | 
				
			||||||
@@ -15,13 +16,23 @@ export interface Props {
 | 
				
			|||||||
      crossorigin='anonymous'
 | 
					      crossorigin='anonymous'
 | 
				
			||||||
      referrerpolicy='no-referrer'
 | 
					      referrerpolicy='no-referrer'
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  </header>
 | 
					    <style>
 | 
				
			||||||
 | 
					      html,
 | 
				
			||||||
 | 
					      body {
 | 
				
			||||||
 | 
					        width: 100%;
 | 
				
			||||||
 | 
					        height: 100%;
 | 
				
			||||||
 | 
					        margin: 0;
 | 
				
			||||||
 | 
					        padding: 0;
 | 
				
			||||||
 | 
					        overflow: hidden;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <header>
 | 
					    <div>
 | 
				
			||||||
      <slot name='header'>
 | 
					      <slot name='header'>
 | 
				
			||||||
        <h1>My Site Header</h1>
 | 
					        <h1>My Site Header</h1>
 | 
				
			||||||
      </slot>
 | 
					      </slot>
 | 
				
			||||||
    </header>
 | 
					    </div>
 | 
				
			||||||
    <main class='markdown-body' style='padding: 1rem'>
 | 
					    <main class='markdown-body' style='padding: 1rem'>
 | 
				
			||||||
      <slot />
 | 
					      <slot />
 | 
				
			||||||
    </main>
 | 
					    </main>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -115,3 +115,18 @@ export const useComputedHeight = () => {
 | 
				
			|||||||
  }, []);
 | 
					  }, []);
 | 
				
			||||||
  return computedHeight;
 | 
					  return computedHeight;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useDragSize = (width = 600, heigth = 400) => {
 | 
				
			||||||
 | 
					  const computedHeight = getComputedHeight();
 | 
				
			||||||
 | 
					  const isMin = computedHeight.width < width;
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    defaultSize: {
 | 
				
			||||||
 | 
					      width: isMin ? computedHeight.width : 600,
 | 
				
			||||||
 | 
					      height: 400,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    style: {
 | 
				
			||||||
 | 
					      left: isMin ? 0 : computedHeight.width / 2 - width / 2,
 | 
				
			||||||
 | 
					      top: computedHeight.height / 2 - heigth / 2,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								src/components/a/modal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/components/a/modal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog';
 | 
				
			||||||
 | 
					import React, { Dispatch, SetStateAction } from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ModalProps = {
 | 
				
			||||||
 | 
					  open?: boolean;
 | 
				
			||||||
 | 
					  setOpen?: (open: boolean) => any;
 | 
				
			||||||
 | 
					  title?: string;
 | 
				
			||||||
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Modal = (props: ModalProps) => {
 | 
				
			||||||
 | 
					  const { open = false, setOpen, title, children } = props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Dialog open={open} onOpenChange={setOpen}>
 | 
				
			||||||
 | 
					      <DialogContent>
 | 
				
			||||||
 | 
					        <DialogHeader>
 | 
				
			||||||
 | 
					          <DialogTitle>{title}</DialogTitle>
 | 
				
			||||||
 | 
					        </DialogHeader>
 | 
				
			||||||
 | 
					        {children}
 | 
				
			||||||
 | 
					      </DialogContent>
 | 
				
			||||||
 | 
					    </Dialog>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
<html lang='zh-CN'>
 | 
					<html lang='zh-CN'>
 | 
				
			||||||
  <head>
 | 
					  <head>
 | 
				
			||||||
    <meta charset='UTF-8' />
 | 
					    <meta charset='UTF-8' />
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
				
			||||||
    <title>AI Pages</title>
 | 
					    <title>AI Pages</title>
 | 
				
			||||||
    <style>
 | 
					    <style>
 | 
				
			||||||
      html,
 | 
					      html,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,4 +12,15 @@ const blog = defineCollection({
 | 
				
			|||||||
    // updatedDate: z.coerce.date().optional(),
 | 
					    // updatedDate: z.coerce.date().optional(),
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
export const collections = { blog };
 | 
					
 | 
				
			||||||
 | 
					const kevisual = defineCollection({
 | 
				
			||||||
 | 
					  // loader: glob({ pattern: '**/*.md', base: './src/data/blogs' }),
 | 
				
			||||||
 | 
					  loader: glob({ pattern: '**/[^_]*.md', base: './src/data/kevisual' }),
 | 
				
			||||||
 | 
					  schema: z.object({
 | 
				
			||||||
 | 
					    title: z.string().optional(),
 | 
				
			||||||
 | 
					    description: z.string().optional(),
 | 
				
			||||||
 | 
					    // pubDate: z.coerce.date(),
 | 
				
			||||||
 | 
					    // updatedDate: z.coerce.date().optional(),
 | 
				
			||||||
 | 
					  }),
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					export const collections = { blog, kevisual };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								src/data/kevisual/router/base.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/data/kevisual/router/base.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					title: router
 | 
				
			||||||
 | 
					tags: ['kevisual', 'lib']
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# @kevisual/router
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					在使用 node 开发的时候,http 服务和 api 是首要关注的内容。但是真实的在开发的时候,发现一件事情,开发应该只关注于对应的内容的东西。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 介绍
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/pages/docs/kevisual/[...id].astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/pages/docs/kevisual/[...id].astro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					import '@/styles/global.css';
 | 
				
			||||||
 | 
					import '@/styles/theme.css';
 | 
				
			||||||
 | 
					import { getCollection, render } from 'astro:content';
 | 
				
			||||||
 | 
					import Main from '@/astro/layouts/mdx/main.astro';
 | 
				
			||||||
 | 
					// import Blank from '@/components/html/blank.astro';
 | 
				
			||||||
 | 
					// 1. 为每个集合条目生成一个新路径
 | 
				
			||||||
 | 
					export async function getStaticPaths() {
 | 
				
			||||||
 | 
					  const posts = await getCollection('kevisual');
 | 
				
			||||||
 | 
					  return posts.map((post) => ({
 | 
				
			||||||
 | 
					    params: { id: post.id },
 | 
				
			||||||
 | 
					    props: { post },
 | 
				
			||||||
 | 
					  }));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type Post = {
 | 
				
			||||||
 | 
					  data: { title: string };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					// 2. 对于你的模板,你可以直接从 prop 获取条目
 | 
				
			||||||
 | 
					const { post } = Astro.props as { post: Post };
 | 
				
			||||||
 | 
					const { Content } = await render(post);
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<Main>
 | 
				
			||||||
 | 
					  <meta charset='UTF-8' slot='head' />
 | 
				
			||||||
 | 
					  <div slot={'header'}>{post.data.title}</div>
 | 
				
			||||||
 | 
					  <Content />
 | 
				
			||||||
 | 
					</Main>
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/pages/docs/kevisual/index.astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/pages/docs/kevisual/index.astro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					import { getCollection } from 'astro:content';
 | 
				
			||||||
 | 
					const posts = await getCollection('kevisual');
 | 
				
			||||||
 | 
					console.log('post', posts);
 | 
				
			||||||
 | 
					import { basename } from '@/modules/basename';
 | 
				
			||||||
 | 
					import Blank from '@/components/html/blank.astro';
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<Blank>
 | 
				
			||||||
 | 
					  <h1>kevisual posts</h1>
 | 
				
			||||||
 | 
					  <ul>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      posts.map((post) => (
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          {/* <a href={`${basename}/demo/${post.id}`}>{post.data.title}</a> */}
 | 
				
			||||||
 | 
					          <a href={`/docs/kevisual/${post.id}`}>{post.data.title}</a>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					      ))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  </ul>
 | 
				
			||||||
 | 
					</Blank>
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
 | 
					import '@/styles/theme.css';
 | 
				
			||||||
import '@/styles/global.css';
 | 
					import '@/styles/global.css';
 | 
				
			||||||
import Blank from '@/components/html/blank.astro';
 | 
					import Blank from '@/components/html/blank.astro';
 | 
				
			||||||
import { App } from '@/apps/ai-mark';
 | 
					import { App } from '@/apps/ai-mark';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
 | 
					import '@/styles/theme.css';  
 | 
				
			||||||
import '@/styles/global.css';
 | 
					import '@/styles/global.css';
 | 
				
			||||||
import Blank from '@/components/html/blank.astro';
 | 
					import Blank from '@/components/html/blank.astro';
 | 
				
			||||||
import { App as AIChat } from '@/apps/ai-chat/index.tsx';
 | 
					import { App as AIChat } from '@/apps/ai-chat/index.tsx';
 | 
				
			||||||
@@ -1,119 +0,0 @@
 | 
				
			|||||||
@import 'tailwindcss';
 | 
					 | 
				
			||||||
@import "tw-animate-css";
 | 
					 | 
				
			||||||
@custom-variant dark (&:is(.dark *));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@theme inline {
 | 
					 | 
				
			||||||
  --radius-sm: calc(var(--radius) - 4px);
 | 
					 | 
				
			||||||
  --radius-md: calc(var(--radius) - 2px);
 | 
					 | 
				
			||||||
  --radius-lg: var(--radius);
 | 
					 | 
				
			||||||
  --radius-xl: calc(var(--radius) + 4px);
 | 
					 | 
				
			||||||
  --color-background: var(--background);
 | 
					 | 
				
			||||||
  --color-foreground: var(--foreground);
 | 
					 | 
				
			||||||
  --color-card: var(--card);
 | 
					 | 
				
			||||||
  --color-card-foreground: var(--card-foreground);
 | 
					 | 
				
			||||||
  --color-popover: var(--popover);
 | 
					 | 
				
			||||||
  --color-popover-foreground: var(--popover-foreground);
 | 
					 | 
				
			||||||
  --color-primary: var(--primary);
 | 
					 | 
				
			||||||
  --color-primary-foreground: var(--primary-foreground);
 | 
					 | 
				
			||||||
  --color-secondary: var(--secondary);
 | 
					 | 
				
			||||||
  --color-secondary-foreground: var(--secondary-foreground);
 | 
					 | 
				
			||||||
  --color-muted: var(--muted);
 | 
					 | 
				
			||||||
  --color-muted-foreground: var(--muted-foreground);
 | 
					 | 
				
			||||||
  --color-accent: var(--accent);
 | 
					 | 
				
			||||||
  --color-accent-foreground: var(--accent-foreground);
 | 
					 | 
				
			||||||
  --color-destructive: var(--destructive);
 | 
					 | 
				
			||||||
  --color-border: var(--border);
 | 
					 | 
				
			||||||
  --color-input: var(--input);
 | 
					 | 
				
			||||||
  --color-ring: var(--ring);
 | 
					 | 
				
			||||||
  --color-chart-1: var(--chart-1);
 | 
					 | 
				
			||||||
  --color-chart-2: var(--chart-2);
 | 
					 | 
				
			||||||
  --color-chart-3: var(--chart-3);
 | 
					 | 
				
			||||||
  --color-chart-4: var(--chart-4);
 | 
					 | 
				
			||||||
  --color-chart-5: var(--chart-5);
 | 
					 | 
				
			||||||
  --color-sidebar: var(--sidebar);
 | 
					 | 
				
			||||||
  --color-sidebar-foreground: var(--sidebar-foreground);
 | 
					 | 
				
			||||||
  --color-sidebar-primary: var(--sidebar-primary);
 | 
					 | 
				
			||||||
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
 | 
					 | 
				
			||||||
  --color-sidebar-accent: var(--sidebar-accent);
 | 
					 | 
				
			||||||
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
 | 
					 | 
				
			||||||
  --color-sidebar-border: var(--sidebar-border);
 | 
					 | 
				
			||||||
  --color-sidebar-ring: var(--sidebar-ring);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:root {
 | 
					 | 
				
			||||||
  --radius: 0.625rem;
 | 
					 | 
				
			||||||
  --background: oklch(1 0 0);
 | 
					 | 
				
			||||||
  --foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --card: oklch(1 0 0);
 | 
					 | 
				
			||||||
  --card-foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --popover: oklch(1 0 0);
 | 
					 | 
				
			||||||
  --popover-foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --primary: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --primary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --secondary: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --secondary-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --muted: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --muted-foreground: oklch(0.556 0 0);
 | 
					 | 
				
			||||||
  --accent: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --accent-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --destructive: oklch(0.577 0.245 27.325);
 | 
					 | 
				
			||||||
  --border: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --input: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --ring: oklch(0.708 0 0);
 | 
					 | 
				
			||||||
  --chart-1: oklch(0.646 0.222 41.116);
 | 
					 | 
				
			||||||
  --chart-2: oklch(0.6 0.118 184.704);
 | 
					 | 
				
			||||||
  --chart-3: oklch(0.398 0.07 227.392);
 | 
					 | 
				
			||||||
  --chart-4: oklch(0.828 0.189 84.429);
 | 
					 | 
				
			||||||
  --chart-5: oklch(0.769 0.188 70.08);
 | 
					 | 
				
			||||||
  --sidebar: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --sidebar-primary: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --sidebar-primary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --sidebar-border: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --sidebar-ring: oklch(0.708 0 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.dark {
 | 
					 | 
				
			||||||
  --background: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --card: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --card-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --popover: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --popover-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --primary: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --primary-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --secondary: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --secondary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --muted: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --muted-foreground: oklch(0.708 0 0);
 | 
					 | 
				
			||||||
  --accent: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --accent-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --destructive: oklch(0.704 0.191 22.216);
 | 
					 | 
				
			||||||
  --border: oklch(1 0 0 / 10%);
 | 
					 | 
				
			||||||
  --input: oklch(1 0 0 / 15%);
 | 
					 | 
				
			||||||
  --ring: oklch(0.556 0 0);
 | 
					 | 
				
			||||||
  --chart-1: oklch(0.488 0.243 264.376);
 | 
					 | 
				
			||||||
  --chart-2: oklch(0.696 0.17 162.48);
 | 
					 | 
				
			||||||
  --chart-3: oklch(0.769 0.188 70.08);
 | 
					 | 
				
			||||||
  --chart-4: oklch(0.627 0.265 303.9);
 | 
					 | 
				
			||||||
  --chart-5: oklch(0.645 0.246 16.439);
 | 
					 | 
				
			||||||
  --sidebar: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --sidebar-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-primary: oklch(0.488 0.243 264.376);
 | 
					 | 
				
			||||||
  --sidebar-primary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-border: oklch(1 0 0 / 10%);
 | 
					 | 
				
			||||||
  --sidebar-ring: oklch(0.556 0 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@layer base {
 | 
					 | 
				
			||||||
  * {
 | 
					 | 
				
			||||||
    @apply border-border outline-ring/50;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  body {
 | 
					 | 
				
			||||||
    @apply bg-background text-foreground;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,119 +0,0 @@
 | 
				
			|||||||
@import 'tailwindcss';
 | 
					 | 
				
			||||||
@import "tw-animate-css";
 | 
					 | 
				
			||||||
@custom-variant dark (&:is(.dark *));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@theme inline {
 | 
					 | 
				
			||||||
  --radius-sm: calc(var(--radius) - 4px);
 | 
					 | 
				
			||||||
  --radius-md: calc(var(--radius) - 2px);
 | 
					 | 
				
			||||||
  --radius-lg: var(--radius);
 | 
					 | 
				
			||||||
  --radius-xl: calc(var(--radius) + 4px);
 | 
					 | 
				
			||||||
  --color-background: var(--background);
 | 
					 | 
				
			||||||
  --color-foreground: var(--foreground);
 | 
					 | 
				
			||||||
  --color-card: var(--card);
 | 
					 | 
				
			||||||
  --color-card-foreground: var(--card-foreground);
 | 
					 | 
				
			||||||
  --color-popover: var(--popover);
 | 
					 | 
				
			||||||
  --color-popover-foreground: var(--popover-foreground);
 | 
					 | 
				
			||||||
  --color-primary: var(--primary);
 | 
					 | 
				
			||||||
  --color-primary-foreground: var(--primary-foreground);
 | 
					 | 
				
			||||||
  --color-secondary: var(--secondary);
 | 
					 | 
				
			||||||
  --color-secondary-foreground: var(--secondary-foreground);
 | 
					 | 
				
			||||||
  --color-muted: var(--muted);
 | 
					 | 
				
			||||||
  --color-muted-foreground: var(--muted-foreground);
 | 
					 | 
				
			||||||
  --color-accent: var(--accent);
 | 
					 | 
				
			||||||
  --color-accent-foreground: var(--accent-foreground);
 | 
					 | 
				
			||||||
  --color-destructive: var(--destructive);
 | 
					 | 
				
			||||||
  --color-border: var(--border);
 | 
					 | 
				
			||||||
  --color-input: var(--input);
 | 
					 | 
				
			||||||
  --color-ring: var(--ring);
 | 
					 | 
				
			||||||
  --color-chart-1: var(--chart-1);
 | 
					 | 
				
			||||||
  --color-chart-2: var(--chart-2);
 | 
					 | 
				
			||||||
  --color-chart-3: var(--chart-3);
 | 
					 | 
				
			||||||
  --color-chart-4: var(--chart-4);
 | 
					 | 
				
			||||||
  --color-chart-5: var(--chart-5);
 | 
					 | 
				
			||||||
  --color-sidebar: var(--sidebar);
 | 
					 | 
				
			||||||
  --color-sidebar-foreground: var(--sidebar-foreground);
 | 
					 | 
				
			||||||
  --color-sidebar-primary: var(--sidebar-primary);
 | 
					 | 
				
			||||||
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
 | 
					 | 
				
			||||||
  --color-sidebar-accent: var(--sidebar-accent);
 | 
					 | 
				
			||||||
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
 | 
					 | 
				
			||||||
  --color-sidebar-border: var(--sidebar-border);
 | 
					 | 
				
			||||||
  --color-sidebar-ring: var(--sidebar-ring);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:root {
 | 
					 | 
				
			||||||
  --radius: 0.625rem;
 | 
					 | 
				
			||||||
  --background: oklch(1 0 0);
 | 
					 | 
				
			||||||
  --foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --card: oklch(1 0 0);
 | 
					 | 
				
			||||||
  --card-foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --popover: oklch(1 0 0);
 | 
					 | 
				
			||||||
  --popover-foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --primary: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --primary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --secondary: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --secondary-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --muted: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --muted-foreground: oklch(0.556 0 0);
 | 
					 | 
				
			||||||
  --accent: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --accent-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --destructive: oklch(0.577 0.245 27.325);
 | 
					 | 
				
			||||||
  --border: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --input: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --ring: oklch(0.708 0 0);
 | 
					 | 
				
			||||||
  --chart-1: oklch(0.646 0.222 41.116);
 | 
					 | 
				
			||||||
  --chart-2: oklch(0.6 0.118 184.704);
 | 
					 | 
				
			||||||
  --chart-3: oklch(0.398 0.07 227.392);
 | 
					 | 
				
			||||||
  --chart-4: oklch(0.828 0.189 84.429);
 | 
					 | 
				
			||||||
  --chart-5: oklch(0.769 0.188 70.08);
 | 
					 | 
				
			||||||
  --sidebar: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-foreground: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --sidebar-primary: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --sidebar-primary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent: oklch(0.97 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --sidebar-border: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --sidebar-ring: oklch(0.708 0 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.dark {
 | 
					 | 
				
			||||||
  --background: oklch(0.145 0 0);
 | 
					 | 
				
			||||||
  --foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --card: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --card-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --popover: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --popover-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --primary: oklch(0.922 0 0);
 | 
					 | 
				
			||||||
  --primary-foreground: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --secondary: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --secondary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --muted: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --muted-foreground: oklch(0.708 0 0);
 | 
					 | 
				
			||||||
  --accent: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --accent-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --destructive: oklch(0.704 0.191 22.216);
 | 
					 | 
				
			||||||
  --border: oklch(1 0 0 / 10%);
 | 
					 | 
				
			||||||
  --input: oklch(1 0 0 / 15%);
 | 
					 | 
				
			||||||
  --ring: oklch(0.556 0 0);
 | 
					 | 
				
			||||||
  --chart-1: oklch(0.488 0.243 264.376);
 | 
					 | 
				
			||||||
  --chart-2: oklch(0.696 0.17 162.48);
 | 
					 | 
				
			||||||
  --chart-3: oklch(0.769 0.188 70.08);
 | 
					 | 
				
			||||||
  --chart-4: oklch(0.627 0.265 303.9);
 | 
					 | 
				
			||||||
  --chart-5: oklch(0.645 0.246 16.439);
 | 
					 | 
				
			||||||
  --sidebar: oklch(0.205 0 0);
 | 
					 | 
				
			||||||
  --sidebar-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-primary: oklch(0.488 0.243 264.376);
 | 
					 | 
				
			||||||
  --sidebar-primary-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent: oklch(0.269 0 0);
 | 
					 | 
				
			||||||
  --sidebar-accent-foreground: oklch(0.985 0 0);
 | 
					 | 
				
			||||||
  --sidebar-border: oklch(1 0 0 / 10%);
 | 
					 | 
				
			||||||
  --sidebar-ring: oklch(0.556 0 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@layer base {
 | 
					 | 
				
			||||||
  * {
 | 
					 | 
				
			||||||
    @apply border-border outline-ring/50;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  body {
 | 
					 | 
				
			||||||
    @apply bg-background text-foreground;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,15 +1,16 @@
 | 
				
			|||||||
@import 'tailwindcss';
 | 
					@import 'tailwindcss';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@theme {
 | 
					@theme {
 | 
				
			||||||
  --color-primary: #ffc107;
 | 
					  /* --color-primary: #ffc107;
 | 
				
			||||||
  --color-secondary: #ffa000;
 | 
					  --color-secondary: #ffa000;
 | 
				
			||||||
  --color-text-primary: #000000;
 | 
					  --color-text-primary: #000000;
 | 
				
			||||||
  --color-text-secondary: #000000;
 | 
					  --color-text-secondary: #000000;
 | 
				
			||||||
  --color-success: #28a745;
 | 
					  --color-success: #28a745; */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  --color-scrollbar-thumb: #999999;
 | 
					  --color-scrollbar-thumb: #999999;
 | 
				
			||||||
  --color-scrollbar-track: rgba(0, 0, 0, 0.1);
 | 
					  --color-scrollbar-track: rgba(0, 0, 0, 0.1);
 | 
				
			||||||
  --color-scrollbar-thumb-hover: #666666;
 | 
					  --color-scrollbar-thumb-hover: #666666;
 | 
				
			||||||
  --scrollbar-color: #ffc107; /* 滚动条颜色 */
 | 
					  --scrollbar-color: #ffc107; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
html,
 | 
					html,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user