This commit is contained in:
2026-04-30 18:53:50 +08:00
parent 88c2fa5d03
commit c764603dbd
20 changed files with 866 additions and 654 deletions
@@ -1,54 +1,23 @@
import { Component } from "react";
import { useEffect, useState } from 'react';
import userService from '../services/user.service';
import UserService from "../services/user.service";
import EventBus from "../common/EventBus";
export default function BoardAdmin() {
const [content, setContent] = useState('');
type Props = {};
type State = {
content: string;
}
export default class BoardAdmin extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
content: ""
};
}
componentDidMount() {
UserService.getAdminBoard().then(
response => {
this.setState({
content: response.data
});
useEffect(() => {
userService.getAdminBoard().then(
(res) => setContent(String(res.data ?? '')),
(error: unknown) => {
setContent(error instanceof Error ? error.message : String(error));
},
error => {
this.setState({
content:
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString()
});
if (error.response && error.response.status === 401) {
EventBus.dispatch("logout");
}
}
);
}
}, []);
render() {
return (
<div className="container">
<header className="jumbotron">
<h3>{this.state.content}</h3>
</header>
</div>
);
}
return (
<div className="container">
<header className="jumbotron">
<h3>{content}</h3>
</header>
</div>
);
}
@@ -1,54 +1,23 @@
import { Component } from "react";
import { useEffect, useState } from 'react';
import userService from '../services/user.service';
import UserService from "../services/user.service";
import EventBus from "../common/EventBus";
export default function BoardModerator() {
const [content, setContent] = useState('');
type Props = {};
type State = {
content: string;
}
export default class BoardAdmin extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
content: ""
};
}
componentDidMount() {
UserService.getModeratorBoard().then(
response => {
this.setState({
content: response.data
});
useEffect(() => {
userService.getModeratorBoard().then(
(res) => setContent(String(res.data ?? '')),
(error: unknown) => {
setContent(error instanceof Error ? error.message : String(error));
},
error => {
this.setState({
content:
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString()
});
if (error.response && error.response.status === 401) {
EventBus.dispatch("logout");
}
}
);
}
}, []);
render() {
return (
<div className="container">
<header className="jumbotron">
<h3>{this.state.content}</h3>
</header>
</div>
);
}
return (
<div className="container">
<header className="jumbotron">
<h3>{content}</h3>
</header>
</div>
);
}
@@ -1,54 +1,23 @@
import { Component } from "react";
import { useEffect, useState } from 'react';
import userService from '../services/user.service';
import UserService from "../services/user.service";
import EventBus from "../common/EventBus";
export default function BoardUser() {
const [content, setContent] = useState('');
type Props = {};
type State = {
content: string;
}
export default class BoardUser extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
content: ""
};
}
componentDidMount() {
UserService.getUserBoard().then(
response => {
this.setState({
content: response.data
});
useEffect(() => {
userService.getUserBoard().then(
(res) => setContent(String(res.data ?? '')),
(error: unknown) => {
setContent(error instanceof Error ? error.message : String(error));
},
error => {
this.setState({
content:
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString()
});
if (error.response && error.response.status === 401) {
EventBus.dispatch("logout");
}
}
);
}
}, []);
render() {
return (
<div className="container">
<header className="jumbotron">
<h3>{this.state.content}</h3>
</header>
</div>
);
}
return (
<div className="container">
<header className="jumbotron">
<h3>{content}</h3>
</header>
</div>
);
}
@@ -4,7 +4,7 @@ import { useUIStore } from '../../stores/useUIStore';
import authService from '../../services/auth.service';
export default function PasswordModal() {
const { updatePasswordModelVisible, setUpdatePasswordModelVisible } = useUIStore();
const { updatePasswordModalVisible, setUpdatePasswordModalVisible } = useUIStore();
const user = useAuthStore((s) => s.user);
const handleSubmit = (values: {
@@ -17,7 +17,7 @@ export default function PasswordModal() {
.then(
() => {
Toast.success('密码修改成功');
setUpdatePasswordModelVisible(false);
setUpdatePasswordModalVisible(false);
},
(error: unknown) => {
const msg =
@@ -30,10 +30,10 @@ export default function PasswordModal() {
return (
<Modal
title="修改密码"
visible={updatePasswordModelVisible}
visible={updatePasswordModalVisible}
size="large"
footer={null}
onCancel={() => setUpdatePasswordModelVisible(false)}
onCancel={() => setUpdatePasswordModalVisible(false)}
closeOnEsc
>
<div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
@@ -10,13 +10,13 @@ interface TrashListModalProps {
}
export default function TrashListModal({ trashList, onRestored }: TrashListModalProps) {
const { deleteModelVisible, setDeleteModelVisible } = useUIStore();
const { deleteModalVisible, setDeleteModalVisible } = useUIStore();
const handleRestore = (id: number) => {
noteService.restoreFromTrash(id).then(
() => {
Toast.success('已从回收站恢复');
setDeleteModelVisible(false);
setDeleteModalVisible(false);
onRestored();
},
() => Toast.error('恢复失败,请重试'),
@@ -26,10 +26,10 @@ export default function TrashListModal({ trashList, onRestored }: TrashListModal
return (
<Modal
title="回收站"
visible={deleteModelVisible}
visible={deleteModalVisible}
size="large"
footer={null}
onCancel={() => setDeleteModelVisible(false)}
onCancel={() => setDeleteModalVisible(false)}
closeOnEsc
>
<div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
@@ -1,69 +1,37 @@
import { Component } from "react";
import { Navigate } from 'react-router';
import AuthService from "../services/auth.service";
import type { IUser } from '../types';
import { useAuthStore } from '../stores/useAuthStore';
type Props = {};
export default function Profile() {
const user = useAuthStore((s) => s.user);
const token = useAuthStore((s) => s.token);
type State = {
redirect: string | null,
userReady: boolean,
currentUser: IUser & { accessToken: string }
}
export default class Profile extends Component<Props, State> {
constructor(props: Props) {
super(props);
if (!user) return <Navigate to="/login" replace />;
this.state = {
redirect: null,
userReady: false,
currentUser: { accessToken: "" }
};
}
componentDidMount() {
const currentUser = AuthService.getCurrentUser();
if (!currentUser) this.setState({ redirect: "/home" });
this.setState({ currentUser: currentUser, userReady: true })
}
render() {
if (this.state.redirect) {
return <Navigate to={this.state.redirect} />
}
const { currentUser } = this.state;
return (
<div className="container">
{(this.state.userReady) ?
<div>
<header className="jumbotron">
<h3>
<strong>{currentUser.username}</strong> Profile
</h3>
</header>
<p>
<strong>Token:</strong>{" "}
{currentUser.accessToken.substring(0, 20)} ...{" "}
{currentUser.accessToken.substr(currentUser.accessToken.length - 20)}
</p>
<p>
<strong>Id:</strong>{" "}
{currentUser.id}
</p>
<p>
<strong>Email:</strong>{" "}
{currentUser.email}
</p>
<strong>Authorities:</strong>
<ul>
{currentUser.roles &&
currentUser.roles.map((role, index) => <li key={index}>{role}</li>)}
</ul>
</div> : null}
return (
<div className="container">
<div>
<header className="jumbotron">
<h3>
<strong>{user.username}</strong> Profile
</h3>
</header>
<p>
<strong>Token:</strong>{' '}
{token ? `${token.substring(0, 20)} ... ${token.substring(token.length - 20)}` : 'N/A'}
</p>
<p>
<strong>Id:</strong> {user.id}
</p>
<p>
<strong>Email:</strong> {user.email}
</p>
<strong>Authorities:</strong>
<ul>
{user.roles.map((role, index) => (
<li key={index}>{role}</li>
))}
</ul>
</div>
);
}
</div>
);
}
@@ -34,6 +34,8 @@ export default function NoteTree({ onRefreshTree, onNavItemClick, onSearch }: No
const { treeData, viewData, currentNoteId, setCurrentNote } = useNoteStore();
const { openDeleteConfirm, setSearchQuery, searchQuery, setActiveView } = useUIStore();
const toNoteId = (id: string | number) => Number(id);
const loadNote = useCallback(
(id: number) => {
noteService.get(id).then(
@@ -81,7 +83,7 @@ export default function NoteTree({ onRefreshTree, onNavItemClick, onSearch }: No
size="small"
icon={<IconCopyAdd />}
onClick={(e) => {
addNote(item.key);
addNote(toNoteId(item.key));
e.stopPropagation();
}}
/>
@@ -90,7 +92,7 @@ export default function NoteTree({ onRefreshTree, onNavItemClick, onSearch }: No
type="warning"
icon={<IconDelete />}
onClick={(e) => {
openDeleteConfirm(item.key, String(label));
openDeleteConfirm(toNoteId(item.key), String(label));
e.stopPropagation();
}}
/>
@@ -188,11 +190,11 @@ export default function NoteTree({ onRefreshTree, onNavItemClick, onSearch }: No
showFilteredOnly
directory
virtualize
value={currentNoteId}
value={currentNoteId === null ? undefined : String(currentNoteId)}
treeData={treeData as unknown as Parameters<typeof Tree>[0]['treeData']}
renderLabel={renderLabel as Parameters<typeof Tree>[0]['renderLabel']}
style={treeStyle}
onSelect={(id) => loadNote(id as unknown as number)}
onSelect={(id) => loadNote(toNoteId(id as string | number))}
/>
</>
);
@@ -9,17 +9,20 @@ import {
Toast,
} from '@douyinfe/semi-ui';
import { useNoteStore } from '../../stores/useNoteStore';
import { useUIStore } from '../../stores/useUIStore';
import noteService from '../../services/note.service';
import type { INote } from '../../types';
export default function HomePage() {
const { homeData, setHomeData, setCurrentNote } = useNoteStore();
const setActiveView = useUIStore((s) => s.setActiveView);
const loadNote = (id: number) => {
noteService.get(id).then(
(res) => {
const note = res.data;
setCurrentNote(note.id, note.title, note.context);
setActiveView('note');
},
() => Toast.error('加载笔记失败'),
);
+5 -5
View File
@@ -63,8 +63,8 @@ export default function NotePage() {
setActiveView,
setSiderFlag,
setSideVisible,
setDeleteModelVisible,
setUpdatePasswordModelVisible,
setDeleteModalVisible,
setUpdatePasswordModalVisible,
} = useUIStore();
const [trashList, setTrashList] = useState<INote[]>([]);
@@ -102,13 +102,13 @@ export default function NotePage() {
noteService.getHomeData('4', '0').then(
(res) => {
setTrashList(res.data);
setDeleteModelVisible(true);
setDeleteModalVisible(true);
},
() => Toast.error('加载回收站失败'),
);
}
},
[setActiveView, setDeleteModelVisible],
[setActiveView, setDeleteModalVisible],
);
const handleSearch = useCallback(() => {
@@ -244,7 +244,7 @@ export default function NotePage() {
theme="solid"
type="secondary"
style={{ marginRight: 8 }}
onClick={() => setUpdatePasswordModelVisible(true)}
onClick={() => setUpdatePasswordModalVisible(true)}
>
</Button>
+9 -9
View File
@@ -10,8 +10,8 @@ interface UIState {
deleteVisible: boolean;
deleteId: number | null;
deleteNoteName: string;
deleteModelVisible: boolean;
updatePasswordModelVisible: boolean;
deleteModalVisible: boolean;
updatePasswordModalVisible: boolean;
searchQuery: string;
setActiveView: (view: ActiveView) => void;
setSideVisible: (visible: boolean) => void;
@@ -19,8 +19,8 @@ interface UIState {
setNoteLoading: (loading: boolean) => void;
openDeleteConfirm: (id: number, name: string) => void;
closeDeleteConfirm: () => void;
setDeleteModelVisible: (visible: boolean) => void;
setUpdatePasswordModelVisible: (visible: boolean) => void;
setDeleteModalVisible: (visible: boolean) => void;
setUpdatePasswordModalVisible: (visible: boolean) => void;
setSearchQuery: (query: string) => void;
}
@@ -32,8 +32,8 @@ export const useUIStore = create<UIState>()((set) => ({
deleteVisible: false,
deleteId: null,
deleteNoteName: '',
deleteModelVisible: false,
updatePasswordModelVisible: false,
deleteModalVisible: false,
updatePasswordModalVisible: false,
searchQuery: '',
setActiveView: (activeView) => set({ activeView }),
setSideVisible: (sideVisible) => set({ sideVisible }),
@@ -43,8 +43,8 @@ export const useUIStore = create<UIState>()((set) => ({
set({ deleteVisible: true, deleteId, deleteNoteName }),
closeDeleteConfirm: () =>
set({ deleteVisible: false, deleteId: null, deleteNoteName: '' }),
setDeleteModelVisible: (deleteModelVisible) => set({ deleteModelVisible }),
setUpdatePasswordModelVisible: (updatePasswordModelVisible) =>
set({ updatePasswordModelVisible }),
setDeleteModalVisible: (deleteModalVisible) => set({ deleteModalVisible }),
setUpdatePasswordModalVisible: (updatePasswordModalVisible) =>
set({ updatePasswordModalVisible }),
setSearchQuery: (searchQuery) => set({ searchQuery }),
}));
+4 -1
View File
@@ -24,7 +24,10 @@ export interface INote {
}
export interface ITreeNode {
key: number;
id?: number;
pid?: number;
key: string;
value?: string;
label: string;
children?: ITreeNode[];
}