feat: add user manager

This commit is contained in:
xion 2025-02-28 15:31:32 +08:00
parent 5f7bd0de5f
commit bd58d5983c
26 changed files with 149 additions and 57 deletions

View File

@ -20,6 +20,7 @@
"@kevisual/codemirror": "^0.0.2", "@kevisual/codemirror": "^0.0.2",
"@kevisual/container": "1.0.0", "@kevisual/container": "1.0.0",
"@kevisual/query": "^0.0.6", "@kevisual/query": "^0.0.6",
"@kevisual/system-ui": "^0.0.3",
"@kevisual/ui": "^0.0.2", "@kevisual/ui": "^0.0.2",
"@monaco-editor/react": "^4.7.0", "@monaco-editor/react": "^4.7.0",
"@tailwindcss/vite": "^4.0.8", "@tailwindcss/vite": "^4.0.8",

12
pnpm-lock.yaml generated
View File

@ -29,6 +29,9 @@ importers:
'@kevisual/query': '@kevisual/query':
specifier: ^0.0.6 specifier: ^0.0.6
version: 0.0.6 version: 0.0.6
'@kevisual/system-ui':
specifier: ^0.0.3
version: 0.0.3
'@kevisual/ui': '@kevisual/ui':
specifier: ^0.0.2 specifier: ^0.0.2
version: 0.0.2 version: 0.0.2
@ -631,6 +634,9 @@ packages:
'@kevisual/query@0.0.6': '@kevisual/query@0.0.6':
resolution: {integrity: sha512-J+poZwIx4r956GDN5zI8zM0YyyxJqARZVVOFYplRThaQLqpsbRNYJoYiT5DekvBftxtFjs/OlI3RzcHDOv3Fjw==} resolution: {integrity: sha512-J+poZwIx4r956GDN5zI8zM0YyyxJqARZVVOFYplRThaQLqpsbRNYJoYiT5DekvBftxtFjs/OlI3RzcHDOv3Fjw==}
'@kevisual/system-ui@0.0.3':
resolution: {integrity: sha512-zRtUnL6wNe6R1W7X6eirDADZWeTmxZCNpLwxCLu30yeNuIhpFJdxHyOg0nX9aOZn6F0Kb6lB3Li2fZpKwdpk0w==}
'@kevisual/ui@0.0.2': '@kevisual/ui@0.0.2':
resolution: {integrity: sha512-MDZDQTrYToLyj3WhiVJQLJ0PUHiN4D0Z5yJIyGzzPewPGpP2xwNgKO1BFX37J95cGZckzCdZwTKP0XKAOq0QtA==} resolution: {integrity: sha512-MDZDQTrYToLyj3WhiVJQLJ0PUHiN4D0Z5yJIyGzzPewPGpP2xwNgKO1BFX37J95cGZckzCdZwTKP0XKAOq0QtA==}
@ -3166,6 +3172,12 @@ snapshots:
'@kevisual/query@0.0.6': {} '@kevisual/query@0.0.6': {}
'@kevisual/system-ui@0.0.3':
dependencies:
dayjs: 1.11.13
lodash-es: 4.17.21
style-to-object: 1.0.8
'@kevisual/ui@0.0.2': '@kevisual/ui@0.0.2':
dependencies: dependencies:
dayjs: 1.11.13 dayjs: 1.11.13

View File

@ -4,6 +4,7 @@ body {
height: 100%; height: 100%;
font-size: 16px; font-size: 16px;
font-family: 'Montserrat', sans-serif; font-family: 'Montserrat', sans-serif;
overflow: hidden;
} }
#root { #root {

View File

@ -1,7 +1,8 @@
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { useLayoutStore } from './store'; import { useLayoutStore } from './store';
import clsx from 'clsx'; import clsx from 'clsx';
import { Button, Dropdown, message } from 'antd'; import { Button, Dropdown } from 'antd';
import { message } from '@/modules/message';
import { import {
CloseOutlined, CloseOutlined,
CodeOutlined, CodeOutlined,

View File

@ -1,7 +1,8 @@
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { useLayoutStore } from './store'; import { useLayoutStore } from './store';
import clsx from 'clsx'; import clsx from 'clsx';
import { Button, message } from 'antd'; import { Button } from 'antd';
import { message } from '@/modules/message';
import { import {
AppstoreOutlined, AppstoreOutlined,
CloseOutlined, CloseOutlined,

View File

@ -1,6 +1,6 @@
import { query } from '@/modules/query'; import { query } from '@/modules/query';
import { message } from 'antd';
import { create } from 'zustand'; import { create } from 'zustand';
import { message } from '@/modules/message';
export const getIsMac = async () => { export const getIsMac = async () => {
// @ts-ignore // @ts-ignore
const userAgentData = navigator.userAgentData; const userAgentData = navigator.userAgentData;
@ -37,7 +37,7 @@ export const usePlatformStore = create<PlatfromStore>((set) => {
init: async () => { init: async () => {
const mac = await getIsMac(); const mac = await getIsMac();
// @ts-ignore // @ts-ignore
const isElectron = getIsElectron() const isElectron = getIsElectron();
set({ isMac: isElectron && mac, isElectron: isElectron, mount: true }); set({ isMac: isElectron && mac, isElectron: isElectron, mount: true });
}, },
}; };

3
src/modules/message.ts Normal file
View File

@ -0,0 +1,3 @@
import { message } from '@kevisual/system-ui/dist/message';
export { message };

View File

@ -1,7 +1,7 @@
import { QueryClient } from '@kevisual/query'; import { QueryClient } from '@kevisual/query';
import { modal } from './redirect-to-login'; import { modal } from './redirect-to-login';
import { create } from 'zustand'; import { create } from 'zustand';
import { message } from 'antd'; import { message } from './message';
export const query = new QueryClient(); export const query = new QueryClient();
query.beforeRequest = async (config) => { query.beforeRequest = async (config) => {
if (config.headers) { if (config.headers) {

View File

@ -2,11 +2,12 @@ import { useNavigation, useParams } from 'react-router';
import { useAppVersionStore } from '../store'; import { useAppVersionStore } from '../store';
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { Button, Form, Input, message, Modal, Space, Tooltip } from 'antd'; import { Button, Form, Input, Modal, Space, Tooltip } from 'antd';
import { CloudUploadOutlined, DeleteOutlined, EditOutlined, FileOutlined, LeftOutlined, LinkOutlined, PlusOutlined } from '@ant-design/icons'; import { CloudUploadOutlined, DeleteOutlined, EditOutlined, FileOutlined, LeftOutlined, LinkOutlined, PlusOutlined } from '@ant-design/icons';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import { FileUpload } from '../modules/FileUpload'; import { FileUpload } from '../modules/FileUpload';
import clsx from 'clsx'; import clsx from 'clsx';
import { message } from '@/modules/message';
import { useNewNavigate } from '@/modules'; import { useNewNavigate } from '@/modules';
const FormModal = () => { const FormModal = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();

View File

@ -1,12 +1,13 @@
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { useUserAppStore } from '../store'; import { useUserAppStore } from '../store';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { Button, Form, Input, message, Space, Modal, Select, Tooltip } from 'antd'; import { Button, Form, Input, Space, Modal, Select, Tooltip } from 'antd';
import { CodeOutlined, DeleteOutlined, EditOutlined, LinkOutlined, PlusOutlined, UnorderedListOutlined } from '@ant-design/icons'; import { CodeOutlined, DeleteOutlined, EditOutlined, LinkOutlined, PlusOutlined, UnorderedListOutlined } from '@ant-design/icons';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import { useNewNavigate } from '@/modules'; import { useNewNavigate } from '@/modules';
import { marked } from 'marked'; import { marked } from 'marked';
import clsx from 'clsx'; import clsx from 'clsx';
import { message } from '@/modules/message';
const FormModal = () => { const FormModal = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const containerStore = useUserAppStore( const containerStore = useUserAppStore(

View File

@ -1,8 +1,8 @@
import { Button, message } from 'antd'; import { Button } from 'antd';
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 { useShallow } from 'zustand/react/shallow';
import { message } from '@/modules/message';
export type FileType = { export type FileType = {
name: string; name: string;
size: number; size: number;

View File

@ -1,8 +1,7 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { query } from '@/modules'; import { query } from '@/modules';
import { message } from 'antd';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import { message } from '@/modules/message';
type AppVersionStore = { type AppVersionStore = {
showEdit: boolean; showEdit: boolean;
setShowEdit: (showEdit: boolean) => void; setShowEdit: (showEdit: boolean) => void;
@ -117,7 +116,7 @@ export const useAppVersionStore = create<AppVersionStore>((set, get) => {
key: 'publish', key: 'publish',
data, data,
}); });
loaded(); setTimeout(loaded, 200);
if (res.code === 200) { if (res.code === 200) {
message.success('Success'); message.success('Success');
// getList(); // getList();

View File

@ -1,6 +1,6 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { query } from '@/modules'; import { query } from '@/modules';
import { message } from 'antd'; import { message } from '@/modules/message';
type UserAppStore = { type UserAppStore = {
showEdit: boolean; showEdit: boolean;
setShowEdit: (showEdit: boolean) => void; setShowEdit: (showEdit: boolean) => void;

View File

@ -1,4 +1,4 @@
import { Button, Input, message, Modal, Select, Space, Switch, Table, Tooltip } from 'antd'; import { Button, Input, Modal, Select, Space, Switch, Table, Tooltip } from 'antd';
import { Fragment, useEffect, useState } from 'react'; import { Fragment, useEffect, useState } from 'react';
import { TextArea } from '../components/TextArea'; import { TextArea } from '../components/TextArea';
import { useContainerStore } from '../store'; import { useContainerStore } from '../store';
@ -6,6 +6,7 @@ import { useShallow } from 'zustand/react/shallow';
import { Form } from 'antd'; import { Form } from 'antd';
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 { import {
EditOutlined, EditOutlined,
SettingOutlined, SettingOutlined,

View File

@ -1,7 +1,7 @@
import { query } from '@/modules'; import { query } from '@/modules';
import { Select as AntSelect, message, SelectProps } from 'antd'; import { Select as AntSelect, SelectProps } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { message } from '@/modules/message';
export const Select = (props: SelectProps) => { export const Select = (props: SelectProps) => {
const [options, setOptions] = useState<{ value: string; id: string }[]>([]); const [options, setOptions] = useState<{ value: string; id: string }[]>([]);
useEffect(() => { useEffect(() => {

View File

@ -2,8 +2,8 @@ import { Container, RenderData, ContainerOne } from '@kevisual/container';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { replace, useParams } from 'react-router'; import { replace, useParams } from 'react-router';
import { query, ws, useStore } from '@/modules'; import { query, ws, useStore } from '@/modules';
import { message } from 'antd';
import { message } from '@/modules/message';
export const useListener = (id?: string, opts?: any) => { export const useListener = (id?: string, opts?: any) => {
const { refresh } = opts || {}; const { refresh } = opts || {};
const connected = useStore((state) => state.connected); const connected = useStore((state) => state.connected);

View File

@ -1,6 +1,6 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { query } from '@/modules'; import { query } from '@/modules';
import { message } from 'antd'; import { message } from '@/modules/message';
import { sortBy } from 'lodash-es'; import { sortBy } from 'lodash-es';
type FileStore = { type FileStore = {
showEdit: boolean; showEdit: boolean;

View File

@ -1,5 +1,6 @@
import { Button, Input, message, Modal, Table, Tooltip } from 'antd'; import { Button, Input, Modal, Table, Tooltip } from 'antd';
import { Fragment, useEffect, useMemo, useState } from 'react'; import { Fragment, useEffect, useMemo, useState } from 'react';
import { message } from '@/modules/message';
import { useOrgStore } from '../store'; import { useOrgStore } from '../store';
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { Form } from 'antd'; import { Form } from 'antd';
@ -204,7 +205,7 @@ export const List = () => {
<CardBlank className='w-[400px]' /> <CardBlank className='w-[400px]' />
</div> </div>
</div> </div>
<div className={clsx('bg-gray-100 border-l-gray-200 border-bg-slate-300 w-[600px] shark-0', !codeEdit && 'hidden', 'hidden')}> <div className={clsx('bg-gray-100 border-gray-200 border-bg-slate-300 w-[600px] shark-0', !codeEdit && 'hidden', 'hidden')}>
<div className='bg-white p-2'> <div className='bg-white p-2'>
<div className='mt-2 ml-2 flex gap-2'> <div className='mt-2 ml-2 flex gap-2'>
<Button <Button

View File

@ -2,22 +2,24 @@ import { useShallow } from 'zustand/react/shallow';
import { useOrgStore } from '../store'; import { useOrgStore } from '../store';
import { useNavigation, useParams } from 'react-router'; import { useNavigation, useParams } from 'react-router';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { Button, Input, message, Modal, Select, Tooltip } from 'antd'; import { Button, Input, Modal, Select, Space, Tooltip } from 'antd';
import { message } from '@/modules/message';
import { DeleteOutlined, EditOutlined, LeftOutlined, PlusOutlined } from '@ant-design/icons'; import { DeleteOutlined, EditOutlined, LeftOutlined, PlusOutlined } from '@ant-design/icons';
import { Form } from 'antd'; import { Form } from 'antd';
import { useNewNavigate } from '@/modules'; import { useNewNavigate } from '@/modules';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import copy from 'copy-to-clipboard';
const FormModal = () => { const FormModal = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const userStore = useOrgStore( const userStore = useOrgStore(
useShallow((state) => { useShallow((state) => {
return { return {
showEdit: state.showEdit, showEdit: state.showUserEdit,
setShowEdit: state.setShowEdit, setShowEdit: state.setShowUserEdit,
formData: state.formData, formData: state.userFormData,
updateData: state.updateData, setFormData: state.setUserFormData,
setFormData: state.setFormData, addUser: state.addUser,
}; };
}), }),
); );
@ -31,7 +33,15 @@ const FormModal = () => {
} }
}, [userStore.showEdit, userStore.formData]); }, [userStore.showEdit, userStore.formData]);
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
userStore.updateData(values); //
console.log(values);
const username = values.username;
const role = values.role;
if (!username) {
message.error('username is required');
return;
}
userStore.addUser({ username: username, role });
}; };
const onClose = () => { const onClose = () => {
userStore.setShowEdit(false); userStore.setShowEdit(false);
@ -70,8 +80,8 @@ const FormModal = () => {
value: 'admin', value: 'admin',
}, },
{ {
label: 'user', label: 'member',
value: 'user', value: 'member',
}, },
]}></Select> ]}></Select>
</Form.Item> </Form.Item>
@ -91,6 +101,8 @@ const FormModal = () => {
export const UserList = () => { export const UserList = () => {
const param = useParams(); const param = useParams();
const navicate = useNewNavigate(); const navicate = useNewNavigate();
const [modal, contextHolder] = Modal.useModal();
const orgStore = useOrgStore( const orgStore = useOrgStore(
useShallow((state) => { useShallow((state) => {
return { return {
@ -98,8 +110,11 @@ export const UserList = () => {
org: state.org, org: state.org,
setOrgId: state.setOrgId, setOrgId: state.setOrgId,
getOrg: state.getOrg, getOrg: state.getOrg,
setFormData: state.setFormData, setShowUserEdit: state.setShowUserEdit,
setUserFormData: state.setUserFormData,
setShowEdit: state.setShowEdit, setShowEdit: state.setShowEdit,
removeUser: state.removeUser,
addUser: state.addUser,
}; };
}), }),
); );
@ -109,7 +124,7 @@ export const UserList = () => {
orgStore.getOrg(); orgStore.getOrg();
} }
return () => { return () => {
orgStore.setFormData({}); orgStore.setUserFormData({});
}; };
}, []); }, []);
return ( return (
@ -118,8 +133,8 @@ export const UserList = () => {
<Button <Button
icon={<PlusOutlined />} icon={<PlusOutlined />}
onClick={() => { onClick={() => {
// orgStore.setShowEdit(true); orgStore.setUserFormData({});
message.info('Coming soon'); orgStore.setShowUserEdit(true);
}}></Button> }}></Button>
</div> </div>
<div className='p-4 pt-12 grow relative'> <div className='p-4 pt-12 grow relative'>
@ -132,36 +147,47 @@ export const UserList = () => {
icon={<LeftOutlined />}></Button> icon={<LeftOutlined />}></Button>
</Tooltip> </Tooltip>
</div> </div>
<div className='p-4 bg-white rounded-lg border shadow-md h-full'> <div className='p-4 bg-white rounded-lg border border-gray-200 shadow-md h-full'>
<div className='flex gap-4'> <div className='flex gap-4'>
{orgStore.users.map((item) => { {orgStore.users.map((item) => {
const isOwner = item.role === 'owner'; const isOwner = item.role === 'owner';
return ( return (
<div key={item.id} className='card w-[300px] border-t justify-between p-2 border-b'> <div key={item.id} className='card w-[300px] border-t border-gray-200 justify-between p-2 border-b'>
<div className='card-title capitalize'>username: {item.username}</div> <div
className='card-title capitalize truncate cursor-pointer'
onClick={() => {
copy(item.username);
}}>
username: {item.username}
</div>
<div className='flex gap-2 capitalize'>{item.role || '-'}</div> <div className='flex gap-2 capitalize'>{item.role || '-'}</div>
<div className='mt-2'> <div className='mt-2'>
<Button.Group> <Space.Compact>
<Tooltip title='Edit'> {/* <Tooltip title='Edit'>
<Button <Button
icon={<EditOutlined />} icon={<EditOutlined />}
disabled={isOwner} disabled={isOwner}
onClick={() => { onClick={() => {
// orgStore.setFormData(item); orgStore.setShowEdit(true);
// orgStore.setShowEdit(true); orgStore.setUserFormData(item);
message.info('Coming soon');
}}></Button> }}></Button>
</Tooltip> </Tooltip> */}
<Tooltip title='delete'> <Tooltip title='delete'>
<Button <Button
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
disabled={isOwner} disabled={isOwner}
onClick={() => { onClick={() => {
// // o-NDO62XGeyEQoz_Sytz-1UUB7kw
message.info('Coming soon'); modal.confirm({
title: 'Delete',
content: 'Are you sure?',
onOk: () => {
orgStore.removeUser(item.id);
},
});
}}></Button> }}></Button>
</Tooltip> </Tooltip>
</Button.Group> </Space.Compact>
</div> </div>
</div> </div>
); );
@ -171,6 +197,7 @@ export const UserList = () => {
</div> </div>
<FormModal /> <FormModal />
{contextHolder}
</div> </div>
); );
}; };

View File

@ -1,11 +1,15 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { query } from '@/modules'; import { query } from '@/modules';
import { message } from 'antd'; import { message } from '@/modules/message';
type OrgStore = { type OrgStore = {
showEdit: boolean; showEdit: boolean;
setShowEdit: (showEdit: boolean) => void; setShowEdit: (showEdit: boolean) => void;
formData: any; formData: any;
setFormData: (formData: any) => void; setFormData: (formData: any) => void;
showUserEdit: boolean;
setShowUserEdit: (showUserEdit: boolean) => void;
userFormData: any;
setUserFormData: (userFormData: any) => void;
loading: boolean; loading: boolean;
setLoading: (loading: boolean) => void; setLoading: (loading: boolean) => void;
list: any[]; list: any[];
@ -18,6 +22,8 @@ type OrgStore = {
orgId: string; orgId: string;
setOrgId: (orgId: string) => void; setOrgId: (orgId: string) => void;
getOrg: () => Promise<any>; getOrg: () => Promise<any>;
addUser: (data: { userId?: string; username?: string; role?: string }) => Promise<void>;
removeUser: (userId: string) => Promise<void>;
}; };
export const useOrgStore = create<OrgStore>((set, get) => { export const useOrgStore = create<OrgStore>((set, get) => {
return { return {
@ -27,6 +33,10 @@ export const useOrgStore = create<OrgStore>((set, get) => {
setFormData: (formData) => set({ formData }), setFormData: (formData) => set({ formData }),
loading: false, loading: false,
setLoading: (loading) => set({ loading }), setLoading: (loading) => set({ loading }),
showUserEdit: false,
setShowUserEdit: (showUserEdit) => set({ showUserEdit }),
userFormData: {},
setUserFormData: (userFormData) => set({ userFormData }),
list: [], list: [],
getList: async () => { getList: async () => {
set({ loading: true }); set({ loading: true });
@ -84,7 +94,7 @@ export const useOrgStore = create<OrgStore>((set, get) => {
key: 'get', key: 'get',
id: orgId, id: orgId,
}); });
loaded(); setTimeout(loaded, 200);
if (res.code === 200) { if (res.code === 200) {
const { org, users } = res.data || {}; const { org, users } = res.data || {};
set({ org, users }); set({ org, users });
@ -92,5 +102,37 @@ export const useOrgStore = create<OrgStore>((set, get) => {
message.error(res.message || 'Request failed'); message.error(res.message || 'Request failed');
} }
}, },
addUser: async (data) => {
const { orgId } = get();
const res = await query.post({
path: 'org-user',
key: 'operate',
data: { orgId, ...data, action: 'add' },
});
if (res.code === 200) {
message.success('Success');
get().getOrg();
} else {
message.error(res.message || 'Request failed');
}
},
removeUser: async (userId: string) => {
const { orgId } = get();
const res = await query.post({
path: 'org-user',
key: 'operate',
data: {
orgId,
userId,
action: 'remove',
},
});
if (res.code === 200) {
message.success('Success');
get().getOrg();
} else {
message.error(res.message || 'Request failed');
}
},
}; };
}); });

View File

@ -1,4 +1,4 @@
import { Button, Input, message, Modal, Space, Table } from 'antd'; import { Button, Input, Modal, Space, Table } from 'antd';
import { Fragment, useEffect, useMemo, useState } from 'react'; import { Fragment, useEffect, useMemo, useState } from 'react';
import { useUserStore } from '../store'; import { useUserStore } from '../store';
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
@ -8,7 +8,7 @@ import { EditOutlined, SettingOutlined, LinkOutlined, SaveOutlined, DeleteOutlin
import clsx from 'clsx'; import clsx from 'clsx';
import { isObjectNull } from '@/utils/is-null'; import { isObjectNull } from '@/utils/is-null';
import { CardBlank } from '@/components/card/CardBlank'; import { CardBlank } from '@/components/card/CardBlank';
import { message } from '@/modules/message';
const FormModal = () => { const FormModal = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const userStore = useUserStore( const userStore = useUserStore(

View File

@ -32,7 +32,7 @@ export const Login = () => {
<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'>Login</h1> <h1 className='mb-4 tracking-widest text-center'>Login</h1>
<div className='card border-t-2 pt-8 px-8'> <div className='card border-t-2 border-gray-200 pt-8 px-8'>
<Form <Form
className='mt-2' className='mt-2'
form={form} form={form}

View File

@ -1,6 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons'; import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { Flex, message, Upload } from 'antd'; import { Flex, Upload } from 'antd';
import { message } from '@/modules/message';
import type { GetProp, UploadProps } from 'antd'; import type { GetProp, UploadProps } from 'antd';
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0]; type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
@ -53,7 +54,7 @@ export const AvatarUpload = () => {
}; };
const customAction = (file) => { const customAction = (file) => {
console.log('file', file); console.log('file', file);
} };
return ( return (
<Flex gap='middle' wrap> <Flex gap='middle' wrap>
<Upload <Upload

View File

@ -1,4 +1,4 @@
import { message } from 'antd'; import { message } from '@/modules/message';
import { useImperativeHandle, useRef, forwardRef } from 'react'; import { useImperativeHandle, useRef, forwardRef } from 'react';
import type { GetProp, UploadProps } from 'antd'; import type { GetProp, UploadProps } from 'antd';
type FileTypeOrg = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0]; type FileTypeOrg = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];

View File

@ -1,6 +1,6 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { query } from '@/modules'; import { query } from '@/modules';
import { message } from 'antd'; import { message } from '@/modules/message';
type UserStore = { type UserStore = {
showEdit: boolean; showEdit: boolean;
setShowEdit: (showEdit: boolean) => void; setShowEdit: (showEdit: boolean) => void;

View File

@ -1,6 +1,6 @@
import { query } from '@/modules'; import { query } from '@/modules';
import { basename } from '@/modules/basename'; import { basename } from '@/modules/basename';
import { message } from 'antd'; import { message } from '@/modules/message';
import { create } from 'zustand'; import { create } from 'zustand';
// 如果自己是在iframe中登录需要调用这个方法 // 如果自己是在iframe中登录需要调用这个方法
export const postLoginInIframe = (token: string) => { export const postLoginInIframe = (token: string) => {
@ -55,7 +55,7 @@ export const useLoginStore = create<LoginStore>((set, get) => {
set({ loading: true }); set({ loading: true });
const loaded = message.loading('loading...', 0); const loaded = message.loading('loading...', 0);
const res = await query.post({ path: 'user', key: 'login', username, password }); const res = await query.post({ path: 'user', key: 'login', username, password });
loaded(); setTimeout(loaded, 200);
if (res.code === 200) { if (res.code === 200) {
const { token } = res.data; const { token } = res.data;
message.success('Success'); message.success('Success');
@ -81,7 +81,7 @@ export const useLoginStore = create<LoginStore>((set, get) => {
set({ loading: true }); set({ loading: true });
const loaded = message.loading('loading...', 0); const loaded = message.loading('loading...', 0);
const res = await query.post({ path: 'user', key: 'register' }); const res = await query.post({ path: 'user', key: 'register' });
loaded(); setTimeout(loaded, 200);
if (res.code === 200) { if (res.code === 200) {
message.success('Success'); message.success('Success');
// 跳到某一个页面 // 跳到某一个页面