import { useManagerStore } from './store'; import { useEffect, useMemo, useState } from 'react'; import { useShallow } from 'zustand/shallow'; import { ChevronDown, X, Edit, Plus, Search, Trash, Menu as MenuIcon, MenuSquare } from 'lucide-react'; import dayjs from 'dayjs'; import { EditMark as EditMarkComponent } from './edit/Edit'; import { toast } from 'sonner'; import clsx from 'clsx'; import { Controller, useForm } from 'react-hook-form'; import { IconButton } from '@/components/a/button'; import { MarkType } from '@kevisual/api/query-mark'; import { Menu } from '@/components/a/menu'; import { MarkTypes } from './constant'; type ManagerProps = { showSearch?: boolean; showAdd?: boolean; onClick?: (data?: any, e?: Event) => void; markType?: MarkType; showSelect?: boolean; }; export { useManagerStore }; export const Manager = (props: ManagerProps) => { const { showSearch = true, showAdd = false, onClick, showSelect = true } = props; const { control } = useForm({ defaultValues: { search: '' } }); const { list, init, setCurrentMarkId, currentMarkId, markData, deleteMark, getMark, setMarkData, pagination, setPagination, getList, search, setSearch } = useManagerStore( useShallow((state) => { return { list: state.list, init: state.init, markData: state.markData, currentMarkId: state.currentMarkId, setCurrentMarkId: state.setCurrentMarkId, deleteMark: state.deleteMark, getMark: state.getMark, setMarkData: state.setMarkData, pagination: state.pagination, setPagination: state.setPagination, search: state.search, setSearch: state.setSearch, getList: state.getList, }; }), ); const handleMenuItemClick = (option: string) => { console.log('option', option); init(option as any); }; useEffect(() => { const url = new URL(window.location.href); let markType = url.searchParams.get('markType') || ''; if (!markType && props.markType) { markType = props.markType; } init((markType as any) || 'md'); }, []); useEffect(() => { if (search) { getList(); } else if (pagination.current > 1) { getList(); } }, [pagination.current, search]); const onEditMark = async (markId: string) => { setCurrentMarkId(markId); const res = await getMark(markId); console.log('mark', res); if (res.code === 200) { setMarkData(res.data!); } }; const onDeleteMark = async (markId: string) => { const res = await deleteMark(markId); if (res.code === 200) { toast.success('删除成功'); } }; return (
(
{ if (event.key === 'Enter') { setSearch(field.value); if (!field.value) { getList(); } } }} />
setSearch(field.value)} />
)} />
{showSelect && ( <> { return { label: item, value: item }; })} onSelect={handleMenuItemClick}> )} {markData && ( )}
{list.map((item, index) => { const isCurrent = item.id === currentMarkId; return (
{ onClick?.(item, e as any); e.stopPropagation(); e.preventDefault(); }}>
{item.title}
类型: {item.markType}
概要: {item.summary}
标签: {item.tags?.join?.(', ')}
{/*
描述: {item.description}
*/}
{ window.open(item.link, '_blank'); }}> 链接: {item.link}
创建时间: {dayjs(item.createdAt).format('YYYY-MM-DD HH:mm:ss')}
更新时间: {dayjs(item.updatedAt).format('YYYY-MM-DD HH:mm:ss')}
); })}
{list.length < pagination.total && ( )}
); }; export const EditMark = () => { const { markData } = useManagerStore( useShallow((state) => { return { markData: state.markData, }; }), ); const mark = markData; if (!mark) { return null; } if (mark) { return ; } return
; }; export const LayoutMain = (props: { children?: React.ReactNode; expandChildren?: React.ReactNode; open?: boolean; hasTopTitle?: boolean }) => { const getDocumentHeight = () => { return document.documentElement.scrollHeight; }; const mStore = useManagerStore( useShallow((state) => { return { open: state.open, setOpen: state.setOpen, markData: state.markData, }; }), ); const markData = mStore.markData; const openMenu = mStore.open; const setOpenMenu = mStore.setOpen; useEffect(() => { if (props.open !== undefined) { setOpenMenu!(props.open); } }, []); const isEdit = !!markData; const hasExpandChildren = !!props.expandChildren; const style = useMemo(() => { const top = props.hasTopTitle ? 70 : 0; // Adjust top based on whether there's a title if (!hasExpandChildren || openMenu) { return { top, }; } return { top: getDocumentHeight() / 2 + 10 + top, }; }, [getDocumentHeight, hasExpandChildren, openMenu, props.hasTopTitle]); return (
{ setOpenMenu(!openMenu); }}>
{props.children}
{(!props.expandChildren || isEdit) && ( )} {props.expandChildren &&
{props.expandChildren}
}
); }; export type AppProps = { /** * 标记类型, wallnote md excalidraw */ markType?: MarkType; /** * 是否显示搜索框 */ showSearch?: boolean; /** * 是否显示添加按钮 */ showAdd?: boolean; /** * 点击事件 */ onClick?: (data?: any) => void; /** * 管理器id, 存储到store的id */ managerId?: string; children?: React.ReactNode; showSelect?: boolean; openMenu?: boolean; hasTopTitle?: boolean; // 是否有顶部标题 }; export const ProviderManagerName = 'mark-manager'; export const App = (props: AppProps) => { return ( ); };