Compare commits

2 Commits
main ... router

Author SHA1 Message Date
0cd189f83e update 2026-01-28 03:26:14 +08:00
78fd9fcda0 test tank 2026-01-28 03:12:53 +08:00
71 changed files with 1886 additions and 875 deletions

View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/user/_index')({
beforeLoad: () => {
throw redirect({
to: '/user/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -62,6 +62,9 @@
"@eslint/js": "^9.39.2", "@eslint/js": "^9.39.2",
"@kevisual/router": "^0.0.63", "@kevisual/router": "^0.0.63",
"@kevisual/ssl": "^0.0.1", "@kevisual/ssl": "^0.0.1",
"@tanstack/react-router": "^1.157.16",
"@tanstack/react-router-devtools": "^1.157.16",
"@tanstack/router-plugin": "^1.157.16",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^25.0.10", "@types/node": "^25.0.10",

559
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +1,50 @@
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; import { RouterProvider, createRouter } from '@tanstack/react-router'
// import { App as ContainerApp } from './pages/container'; import { routeTree } from './routeTree.gen'
import { App as UserAppApp } from './pages/app'; import { useTheme, theme } from '@kevisual/components/theme/index.tsx'
import { App as HomeApp } from './pages/home'; import { ToastContainer } from 'react-toastify'
import { useEffect, useState } from 'react'
import 'dayjs/locale/zh-cn'
import 'dayjs/locale/en'
import zhCN from 'antd/locale/zh_CN'
import enUS from 'antd/locale/en_US'
import ConfigProvider from 'antd/es/config-provider'
import { useTranslation } from 'react-i18next'
import React from 'react'
import { ThemeProvider } from '@mui/material'
// import { App as MapApp } from './pages/map'; // Set up a Router instance
// import { App as UserApp } from './pages/user'; const router = createRouter({
// import { App as FileApp } from './pages/file'; routeTree,
// import { App as OrgApp } from './pages/org'; defaultPreload: 'intent',
// import { App as ConfigApp } from './pages/config'; scrollRestoration: true,
// import { App as DomainApp } from './pages/domain'; })
import { basename } from './modules/basename'; // Register things for typesafety
import { Redirect } from './modules/Redirect'; declare module '@tanstack/react-router' {
import { useTheme, theme } from '@kevisual/components/theme/index.tsx'; interface Register {
import { ToastContainer } from 'react-toastify'; router: typeof router
import { lazy, Suspense } from 'react'; }
import 'dayjs/locale/zh-cn'; }
import 'dayjs/locale/en';
import zhCN from 'antd/locale/zh_CN'; const CustomThemeProvider2 = ({ children }: { children: React.ReactNode }) => {
import enUS from 'antd/locale/en_US'; return <ThemeProvider theme={theme}>{children}</ThemeProvider>
import ConfigProvider from 'antd/es/config-provider'; }
import { useTranslation } from 'react-i18next';
import React, { useEffect, useState } from 'react';
import { ThemeProvider } from '@mui/material';
const ContainerApp = lazy(() => import('./pages/container'));
const MapApp = lazy(() => import('./pages/map'));
const UserApp = lazy(() => import('./pages/user'));
const FileApp = lazy(() => import('./pages/file'));
const OrgApp = lazy(() => import('./pages/org'));
const ConfigApp = lazy(() => import('./pages/config'));
const DomainApp = lazy(() => import('./pages/domain'));
export const CustomThemeProvider2 = ({ children }: { children: React.ReactNode }) => {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};
const AntProvider = ({ children }: { children: React.ReactNode }) => { const AntProvider = ({ children }: { children: React.ReactNode }) => {
const theme = useTheme(); const themeContext = useTheme()
const primaryColor = theme.palette.primary.main; const primaryColor = themeContext.palette.primary.main
const secondaryColor = theme.palette.secondary.main; const secondaryColor = themeContext.palette.secondary.main
const { i18n } = useTranslation(); const { i18n } = useTranslation()
const [locale, setLocale] = useState(zhCN); const [locale, setLocale] = useState(zhCN)
useEffect(() => { useEffect(() => {
if (i18n.language === 'en') { if (i18n.language === 'en') {
setLocale(enUS); setLocale(enUS)
} else { } else {
setLocale(zhCN); setLocale(zhCN)
} }
}, [i18n.language]); }, [i18n.language])
return ( return (
<ConfigProvider <ConfigProvider
locale={locale} locale={locale}
@@ -75,44 +73,20 @@ const AntProvider = ({ children }: { children: React.ReactNode }) => {
}}> }}>
{children} {children}
</ConfigProvider> </ConfigProvider>
); )
}; }
export const App = () => {
const App = () => {
return ( return (
<CustomThemeProvider2> <CustomThemeProvider2>
<AntProvider> <AntProvider>
<div className='w-full h-full'> <RouterProvider router={router} />
<Router basename={basename}>
<Routes>
<Route path='/' element={<Redirect to='/app/' />} />
<Route
path='/container/*'
element={
<Suspense fallback={'loading container'}>
<ContainerApp />
</Suspense>
}
/>
<Route path='/map/*' element={<MapApp />} />
<Route path='/user-center/*' element={<UserApp />} />
<Route path='/user/*' element={<UserApp />} />
<Route path='/org/*' element={<OrgApp />} />
<Route path='/config/*' element={<ConfigApp />} />
<Route path='/app/*' element={<UserAppApp />} />
<Route path='/file/*' element={<FileApp />} />
<Route path='/domain/*' element={<DomainApp />} />
{/* <Route path='/home/*' element={<HomeApp />} /> */}
<Route path='/404' element={<div>404</div>} />
<Route path='*' element={<div>404</div>} />
</Routes>
</Router>
</div>
</AntProvider> </AntProvider>
<div id='for-drawer'></div> <div id='for-drawer'></div>
<div id='for-modal'> <div id='for-modal'></div>
</div>
<ToastContainer /> <ToastContainer />
</CustomThemeProvider2> </CustomThemeProvider2>
); )
}; }
export default App

View File

@@ -1,13 +1,24 @@
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
import { App } from './App.tsx'; import { RouterProvider, createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
import './globals.css'; import './globals.css';
import { Suspense } from 'react';
import { I18NextProvider } from '@kevisual/components/translate/I18Next.tsx'; import { I18NextProvider } from '@kevisual/components/translate/I18Next.tsx';
// Set up a Router instance
const router = createRouter({
routeTree,
defaultPreload: 'intent',
scrollRestoration: true,
})
// Register things for typesafety
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<I18NextProvider basename={!DEV_SERVER ? '/root/locales' : '/'}> <I18NextProvider basename={!DEV_SERVER ? '/root/locales' : '/'}>
<Suspense fallback={<div>Loading...</div>}> <RouterProvider router={router} />
<App />
</Suspense>
</I18NextProvider>, </I18NextProvider>,
); );

View File

@@ -1,6 +1,5 @@
import { basename } from './basename'; import { redirect } from '@tanstack/react-router';
import { Navigate } from 'react-router-dom';
export const Redirect = (({ to }) => { export const Redirect = ({ to }: { to: string }) => {
return <Navigate to={`${to}`} />; throw redirect({ to });
}) as any as typeof Navigate; };

View File

@@ -1,4 +1,3 @@
import { useShallow } from 'zustand/react/shallow';
import { useLayoutStore } from './store'; import { useLayoutStore } from './store';
import clsx from 'clsx'; import clsx from 'clsx';
import { Menu, MenuItem, Tooltip } from '@mui/material'; import { Menu, MenuItem, Tooltip } from '@mui/material';
@@ -14,19 +13,14 @@ import { useTranslation } from 'react-i18next';
import React from 'react'; import React from 'react';
export const LayoutUser = () => { export const LayoutUser = () => {
const { open, setOpen, isAdmin, ...store } = useLayoutStore( const menuStore = useLayoutStore();
useShallow((state) => ({
open: state.openUser, //
setOpen: state.setOpenUser,
me: state.me,
switchOrg: state.switchOrg,
isAdmin: state.isAdmin,
})),
);
const navigate = useNewNavigate(); const navigate = useNewNavigate();
const { t } = useTranslation(); const { t } = useTranslation();
const { openUser, setOpenUser, me, switchOrg, isAdmin } = menuStore;
const items = useMemo(() => { const items = useMemo(() => {
const orgs = store.me?.orgs || []; const orgs = me?.orgs || [];
return orgs.map((item) => { return orgs.map((item) => {
return { return {
label: item, label: item,
@@ -34,9 +28,10 @@ export const LayoutUser = () => {
icon: <SmileOutlined />, icon: <SmileOutlined />,
}; };
}); });
}, [store.me]); }, [me]);
const menu = useMemo(() => { const menu = useMemo(() => {
const orgs = store.me?.orgs || []; const orgs = me?.orgs || [];
const hasOrg = orgs.length > 0; const hasOrg = orgs.length > 0;
const items = [ const items = [
{ {
@@ -71,7 +66,8 @@ export const LayoutUser = () => {
} }
return true; return true;
}); });
}, [store.me]); }, [me]);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleClick = (event: React.MouseEvent<HTMLElement>) => { const handleClick = (event: React.MouseEvent<HTMLElement>) => {
@@ -82,16 +78,16 @@ export const LayoutUser = () => {
}; };
return ( return (
<div className={clsx('w-full h-full absolute z-20 no-drag text-primary', !open && 'hidden')}> <div className={clsx('w-full h-full absolute z-20 no-drag text-primary', !openUser && 'hidden')}>
<div <div
className='w-full absolute h-full opacity-60 z-0' className='w-full absolute h-full opacity-60 z-0'
onClick={() => { onClick={() => {
setOpen(false); setOpenUser(false);
}}></div> }}></div>
<div className='w-[400px] bg-amber-900 transition-all duration-300 h-full absolute top-0 right-0 rounded-l-lg'> <div className='w-[400px] bg-amber-900 transition-all duration-300 h-full absolute top-0 right-0 rounded-l-lg'>
<div className='flex justify-between p-6 mt-4 font-bold items-center border-b'> <div className='flex justify-between p-6 mt-4 font-bold items-center border-b'>
<div className='flex items-center gap-2'> <div className='flex items-center gap-2'>
{t('User')}: <span className='text-primary'>{store.me?.username}</span> {t('User')}: <span className='text-primary'>{me?.username}</span>
</div> </div>
<div className='flex gap-4'> <div className='flex gap-4'>
{items.length > 0 && ( {items.length > 0 && (
@@ -102,7 +98,7 @@ export const LayoutUser = () => {
</Tooltip> </Tooltip>
)} )}
<Button onClick={() => setOpen(false)}> <Button onClick={() => setOpenUser(false)}>
<X /> <X />
</Button> </Button>
</div> </div>
@@ -116,7 +112,7 @@ export const LayoutUser = () => {
onClick={() => { onClick={() => {
if (item.link) { if (item.link) {
navigate(item.link); navigate(item.link);
setOpen(false); setOpenUser(false);
} else { } else {
message.info('Coming soon'); message.info('Coming soon');
} }
@@ -131,7 +127,6 @@ export const LayoutUser = () => {
className='flex items-center p-4 hover:bg-secondary hover:text-white cursor-pointer' className='flex items-center p-4 hover:bg-secondary hover:text-white cursor-pointer'
onClick={async () => { onClick={async () => {
const res = await queryLogin.logout(); const res = await queryLogin.logout();
// console.log(res);
if (res.success) { if (res.success) {
window.open('/user/login', '_self'); window.open('/user/login', '_self');
} else { } else {
@@ -150,7 +145,7 @@ export const LayoutUser = () => {
<MenuItem <MenuItem
key={index} key={index}
onClick={() => { onClick={() => {
store.switchOrg(item.key, 'org'); switchOrg(item.key, 'org');
handleClose(); handleClose();
}}> }}>
<div className='mr-4'>{item.icon}</div> <div className='mr-4'>{item.icon}</div>

View File

@@ -1,4 +1,3 @@
import { useShallow } from 'zustand/react/shallow';
import { useLayoutStore } from './store'; import { useLayoutStore } from './store';
import clsx from 'clsx'; import clsx from 'clsx';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
@@ -13,6 +12,7 @@ import { X, Settings } from 'lucide-react';
import { useNewNavigate } from '../navicate'; import { useNewNavigate } from '../navicate';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Map } from 'lucide-react'; import { Map } from 'lucide-react';
export const useQuickMenu = () => { export const useQuickMenu = () => {
const { t } = useTranslation(); const { t } = useTranslation();
return [ return [
@@ -33,8 +33,12 @@ export const useQuickMenu = () => {
}, },
]; ];
}; };
export const LayoutMenu = () => { export const LayoutMenu = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const menuStore = useLayoutStore();
const navigate = useNewNavigate();
const meun = [ const meun = [
{ {
title: t('Home'), title: t('Home'),
@@ -63,8 +67,9 @@ export const LayoutMenu = () => {
icon: <SmileOutlined />, icon: <SmileOutlined />,
}, },
]; ];
const { open, setOpen } = useLayoutStore(useShallow((state) => ({ open: state.open, setOpen: state.setOpen })));
const navigate = useNewNavigate(); const { open, setOpen } = menuStore;
return ( return (
<div className={clsx('w-full h-full text-primary absolute z-20 no-drag', !open && 'hidden')}> <div className={clsx('w-full h-full text-primary absolute z-20 no-drag', !open && 'hidden')}>
<div <div

View File

@@ -1,9 +1,8 @@
import { MenuOutlined, SwapOutlined } from '@ant-design/icons'; import { MenuOutlined, SwapOutlined } from '@ant-design/icons';
import { Tooltip } from '@mui/material'; import { Tooltip } from '@mui/material';
import { Outlet, useNavigate } from 'react-router-dom'; import { Outlet, useNavigate } from '@tanstack/react-router';
import { LayoutMenu, useQuickMenu } from './Menu'; import { LayoutMenu, useQuickMenu } from './Menu';
import { useLayoutStore, usePlatformStore } from './store'; import { useLayoutStore, usePlatformStore } from './store';
import { useShallow } from 'zustand/react/shallow';
import { useEffect, useLayoutEffect, useState } from 'react'; import { useEffect, useLayoutEffect, useState } from 'react';
import { LayoutUser } from './LayoutUser'; import { LayoutUser } from './LayoutUser';
import { PandaPNG } from '@/assets/index.tsx'; import { PandaPNG } from '@/assets/index.tsx';
@@ -25,29 +24,11 @@ type LayoutMainProps = {
children?: React.ReactNode; children?: React.ReactNode;
}; };
export const LayoutMain = (props: LayoutMainProps) => { export const LayoutMain = (props: LayoutMainProps) => {
const menuStore = useLayoutStore( const menuStore = useLayoutStore();
useShallow((state) => { const platformStore = usePlatformStore();
return { const isMac = platformStore.isMac;
open: state.open, const mount = platformStore.mount;
setOpen: state.setOpen, // const isElectron = platformStore.isElectron;
getMe: state.getMe,
me: state.me,
setOpenUser: state.setOpenUser,
switchOrg: state.switchOrg,
};
}),
);
const platformStore = usePlatformStore(
useShallow((state) => {
return {
isMac: state.isMac,
mount: state.mount,
isElectron: state.isElectron,
init: state.init,
};
}),
);
const { isMac, mount, isElectron } = platformStore;
const navigate = useNavigate(); const navigate = useNavigate();
const quickMenu = useQuickMenu(); const quickMenu = useQuickMenu();

View File

@@ -1,14 +1,12 @@
import { NavigateFunction, To, useNavigate } from 'react-router-dom'; import { To, useNavigate } from '@tanstack/react-router';
import { basename } from './basename';
/** /**
* 如果有basepath刚好给path加上basepath * 如果有basepath刚好给path加上basepath
* @returns NavigateFunction * @returns NavigateFunction
*/ */
export const useNewNavigate = (): NavigateFunction => { export const useNewNavigate = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const fn = (path: To, data?: any) => { const fn = (path: To, data?: any) => {
// navigate(basename + '/' + path, data);
navigate(path, data); navigate(path, data);
}; };
return fn as NavigateFunction; return fn;
}; };

View File

@@ -3,25 +3,22 @@ import { Folder } from 'lucide-react';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import { useLayoutStore } from '@/modules/layout/store'; import { useLayoutStore } from '@/modules/layout/store';
import { useShallow } from 'zustand/shallow';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
type Props = { type Props = {
pathname?: string; pathname?: string;
}; };
export const AIEditorLink = (props: Props) => { export const AIEditorLink = (props: Props) => {
const layoutUser = useLayoutStore( const layoutStore = useLayoutStore();
useShallow((state) => ({ const { me } = layoutStore;
user: state.me?.username || '', const username = me?.username || '';
})),
);
return ( return (
<Tooltip title={'打开对应的文件夹'}> <Tooltip title={'打开对应的文件夹'}>
<Button <Button
onClick={() => { onClick={() => {
if (!layoutUser.user) { if (!username) {
toast.error('请先登录'); toast.error('请先登录');
} }
let folder = `${layoutUser.user}/resources/${props.pathname}`; let folder = `${username}/resources/${props.pathname}`;
if (folder.endsWith('/')) { if (folder.endsWith('/')) {
folder = folder.slice(0, -1); folder = folder.slice(0, -1);
} }

View File

@@ -1,6 +1,5 @@
import { useNavigation, useParams } from 'react-router'; import { useNavigation, useParams } from 'react-router';
import { useAppVersionStore } from '../store'; import { useAppVersionStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import CloudUploadOutlined from '@ant-design/icons/CloudUploadOutlined'; import CloudUploadOutlined from '@ant-design/icons/CloudUploadOutlined';
import DeleteOutlined from '@ant-design/icons/DeleteOutlined'; import DeleteOutlined from '@ant-design/icons/DeleteOutlined';
@@ -28,45 +27,37 @@ import { AIEditorLink } from './AIEditorLink';
const FormModal = () => { const FormModal = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { control, handleSubmit, reset } = useForm(); const { control, handleSubmit, reset } = useForm();
const containerStore = useAppVersionStore( const versionStore = useAppVersionStore();
useShallow((state) => { const { showEdit, setShowEdit, formData, updateData } = versionStore;
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
updateData: state.updateData,
};
}),
);
useEffect(() => { useEffect(() => {
const open = containerStore.showEdit; const open = showEdit;
if (open) { if (open) {
const isNull = isObjectNull(containerStore.formData); const isNull = isObjectNull(formData);
if (isNull) { if (isNull) {
reset({}); reset({});
} else { } else {
reset(containerStore.formData); reset(formData);
} }
} }
}, [containerStore.showEdit]); }, [showEdit]);
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
const pickValues = pick(values, ['id', 'key', 'version']); const pickValues = pick(values, ['id', 'key', 'version']);
containerStore.updateData(pickValues); updateData(pickValues);
}; };
const onClose = () => { const onClose = () => {
containerStore.setShowEdit(false); setShowEdit(false);
reset(); reset();
}; };
const isEdit = containerStore.formData.id; const isEdit = formData.id;
return ( return (
<Dialog <Dialog
open={containerStore.showEdit} open={showEdit}
onClose={() => containerStore.setShowEdit(false)} onClose={() => setShowEdit(false)}
sx={{ sx={{
'& .MuiDialog-paper': { '& .MuiDialog-paper': {
width: '800px', width: '800px',
@@ -94,48 +85,29 @@ const FormModal = () => {
export const AppVersionList = () => { export const AppVersionList = () => {
const params = useParams(); const params = useParams();
const appKey = params.appKey; const appKey = params.appKey;
const versionStore = useAppVersionStore( const versionStore = useAppVersionStore();
useShallow((state) => { const { list, getList, key, setKey, setShowEdit, formData, setFormData, deleteData, publishVersion, app } = versionStore;
return { const appDeleteModalStore = useAppDeleteModalStore();
list: state.list, const { onClickDelete } = appDeleteModalStore;
getList: state.getList,
key: state.key,
setKey: state.setKey,
setShowEdit: state.setShowEdit,
formData: state.formData,
setFormData: state.setFormData,
deleteData: state.deleteData,
publishVersion: state.publishVersion,
app: state.app,
};
}),
);
const appDeleteModalStore = useAppDeleteModalStore(
useShallow((state) => {
return {
onClickDelete: state.onClickDelete,
};
}),
);
const navigate = useNewNavigate(); const navigate = useNewNavigate();
const [isUpload, setIsUpload] = useState(false); const [isUpload, setIsUpload] = useState(false);
useEffect(() => { useEffect(() => {
// fetch app version list // fetch app version list
if (appKey) { if (appKey) {
versionStore.setKey(appKey); setKey(appKey);
versionStore.getList(); getList();
} }
}, [appKey]); }, [appKey]);
const appVersion = useMemo(() => { const appVersion = useMemo(() => {
return versionStore.app?.version || ''; return app?.version || '';
}, [versionStore.app?.version]); }, [app?.version]);
return ( return (
<div className='w-full h-full flex bg-slate-100'> <div className='w-full h-full flex bg-slate-100'>
<div className='p-2 bg-white'> <div className='p-2 bg-white'>
<IconButton <IconButton
onClick={() => { onClick={() => {
versionStore.setFormData({ key: appKey }); setFormData({ key: appKey });
versionStore.setShowEdit(true); setShowEdit(true);
}}> }}>
<PlusOutlined /> <PlusOutlined />
</IconButton> </IconButton>
@@ -185,7 +157,7 @@ export const AppVersionList = () => {
<Tooltip title='Delete'> <Tooltip title='Delete'>
<Button <Button
onClick={(e) => { onClick={(e) => {
appDeleteModalStore.onClickDelete('app-version', item); onClickDelete('app-version', item);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<DeleteOutlined /> <DeleteOutlined />
@@ -194,7 +166,7 @@ export const AppVersionList = () => {
<Tooltip title='使用当前版本,发布为此版本'> <Tooltip title='使用当前版本,发布为此版本'>
<Button <Button
onClick={() => { onClick={() => {
versionStore.publishVersion({ id: item.id }); publishVersion({ id: item.id });
}}> }}>
<CloudUploadOutlined /> <CloudUploadOutlined />
</Button> </Button>
@@ -243,7 +215,7 @@ export const AppVersionList = () => {
<LeftOutlined /> <LeftOutlined />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<div className='font-bold'>{versionStore.key}</div> <div className='font-bold'>{key}</div>
</div> </div>
<AppVersionFile /> <AppVersionFile />
</div> </div>
@@ -255,28 +227,22 @@ export const AppVersionList = () => {
); );
}; };
export const AppVersionFile = () => { export const AppVersionFile = () => {
const versionStore = useAppVersionStore( const versionStore = useAppVersionStore();
useShallow((state) => { const { formData, detectVersionList } = versionStore;
return {
formData: state.formData,
detectVersionList: state.detectVersionList,
};
}),
);
const versionFiles = useMemo(() => { const versionFiles = useMemo(() => {
if (!versionStore.formData?.data) return []; if (!versionStore.formData?.data) return [];
const files = versionStore.formData.data.files || []; const files = versionStore.formData.data.files || [];
return files; return files;
}, [versionStore.formData]); }, [versionStore.formData]);
const onDetect = useCallback(async () => { const onDetect = useCallback(async () => {
console.log('formData', versionStore.formData); console.log('formData', formData);
if (!versionStore.formData.key || !versionStore.formData.version) { if (!formData.key || !formData.version) {
toast.error('请先选择应用和版本'); toast.error('请先选择应用和版本');
return; return;
} }
const res = await versionStore.detectVersionList({ const res = await detectVersionList({
appKey: versionStore.formData.key, appKey: formData.key,
version: versionStore.formData.version, version: formData.version,
}); });
console.log('res', res); console.log('res', res);
if (res.code === 200) { if (res.code === 200) {
@@ -284,11 +250,11 @@ export const AppVersionFile = () => {
} else { } else {
toast.error(res.message || 'Detect failed'); toast.error(res.message || 'Detect failed');
} }
}, [versionStore.formData]); }, [formData]);
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>
<div>version: {versionStore.formData.version}</div> <div>version: {formData.version}</div>
<div className='border border-gray-200 rounded-md my-2 grow overflow-hidden'> <div className='border border-gray-200 rounded-md my-2 grow overflow-hidden'>
<div className='flex gap-2 items-center border-b border-b-gray-200 py-2 px-2'> <div className='flex gap-2 items-center border-b border-b-gray-200 py-2 px-2'>
Files Files
@@ -304,7 +270,7 @@ export const AppVersionFile = () => {
}}> }}>
<div className='h-full overflow-auto mb-4 pb-8 scrollbar'> <div className='h-full overflow-auto mb-4 pb-8 scrollbar'>
{versionFiles.map((file, index) => { {versionFiles.map((file, index) => {
const prefix = versionStore.formData.key + '/' + versionStore.formData.version + '/'; const prefix = formData.key + '/' + formData.version + '/';
const _path = file.path || ''; const _path = file.path || '';
const path = _path.replace(prefix, ''); const path = _path.replace(prefix, '');
return ( return (

View File

@@ -1,4 +1,3 @@
import { useShallow } from 'zustand/react/shallow';
import { useAppVersionStore, useUserAppStore } from '../store'; import { useAppVersionStore, useUserAppStore } from '../store';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useModal } from '@kevisual/components/modal/Confirm.tsx'; import { useModal } from '@kevisual/components/modal/Confirm.tsx';
@@ -42,44 +41,37 @@ const FormModal = () => {
const { control, handleSubmit, reset } = useForm({ const { control, handleSubmit, reset } = useForm({
defaultValues, defaultValues,
}); });
const containerStore = useUserAppStore( const userAppStore = useUserAppStore();
useShallow((state) => { const { showEdit, setShowEdit, userApp, updateData } = userAppStore;
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
userApp: state.userApp,
updateData: state.updateData,
};
}),
);
useEffect(() => { useEffect(() => {
const open = containerStore.showEdit; const open = showEdit;
if (open) { if (open) {
const isNull = isObjectNull(containerStore.userApp); const isNull = isObjectNull(userApp);
if (isNull) { if (isNull) {
reset(defaultValues); reset(defaultValues);
} else { } else {
reset(containerStore.userApp); reset(userApp);
} }
} }
}, [containerStore.showEdit, containerStore.userApp]); }, [showEdit, userApp]);
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
const pickValues = pick(values, ['id', 'title', 'domain', 'key', 'description', 'proxy', 'status']); const pickValues = pick(values, ['id', 'title', 'domain', 'key', 'description', 'proxy', 'status']);
containerStore.updateData(pickValues); updateData(pickValues);
}; };
const onClose = () => { const onClose = () => {
containerStore.setShowEdit(false); setShowEdit(false);
reset(); reset();
}; };
const isEdit = containerStore?.userApp?.id; const isEdit = userApp?.id;
const theme = useTheme(); const theme = useTheme();
const defaultProps = theme.components?.MuiTextField?.defaultProps as any; const defaultProps = theme.components?.MuiTextField?.defaultProps as any;
const isAdmin = useLayoutStore(useShallow((state) => state.isAdmin)); const layoutStore = useLayoutStore();
const { isAdmin } = layoutStore;
return ( return (
<Dialog <Dialog
open={containerStore.showEdit} open={showEdit}
onClose={() => containerStore.setShowEdit(false)} onClose={() => setShowEdit(false)}
sx={{ sx={{
'& .MuiDialog-paper': { '& .MuiDialog-paper': {
width: '1000px', width: '1000px',
@@ -134,51 +126,44 @@ const FormModal = () => {
const ShareModal = () => { const ShareModal = () => {
const [permission, setPermission] = useState<any>(null); const [permission, setPermission] = useState<any>(null);
const [runtime, setRuntime] = useState<string[]>([]); const [runtime, setRuntime] = useState<string[]>([]);
const containerStore = useUserAppStore( const userAppStore = useUserAppStore();
useShallow((state) => { const { showShareEdit, setShowShareEdit, updateData, userApp } = userAppStore;
return {
showEdit: state.showShareEdit,
setShowEdit: state.setShowShareEdit,
updateData: state.updateData,
userApp: state.userApp,
};
}),
);
useEffect(() => { useEffect(() => {
const open = containerStore.showEdit; const open = showShareEdit;
if (open) { if (open) {
const permission = containerStore.userApp?.data?.permission || {}; const perm = userApp?.data?.permission || {};
const runtime = containerStore.userApp?.data?.runtime || []; const run = userApp?.data?.runtime || [];
if (isObjectNull(permission)) { if (isObjectNull(perm)) {
setPermission({ share: 'private' }); setPermission({ share: 'private' });
} else { } else {
setPermission(permission); setPermission(perm);
} }
setRuntime(runtime); setRuntime(run);
} }
}, [containerStore.showEdit, containerStore.userApp]); }, [showShareEdit, userApp]);
const onFinish = async () => { const onFinish = async () => {
const values = { const values = {
id: containerStore.userApp.id, id: userApp.id,
data: { data: {
permission, permission,
runtime, runtime,
}, },
}; };
containerStore.updateData(values); updateData(values);
}; };
const onClose = () => { const onClose = () => {
containerStore.setShowEdit(false); setShowShareEdit(false);
}; };
const { t } = useTranslation(); const { t } = useTranslation();
const theme = useTheme(); const theme = useTheme();
const defaultProps = theme.components?.MuiTextField?.defaultProps as any; const defaultProps = theme.components?.MuiTextField?.defaultProps as any;
const isAdmin = useLayoutStore(useShallow((state) => state.isAdmin)); const layoutStore = useLayoutStore();
const { isAdmin } = layoutStore;
return ( return (
<Dialog <Dialog
open={containerStore.showEdit} open={showShareEdit}
onClose={() => { onClose={() => {
containerStore.setShowEdit(false); setShowShareEdit(false);
}}> }}>
<DialogTitle>{t('app.share')}</DialogTitle> <DialogTitle>{t('app.share')}</DialogTitle>
<DialogContent> <DialogContent>
@@ -236,37 +221,15 @@ const ShareModal = () => {
export const List = () => { export const List = () => {
const [modal, contextHolder] = useModal(); const [modal, contextHolder] = useModal();
const { t } = useTranslation(); const { t } = useTranslation();
const userAppStore = useUserAppStore( const userAppStore = useUserAppStore();
useShallow((state) => { const { list, getList, setShowEdit, formData, setFormData, deleteData, setShowShareEdit, getUserApp } = userAppStore;
return { const appVersionStore = useAppVersionStore();
list: state.list, const { publishVersion } = appVersionStore;
getList: state.getList, const appDeleteModalStore = useAppDeleteModalStore();
setShowEdit: state.setShowEdit, const { onClickDelete } = appDeleteModalStore;
formData: state.formData,
setFormData: state.setFormData,
deleteData: state.deleteData,
setShowShareEdit: state.setShowShareEdit,
getUserApp: state.getUserApp,
};
}),
);
const appVersionStore = useAppVersionStore(
useShallow((state) => {
return {
publishVersion: state.publishVersion,
};
}),
);
const appDeleteModalStore = useAppDeleteModalStore(
useShallow((state) => {
return {
onClickDelete: state.onClickDelete,
};
}),
);
const navicate = useNewNavigate(); const navicate = useNewNavigate();
useEffect(() => { useEffect(() => {
userAppStore.getList(); getList();
}, []); }, []);
return ( return (
<div className='w-full h-full flex bg-slate-100'> <div className='w-full h-full flex bg-slate-100'>
@@ -277,8 +240,8 @@ export const List = () => {
padding: '8px', padding: '8px',
}} }}
onClick={() => { onClick={() => {
userAppStore.setFormData({}); setFormData({});
userAppStore.setShowEdit(true); setShowEdit(true);
}}> }}>
<PlusOutlined /> <PlusOutlined />
</IconButton> </IconButton>
@@ -369,9 +332,9 @@ export const List = () => {
<Tooltip title={'Edit'}> <Tooltip title={'Edit'}>
<Button <Button
onClick={() => { onClick={() => {
userAppStore.getUserApp(item.id); getUserApp(item.id);
userAppStore.setFormData(item); setFormData(item);
userAppStore.setShowEdit(true); setShowEdit(true);
}}> }}>
<Edit size={16} /> <Edit size={16} />
</Button> </Button>
@@ -387,9 +350,9 @@ export const List = () => {
<Tooltip title={iText.share.tips}> <Tooltip title={iText.share.tips}>
<Button <Button
onClick={() => { onClick={() => {
userAppStore.getUserApp(item.id); getUserApp(item.id);
userAppStore.setFormData(item); setFormData(item);
userAppStore.setShowShareEdit(true); setShowShareEdit(true);
}}> }}>
<Share2 size={16} /> <Share2 size={16} />
</Button> </Button>
@@ -397,7 +360,7 @@ export const List = () => {
<Tooltip title={'reload'}> <Tooltip title={'reload'}>
<Button <Button
onClick={() => { onClick={() => {
appVersionStore.publishVersion({ appKey: item.key, version: item.version }, { showToast: false }); publishVersion({ appKey: item.key, version: item.version }, { showToast: false });
}}> }}>
<RefreshCcw size={16} /> <RefreshCcw size={16} />
</Button> </Button>
@@ -438,7 +401,7 @@ export const List = () => {
<Tooltip title={'Delete'}> <Tooltip title={'Delete'}>
<Button <Button
onClick={(e) => { onClick={(e) => {
appDeleteModalStore.onClickDelete('user-app', item); onClickDelete('user-app', item);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<Trash size={16} /> <Trash size={16} />

View File

@@ -1,18 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { Main } from './layouts'; import { Main } from './layouts';
import { List } from './edit/List';
import { AppVersionList } from './edit/AppVersionList';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <Main />;
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/app/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
<Route path='/:appKey/version/list' element={<AppVersionList />} />
</Route>
</Routes>
);
}; };
export default App; export default App;

View File

@@ -3,7 +3,6 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { create } from 'zustand'; import { create } from 'zustand';
import { useAppVersionStore, useUserAppStore } from '../store'; import { useAppVersionStore, useUserAppStore } from '../store';
import { useShallow } from 'zustand/shallow';
type AppDeleteModalStore = { type AppDeleteModalStore = {
open: boolean; open: boolean;
@@ -29,28 +28,18 @@ export const useAppDeleteModalStore = create<AppDeleteModalStore>((set) => ({
export const AppDeleteModal = () => { export const AppDeleteModal = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { open, setOpen, app, type, setType } = useAppDeleteModalStore(); const { open, setOpen, app, type, setType } = useAppDeleteModalStore();
const userAppStore = useUserAppStore( const userAppStore = useUserAppStore();
useShallow((state) => { const { deleteData: deleteUserAppData } = userAppStore;
return { const appVersionStore = useAppVersionStore();
deleteData: state.deleteData, const { deleteData: deleteVersionData } = appVersionStore;
};
}),
);
const appVersionStore = useAppVersionStore(
useShallow((state) => {
return {
deleteData: state.deleteData,
};
}),
);
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);
}; };
const onDelete = (deleteFile = false) => { const onDelete = (deleteFile = false) => {
if (type === 'user-app') { if (type === 'user-app') {
userAppStore.deleteData(app.id, deleteFile); deleteUserAppData(app.id, deleteFile);
} else { } else {
appVersionStore.deleteData(app.id, deleteFile); deleteVersionData(app.id, deleteFile);
} }
setOpen(false); setOpen(false);
}; };

View File

@@ -1,7 +1,6 @@
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import { useCallback, useRef } from 'react'; import { useCallback, useRef } from 'react';
import { useAppVersionStore } from '../store'; import { useAppVersionStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { message } from '@/modules/message'; import { message } from '@/modules/message';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
export type FileType = { export type FileType = {
@@ -14,15 +13,8 @@ export type FileType = {
export const FileUpload = () => { export const FileUpload = () => {
const ref = useRef<HTMLInputElement | null>(null); const ref = useRef<HTMLInputElement | null>(null);
const { t } = useTranslation(); const { t } = useTranslation();
const appVersionStore = useAppVersionStore( const versionStore = useAppVersionStore();
useShallow((state) => { const { formData, setFormData, updateByFromData } = versionStore;
return {
formData: state.formData,
setFormData: state.setFormData,
updateByFromData: state.updateByFromData,
};
}),
);
const onChange = useCallback( const onChange = useCallback(
async (e) => { async (e) => {
console.log(e.target.files); console.log(e.target.files);
@@ -57,8 +49,8 @@ export const FileUpload = () => {
const webkitRelativePath = file.webkitRelativePath.replace(root + '/', ''); const webkitRelativePath = file.webkitRelativePath.replace(root + '/', '');
formData.append('file', file, webkitRelativePath); // 保留文件夹路径 formData.append('file', file, webkitRelativePath); // 保留文件夹路径
}); });
const key = appVersionStore.formData.key; const key = formData.key;
const version = appVersionStore.formData.version; const version = formData.version;
formData.append('appKey', key); formData.append('appKey', key);
formData.append('version', version); formData.append('version', version);
const res = await fetch('/api/app/upload', { const res = await fetch('/api/app/upload', {
@@ -69,15 +61,15 @@ export const FileUpload = () => {
}, },
}).then((res) => res.json()); }).then((res) => res.json());
if (res?.code === 200) { if (res?.code === 200) {
appVersionStore.setFormData(res.data); setFormData(res.data);
appVersionStore.updateByFromData(); updateByFromData();
} else { } else {
message.error(res.message || 'Request failed'); message.error(res.message || 'Request failed');
} }
// 清理之前上传的文件 // 清理之前上传的文件
e.target.value = ''; e.target.value = '';
}, },
[appVersionStore.formData], [formData],
); );
return ( return (
@@ -93,8 +85,8 @@ export const FileUpload = () => {
/> />
<Button <Button
onClick={() => { onClick={() => {
const key = appVersionStore.formData.key; const key = formData.key;
const version = appVersionStore.formData.version; const version = formData.version;
if (!key || !version) { if (!key || !version) {
message.error('请先选择应用和版本'); message.error('请先选择应用和版本');
return; return;

View File

@@ -11,7 +11,6 @@ import { useController } from 'react-hook-form';
import { TextField, TextFieldLabel } from '@kevisual/components/input/TextField.tsx'; import { TextField, TextFieldLabel } from '@kevisual/components/input/TextField.tsx';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { IconButton } from '@kevisual/components/button/index.tsx'; import { IconButton } from '@kevisual/components/button/index.tsx';
import { useShallow } from 'zustand/shallow';
import { load, dump } from 'js-yaml'; import { load, dump } from 'js-yaml';
import CodeEditor from '@uiw/react-textarea-code-editor'; import CodeEditor from '@uiw/react-textarea-code-editor';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
@@ -25,13 +24,8 @@ type DataYamlEditProps = {
type?: 'yaml' | 'json'; type?: 'yaml' | 'json';
}; };
export const DataYamlEdit = ({ onSave, type }: DataYamlEditProps) => { export const DataYamlEdit = ({ onSave, type }: DataYamlEditProps) => {
const { formData } = useConfigStore( const configStore = useConfigStore();
useShallow((state) => { const { formData } = configStore;
return {
formData: state.formData,
};
}),
);
const [yaml, setYaml] = useState(formData.data); const [yaml, setYaml] = useState(formData.data);
useEffect(() => { useEffect(() => {
const _fromData = formData.data || {}; const _fromData = formData.data || {};
@@ -79,16 +73,8 @@ export const DataYamlEdit = ({ onSave, type }: DataYamlEditProps) => {
}; };
export const DrawerEdit = () => { export const DrawerEdit = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { showEdit, setShowEdit, formData, updateData } = useConfigStore( const configStore = useConfigStore();
useShallow((state) => { const { showEdit, setShowEdit, formData, updateData } = configStore;
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
updateData: state.updateData,
};
}),
);
const [tab, setTab] = useState<'base' | 'yaml' | 'json'>('base'); const [tab, setTab] = useState<'base' | 'yaml' | 'json'>('base');
const { control, handleSubmit, reset } = useForm({ const { control, handleSubmit, reset } = useForm({
@@ -189,9 +175,11 @@ export const DrawerEdit = () => {
}; };
export const List = () => { export const List = () => {
const { list, getConfigList, setShowEdit, setFormData, deleteConfig, updateData, formData, detectConfig, onOpenKey } = useConfigStore(); const configStore = useConfigStore();
const { list, getConfigList, setShowEdit, setFormData, deleteConfig, updateData, formData, detectConfig, onOpenKey } = configStore;
const [modal, contextHolder] = useModal(); const [modal, contextHolder] = useModal();
const isAdmin = useLayoutStore(useShallow((state) => state.isAdmin)); const layoutStore = useLayoutStore();
const { isAdmin } = layoutStore;
useEffect(() => { useEffect(() => {
getConfigList(); getConfigList();
}, []); }, []);

View File

@@ -1,16 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { LayoutMain } from '@/modules/layout'; import { LayoutMain } from '@/modules/layout';
import { List } from './edit/List.tsx';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <LayoutMain title='Config' />;
<Routes>
<Route element={<LayoutMain title='Config' />}>
<Route path='/' element={<Redirect to='/config/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
</Route>
</Routes>
);
}; };
export default App; export default App;

View File

@@ -1,6 +1,5 @@
import { Fragment, Suspense, useEffect, useState } from 'react'; import { Fragment, Suspense, useEffect, useState } from 'react';
import { useContainerStore } from '../store'; import { useContainerStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
// import copy from 'copy-to-clipboard'; // import copy from 'copy-to-clipboard';
import { useNewNavigate } from '@/modules'; import { useNewNavigate } from '@/modules';
import { message } from '@/modules/message'; import { message } from '@/modules/message';
@@ -26,45 +25,37 @@ const DrawEdit = React.lazy(() => import('../module/DrawEdit'));
const FormModal = () => { const FormModal = () => {
const { control, handleSubmit, reset, setValue } = useForm(); const { control, handleSubmit, reset, setValue } = useForm();
const containerStore = useContainerStore( const containerStore = useContainerStore();
useShallow((state) => { const { showEdit, setShowEdit, formData, updateData } = containerStore;
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
updateData: state.updateData,
};
}),
);
useEffect(() => { useEffect(() => {
const open = containerStore.showEdit; const open = showEdit;
if (open) { if (open) {
const isNull = isObjectNull(containerStore.formData); const isNull = isObjectNull(formData);
if (isNull) { if (isNull) {
reset({}); reset({});
} else { } else {
Object.keys(containerStore.formData).forEach((key) => { Object.keys(formData).forEach((key) => {
setValue(key, containerStore.formData[key]); setValue(key, formData[key]);
}); });
} }
} }
return () => { return () => {
reset({}); reset({});
}; };
}, [containerStore.showEdit]); }, [showEdit]);
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
const pickValues = pick(values, ['id', 'title', 'description', 'tags', 'code']); const pickValues = pick(values, ['id', 'title', 'description', 'tags', 'code']);
containerStore.updateData(pickValues); updateData(pickValues);
}; };
const onClose = () => { const onClose = () => {
containerStore.setShowEdit(false); setShowEdit(false);
reset(); reset();
}; };
const isEdit = containerStore.formData.id; const isEdit = formData.id;
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Dialog open={containerStore.showEdit} onClose={onClose}> <Dialog open={containerStore.showEdit} onClose={onClose}>
@@ -105,35 +96,27 @@ const FormModal = () => {
const PublishFormModal = () => { const PublishFormModal = () => {
const { control, handleSubmit, reset, setValue, getValues } = useForm(); const { control, handleSubmit, reset, setValue, getValues } = useForm();
const { t } = useTranslation(); const { t } = useTranslation();
const containerStore = useContainerStore( const containerStore = useContainerStore();
useShallow((state) => { const { showPublish, setShowPublish, formData, updateData } = containerStore;
return {
showEdit: state.showPublish,
setShowEdit: state.setShowPublish,
formData: state.formData,
updateData: state.updateData,
};
}),
);
useEffect(() => { useEffect(() => {
const open = containerStore.showEdit; const open = showPublish;
if (open) { if (open) {
const isNull = isObjectNull(containerStore.formData); const isNull = isObjectNull(formData);
if (isNull) { if (isNull) {
reset({}); reset({});
} else { } else {
Object.keys(containerStore.formData).forEach((key) => { Object.keys(formData).forEach((key) => {
setValue(key, containerStore.formData[key]); setValue(key, formData[key]);
}); });
} }
} }
}, [containerStore.showEdit]); }, [showPublish]);
const onFinish = async () => { const onFinish = async () => {
const values = getValues(); const values = getValues();
const pickValues = pick(values, ['id', 'publish.key', 'publish.version', 'publish.fileName', 'publish.description']); const pickValues = pick(values, ['id', 'publish.key', 'publish.version', 'publish.fileName', 'publish.description']);
const containerRes = await containerStore.updateData(pickValues, { closePublish: false }); const containerRes = await updateData(pickValues, { closePublish: false });
if (containerRes.code === 200) { if (containerRes.code === 200) {
const code = containerRes.data?.code || '-'; const code = containerRes.data?.code || '-';
const fileName = values['publish']?.['fileName']; const fileName = values['publish']?.['fileName'];
@@ -167,16 +150,16 @@ const PublishFormModal = () => {
const onUpdate = async () => { const onUpdate = async () => {
const values = getValues(); const values = getValues();
containerStore.updateData(values); updateData(values);
}; };
const onClose = () => { const onClose = () => {
containerStore.setShowEdit(false); setShowPublish(false);
reset(); reset();
}; };
return ( return (
<Dialog open={containerStore.showEdit} onClose={onClose}> <Dialog open={showPublish} onClose={onClose}>
<DialogTitle>Publish</DialogTitle> <DialogTitle>Publish</DialogTitle>
<DialogContent sx={{ padding: '10px', minWidth: '600px' }}> <DialogContent sx={{ padding: '10px', minWidth: '600px' }}>
<form className='flex flex-col gap-6 pt-2' onSubmit={handleSubmit(onFinish)}> <form className='flex flex-col gap-6 pt-2' onSubmit={handleSubmit(onFinish)}>
@@ -224,28 +207,11 @@ const PublishFormModal = () => {
}; };
export const ContainerList = () => { export const ContainerList = () => {
const [modal, contextHolder] = useModal(); const [modal, contextHolder] = useModal();
const containerStore = useContainerStore( const containerStore = useContainerStore();
useShallow((state) => { const { setFormData, setShowEdit, list, deleteData, getList, loading, setShowPublish, updateData, formData, getOne, setOpenDrawEdit, openDrawEdit } = containerStore;
return {
setFormData: state.setFormData,
setShowEdit: state.setShowEdit,
list: state.list,
deleteData: state.deleteData,
getList: state.getList,
loading: state.loading,
// publishData: state.publishData,
setShowPublish: state.setShowPublish,
updateData: state.updateData,
formData: state.formData,
getOne: state.getOne,
setOpenDrawEdit: state.setOpenDrawEdit,
openDrawEdit: state.openDrawEdit,
};
}),
);
useEffect(() => { useEffect(() => {
containerStore.getList(); getList();
}, []); }, []);
const onAdd = () => { const onAdd = () => {
@@ -302,9 +268,9 @@ export const ContainerList = () => {
<Tooltip title='编辑代码'> <Tooltip title='编辑代码'>
<Button <Button
onClick={(e) => { onClick={(e) => {
containerStore.getOne(item.id); getOne(item.id);
containerStore.setFormData(item); setFormData(item);
containerStore.setOpenDrawEdit(true); setOpenDrawEdit(true);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<Settings size={16} /> <Settings size={16} />
@@ -313,8 +279,8 @@ export const ContainerList = () => {
<Tooltip title='编辑'> <Tooltip title='编辑'>
<Button <Button
onClick={(e) => { onClick={(e) => {
containerStore.setFormData(item); setFormData(item);
containerStore.setShowEdit(true); setShowEdit(true);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<EditOutlined /> <EditOutlined />
@@ -323,9 +289,8 @@ export const ContainerList = () => {
<Tooltip title='添加到 user app当中'> <Tooltip title='添加到 user app当中'>
<Button <Button
onClick={(e) => { onClick={(e) => {
// containerStore.publishData(item); setFormData(item);
containerStore.setFormData(item); setShowPublish(true);
containerStore.setShowPublish(true);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<CloudUploadOutlined /> <CloudUploadOutlined />
@@ -340,7 +305,7 @@ export const ContainerList = () => {
title: 'Delete', title: 'Delete',
content: 'Are you sure delete this data?', content: 'Are you sure delete this data?',
onOk: () => { onOk: () => {
containerStore.deleteData(item.id); deleteData(item.id);
}, },
}); });
e.stopPropagation(); e.stopPropagation();

View File

@@ -1,19 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { ContainerList } from './edit/List';
import { Main } from './layouts'; import { Main } from './layouts';
import { Preview, PreviewWrapper } from './preview';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <Main />;
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/container/edit/list' />}></Route>
<Route path='edit/list' element={<ContainerList />} />
<Route path='preview/:id/wrapper' element={<PreviewWrapper />} />
</Route>
<Route path='preview/:id' element={<Preview />} />
</Routes>
);
}; };
export default App; export default App;

View File

@@ -1,6 +1,5 @@
import { lazy, useEffect, useRef, useState } from 'react'; import { lazy, useEffect, useRef, useState } from 'react';
import { Box, Drawer } from '@mui/material'; import { Box, Drawer } from '@mui/material';
import { useShallow } from 'zustand/shallow';
import { useContainerStore } from '../store'; import { useContainerStore } from '../store';
import { Tooltip } from '@mui/material'; import { Tooltip } from '@mui/material';
import { IconButton } from '@kevisual/components/button/index.tsx'; import { IconButton } from '@kevisual/components/button/index.tsx';
@@ -12,17 +11,8 @@ import { BaseEditor } from '@kevisual/codemirror/editor/editor.ts';
export const DrawEdit = () => { export const DrawEdit = () => {
const editorElRef = useRef<HTMLDivElement>(null); const editorElRef = useRef<HTMLDivElement>(null);
const editorRef = useRef<BaseEditor>(null); const editorRef = useRef<BaseEditor>(null);
const containerStore = useContainerStore( const containerStore = useContainerStore();
useShallow((state) => { const { openDrawEdit, setOpenDrawEdit, data, updateData } = containerStore;
return {
openDrawEdit: state.openDrawEdit,
setOpenDrawEdit: state.setOpenDrawEdit,
data: state.data,
updateData: state.updateData,
};
}),
);
const { openDrawEdit, setOpenDrawEdit } = containerStore;
const [mount, setMount] = useState(false); const [mount, setMount] = useState(false);
useEffect(() => { useEffect(() => {
if (openDrawEdit && editorElRef.current && !mount) { if (openDrawEdit && editorElRef.current && !mount) {
@@ -95,7 +85,7 @@ export const DrawEdit = () => {
}} }}
onClick={() => { onClick={() => {
const code = editorRef.current?.getContent(); const code = editorRef.current?.getContent();
containerStore.updateData({ id: containerStore.data.id, code }, { refresh: false }); updateData({ id: data.id, code }, { refresh: false });
}}> }}>
<SaveOutlined /> <SaveOutlined />
</IconButton> </IconButton>
@@ -114,7 +104,7 @@ export const DrawEdit = () => {
</IconButton> </IconButton>
</Tooltip> */} </Tooltip> */}
</div> </div>
<div className='flex-1 ml-2 flex items-center'>{containerStore.data?.title}</div> <div className='flex-1 ml-2 flex items-center'>{data?.title}</div>
</div> </div>
</div> </div>
<Box <Box

View File

@@ -1,16 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { Main } from './layouts'; import { Main } from './layouts';
import { List } from './edit/List';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <Main />;
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/domain/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
</Route>
</Routes>
);
}; };
export default App; export default App;

View File

@@ -1,4 +1,3 @@
import { useShallow } from 'zustand/react/shallow';
import { useFileStore } from '../store'; import { useFileStore } from '../store';
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import path from 'path-browserify'; import path from 'path-browserify';
@@ -17,16 +16,8 @@ import { useTranslation } from 'react-i18next';
import { UploadButton } from '@kevisual/resources/pages/upload/index.tsx'; import { UploadButton } from '@kevisual/resources/pages/upload/index.tsx';
import { DialogDirectory, DialogDeleteDirectory } from '@kevisual/resources/pages/upload/DialogDirectory.tsx'; import { DialogDirectory, DialogDeleteDirectory } from '@kevisual/resources/pages/upload/DialogDirectory.tsx';
export const CardPath = ({ children }: any) => { export const CardPath = ({ children }: any) => {
const userAppStore = useFileStore( const fileStore = useFileStore();
useShallow((state) => { const { list, getList, setPath, path } = fileStore;
return {
list: state.list,
getList: state.getList,
setPath: state.setPath,
path: state.path,
};
}),
);
const [dialogDirectory, setDialogDirectory] = useState(false); const [dialogDirectory, setDialogDirectory] = useState(false);
const [dialogDeleteDirectory, setDialogDeleteDirectory] = useState(false); const [dialogDeleteDirectory, setDialogDeleteDirectory] = useState(false);
const paths = ['root', ...userAppStore.path.split('/').filter((item) => item)]; const paths = ['root', ...userAppStore.path.split('/').filter((item) => item)];
@@ -163,29 +154,10 @@ export const CardPath = ({ children }: any) => {
export const List = () => { export const List = () => {
const [tab, setTab] = useState<'folder' | 'upload'>('folder'); const [tab, setTab] = useState<'folder' | 'upload'>('folder');
const uploadRef = useRef<HTMLDivElement>(null); const uploadRef = useRef<HTMLDivElement>(null);
const { setOpenDrawer, setPrefix, setResource, getStatFile, setOnce } = useResourceFileStore( const resourceFileStore = useResourceFileStore();
useShallow((state) => { const { setOpenDrawer, setPrefix, setResource, getStatFile, setOnce } = resourceFileStore;
return { const fileStore = useFileStore();
setOpenDrawer: state.setOpenDrawer, const { list, getList, setPath, path, getFile, file } = fileStore;
setPrefix: state.setPrefix,
setResource: state.setResource,
getStatFile: state.getStatFile,
setOnce: state.setOnce,
};
}),
);
const userAppStore = useFileStore(
useShallow((state) => {
return {
list: state.list,
getList: state.getList,
setPath: state.setPath,
path: state.path,
getFile: state.getFile,
file: state.file,
};
}),
);
useEffect(() => { useEffect(() => {
userAppStore.getList(); userAppStore.getList();
return () => { return () => {
@@ -201,9 +173,9 @@ export const List = () => {
<> <>
<CardPath> <CardPath>
<div className='flex flex-col'> <div className='flex flex-col'>
{userAppStore.list.map((item, index) => { {fileStore.list.map((item, index) => {
if (item.prefix) { if (item.prefix) {
let showPrefix = item.prefix.replace(userAppStore.path, ''); let showPrefix = item.prefix.replace(path, '');
showPrefix = showPrefix.replace('/', ''); showPrefix = showPrefix.replace('/', '');
return ( return (
<div <div

View File

@@ -1,16 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { Main } from './layouts'; import { Main } from './layouts';
import { List } from './edit/List';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <Main />;
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/file/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
</Route>
</Routes>
);
}; };
export default App; export default App;

View File

@@ -9,16 +9,14 @@ import { useDropzone } from 'react-dropzone';
import { CacheWorkspace } from '@kevisual/cache'; import { CacheWorkspace } from '@kevisual/cache';
import { useHomeStore } from './store/index.ts'; import { useHomeStore } from './store/index.ts';
import { UploadModal } from './module/UploadModal.tsx'; import { UploadModal } from './module/UploadModal.tsx';
import { useShallow } from 'zustand/shallow';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { SuccessModal } from './module/SuccessModal.tsx'; import { SuccessModal } from './module/SuccessModal.tsx';
export const Home = () => { export const Home = () => {
const editorElRef = useRef<HTMLDivElement>(null); const editorElRef = useRef<HTMLDivElement>(null);
const editorRef = useRef<BaseEditor>(null); const editorRef = useRef<BaseEditor>(null);
const { initApp, setOpenUploadModal, setText, filename } = useHomeStore( const homeStore = useHomeStore();
useShallow((state) => ({ initApp: state.initApp, setOpenUploadModal: state.setOpenUploadModal, setText: state.setText, filename: state.filename })), const { initApp, setOpenUploadModal, setText, filename } = homeStore;
);
const onDrop = (acceptedFiles) => { const onDrop = (acceptedFiles) => {
console.log(acceptedFiles); console.log(acceptedFiles);
const file = acceptedFiles[0]; const file = acceptedFiles[0];

View File

@@ -1,14 +1,12 @@
import { Route, Routes } from 'react-router-dom';
import { Main } from './layouts'; import { Main } from './layouts';
import { Home } from './Home'; import { Home } from './Home';
export const App = () => { export const App = () => {
return ( return (
<Routes> <Main>
<Route element={<Main />}> <Home />
<Route path='/' element={<Home />}></Route> </Main>
</Route>
</Routes>
); );
}; };
export default App; export default App;

View File

@@ -1,5 +1,5 @@
import { LayoutMain } from '@/modules/layout'; import { LayoutMain } from '@/modules/layout';
export const Main = () => { export const Main = ({ children }: { children?: React.ReactNode }) => {
return <LayoutMain title='Home' />; return <LayoutMain title='Home'>{children}</LayoutMain>;
}; };

View File

@@ -1,5 +1,4 @@
import { Dialog, DialogContent, DialogTitle } from '@mui/material'; import { Dialog, DialogContent, DialogTitle } from '@mui/material';
import { useShallow } from 'zustand/shallow';
import { useHomeStore } from '../store'; import { useHomeStore } from '../store';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useLayoutStore } from '@/modules/layout/store'; import { useLayoutStore } from '@/modules/layout/store';
@@ -12,16 +11,10 @@ export const Label = ({ label, children }: { label: string; children: React.Reac
); );
}; };
export const SuccessModal = () => { export const SuccessModal = () => {
const { openSuccessModal, setOpenSuccessModal, appKey, version, filename } = useHomeStore( const homeStore = useHomeStore();
useShallow((state) => ({ const { openSuccessModal, setOpenSuccessModal, appKey, version, filename } = homeStore;
openSuccessModal: state.openSuccessModal, const layoutStore = useLayoutStore();
setOpenSuccessModal: state.setOpenSuccessModal, const { me } = layoutStore;
appKey: state.appKey, //
version: state.version, //
filename: state.filename, //
})),
);
const { me } = useLayoutStore(useShallow((state) => ({ me: state.me })));
const link = useMemo(() => { const link = useMemo(() => {
const _currentHref = new URL(window.location.href); const _currentHref = new URL(window.location.href);
const username = me?.username; const username = me?.username;

View File

@@ -8,14 +8,15 @@ import { useTranslation } from 'react-i18next';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { uploadFile } from './upload-file'; import { uploadFile } from './upload-file';
import { useAppVersionStore } from '@/pages/app/store'; import { useAppVersionStore } from '@/pages/app/store';
import { useShallow } from 'zustand/shallow';
import { RefreshCcw } from 'lucide-react'; import { RefreshCcw } from 'lucide-react';
export const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10); export const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10);
export const UploadModal = () => { export const UploadModal = () => {
const { appKey, version, filename, openUploadModal, text, setOpenUploadModal, setAppKey, setVersion, setFilename, setOpenSuccessModal } = useHomeStore(); const homeStore = useHomeStore();
const { appKey, version, filename, openUploadModal, text, setOpenUploadModal, setAppKey, setVersion, setFilename, setOpenSuccessModal } = homeStore;
const { control, handleSubmit, reset, setValue } = useForm(); const { control, handleSubmit, reset, setValue } = useForm();
const { publishVersion } = useAppVersionStore(useShallow((state) => ({ publishVersion: state.publishVersion }))); const appVersionStore = useAppVersionStore();
const { publishVersion } = appVersionStore;
useEffect(() => { useEffect(() => {
if (openUploadModal) { if (openUploadModal) {
reset({ appKey: appKey || randomAppKey(), version: version || '1.0.0', filename: filename || 'index.html' }); reset({ appKey: appKey || randomAppKey(), version: version || '1.0.0', filename: filename || 'index.html' });

View File

@@ -2,20 +2,13 @@ import clsx from 'clsx';
import { useNewNavigate } from '@/modules'; import { useNewNavigate } from '@/modules';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLayoutStore } from '@/modules/layout/store'; import { useLayoutStore } from '@/modules/layout/store';
import { useShallow } from 'zustand/shallow';
import { useMemo } from 'react'; import { useMemo } from 'react';
const ServerPath = () => { const ServerPath = () => {
const navigate = useNewNavigate(); const navigate = useNewNavigate();
const { t } = useTranslation(); const { t } = useTranslation();
const layoutStore = useLayoutStore( const layoutStore = useLayoutStore();
useShallow((state) => { const { isAdmin, checkHasOrg } = layoutStore;
return {
isAdmin: state.isAdmin,
checkHasOrg: state.checkHasOrg,
};
}),
);
const serverPath = [ const serverPath = [
{ {
path: 'container', path: 'container',

View File

@@ -1,6 +1,5 @@
import { Fragment, useEffect, useState } from 'react'; import { Fragment, useEffect, useState } from 'react';
import { useOrgStore } from '../store'; import { useOrgStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { useNewNavigate } from '@/modules'; import { useNewNavigate } from '@/modules';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Tooltip, Button, ButtonGroup, Dialog, DialogTitle, DialogContent } from '@mui/material'; import { Tooltip, Button, ButtonGroup, Dialog, DialogTitle, DialogContent } from '@mui/material';
@@ -24,46 +23,37 @@ import { pick } from 'lodash-es';
const FormModal = () => { const FormModal = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { control, handleSubmit, reset } = useForm(); const { control, handleSubmit, reset } = useForm();
const userStore = useOrgStore( const orgStore = useOrgStore();
useShallow((state) => { const { showEdit, setShowEdit, formData, updateData, setFormData } = orgStore;
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
updateData: state.updateData,
setFormData: state.setFormData,
};
}),
);
useEffect(() => { useEffect(() => {
const open = userStore.showEdit; const open = showEdit;
if (open) { if (open) {
const isNull = isObjectNull(userStore.formData); const isNull = isObjectNull(formData);
if (isNull) { if (isNull) {
reset({}); reset({});
} else reset(userStore.formData); } else reset(formData);
} }
return () => { return () => {
reset({}); reset({});
}; };
}, [userStore.showEdit, userStore.formData, reset]); }, [showEdit, formData, reset]);
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
const pickValues = pick(values, ['id', 'username', 'description']); const pickValues = pick(values, ['id', 'username', 'description']);
userStore.updateData(pickValues); updateData(pickValues);
}; };
const onClose = () => { const onClose = () => {
userStore.setShowEdit(false); setShowEdit(false);
reset({}); reset({});
userStore.setFormData({}); setFormData({});
}; };
const isEdit = userStore.formData.id; const isEdit = formData.id;
return ( return (
<Dialog open={userStore.showEdit} onClose={() => userStore.setShowEdit(false)}> <Dialog open={showEdit} onClose={() => setShowEdit(false)}>
<DialogTitle>{isEdit ? 'Edit' : 'Add'}</DialogTitle> <DialogTitle>{isEdit ? 'Edit' : 'Add'}</DialogTitle>
<DialogContent sx={{ padding: '20px', minWidth: '600px' }}> <DialogContent sx={{ padding: '20px', minWidth: '600px' }}>
<form onSubmit={handleSubmit(onFinish)}> <form onSubmit={handleSubmit(onFinish)}>
@@ -94,30 +84,13 @@ const FormModal = () => {
}; };
export const List = () => { export const List = () => {
const navicate = useNewNavigate(); const navicate = useNewNavigate();
const userStore = useOrgStore( const orgStore = useOrgStore();
useShallow((state) => { const { setFormData, setShowEdit, list, deleteData, getList, loading, updateData, formData } = orgStore;
return { const layoutStore = useLayoutStore();
setFormData: state.setFormData, const { switchOrg } = layoutStore;
setShowEdit: state.setShowEdit,
list: state.list,
deleteData: state.deleteData,
getList: state.getList,
loading: state.loading,
updateData: state.updateData,
formData: state.formData,
};
}),
);
const layoutStore = useLayoutStore(
useShallow((state) => {
return {
switchOrg: state.switchOrg,
};
}),
);
const [modal, contextHolder] = useModal(); const [modal, contextHolder] = useModal();
useEffect(() => { useEffect(() => {
userStore.getList(); getList();
}, []); }, []);
const onAdd = () => { const onAdd = () => {
@@ -166,8 +139,8 @@ export const List = () => {
<Tooltip title={t('Edit')}> <Tooltip title={t('Edit')}>
<Button <Button
onClick={(e) => { onClick={(e) => {
userStore.setFormData(item); setFormData(item);
userStore.setShowEdit(true); setShowEdit(true);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<EditOutlined /> <EditOutlined />

View File

@@ -1,4 +1,3 @@
import { useShallow } from 'zustand/react/shallow';
import { useOrgStore } from '../store'; import { useOrgStore } from '../store';
import { useParams } from 'react-router'; import { useParams } from 'react-router';
import { useEffect } from 'react'; import { useEffect } from 'react';
@@ -19,30 +18,21 @@ import { useForm, Controller } from 'react-hook-form';
const FormModal = () => { const FormModal = () => {
const { control, handleSubmit, reset } = useForm(); const { control, handleSubmit, reset } = useForm();
const userStore = useOrgStore( const orgStore = useOrgStore();
useShallow((state) => { const { showUserEdit, setShowUserEdit, userFormData, setUserFormData, addUser } = orgStore;
return {
showEdit: state.showUserEdit,
setShowEdit: state.setShowUserEdit,
formData: state.userFormData,
setFormData: state.setUserFormData,
addUser: state.addUser,
};
}),
);
useEffect(() => { useEffect(() => {
const open = userStore.showEdit; const open = showUserEdit;
if (open) { if (open) {
const isNull = isObjectNull(userStore.formData); const isNull = isObjectNull(userFormData);
if (isNull) { if (isNull) {
reset({}); reset({});
} else reset(userStore.formData); } else reset(userFormData);
} }
return () => { return () => {
reset({}); reset({});
}; };
}, [userStore.showEdit, userStore.formData, reset]); }, [showUserEdit, userFormData, reset]);
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
console.log(values); console.log(values);
@@ -52,22 +42,22 @@ const FormModal = () => {
message.error('username is required'); message.error('username is required');
return; return;
} }
const res = await userStore.addUser({ username: username, role }); const res = await addUser({ username: username, role });
if (res?.code === 200) { if (res?.code === 200) {
userStore.setShowEdit(false); setShowUserEdit(false);
} }
}; };
const onClose = () => { const onClose = () => {
userStore.setShowEdit(false); setShowUserEdit(false);
userStore.setFormData({}); setUserFormData({});
}; };
const isEdit = userStore.formData.id; const isEdit = userFormData.id;
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Dialog open={userStore.showEdit} onClose={() => userStore.setShowEdit(false)}> <Dialog open={showUserEdit} onClose={() => setShowUserEdit(false)}>
<DialogTitle>{isEdit ? 'Edit' : 'Add'}</DialogTitle> <DialogTitle>{isEdit ? 'Edit' : 'Add'}</DialogTitle>
<DialogContent sx={{ padding: '20px', minWidth: '600px' }}> <DialogContent sx={{ padding: '20px', minWidth: '600px' }}>
<form className='flex flex-col gap-6' onSubmit={handleSubmit(onFinish)}> <form className='flex flex-col gap-6' onSubmit={handleSubmit(onFinish)}>
@@ -111,28 +101,15 @@ export const UserList = () => {
const navicate = useNewNavigate(); const navicate = useNewNavigate();
const [modal, contextHolder] = useModal(); const [modal, contextHolder] = useModal();
const { t } = useTranslation(); const { t } = useTranslation();
const orgStore = useOrgStore( const orgStore = useOrgStore();
useShallow((state) => { const { users, org, setOrgId, getOrg, setShowUserEdit, setUserFormData, setShowEdit, removeUser, addUser } = orgStore;
return {
users: state.users,
org: state.org,
setOrgId: state.setOrgId,
getOrg: state.getOrg,
setShowUserEdit: state.setShowUserEdit,
setUserFormData: state.setUserFormData,
setShowEdit: state.setShowEdit,
removeUser: state.removeUser,
addUser: state.addUser,
};
}),
);
useEffect(() => { useEffect(() => {
if (param.id) { if (param.id) {
orgStore.setOrgId(param.id); setOrgId(param.id);
orgStore.getOrg(); getOrg();
} }
return () => { return () => {
orgStore.setUserFormData({}); setUserFormData({});
}; };
}, []); }, []);
return ( return (
@@ -140,8 +117,8 @@ export const UserList = () => {
<div className='p-2 bg-white mr-2'> <div className='p-2 bg-white mr-2'>
<IconButton <IconButton
onClick={() => { onClick={() => {
orgStore.setUserFormData({}); setUserFormData({});
orgStore.setShowUserEdit(true); setShowUserEdit(true);
}}> }}>
<PlusOutlined /> <PlusOutlined />
</IconButton> </IconButton>
@@ -194,7 +171,7 @@ export const UserList = () => {
title: 'Delete', title: 'Delete',
content: 'Are you sure?', content: 'Are you sure?',
onOk: () => { onOk: () => {
orgStore.removeUser(item.id); removeUser(item.id);
}, },
}); });
}}> }}>

View File

@@ -1,19 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { List } from './edit/List';
import { Main } from './layouts'; import { Main } from './layouts';
import { UserList } from './edit/UserList';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <Main />;
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/org/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
<Route path='edit/user/:id' element={<UserList />} />
</Route>
</Routes>
);
}; };
export default App; export default App;

View File

@@ -1,6 +1,5 @@
import { Fragment, useEffect, useState } from 'react'; import { Fragment, useEffect, useState } from 'react';
import { useUserStore } from '../store'; import { useUserStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import { CardBlank } from '@kevisual/components/card/CardBlank.tsx'; import { CardBlank } from '@kevisual/components/card/CardBlank.tsx';
import { Dialog, ButtonGroup, Button, DialogContent, DialogTitle, Tooltip } from '@mui/material'; import { Dialog, ButtonGroup, Button, DialogContent, DialogTitle, Tooltip } from '@mui/material';
@@ -15,35 +14,26 @@ import { SquareAsterisk, Edit as EditOutlined, Trash as DeleteOutlined, Plus as
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
const FormModal = () => { const FormModal = () => {
const { control, handleSubmit, reset } = useForm(); const { control, handleSubmit, reset } = useForm();
const userStore = useUserStore( const userStore = useUserStore();
useShallow((state) => { const { showEdit, setShowEdit, formData, updateData, setFormData } = userStore;
return { const adminStore = useAdminStore();
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
updateData: state.updateData,
setFormData: state.setFormData,
};
}),
);
const adminStore = useAdminStore(useShallow((state) => state));
useEffect(() => { useEffect(() => {
const open = userStore.showEdit; const open = showEdit;
if (open) { if (open) {
const isNull = isObjectNull(userStore.formData); const isNull = isObjectNull(formData);
if (isNull) { if (isNull) {
reset({}); reset({});
} else reset(userStore.formData); } else reset(formData);
} }
return () => { return () => {
reset({}); reset({});
}; };
}, [userStore.showEdit]); }, [showEdit]);
const onFinish = (values: any) => { const onFinish = (values: any) => {
const pickValues = pick(values, ['id', 'username', 'description']); const pickValues = pick(values, ['id', 'username', 'description']);
if (pickValues.id) { if (pickValues.id) {
userStore.updateData(pickValues); updateData(pickValues);
} else { } else {
const newPickValues = pick(values, ['username', 'description', 'password']); const newPickValues = pick(values, ['username', 'description', 'password']);
adminStore.createNewUser(newPickValues); adminStore.createNewUser(newPickValues);
@@ -51,12 +41,12 @@ const FormModal = () => {
}; };
const onClose = () => { const onClose = () => {
userStore.setShowEdit(false); setShowEdit(false);
reset({}); reset({});
userStore.setFormData({}); setFormData({});
}; };
const isEdit = userStore.formData.id; const isEdit = formData.id;
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
@@ -101,8 +91,8 @@ const FormModal = () => {
}; };
export const NameModal = () => { export const NameModal = () => {
const { control, handleSubmit, reset } = useForm(); const { control, handleSubmit, reset } = useForm();
const userStore = useUserStore(useShallow((state) => state)); const userStore = useUserStore();
const adminStore = useAdminStore(useShallow((state) => state)); const adminStore = useAdminStore();
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
const check = await adminStore.checkUserExist(values.username); const check = await adminStore.checkUserExist(values.username);
if (check === false) { if (check === false) {
@@ -147,23 +137,11 @@ export const NameModal = () => {
}; };
export const List = () => { export const List = () => {
const [modal, contextHolder] = useModal(); const [modal, contextHolder] = useModal();
const userStore = useUserStore( const userStore = useUserStore();
useShallow((state) => { const { setFormData, setShowEdit, setShowNameEdit, list, deleteData, getList, loading, formData } = userStore;
return { const adminStore = useAdminStore();
setFormData: state.setFormData,
setShowEdit: state.setShowEdit,
setShowNameEdit: state.setShowNameEdit,
list: state.list,
deleteData: state.deleteData,
getList: state.getList,
loading: state.loading,
formData: state.formData,
};
}),
);
const adminStore = useAdminStore(useShallow((state) => state));
useEffect(() => { useEffect(() => {
userStore.getList(); getList();
}, []); }, []);
const onAdd = () => { const onAdd = () => {
@@ -209,8 +187,8 @@ export const List = () => {
<Tooltip title='编辑'> <Tooltip title='编辑'>
<Button <Button
onClick={(e) => { onClick={(e) => {
userStore.setFormData(item); setFormData(item);
userStore.setShowEdit(true); setShowEdit(true);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<EditOutlined /> <EditOutlined />
@@ -219,8 +197,8 @@ export const List = () => {
<Tooltip title='修改用户名'> <Tooltip title='修改用户名'>
<Button <Button
onClick={(e) => { onClick={(e) => {
userStore.setFormData(item); setFormData(item);
userStore.setShowNameEdit(true); setShowNameEdit(true);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<UserPen /> <UserPen />
@@ -249,7 +227,7 @@ export const List = () => {
content: 'Are you sure delete this data?', content: 'Are you sure delete this data?',
onOk: async () => { onOk: async () => {
await adminStore.deleteUser(item.id); await adminStore.deleteUser(item.id);
userStore.getList(); getList();
}, },
}); });
e.stopPropagation(); e.stopPropagation();
@@ -264,7 +242,7 @@ export const List = () => {
); );
})} })}
<CardBlank className='w-[400px]' /> <CardBlank className='w-[400px]' />
{userStore.list.length == 0 && ( {list.length == 0 && (
<div className='text-center' key={'no-data'}> <div className='text-center' key={'no-data'}>
No Data No Data
</div> </div>

View File

@@ -3,7 +3,6 @@ import { useForm, Controller } from 'react-hook-form';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import { useUserStore } from '../store'; import { useUserStore } from '../store';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useShallow } from 'zustand/react/shallow';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import { useLayoutStore } from '@/modules/layout/store'; import { useLayoutStore } from '@/modules/layout/store';
import UploadOutlined from '@ant-design/icons/UploadOutlined'; import UploadOutlined from '@ant-design/icons/UploadOutlined';
@@ -16,23 +15,12 @@ import { useAdminStore } from '../admin/store/admin-store';
import { IconButton } from '@kevisual/components/button/index.tsx'; import { IconButton } from '@kevisual/components/button/index.tsx';
export const CheckUserExistModal = () => { export const CheckUserExistModal = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const userStore = useUserStore( const userStore = useUserStore();
useShallow((state) => { const { showCheckUserExist, setShowCheckUserExist } = userStore;
return { const adminStore = useAdminStore();
showCheckUserExist: state.showCheckUserExist, const { checkUserExist } = adminStore;
setShowCheckUserExist: state.setShowCheckUserExist,
};
}),
);
const adminStore = useAdminStore(
useShallow((state) => {
return {
checkUserExist: state.checkUserExist,
};
}),
);
const onClose = () => { const onClose = () => {
userStore.setShowCheckUserExist(false); setShowCheckUserExist(false);
}; };
const [username, setUsername] = useState('@'); const [username, setUsername] = useState('@');
@@ -49,7 +37,7 @@ export const CheckUserExistModal = () => {
} }
}; };
return ( return (
<Dialog open={userStore.showCheckUserExist} onClose={onClose}> <Dialog open={showCheckUserExist} onClose={onClose}>
<DialogTitle>{t('Tips')}</DialogTitle> <DialogTitle>{t('Tips')}</DialogTitle>
<DialogContent> <DialogContent>
<div className='flex flex-col pt-4 gap-6 w-[400px]'> <div className='flex flex-col pt-4 gap-6 w-[400px]'>
@@ -65,15 +53,8 @@ export const CheckUserExistModal = () => {
}; };
export const ChangePasswordModal = () => { export const ChangePasswordModal = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const userStore = useUserStore( const userStore = useUserStore();
useShallow((state) => { const { showChangePassword, setShowChangePassword, updateSelf } = userStore;
return {
showChangePassword: state.showChangePassword,
setShowChangePassword: state.setShowChangePassword,
updateSelf: state.updateSelf,
};
}),
);
const [newPassword, setNewPassword] = useState(''); const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState('');
const onSubmit = async () => { const onSubmit = async () => {
@@ -81,7 +62,7 @@ export const ChangePasswordModal = () => {
toast.error('两次密码不一致'); toast.error('两次密码不一致');
return; return;
} }
const res = await userStore.updateSelf({ const res = await updateSelf({
password: newPassword, password: newPassword,
}); });
if (res.code === 200) { if (res.code === 200) {
@@ -91,10 +72,10 @@ export const ChangePasswordModal = () => {
const onClose = () => { const onClose = () => {
setNewPassword(''); setNewPassword('');
setConfirmPassword(''); setConfirmPassword('');
userStore.setShowChangePassword(false); setShowChangePassword(false);
}; };
return ( return (
<Dialog open={userStore.showChangePassword} onClose={onClose}> <Dialog open={showChangePassword} onClose={onClose}>
<DialogTitle>{t('Change Password')}</DialogTitle> <DialogTitle>{t('Change Password')}</DialogTitle>
<DialogContent> <DialogContent>
<div className='flex flex-col w-[400px] p-4 gap-4 pt-2'> <div className='flex flex-col w-[400px] p-4 gap-4 pt-2'>
@@ -124,29 +105,11 @@ export const Profile = () => {
}, },
}); });
const ref = useRef<any>(null); const ref = useRef<any>(null);
const userStore = useUserStore( const userStore = useUserStore();
useShallow((state) => { const { showEdit, setShowEdit, formData, updateData, setFormData, updateSelf, setShowCheckUserExist, setShowChangePassword } = userStore;
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
updateData: state.updateData,
setFormData: state.setFormData,
updateSelf: state.updateSelf,
setShowCheckUserExist: state.setShowCheckUserExist,
setShowChangePassword: state.setShowChangePassword,
};
}),
);
const [avatar, setAvatar] = useState<string>(''); const [avatar, setAvatar] = useState<string>('');
const layoutStore = useLayoutStore( const layoutStore = useLayoutStore();
useShallow((state) => { const { me, setMe } = layoutStore;
return {
me: state.me,
setMe: state.setMe,
};
}),
);
useEffect(() => { useEffect(() => {
const fromData = layoutStore.me; const fromData = layoutStore.me;
if (isObjectNull(fromData)) { if (isObjectNull(fromData)) {
@@ -207,7 +170,7 @@ export const Profile = () => {
className='w-4 h-4 cursor-pointer text-primary' className='w-4 h-4 cursor-pointer text-primary'
onClick={() => { onClick={() => {
console.log('onClick edit'); console.log('onClick edit');
userStore.setShowCheckUserExist(true); setShowCheckUserExist(true);
}} }}
/> />
</InputAdornment> </InputAdornment>
@@ -255,7 +218,7 @@ export const Profile = () => {
</div> </div>
<div className='mt-2'> <div className='mt-2'>
<Tooltip title={t('Change Password')}> <Tooltip title={t('Change Password')}>
<IconButton className='' onClick={() => userStore.setShowChangePassword(true)}> <IconButton className='' onClick={() => setShowChangePassword(true)}>
<UserCog size={16} /> <UserCog size={16} />
</IconButton> </IconButton>
</Tooltip> </Tooltip>

View File

@@ -1,22 +1,7 @@
import { Route, Routes } from 'react-router-dom';
import { List } from './edit/List';
import { Main } from './layouts'; import { Main } from './layouts';
import { Login } from './login/Login';
import { Login as WxLogin } from './wx/Login';
import { Profile } from './edit/Profile';
import { Redirect } from '@/modules/Redirect';
export const App = () => { export const App = () => {
return ( return <Main />;
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/user/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
<Route path='profile' element={<Profile />} />
</Route>
<Route path='login' element={<Login />} />
<Route path='wx/login' element={<WxLogin />} />
</Routes>
);
}; };
export default App; export default App;

View File

@@ -1,5 +1,4 @@
import { useLoginStore } from '../store/login'; import { useLoginStore } from '../store/login';
import { useShallow } from 'zustand/react/shallow';
import LockOutlined from '@ant-design/icons/LockOutlined'; import LockOutlined from '@ant-design/icons/LockOutlined';
import UserOutlined from '@ant-design/icons/UserOutlined'; import UserOutlined from '@ant-design/icons/UserOutlined';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
@@ -9,19 +8,12 @@ import { useForm, Controller } from 'react-hook-form';
export const Login = () => { export const Login = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { control, handleSubmit } = useForm(); const { control, handleSubmit } = useForm();
const loginStore = useLoginStore( const loginStore = useLoginStore();
useShallow((state) => { const { login, formData, setFormData } = loginStore;
return {
login: state.login,
formData: state.formData,
setFormData: state.setFormData,
};
}),
);
const onFinish = (values: any) => { const onFinish = (values: any) => {
loginStore.setFormData(values); setFormData(values);
loginStore.login(); login();
}; };
return ( return (

728
src/routeTree.gen.ts Normal file
View File

@@ -0,0 +1,728 @@
/* eslint-disable */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
import { Route as UserRouteImport } from './routes/user'
import { Route as OrgRouteImport } from './routes/org'
import { Route as MapRouteImport } from './routes/map'
import { Route as HomeRouteImport } from './routes/home'
import { Route as FileRouteImport } from './routes/file'
import { Route as DomainRouteImport } from './routes/domain'
import { Route as ContainerRouteImport } from './routes/container'
import { Route as ConfigRouteImport } from './routes/config'
import { Route as AppRouteImport } from './routes/app'
import { Route as IndexRouteImport } from './routes/index'
import { Route as UserLoginRouteImport } from './routes/user.login'
import { Route as UserIndexRouteImport } from './routes/user._index'
import { Route as OrgIndexRouteImport } from './routes/org._index'
import { Route as FileIndexRouteImport } from './routes/file._index'
import { Route as DomainIndexRouteImport } from './routes/domain._index'
import { Route as ContainerIndexRouteImport } from './routes/container._index'
import { Route as ConfigIndexRouteImport } from './routes/config._index'
import { Route as AppIndexRouteImport } from './routes/app._index'
import { Route as UserWxLoginRouteImport } from './routes/user.wx.login'
import { Route as UserEditProfileRouteImport } from './routes/user.edit.profile'
import { Route as UserEditListRouteImport } from './routes/user.edit.list'
import { Route as OrgEditListRouteImport } from './routes/org.edit.list'
import { Route as FileEditListRouteImport } from './routes/file.edit.list'
import { Route as DomainEditListRouteImport } from './routes/domain.edit.list'
import { Route as ContainerPreviewIdRouteImport } from './routes/container.preview.$id'
import { Route as ContainerEditListRouteImport } from './routes/container.edit.list'
import { Route as ConfigEditListRouteImport } from './routes/config.edit.list'
import { Route as AppEditListRouteImport } from './routes/app.edit.list'
import { Route as OrgEditUserIdRouteImport } from './routes/org.edit.user.$id'
import { Route as ContainerPreviewIdWrapperRouteImport } from './routes/container.preview.$id.wrapper'
import { Route as AppAppKeyVersionListRouteImport } from './routes/app.$appKey.version.list'
const UserRoute = UserRouteImport.update({
id: '/user',
path: '/user',
getParentRoute: () => rootRouteImport,
} as any)
const OrgRoute = OrgRouteImport.update({
id: '/org',
path: '/org',
getParentRoute: () => rootRouteImport,
} as any)
const MapRoute = MapRouteImport.update({
id: '/map',
path: '/map',
getParentRoute: () => rootRouteImport,
} as any)
const HomeRoute = HomeRouteImport.update({
id: '/home',
path: '/home',
getParentRoute: () => rootRouteImport,
} as any)
const FileRoute = FileRouteImport.update({
id: '/file',
path: '/file',
getParentRoute: () => rootRouteImport,
} as any)
const DomainRoute = DomainRouteImport.update({
id: '/domain',
path: '/domain',
getParentRoute: () => rootRouteImport,
} as any)
const ContainerRoute = ContainerRouteImport.update({
id: '/container',
path: '/container',
getParentRoute: () => rootRouteImport,
} as any)
const ConfigRoute = ConfigRouteImport.update({
id: '/config',
path: '/config',
getParentRoute: () => rootRouteImport,
} as any)
const AppRoute = AppRouteImport.update({
id: '/app',
path: '/app',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const UserLoginRoute = UserLoginRouteImport.update({
id: '/login',
path: '/login',
getParentRoute: () => UserRoute,
} as any)
const UserIndexRoute = UserIndexRouteImport.update({
id: '/_index',
getParentRoute: () => UserRoute,
} as any)
const OrgIndexRoute = OrgIndexRouteImport.update({
id: '/_index',
getParentRoute: () => OrgRoute,
} as any)
const FileIndexRoute = FileIndexRouteImport.update({
id: '/_index',
getParentRoute: () => FileRoute,
} as any)
const DomainIndexRoute = DomainIndexRouteImport.update({
id: '/_index',
getParentRoute: () => DomainRoute,
} as any)
const ContainerIndexRoute = ContainerIndexRouteImport.update({
id: '/_index',
getParentRoute: () => ContainerRoute,
} as any)
const ConfigIndexRoute = ConfigIndexRouteImport.update({
id: '/_index',
getParentRoute: () => ConfigRoute,
} as any)
const AppIndexRoute = AppIndexRouteImport.update({
id: '/_index',
getParentRoute: () => AppRoute,
} as any)
const UserWxLoginRoute = UserWxLoginRouteImport.update({
id: '/wx/login',
path: '/wx/login',
getParentRoute: () => UserRoute,
} as any)
const UserEditProfileRoute = UserEditProfileRouteImport.update({
id: '/edit/profile',
path: '/edit/profile',
getParentRoute: () => UserRoute,
} as any)
const UserEditListRoute = UserEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => UserRoute,
} as any)
const OrgEditListRoute = OrgEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => OrgRoute,
} as any)
const FileEditListRoute = FileEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => FileRoute,
} as any)
const DomainEditListRoute = DomainEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => DomainRoute,
} as any)
const ContainerPreviewIdRoute = ContainerPreviewIdRouteImport.update({
id: '/preview/$id',
path: '/preview/$id',
getParentRoute: () => ContainerRoute,
} as any)
const ContainerEditListRoute = ContainerEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => ContainerRoute,
} as any)
const ConfigEditListRoute = ConfigEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => ConfigRoute,
} as any)
const AppEditListRoute = AppEditListRouteImport.update({
id: '/edit/list',
path: '/edit/list',
getParentRoute: () => AppRoute,
} as any)
const OrgEditUserIdRoute = OrgEditUserIdRouteImport.update({
id: '/edit/user/$id',
path: '/edit/user/$id',
getParentRoute: () => OrgRoute,
} as any)
const ContainerPreviewIdWrapperRoute =
ContainerPreviewIdWrapperRouteImport.update({
id: '/wrapper',
path: '/wrapper',
getParentRoute: () => ContainerPreviewIdRoute,
} as any)
const AppAppKeyVersionListRoute = AppAppKeyVersionListRouteImport.update({
id: '/$appKey/version/list',
path: '/$appKey/version/list',
getParentRoute: () => AppRoute,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/app': typeof AppIndexRoute
'/config': typeof ConfigIndexRoute
'/container': typeof ContainerIndexRoute
'/domain': typeof DomainIndexRoute
'/file': typeof FileIndexRoute
'/home': typeof HomeRoute
'/map': typeof MapRoute
'/org': typeof OrgIndexRoute
'/user': typeof UserIndexRoute
'/user/login': typeof UserLoginRoute
'/app/edit/list': typeof AppEditListRoute
'/config/edit/list': typeof ConfigEditListRoute
'/container/edit/list': typeof ContainerEditListRoute
'/container/preview/$id': typeof ContainerPreviewIdRouteWithChildren
'/domain/edit/list': typeof DomainEditListRoute
'/file/edit/list': typeof FileEditListRoute
'/org/edit/list': typeof OrgEditListRoute
'/user/edit/list': typeof UserEditListRoute
'/user/edit/profile': typeof UserEditProfileRoute
'/user/wx/login': typeof UserWxLoginRoute
'/app/$appKey/version/list': typeof AppAppKeyVersionListRoute
'/container/preview/$id/wrapper': typeof ContainerPreviewIdWrapperRoute
'/org/edit/user/$id': typeof OrgEditUserIdRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/app': typeof AppIndexRoute
'/config': typeof ConfigIndexRoute
'/container': typeof ContainerIndexRoute
'/domain': typeof DomainIndexRoute
'/file': typeof FileIndexRoute
'/home': typeof HomeRoute
'/map': typeof MapRoute
'/org': typeof OrgIndexRoute
'/user': typeof UserIndexRoute
'/user/login': typeof UserLoginRoute
'/app/edit/list': typeof AppEditListRoute
'/config/edit/list': typeof ConfigEditListRoute
'/container/edit/list': typeof ContainerEditListRoute
'/container/preview/$id': typeof ContainerPreviewIdRouteWithChildren
'/domain/edit/list': typeof DomainEditListRoute
'/file/edit/list': typeof FileEditListRoute
'/org/edit/list': typeof OrgEditListRoute
'/user/edit/list': typeof UserEditListRoute
'/user/edit/profile': typeof UserEditProfileRoute
'/user/wx/login': typeof UserWxLoginRoute
'/app/$appKey/version/list': typeof AppAppKeyVersionListRoute
'/container/preview/$id/wrapper': typeof ContainerPreviewIdWrapperRoute
'/org/edit/user/$id': typeof OrgEditUserIdRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/app': typeof AppRouteWithChildren
'/config': typeof ConfigRouteWithChildren
'/container': typeof ContainerRouteWithChildren
'/domain': typeof DomainRouteWithChildren
'/file': typeof FileRouteWithChildren
'/home': typeof HomeRoute
'/map': typeof MapRoute
'/org': typeof OrgRouteWithChildren
'/user': typeof UserRouteWithChildren
'/app/_index': typeof AppIndexRoute
'/config/_index': typeof ConfigIndexRoute
'/container/_index': typeof ContainerIndexRoute
'/domain/_index': typeof DomainIndexRoute
'/file/_index': typeof FileIndexRoute
'/org/_index': typeof OrgIndexRoute
'/user/_index': typeof UserIndexRoute
'/user/login': typeof UserLoginRoute
'/app/edit/list': typeof AppEditListRoute
'/config/edit/list': typeof ConfigEditListRoute
'/container/edit/list': typeof ContainerEditListRoute
'/container/preview/$id': typeof ContainerPreviewIdRouteWithChildren
'/domain/edit/list': typeof DomainEditListRoute
'/file/edit/list': typeof FileEditListRoute
'/org/edit/list': typeof OrgEditListRoute
'/user/edit/list': typeof UserEditListRoute
'/user/edit/profile': typeof UserEditProfileRoute
'/user/wx/login': typeof UserWxLoginRoute
'/app/$appKey/version/list': typeof AppAppKeyVersionListRoute
'/container/preview/$id/wrapper': typeof ContainerPreviewIdWrapperRoute
'/org/edit/user/$id': typeof OrgEditUserIdRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
| '/'
| '/app'
| '/config'
| '/container'
| '/domain'
| '/file'
| '/home'
| '/map'
| '/org'
| '/user'
| '/user/login'
| '/app/edit/list'
| '/config/edit/list'
| '/container/edit/list'
| '/container/preview/$id'
| '/domain/edit/list'
| '/file/edit/list'
| '/org/edit/list'
| '/user/edit/list'
| '/user/edit/profile'
| '/user/wx/login'
| '/app/$appKey/version/list'
| '/container/preview/$id/wrapper'
| '/org/edit/user/$id'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
| '/app'
| '/config'
| '/container'
| '/domain'
| '/file'
| '/home'
| '/map'
| '/org'
| '/user'
| '/user/login'
| '/app/edit/list'
| '/config/edit/list'
| '/container/edit/list'
| '/container/preview/$id'
| '/domain/edit/list'
| '/file/edit/list'
| '/org/edit/list'
| '/user/edit/list'
| '/user/edit/profile'
| '/user/wx/login'
| '/app/$appKey/version/list'
| '/container/preview/$id/wrapper'
| '/org/edit/user/$id'
id:
| '__root__'
| '/'
| '/app'
| '/config'
| '/container'
| '/domain'
| '/file'
| '/home'
| '/map'
| '/org'
| '/user'
| '/app/_index'
| '/config/_index'
| '/container/_index'
| '/domain/_index'
| '/file/_index'
| '/org/_index'
| '/user/_index'
| '/user/login'
| '/app/edit/list'
| '/config/edit/list'
| '/container/edit/list'
| '/container/preview/$id'
| '/domain/edit/list'
| '/file/edit/list'
| '/org/edit/list'
| '/user/edit/list'
| '/user/edit/profile'
| '/user/wx/login'
| '/app/$appKey/version/list'
| '/container/preview/$id/wrapper'
| '/org/edit/user/$id'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
AppRoute: typeof AppRouteWithChildren
ConfigRoute: typeof ConfigRouteWithChildren
ContainerRoute: typeof ContainerRouteWithChildren
DomainRoute: typeof DomainRouteWithChildren
FileRoute: typeof FileRouteWithChildren
HomeRoute: typeof HomeRoute
MapRoute: typeof MapRoute
OrgRoute: typeof OrgRouteWithChildren
UserRoute: typeof UserRouteWithChildren
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/user': {
id: '/user'
path: '/user'
fullPath: '/user'
preLoaderRoute: typeof UserRouteImport
parentRoute: typeof rootRouteImport
}
'/org': {
id: '/org'
path: '/org'
fullPath: '/org'
preLoaderRoute: typeof OrgRouteImport
parentRoute: typeof rootRouteImport
}
'/map': {
id: '/map'
path: '/map'
fullPath: '/map'
preLoaderRoute: typeof MapRouteImport
parentRoute: typeof rootRouteImport
}
'/home': {
id: '/home'
path: '/home'
fullPath: '/home'
preLoaderRoute: typeof HomeRouteImport
parentRoute: typeof rootRouteImport
}
'/file': {
id: '/file'
path: '/file'
fullPath: '/file'
preLoaderRoute: typeof FileRouteImport
parentRoute: typeof rootRouteImport
}
'/domain': {
id: '/domain'
path: '/domain'
fullPath: '/domain'
preLoaderRoute: typeof DomainRouteImport
parentRoute: typeof rootRouteImport
}
'/container': {
id: '/container'
path: '/container'
fullPath: '/container'
preLoaderRoute: typeof ContainerRouteImport
parentRoute: typeof rootRouteImport
}
'/config': {
id: '/config'
path: '/config'
fullPath: '/config'
preLoaderRoute: typeof ConfigRouteImport
parentRoute: typeof rootRouteImport
}
'/app': {
id: '/app'
path: '/app'
fullPath: '/app'
preLoaderRoute: typeof AppRouteImport
parentRoute: typeof rootRouteImport
}
'/': {
id: '/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/user/login': {
id: '/user/login'
path: '/login'
fullPath: '/user/login'
preLoaderRoute: typeof UserLoginRouteImport
parentRoute: typeof UserRoute
}
'/user/_index': {
id: '/user/_index'
path: ''
fullPath: '/user'
preLoaderRoute: typeof UserIndexRouteImport
parentRoute: typeof UserRoute
}
'/org/_index': {
id: '/org/_index'
path: ''
fullPath: '/org'
preLoaderRoute: typeof OrgIndexRouteImport
parentRoute: typeof OrgRoute
}
'/file/_index': {
id: '/file/_index'
path: ''
fullPath: '/file'
preLoaderRoute: typeof FileIndexRouteImport
parentRoute: typeof FileRoute
}
'/domain/_index': {
id: '/domain/_index'
path: ''
fullPath: '/domain'
preLoaderRoute: typeof DomainIndexRouteImport
parentRoute: typeof DomainRoute
}
'/container/_index': {
id: '/container/_index'
path: ''
fullPath: '/container'
preLoaderRoute: typeof ContainerIndexRouteImport
parentRoute: typeof ContainerRoute
}
'/config/_index': {
id: '/config/_index'
path: ''
fullPath: '/config'
preLoaderRoute: typeof ConfigIndexRouteImport
parentRoute: typeof ConfigRoute
}
'/app/_index': {
id: '/app/_index'
path: ''
fullPath: '/app'
preLoaderRoute: typeof AppIndexRouteImport
parentRoute: typeof AppRoute
}
'/user/wx/login': {
id: '/user/wx/login'
path: '/wx/login'
fullPath: '/user/wx/login'
preLoaderRoute: typeof UserWxLoginRouteImport
parentRoute: typeof UserRoute
}
'/user/edit/profile': {
id: '/user/edit/profile'
path: '/edit/profile'
fullPath: '/user/edit/profile'
preLoaderRoute: typeof UserEditProfileRouteImport
parentRoute: typeof UserRoute
}
'/user/edit/list': {
id: '/user/edit/list'
path: '/edit/list'
fullPath: '/user/edit/list'
preLoaderRoute: typeof UserEditListRouteImport
parentRoute: typeof UserRoute
}
'/org/edit/list': {
id: '/org/edit/list'
path: '/edit/list'
fullPath: '/org/edit/list'
preLoaderRoute: typeof OrgEditListRouteImport
parentRoute: typeof OrgRoute
}
'/file/edit/list': {
id: '/file/edit/list'
path: '/edit/list'
fullPath: '/file/edit/list'
preLoaderRoute: typeof FileEditListRouteImport
parentRoute: typeof FileRoute
}
'/domain/edit/list': {
id: '/domain/edit/list'
path: '/edit/list'
fullPath: '/domain/edit/list'
preLoaderRoute: typeof DomainEditListRouteImport
parentRoute: typeof DomainRoute
}
'/container/preview/$id': {
id: '/container/preview/$id'
path: '/preview/$id'
fullPath: '/container/preview/$id'
preLoaderRoute: typeof ContainerPreviewIdRouteImport
parentRoute: typeof ContainerRoute
}
'/container/edit/list': {
id: '/container/edit/list'
path: '/edit/list'
fullPath: '/container/edit/list'
preLoaderRoute: typeof ContainerEditListRouteImport
parentRoute: typeof ContainerRoute
}
'/config/edit/list': {
id: '/config/edit/list'
path: '/edit/list'
fullPath: '/config/edit/list'
preLoaderRoute: typeof ConfigEditListRouteImport
parentRoute: typeof ConfigRoute
}
'/app/edit/list': {
id: '/app/edit/list'
path: '/edit/list'
fullPath: '/app/edit/list'
preLoaderRoute: typeof AppEditListRouteImport
parentRoute: typeof AppRoute
}
'/org/edit/user/$id': {
id: '/org/edit/user/$id'
path: '/edit/user/$id'
fullPath: '/org/edit/user/$id'
preLoaderRoute: typeof OrgEditUserIdRouteImport
parentRoute: typeof OrgRoute
}
'/container/preview/$id/wrapper': {
id: '/container/preview/$id/wrapper'
path: '/wrapper'
fullPath: '/container/preview/$id/wrapper'
preLoaderRoute: typeof ContainerPreviewIdWrapperRouteImport
parentRoute: typeof ContainerPreviewIdRoute
}
'/app/$appKey/version/list': {
id: '/app/$appKey/version/list'
path: '/$appKey/version/list'
fullPath: '/app/$appKey/version/list'
preLoaderRoute: typeof AppAppKeyVersionListRouteImport
parentRoute: typeof AppRoute
}
}
}
interface AppRouteChildren {
AppIndexRoute: typeof AppIndexRoute
AppEditListRoute: typeof AppEditListRoute
AppAppKeyVersionListRoute: typeof AppAppKeyVersionListRoute
}
const AppRouteChildren: AppRouteChildren = {
AppIndexRoute: AppIndexRoute,
AppEditListRoute: AppEditListRoute,
AppAppKeyVersionListRoute: AppAppKeyVersionListRoute,
}
const AppRouteWithChildren = AppRoute._addFileChildren(AppRouteChildren)
interface ConfigRouteChildren {
ConfigIndexRoute: typeof ConfigIndexRoute
ConfigEditListRoute: typeof ConfigEditListRoute
}
const ConfigRouteChildren: ConfigRouteChildren = {
ConfigIndexRoute: ConfigIndexRoute,
ConfigEditListRoute: ConfigEditListRoute,
}
const ConfigRouteWithChildren =
ConfigRoute._addFileChildren(ConfigRouteChildren)
interface ContainerPreviewIdRouteChildren {
ContainerPreviewIdWrapperRoute: typeof ContainerPreviewIdWrapperRoute
}
const ContainerPreviewIdRouteChildren: ContainerPreviewIdRouteChildren = {
ContainerPreviewIdWrapperRoute: ContainerPreviewIdWrapperRoute,
}
const ContainerPreviewIdRouteWithChildren =
ContainerPreviewIdRoute._addFileChildren(ContainerPreviewIdRouteChildren)
interface ContainerRouteChildren {
ContainerIndexRoute: typeof ContainerIndexRoute
ContainerEditListRoute: typeof ContainerEditListRoute
ContainerPreviewIdRoute: typeof ContainerPreviewIdRouteWithChildren
}
const ContainerRouteChildren: ContainerRouteChildren = {
ContainerIndexRoute: ContainerIndexRoute,
ContainerEditListRoute: ContainerEditListRoute,
ContainerPreviewIdRoute: ContainerPreviewIdRouteWithChildren,
}
const ContainerRouteWithChildren = ContainerRoute._addFileChildren(
ContainerRouteChildren,
)
interface DomainRouteChildren {
DomainIndexRoute: typeof DomainIndexRoute
DomainEditListRoute: typeof DomainEditListRoute
}
const DomainRouteChildren: DomainRouteChildren = {
DomainIndexRoute: DomainIndexRoute,
DomainEditListRoute: DomainEditListRoute,
}
const DomainRouteWithChildren =
DomainRoute._addFileChildren(DomainRouteChildren)
interface FileRouteChildren {
FileIndexRoute: typeof FileIndexRoute
FileEditListRoute: typeof FileEditListRoute
}
const FileRouteChildren: FileRouteChildren = {
FileIndexRoute: FileIndexRoute,
FileEditListRoute: FileEditListRoute,
}
const FileRouteWithChildren = FileRoute._addFileChildren(FileRouteChildren)
interface OrgRouteChildren {
OrgIndexRoute: typeof OrgIndexRoute
OrgEditListRoute: typeof OrgEditListRoute
OrgEditUserIdRoute: typeof OrgEditUserIdRoute
}
const OrgRouteChildren: OrgRouteChildren = {
OrgIndexRoute: OrgIndexRoute,
OrgEditListRoute: OrgEditListRoute,
OrgEditUserIdRoute: OrgEditUserIdRoute,
}
const OrgRouteWithChildren = OrgRoute._addFileChildren(OrgRouteChildren)
interface UserRouteChildren {
UserIndexRoute: typeof UserIndexRoute
UserLoginRoute: typeof UserLoginRoute
UserEditListRoute: typeof UserEditListRoute
UserEditProfileRoute: typeof UserEditProfileRoute
UserWxLoginRoute: typeof UserWxLoginRoute
}
const UserRouteChildren: UserRouteChildren = {
UserIndexRoute: UserIndexRoute,
UserLoginRoute: UserLoginRoute,
UserEditListRoute: UserEditListRoute,
UserEditProfileRoute: UserEditProfileRoute,
UserWxLoginRoute: UserWxLoginRoute,
}
const UserRouteWithChildren = UserRoute._addFileChildren(UserRouteChildren)
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
AppRoute: AppRouteWithChildren,
ConfigRoute: ConfigRouteWithChildren,
ContainerRoute: ContainerRouteWithChildren,
DomainRoute: DomainRouteWithChildren,
FileRoute: FileRouteWithChildren,
HomeRoute: HomeRoute,
MapRoute: MapRoute,
OrgRoute: OrgRouteWithChildren,
UserRoute: UserRouteWithChildren,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()

16
src/routes/__root.tsx Normal file
View File

@@ -0,0 +1,16 @@
import { Link, Outlet, createRootRoute } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
export const Route = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<>
<hr />
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
</>
)
}

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { AppVersionList } from '../pages/app/edit/AppVersionList'
export const Route = createFileRoute('/app/$appKey/version/list')({
component: () => <AppVersionList />,
})

11
src/routes/app._index.tsx Normal file
View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/app/_index')({
beforeLoad: () => {
throw redirect({
to: '/app/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { List } from '../pages/app/edit/List'
export const Route = createFileRoute('/app/edit/list')({
component: () => <List />,
})

6
src/routes/app.tsx Normal file
View File

@@ -0,0 +1,6 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { Main } from '../pages/app/layouts'
export const Route = createFileRoute('/app')({
component: () => <Main><Outlet /></Main>,
})

View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/config/_index')({
beforeLoad: () => {
throw redirect({
to: '/config/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { List } from '../pages/config/edit/List'
export const Route = createFileRoute('/config/edit/list')({
component: () => <List />,
})

10
src/routes/config.tsx Normal file
View File

@@ -0,0 +1,10 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { LayoutMain } from '@/modules/layout'
export const Route = createFileRoute('/config')({
component: () => (
<LayoutMain title='Config'>
<Outlet />
</LayoutMain>
),
})

View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/container/_index')({
beforeLoad: () => {
throw redirect({
to: '/container/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { ContainerList } from '../pages/container/edit/List'
export const Route = createFileRoute('/container/edit/list')({
component: () => <ContainerList />,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { Preview } from '../pages/container/preview'
export const Route = createFileRoute('/container/preview/$id')({
component: () => <Preview />,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { PreviewWrapper } from '../pages/container/preview'
export const Route = createFileRoute('/container/preview/$id/wrapper')({
component: () => <PreviewWrapper />,
})

10
src/routes/container.tsx Normal file
View File

@@ -0,0 +1,10 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { LayoutMain } from '@/modules/layout'
export const Route = createFileRoute('/container')({
component: () => (
<LayoutMain title='Container'>
<Outlet />
</LayoutMain>
),
})

View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/domain/_index')({
beforeLoad: () => {
throw redirect({
to: '/domain/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { List } from '../pages/domain/edit/List'
export const Route = createFileRoute('/domain/edit/list')({
component: () => <List />,
})

6
src/routes/domain.tsx Normal file
View File

@@ -0,0 +1,6 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { Main } from '../pages/domain/layouts'
export const Route = createFileRoute('/domain')({
component: () => <Main><Outlet /></Main>,
})

View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/file/_index')({
beforeLoad: () => {
throw redirect({
to: '/file/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { List } from '../pages/file/edit/List'
export const Route = createFileRoute('/file/edit/list')({
component: () => <List />,
})

6
src/routes/file.tsx Normal file
View File

@@ -0,0 +1,6 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { Main } from '../pages/file/layouts'
export const Route = createFileRoute('/file')({
component: () => <Main><Outlet /></Main>,
})

6
src/routes/home.tsx Normal file
View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { App as HomeApp } from '../pages/home'
export const Route = createFileRoute('/home')({
component: () => <HomeApp />,
})

11
src/routes/index.tsx Normal file
View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
beforeLoad: () => {
throw redirect({
to: '/app',
throw: true,
})
},
component: () => null,
})

6
src/routes/map.tsx Normal file
View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { App as MapApp } from '../pages/map'
export const Route = createFileRoute('/map')({
component: () => <MapApp />,
})

11
src/routes/org._index.tsx Normal file
View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/org/_index')({
beforeLoad: () => {
throw redirect({
to: '/org/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { List } from '../pages/org/edit/List'
export const Route = createFileRoute('/org/edit/list')({
component: () => <List />,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { UserList } from '../pages/org/edit/UserList'
export const Route = createFileRoute('/org/edit/user/$id')({
component: () => <UserList />,
})

6
src/routes/org.tsx Normal file
View File

@@ -0,0 +1,6 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { Main } from '../pages/org/layouts'
export const Route = createFileRoute('/org')({
component: () => <Main><Outlet /></Main>,
})

View File

@@ -0,0 +1,11 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/user/_index')({
beforeLoad: () => {
throw redirect({
to: '/user/edit/list',
throw: true,
})
},
component: () => null,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { List } from '../pages/user/edit/List'
export const Route = createFileRoute('/user/edit/list')({
component: () => <List />,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { Profile } from '../pages/user/edit/Profile'
export const Route = createFileRoute('/user/edit/profile')({
component: () => <Profile />,
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { Login as UserLogin } from '../pages/user/login/Login'
export const Route = createFileRoute('/user/login')({
component: () => <UserLogin />,
})

10
src/routes/user.tsx Normal file
View File

@@ -0,0 +1,10 @@
import { Outlet, createFileRoute } from '@tanstack/react-router'
import { LayoutMain } from '@/modules/layout'
export const Route = createFileRoute('/user')({
component: () => (
<LayoutMain title='User'>
<Outlet />
</LayoutMain>
),
})

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { Login as WxLogin } from '../pages/user/wx/Login'
export const Route = createFileRoute('/user/wx/login')({
component: () => <WxLogin />,
})

View File

@@ -2,6 +2,8 @@ import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
import path from 'path'; import path from 'path';
import tailwindcss from '@tailwindcss/vite'; import tailwindcss from '@tailwindcss/vite';
import { tanstackRouter } from '@tanstack/router-plugin/vite'
const isDev = process.env.NODE_ENV === 'development'; const isDev = process.env.NODE_ENV === 'development';
const centerEnv = process.env.CENTER_ENV; const centerEnv = process.env.CENTER_ENV;
const plugins: any[] = []; const plugins: any[] = [];
@@ -17,7 +19,13 @@ let proxy = {
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react(), ...plugins], plugins: [
// Please make sure that '@tanstack/router-plugin' is passed before '@vitejs/plugin-react'
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
}),
react(), ...plugins],
css: { css: {
postcss: {}, postcss: {},
@@ -34,38 +42,6 @@ export default defineConfig({
base: isDev ? '/' : '/root/center-v1/', base: isDev ? '/' : '/root/center-v1/',
build: { build: {
sourcemap: false, sourcemap: false,
rollupOptions: {
output: {
// 控制输出
// 在rollup里面, hash代表将你的文件名和文件内容进行组合计算得来的结果
assetFileNames: (chunkInfo) => {
console.log(chunkInfo.names);
if (chunkInfo.names?.includes('panda.jpg')) {
return '[name].[ext]';
}
const qrcode = ['qrcode-8x8.jpg'];
const names = chunkInfo.names || [];
if (qrcode.some((name) => names.includes(name))) {
return '[name].[ext]';
}
return '[name].[hash].[ext]';
},
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react')) {
return 'vendor-react';
}
// prettier
if (id.includes('prettier')) {
return 'vendor-prettier';
}
// codemirror
// console.log(id);
return 'vendor';
}
},
},
},
}, },
server: { server: {
port: 6020, port: 6020,