generated from template/vite-react-template
update mark
This commit is contained in:
parent
508ec96029
commit
a99d9c2322
@ -17,6 +17,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kevisual/query-mark": "workspace:*",
|
||||
"@kevisual/components": "workspace:*",
|
||||
"@kevisual/router": "0.0.9",
|
||||
"@kevisual/store": "workspace:*",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
@ -28,6 +29,7 @@
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-i18next": "^15.4.1",
|
||||
"react-toastify": "^11.0.5",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
|
3
src/Module.tsx
Normal file
3
src/Module.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import { App as Manager } from './manager/Manager';
|
||||
|
||||
export { Manager };
|
@ -2,7 +2,7 @@ import { useManagerStore } from './store';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useShallow } from 'zustand/shallow';
|
||||
import { ManagerProvider } from './Provider';
|
||||
import { ChevronDown, ChevronLeft, Edit, Plus, Search, Trash, Menu as MenuIcon, MenuSquare } from 'lucide-react';
|
||||
import { ChevronDown, ChevronLeft, X, Edit, Plus, Search, Trash, Menu as MenuIcon, MenuSquare } from 'lucide-react';
|
||||
import dayjs from 'dayjs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { EditMark as EditMarkComponent } from './edit/Edit';
|
||||
@ -16,17 +16,19 @@ type ManagerProps = {
|
||||
showAdd?: boolean;
|
||||
onClick?: (data?: any) => void;
|
||||
markType?: MarkType;
|
||||
showSelect?: boolean;
|
||||
};
|
||||
export const Manager = (props: ManagerProps) => {
|
||||
const { showSearch = true, showAdd = false, onClick } = props;
|
||||
const { showSearch = true, showAdd = false, onClick, showSelect = true } = props;
|
||||
|
||||
const { control } = useForm({ defaultValues: { search: '' } });
|
||||
const { list, init, setCurrentMarkId, currentMarkId, deleteMark, getMark, setMarkData, pagination, setPagination, getList, search, setSearch } =
|
||||
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,
|
||||
@ -87,8 +89,9 @@ export const Manager = (props: ManagerProps) => {
|
||||
}
|
||||
};
|
||||
console.log('list', list.length, pagination.total);
|
||||
|
||||
return (
|
||||
<div className='w-full h-full p-4 relative'>
|
||||
<div className='w-full h-full p-4 bg-white border-r border-r-gray-200 relative'>
|
||||
<div className='flex px-4 mb-4 justify-between items-center absolute top-0 left-0 h-[56px] w-full'>
|
||||
<div className='flex ml-12 items-center space-x-2 '>
|
||||
<Controller
|
||||
@ -122,6 +125,8 @@ export const Manager = (props: ManagerProps) => {
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center space-x-2'}>
|
||||
{showSelect && (
|
||||
<>
|
||||
<IconButton onClick={handleClick}>
|
||||
<MenuIcon className='w-4 h-4' />
|
||||
</IconButton>
|
||||
@ -143,13 +148,15 @@ export const Manager = (props: ManagerProps) => {
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</>
|
||||
)}
|
||||
<button
|
||||
className={clsx(
|
||||
'text-blue-500 cursor-pointer hover:underline flex items-center p-2 rounded-md hover:bg-blue-100 transition duration-200',
|
||||
showAdd ? '' : 'hidden',
|
||||
)}>
|
||||
<Plus
|
||||
className={clsx('w-4 h-4 ', currentMarkId ? 'rotate-12' : 'rotate-0')}
|
||||
className={clsx('w-4 h-4 ')}
|
||||
onClick={() => {
|
||||
setCurrentMarkId('');
|
||||
|
||||
@ -157,7 +164,7 @@ export const Manager = (props: ManagerProps) => {
|
||||
id: '',
|
||||
title: '',
|
||||
description: '',
|
||||
markType: 'md' as any,
|
||||
markType: props.markType || ('md' as any),
|
||||
summary: '',
|
||||
tags: [],
|
||||
link: '',
|
||||
@ -165,6 +172,16 @@ export const Manager = (props: ManagerProps) => {
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
{markData && (
|
||||
<button
|
||||
className='text-blue-500 cursor-pointer hover:underline flex items-center p-2 rounded-md hover:bg-blue-100 transition duration-200'
|
||||
onClick={() => {
|
||||
setCurrentMarkId('');
|
||||
setMarkData(undefined);
|
||||
}}>
|
||||
<X className='w-4 h-4 ' />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-[56px] overflow-auto scrollbar' style={{ height: 'calc(100% - 56px)' }}>
|
||||
@ -259,11 +276,25 @@ export const EditMark = () => {
|
||||
}
|
||||
return <div className='w-full h-full'></div>;
|
||||
};
|
||||
export const LayoutMain = (props: { children?: React.ReactNode }) => {
|
||||
export const LayoutMain = (props: { children?: React.ReactNode; expandChildren?: React.ReactNode }) => {
|
||||
const [openMenu, setOpenMenu] = useState(false);
|
||||
const getDocumentHeight = () => {
|
||||
return document.documentElement.scrollHeight;
|
||||
};
|
||||
const markData = useManagerStore((state) => state.markData);
|
||||
const isEdit = !!markData;
|
||||
const hasExpandChildren = !!props.expandChildren;
|
||||
const style = useMemo(() => {
|
||||
if (!hasExpandChildren || openMenu) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
top: getDocumentHeight() / 2 + 10,
|
||||
};
|
||||
}, [getDocumentHeight, hasExpandChildren, openMenu]);
|
||||
return (
|
||||
<div className='w-full h-full flex'>
|
||||
<div className='absolute top-4 left-4 z-10'>
|
||||
<div className={clsx('absolute top-4 z-10', openMenu ? 'left-4' : '-left-4')} style={style}>
|
||||
<Button
|
||||
variant='contained'
|
||||
color={openMenu ? 'info' : 'primary'}
|
||||
@ -278,9 +309,12 @@ export const LayoutMain = (props: { children?: React.ReactNode }) => {
|
||||
</Button>
|
||||
</div>
|
||||
<div className={clsx('h-full w-full sm:w-1/3', openMenu ? '' : 'hidden')}>{props.children}</div>
|
||||
{(!props.expandChildren || isEdit) && (
|
||||
<div className={clsx('h-full hidden sm:block sm:w-2/3', openMenu ? '' : 'hidden')}>
|
||||
<EditMark />
|
||||
</div>
|
||||
)}
|
||||
{props.expandChildren && <div className='h-full grow'>{props.expandChildren}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -305,12 +339,19 @@ export type AppProps = {
|
||||
* 管理器id, 存储到store的id
|
||||
*/
|
||||
managerId?: string;
|
||||
children?: React.ReactNode;
|
||||
showSelect?: boolean;
|
||||
};
|
||||
export const App = (props: AppProps) => {
|
||||
return (
|
||||
<ManagerProvider id={props.managerId}>
|
||||
<LayoutMain>
|
||||
<Manager markType={props.markType} showSearch={props.showSearch} showAdd={props.showAdd} onClick={props.onClick} />
|
||||
<LayoutMain expandChildren={props.children}>
|
||||
<Manager
|
||||
markType={props.markType}
|
||||
showSearch={props.showSearch}
|
||||
showAdd={props.showAdd}
|
||||
onClick={props.onClick}
|
||||
showSelect={props.showSelect}></Manager>
|
||||
</LayoutMain>
|
||||
</ManagerProvider>
|
||||
);
|
||||
|
@ -91,9 +91,20 @@ export const EditMark = () => {
|
||||
defaultValue={mark?.thumbnail || ''}
|
||||
render={({ field }) => <TextField {...field} label={t('thumbnail')} variant='outlined' fullWidth margin='normal' />}
|
||||
/>
|
||||
<div className='flex gap-2'>
|
||||
<Button type='submit' variant='contained' color='primary'>
|
||||
{t('save')}
|
||||
</Button>
|
||||
<Button
|
||||
variant='contained'
|
||||
color='secondary'
|
||||
onClick={() => {
|
||||
setCurrentMarkId('');
|
||||
setMarkData(undefined);
|
||||
}}>
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ export const createManagerStore: StateCreator<ManagerStore, [], [], any> = (set,
|
||||
},
|
||||
updateMark: async (mark: Mark) => {
|
||||
const queryMark = get().queryMark;
|
||||
const res = await queryMark.updateMark(mark.id, mark);
|
||||
const res = await queryMark.updateMark(mark);
|
||||
if (res.code === 200) {
|
||||
set((state) => {
|
||||
const oldList = state.list;
|
||||
|
30
vite.lib.config.ts
Normal file
30
vite.lib.config.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import path from 'path';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import pkgs from './package.json' with { type: 'json' };
|
||||
const version = pkgs.version || '0.0.1';
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const basename = isDev ? '/' : pkgs?.basename || '/';
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
base: basename,
|
||||
define: {
|
||||
BASE_NAME: JSON.stringify(basename),
|
||||
},
|
||||
build: {
|
||||
target: 'esnext',
|
||||
lib: {
|
||||
entry: path.resolve(__dirname, './src/pages/App.tsx'),
|
||||
name: 'Mark',
|
||||
fileName: (format) => `mark.${format}.js`,
|
||||
},
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user