add wx mp

This commit is contained in:
xion 2025-04-01 23:50:16 +08:00
parent 122fbec7da
commit 151f74441f
15 changed files with 36 additions and 19 deletions

@ -1 +1 @@
Subproject commit 0a8d7abf9a78bce528e31741d4643e017812616d Subproject commit a857afbb2c8f5b5f98771824e875dfffd23b6ad2

View File

@ -12,7 +12,6 @@ import 'dayjs/locale/zh-cn';
import zhCN from 'antd/locale/zh_CN'; import zhCN from 'antd/locale/zh_CN';
import ConfigProvider from 'antd/es/config-provider'; import ConfigProvider from 'antd/es/config-provider';
dayjs.locale('zh-cn');
export const AntdConfigProvider = ({ children }: { children: React.ReactNode }) => { export const AntdConfigProvider = ({ children }: { children: React.ReactNode }) => {
const theme = useTheme(); const theme = useTheme();
const primaryColor = theme.palette.primary.main; const primaryColor = theme.palette.primary.main;
@ -49,6 +48,7 @@ export const InitProvider = ({ children }: { children: React.ReactNode }) => {
const { setPrefix, init: initResource } = useResourceStore(); const { setPrefix, init: initResource } = useResourceStore();
useEffect(() => { useEffect(() => {
init(); init();
dayjs.locale('zh-cn');
initResource(); initResource();
}, []); }, []);
useEffect(() => { useEffect(() => {

View File

@ -7,6 +7,7 @@ import { filterFiles } from './utils/filter-files';
import { IconButton } from '@kevisual/components/button/index.tsx'; import { IconButton } from '@kevisual/components/button/index.tsx';
import { uploadChunkV2 } from './v2/upload-chunk'; import { uploadChunkV2 } from './v2/upload-chunk';
import { uploadFilesV2 } from './v2/upload'; import { uploadFilesV2 } from './v2/upload';
import dayjs from 'dayjs';
type UploadButtonProps = { type UploadButtonProps = {
/** /**
@ -83,10 +84,11 @@ export const UploadButton = (props: UploadButtonProps) => {
export const Upload = ({ uploadDirectory = false }: { uploadDirectory?: boolean }) => { export const Upload = ({ uploadDirectory = false }: { uploadDirectory?: boolean }) => {
const onDrop = async (acceptedFiles) => { const onDrop = async (acceptedFiles) => {
acceptedFiles = filterFiles(acceptedFiles); acceptedFiles = filterFiles(acceptedFiles);
const directory = dayjs().format('YYYY-MM-DD');
if (acceptedFiles.length > 1) { if (acceptedFiles.length > 1) {
const res = await uploadFilesV2(acceptedFiles, {}); const res = await uploadFilesV2(acceptedFiles, { directory });
} else if (acceptedFiles.length === 1) { } else if (acceptedFiles.length === 1) {
const res = await uploadChunkV2(acceptedFiles[0], {}); const res = await uploadChunkV2(acceptedFiles[0], { directory });
} }
}; };

View File

@ -71,10 +71,9 @@ export const App = () => {
<div className='w-full h-full'> <div className='w-full h-full'>
<Router basename={basename}> <Router basename={basename}>
<Routes> <Routes>
<Route path='/' element={<Redirect to='/container/' />} /> <Route path='/' element={<Redirect to='/app/' />} />
<Route path='/container/*' element={<ContainerApp />} /> <Route path='/container/*' element={<ContainerApp />} />
<Route path='/map/*' element={<MapApp />} /> <Route path='/map/*' element={<MapApp />} />
<Route path='/user/*' element={<UserApp />} />
<Route path='/user-center/*' element={<UserApp />} /> <Route path='/user-center/*' element={<UserApp />} />
<Route path='/org/*' element={<OrgApp />} /> <Route path='/org/*' element={<OrgApp />} />
<Route path='/config/*' element={<ConfigApp />} /> <Route path='/config/*' element={<ConfigApp />} />

BIN
src/assets/qrcode-8x8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -95,7 +95,7 @@ export const LayoutUser = () => {
onClick={() => { onClick={() => {
setOpen(false); setOpen(false);
}}></div> }}></div>
<div className='w-[400px] bg-amber-900 text-primary 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'>{store.me?.username}</span>

View File

@ -45,13 +45,13 @@ export const LayoutMenu = () => {
const { open, setOpen } = useLayoutStore(useShallow((state) => ({ open: state.open, setOpen: state.setOpen }))); const { open, setOpen } = useLayoutStore(useShallow((state) => ({ open: state.open, setOpen: state.setOpen })));
const navigate = useNewNavigate(); const navigate = useNewNavigate();
return ( return (
<div className={clsx('w-full h-full 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
className='bg-white w-full absolute h-full opacity-60 z-0' className='bg-white w-full absolute h-full opacity-60 z-0'
onClick={() => { onClick={() => {
setOpen(false); setOpen(false);
}}></div> }}></div>
<div className='w-[300px] h-full absolute top-0 left-0 bg-amber-900 text-primary'> <div className='w-[300px] h-full absolute top-0 left-0 bg-amber-900 '>
<div className='flex justify-between p-6 mt-4 font-bold items-center'> <div className='flex justify-between p-6 mt-4 font-bold items-center'>
Envision Center Envision Center
<div> <div>

View File

@ -7,13 +7,14 @@ 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/panda.png'; import PandaPNG from '@/assets/panda.png';
import QRCodePNG from '@/assets/qrcode-8x8.jpg';
import { Panel, PanelGroup } from 'react-resizable-panels'; import { Panel, PanelGroup } from 'react-resizable-panels';
import clsx from 'clsx'; import clsx from 'clsx';
import { Button, Menu, MenuItem } from '@mui/material'; import { Button, Menu, MenuItem } from '@mui/material';
import i18n from 'i18next'; import i18n from 'i18next';
import { IconButton } from '@kevisual/components/button/index.tsx'; import { IconButton } from '@kevisual/components/button/index.tsx';
import { Languages } from 'lucide-react'; import { Languages, QrCode } from 'lucide-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
@ -89,6 +90,15 @@ export const LayoutMain = (props: LayoutMainProps) => {
<div className='flex grow justify-between pl-4 items-center'> <div className='flex grow justify-between pl-4 items-center'>
{props.title} {props.title}
<div className='mr-4 flex gap-4 items-center no-drag'> <div className='mr-4 flex gap-4 items-center no-drag'>
<div className='group relative'>
<IconButton>
<QrCode size={16} />
</IconButton>
<div className='absolute hidden group-hover:flex bg-white p-2 border shadow-md top-10 -left-15 w-40 z-[9999] flex-col items-center justify-center rounded-md'>
<img src={QRCodePNG} alt='QR Code' />
<div className='text-sm text-black'></div>
</div>
</div>
<div> <div>
<Tooltip title={currentLanguage === 'en' ? 'English' : 'Chinese'}> <Tooltip title={currentLanguage === 'en' ? 'English' : 'Chinese'}>
<IconButton onClick={handleClick} variant='contained'> <IconButton onClick={handleClick} variant='contained'>
@ -154,7 +164,7 @@ export const LayoutMain = (props: LayoutMainProps) => {
<PanelGroup className='w-full h-full panel-layout' autoSaveId='editor-layout-main' direction='horizontal'> <PanelGroup className='w-full h-full panel-layout' autoSaveId='editor-layout-main' direction='horizontal'>
<Panel style={{ height: '100%' }}> <Panel style={{ height: '100%' }}>
<div className='h-full overflow-hidden'> <div className='h-full overflow-hidden'>
<div className='w-full h-full rounded-lg text-primary'> <div className='w-full h-full rounded-lg text-text-primary'>
<Outlet /> <Outlet />
</div> </div>
</div> </div>

View File

@ -252,7 +252,7 @@ export const List = () => {
userAppStore.getList(); userAppStore.getList();
}, []); }, []);
return ( return (
<div className='w-full h-full flex bg-slate-100 text-primary'> <div className='w-full h-full flex bg-slate-100'>
<div className='p-2 h-full bg-white flex flex-col gap-2'> <div className='p-2 h-full bg-white flex flex-col gap-2'>
<Tooltip title='添加一个应用'> <Tooltip title='添加一个应用'>
<IconButton <IconButton
@ -298,7 +298,7 @@ export const List = () => {
const hasDescription = !!item.description; const hasDescription = !!item.description;
const content = marked.parse(item.description); const content = marked.parse(item.description);
return ( return (
<div className='card w-[300px] ' key={item.id}> <div className='card w-[300px] relative pb-10 ' key={item.id}>
<div className='card-title flex font-bold justify-between' onClick={() => {}}> <div className='card-title flex font-bold justify-between' onClick={() => {}}>
{item.title} {item.title}
<div> <div>
@ -330,7 +330,8 @@ export const List = () => {
<div dangerouslySetInnerHTML={{ __html: content }}></div> <div dangerouslySetInnerHTML={{ __html: content }}></div>
</div> </div>
</div> </div>
<div className='mt-2'> <div className='py-4'></div>
<div className='absolute bottom-0 left-4 py-4'>
<ButtonGroup <ButtonGroup
variant='contained' variant='contained'
color='primary' color='primary'

View File

@ -358,7 +358,7 @@ export const ContainerList = () => {
</div> </div>
</div> </div>
</div> </div>
<Suspense fallback={<div>Loading...</div>}> <Suspense fallback={<div></div>}>
<DrawEdit /> <DrawEdit />
</Suspense> </Suspense>
<PublishFormModal /> <PublishFormModal />

View File

@ -28,7 +28,7 @@ const ServerPath = () => {
}, },
]; ];
return ( return (
<div className='p-2 w-full h-full bg-gray-200 text-primary'> <div className='p-2 w-full h-full bg-gray-200'>
<h1 className='p-4 w-1/2 m-auto h1'>{t('Site Map')}</h1> <h1 className='p-4 w-1/2 m-auto h1'>{t('Site Map')}</h1>
<div className='w-1/2 m-auto bg-white p-4 border rounded-md shadow-md min-w-[700px] max-h-[80vh] overflow-auto scrollbar'> <div className='w-1/2 m-auto bg-white p-4 border rounded-md shadow-md min-w-[700px] max-h-[80vh] overflow-auto scrollbar'>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>

View File

@ -136,7 +136,7 @@ export const UserList = () => {
}; };
}, []); }, []);
return ( return (
<div className='w-full h-full bg-gray-100 flex text-primary'> <div className='w-full h-full bg-gray-100 flex'>
<div className='p-2 bg-white mr-2'> <div className='p-2 bg-white mr-2'>
<IconButton <IconButton
onClick={() => { onClick={() => {

View File

@ -73,7 +73,7 @@ export const Profile = () => {
} }
}; };
return ( return (
<div className='w-full h-full bg-amber-50 p-4 text-primary'> <div className='w-full h-full bg-amber-50 p-4 '>
<div className=' shadow-lg p-4 bg-white rounded-lg'> <div className=' shadow-lg p-4 bg-white rounded-lg'>
<div className='text-2xl'>{t('Profile')}</div> <div className='text-2xl'>{t('Profile')}</div>
<div className='text-sm text-secondary'>{t('Edit your profile')}</div> <div className='text-sm text-secondary'>{t('Edit your profile')}</div>

View File

@ -25,7 +25,7 @@ export const Login = () => {
}; };
return ( return (
<div className='bg-gray-100 text-primary w-full h-full overflow-hidden'> <div className='bg-gray-100 w-full h-full overflow-hidden'>
<div className='w-full h-full absolute top-[10%] xl:top-[15%] 2xl:top-[18%] 3xl:top-[20%] '> <div className='w-full h-full absolute top-[10%] xl:top-[15%] 2xl:top-[18%] 3xl:top-[20%] '>
<div className='w-[400px] mx-auto'> <div className='w-[400px] mx-auto'>
<h1 className='mb-4 tracking-widest text-center'>{t('Login')}</h1> <h1 className='mb-4 tracking-widest text-center'>{t('Login')}</h1>

View File

@ -60,6 +60,11 @@ export default defineConfig({
if (chunkInfo.names?.includes('panda.png')) { if (chunkInfo.names?.includes('panda.png')) {
return '[name].[ext]'; 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]'; return '[name].[hash].[ext]';
}, },
}, },