feat: migrate all files to typescript with strict false mode

This commit is contained in:
BenjaminNH 2025-09-05 20:46:56 +08:00
parent b3d4e14409
commit d56bca6692
35 changed files with 407 additions and 191 deletions

View File

@ -1,9 +1,9 @@
import dayjs from "dayjs";
import dayjs, { Dayjs } from "dayjs";
import quarterOfYear from "dayjs/plugin/quarterOfYear";
dayjs.extend(quarterOfYear);
export const datePresets = [
export const datePresets: Array<{ label: string; value: [Dayjs, Dayjs] }> = [
{
label: "本月",
value: [dayjs().startOf("month"), dayjs().endOf("month")],

View File

@ -30,7 +30,7 @@ const authSlice = createSlice({
state.roles = payload.roles;
state.token = payload.token;
localStorage.setItem("userId", payload.userId);
localStorage.setItem("userId", payload.userId.toString());
localStorage.setItem("name", payload.name);
localStorage.setItem("roles", JSON.stringify(payload.roles));
localStorage.setItem("token", action.payload.token);

View File

@ -1,11 +0,0 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axiosInstance from "../../api/axios";
export const login = createAsyncThunk(
"auth/login",
async (values, thunkAPI) => {
const res = await axiosInstance.post("/login", values);
return res;
}
);

View File

@ -0,0 +1,15 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axiosInstance from "../../api/axios";
import { LoginResponse } from "./types";
export const login = createAsyncThunk<LoginResponse>(
"auth/login",
async (values) => {
const res = await axiosInstance.post<LoginResponse, LoginResponse>(
"/login",
values
);
return res;
}
);

View File

@ -0,0 +1,6 @@
export interface LoginResponse {
userId: number;
name: string;
roles: string[];
token: string;
}

View File

@ -3,7 +3,7 @@ import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { RouterProvider } from "react-router-dom";
import "./index.css";
import router from "./router/index.jsx";
import router from "./router/index.js";
import { store } from "./store/index.js";
import dayjs from "dayjs";
import zhCN from "antd/locale/zh_CN";

View File

@ -4,9 +4,10 @@ import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { login } from "../features/auth/authThunk";
import roleRoute from "../config/roleRouteConfig";
import { store } from "store";
export default function Login() {
const dispatch = useDispatch();
const dispatch = useDispatch<typeof store.dispatch>();
const navigate = useNavigate();
const onFinish = async (values) => {

View File

@ -1,7 +1,14 @@
import { message, Modal, Space, Spin, Table } from "antd";
import { useEffect, useState } from "react";
import { message, Modal, Spin, Table } from "antd";
import { useCallback, useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
interface DeviceDetailStats {
applicantName: string;
applicantTeam: string;
startDay: Date;
endDay: Date;
}
export default function DeviceDetailStatsModal({
visible,
record,
@ -9,12 +16,15 @@ export default function DeviceDetailStatsModal({
onClose,
}) {
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [data, setData] = useState<DeviceDetailStats[]>([]);
const fetchData = async () => {
const fetchData = useCallback(async () => {
setLoading(true);
try {
const res = await axiosInstance.get("/device/detail-stats", {
const res = await axiosInstance.get<
DeviceDetailStats[],
DeviceDetailStats[]
>("/device/detail-stats", {
params: {
deviceId: record.deviceId,
start: range[0].format("YYYY-MM-DD"),
@ -22,12 +32,12 @@ export default function DeviceDetailStatsModal({
},
});
setData(res);
} catch (e) {
} catch {
message.error("获取数据失败");
} finally {
setLoading(false);
}
};
}, [record, range]);
const handleExport = async () => {
setLoading(true);
@ -73,7 +83,7 @@ export default function DeviceDetailStatsModal({
if (visible) {
fetchData();
}
}, [visible, record]);
}, [visible, fetchData]);
const columns = [
{

View File

@ -1,41 +1,52 @@
import { Button, DatePicker, Input, Space, Spin, Table, message } from "antd";
import dayjs from "dayjs";
import { useEffect, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { useCallback, useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import { datePresets } from "../../config/datePresetsConfig";
import DeviceDetailStatsModal from "./DeviceDetailStatsModal";
interface UsageStats {
deviceId: string;
deviceName: string;
usageCount: number;
totalUsageDays: number;
}
const { RangePicker } = DatePicker;
export default function DeviceStats() {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [range, setRange] = useState([
const [data, setData] = useState<UsageStats[]>([]);
const [filteredData, setFilteredData] = useState<UsageStats[]>([]);
const [range, setRange] = useState<[Dayjs, Dayjs]>([
dayjs().startOf("month"),
dayjs().endOf("month"),
]);
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
const [search, setSearch] = useState("");
const [loading, setLoading] = useState(false);
const [visiable, setVisiable] = useState(false);
const [selectedRecord, setSelectedRecord] = useState(null);
const fetchData = async () => {
const fetchData = useCallback(async () => {
setLoading(true);
try {
const res = await axiosInstance.get("/device/usage-stats", {
params: {
start: range[0].format("YYYY-MM-DD"),
end: range[1].format("YYYY-MM-DD"),
},
});
const res = await axiosInstance.get<UsageStats[], UsageStats[]>(
"/device/usage-stats",
{
params: {
start: range[0].format("YYYY-MM-DD"),
end: range[1].format("YYYY-MM-DD"),
},
}
);
setData(res);
setFilteredData(res);
} catch (e) {
} catch {
message.error("获取数据失败");
} finally {
setLoading(false);
}
};
}, [range]);
const handleSearch = (value) => {
setSearch(value);
@ -89,7 +100,7 @@ export default function DeviceStats() {
useEffect(() => {
fetchData();
}, [range]);
}, [fetchData]);
const columns = [
{

View File

@ -1,38 +1,50 @@
import { Button, DatePicker, Input, Space, Spin, Table, message } from "antd";
import dayjs from "dayjs";
import { useEffect, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { useCallback, useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import { datePresets } from "../../config/datePresetsConfig";
interface ReservationStat {
deviceId: string;
deviceName: string;
applicantName: string;
applicantTeam: string;
usageCount: number;
}
const { RangePicker } = DatePicker;
export default function ReservationStats() {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [range, setRange] = useState([
const [data, setData] = useState<ReservationStat[]>([]);
const [filteredData, setFilteredData] = useState<ReservationStat[]>([]);
const [range, setRange] = useState<[Dayjs, Dayjs]>([
dayjs().startOf("month"),
dayjs().endOf("month"),
]);
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
const [search, setSearch] = useState("");
const [loading, setLoading] = useState(false);
const fetchData = async () => {
const fetchData = useCallback(async () => {
setLoading(true);
try {
const res = await axiosInstance.get("/reservation/stats", {
params: {
start: range[0].format("YYYY-MM-DD"),
end: range[1].format("YYYY-MM-DD"),
},
});
const res = await axiosInstance.get<ReservationStat[], ReservationStat[]>(
"/reservation/stats",
{
params: {
start: range[0].format("YYYY-MM-DD"),
end: range[1].format("YYYY-MM-DD"),
},
}
);
setData(res);
setFilteredData(res);
} catch (e) {
} catch {
message.error("获取数据失败");
} finally {
setLoading(false);
}
};
}, [range]);
const handleSearch = (value) => {
setSearch(value);
@ -86,7 +98,7 @@ export default function ReservationStats() {
useEffect(() => {
fetchData();
}, [range]);
}, [fetchData]);
const columns = [
{

View File

@ -1,20 +1,22 @@
import { List, Modal, Typography } from "antd";
import { useEffect, useState } from "react";
import { List, Modal } from "antd";
import { useCallback, useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
export default function TeamDetailModal({ open, team, onclose }) {
const [data, setData] = useState([]);
const [data, setData] = useState<string[]>([]);
const fetchData = async () => {
const data = await axiosInstance.get(`/user-team/${team.id}`);
const fetchData = useCallback(async () => {
const data = await axiosInstance.get<string[], string[]>(
`/user-team/${team.id}`
);
setData(data);
};
}, [team]);
useEffect(() => {
if (open) {
fetchData();
}
}, [open, team]);
}, [open, fetchData]);
return (
<Modal

View File

@ -4,19 +4,20 @@ import { useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import TeamDeleteButton from "../../components/TeamDeleteButton";
import TeamDetailModal from "./TeamDetailModal";
import { Team } from "types/model";
export default function TeamManage() {
const [teams, setTeams] = useState([]);
const [data, setData] = useState([]);
const [searchName, setSearchName] = useState();
const [teams, setTeams] = useState<Team[]>([]);
const [data, setData] = useState<Team[]>([]);
const [searchName, setSearchName] = useState<string>();
const [editingId, setEditingId] = useState();
const [editingName, setEditingName] = useState("");
const [newTeamName, setNewTeamName] = useState();
const [newTeamName, setNewTeamName] = useState("");
const [open, setOpen] = useState(false);
const [selectedTeam, setSelectedTeam] = useState(null);
const fetchData = async () => {
const data = await axiosInstance.get("/teams");
const data = await axiosInstance.get<Team[], Team[]>("/teams");
setData(data);
setTeams(data);
setSearchName(null);

View File

@ -1,7 +1,15 @@
import { Form, Input, message, Modal, Select } from "antd";
import { useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import Password from "antd/es/input/Password";
interface UserDTO {
username: string;
name: string;
phone: string;
password?: string;
teamId: string;
roleId: string;
}
export default function UserDetailModal({
visiable,
@ -12,11 +20,14 @@ export default function UserDetailModal({
onSuccess,
}) {
const [form] = Form.useForm();
const [initialValues, setInitialValues] = useState();
const [teams, setTeams] = useState([]);
const [initialValues, setInitialValues] = useState<UserDTO>();
const [teams, setTeams] = useState<{ label: string; value: string }[]>();
const fetchTeams = async () => {
const data = await axiosInstance.get("/team-label");
const data = await axiosInstance.get<
unknown,
{ label: string; value: string }[]
>("/team-label");
setTeams(data);
};
@ -27,7 +38,7 @@ export default function UserDetailModal({
useEffect(() => {
if (visiable) {
if (mode === "edit") {
const values = {
const values: UserDTO = {
username: user.username,
name: user.name,
phone: user.phone,
@ -38,7 +49,7 @@ export default function UserDetailModal({
setInitialValues(values);
form.setFieldsValue(values);
} else {
const values = {
const values: UserDTO = {
username: undefined,
password: undefined,
name: undefined,

View File

@ -2,29 +2,33 @@ import { Button, Flex, Input, Popconfirm, Space, Table } from "antd";
import Column from "antd/es/table/Column";
import { useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import DeviceDetailModal from "../deviceAdmin/DeviceDetailModal";
import UserDetailModal from "./UserDetailModal";
import { PageResult, Pagination } from "types/common";
import { UserVo } from "types/model";
export default function UserManage() {
const [users, setUsers] = useState([]);
const [teams, setTeams] = useState([]);
const [modalMode, setModalMode] = useState();
const [selectedUser, setSelectedUser] = useState();
// const [teams, setTeams] = useState([]);
const [modalMode, setModalMode] = useState<string>();
const [selectedUser, setSelectedUser] = useState<UserVo>();
const [modalOpen, setModalOpen] = useState(false);
const [roles, setRoles] = useState([]);
const [pagination, setPagination] = useState({
const [roles, setRoles] = useState<{ label: string; value: string }[]>([]);
const [pagination, setPagination] = useState<Pagination>({
current: 1,
pageSize: 10,
total: 0,
});
const fetchRoles = async () => {
const data = await axiosInstance.get("/role");
const data = await axiosInstance.get<
unknown,
{ label: string; value: string }[]
>("/role");
setRoles(data);
};
const fetchData = async (pagination, name) => {
const data = await axiosInstance.get("/user", {
const fetchData = async (pagination: Pagination, name?: string) => {
const data = await axiosInstance.get<unknown, PageResult<UserVo>>("/user", {
params: {
page: pagination.current,
size: pagination.pageSize,
@ -108,7 +112,7 @@ export default function UserManage() {
/>
<Column
title="操作"
render={(_, record) => {
render={(_, record: UserVo) => {
return (
<Space>
<Button

View File

@ -15,6 +15,7 @@ import { useSelector } from "react-redux";
import axiosInstance, { baseURL } from "../../api/axios";
import { deviceStatusOptions } from "../../config/DeviceStatusConfig";
import { selectUserId } from "../../features/auth/authSlice";
import { UploadFile } from "antd/lib";
export default function DeviceDetailModal({
visiable,
@ -26,7 +27,7 @@ export default function DeviceDetailModal({
const [form] = Form.useForm();
const [imageFile, setImageFile] = useState(null);
const [initialValues, setInitialValues] = useState({});
const [fileList, setFileList] = useState();
const [fileList, setFileList] = useState<UploadFile[]>();
const userId = useSelector(selectUserId);
useEffect(() => {
if (visiable) {

View File

@ -9,45 +9,61 @@ import {
Tag,
} from "antd";
import Column from "antd/es/table/Column";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import axiosInstance from "../../api/axios";
import { deviceStatusOptions } from "../../config/DeviceStatusConfig";
import { selectUserId } from "../../features/auth/authSlice";
import DeviceDetailModal from "./DeviceDetailModal";
import { PageResult, Pagination } from "types/common";
interface DeviceAdminVO {
deviceId: string;
name: string;
usageRequirement: string;
location: string;
imagePath: string;
status: string;
}
export default function DeviceManage() {
const [devices, setDevices] = useState([]);
const [selectedDevice, setSelectedDevice] = useState(null);
const [modalOpen, setModalOpen] = useState(false);
const [modalMode, setModalMode] = useState(null);
const [searchName, setSearchName] = useState(null);
const [pagination, setPagination] = useState({
const [searchName, setSearchName] = useState<string>(null);
const [pagination, setPagination] = useState<Pagination>({
current: 1,
pageSize: 10,
total: 0,
});
const userId = useSelector(selectUserId);
const fetchData = async (pagination, name = searchName) => {
const data = await axiosInstance.get(`/device/${userId}`, {
params: {
page: pagination.current,
size: pagination.pageSize,
name,
},
});
const fetchData = useCallback(
async (pagination: Pagination, name: string = searchName) => {
const data = await axiosInstance.get<unknown, PageResult<DeviceAdminVO>>(
`/device/${userId}`,
{
params: {
page: pagination.current,
size: pagination.pageSize,
name,
},
}
);
setDevices(data.records);
setPagination({
...pagination,
total: data.total,
});
};
setDevices(data.records);
setPagination({
...pagination,
total: data.total,
});
},
[userId, searchName]
);
useEffect(() => {
fetchData(pagination);
}, []);
}, [fetchData, pagination]);
const handlePageChange = async (pagination) => {
await fetchData(pagination);

View File

@ -1,10 +1,22 @@
import { Button, message, Space, Table } from "antd";
import Column from "antd/es/table/Column";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import axiosInstance from "../../api/axios";
import { selectUserId } from "../../features/auth/authSlice";
import { selectUserRole } from "../../features/auth/authSlice";
import { PageResult, Pagination } from "types/common";
interface ReservationVO {
reservationId: string;
applicantName: string;
applicantTeam: string;
applicantContact: string;
deviceId: string;
deviceName: string;
startTime: Date;
endTime: Date;
}
export default function Approval() {
const [reservations, setReservations] = useState([]);
@ -21,24 +33,30 @@ export default function Approval() {
showNeedAssist = true;
}
const fetchData = async (pagination) => {
const data = await axiosInstance.get(`/reservation/approval/${userId}`, {
params: {
page: pagination.current,
size: pagination.pageSize,
},
});
const fetchData = useCallback(
async (pagination: Pagination) => {
const data = await axiosInstance.get<unknown, PageResult<ReservationVO>>(
`/reservation/approval/${userId}`,
{
params: {
page: pagination.current,
size: pagination.pageSize,
},
}
);
setReservations(data.records);
setPagination({
...pagination,
total: data.total,
});
};
setReservations(data.records);
setPagination({
...pagination,
total: data.total,
});
},
[userId]
);
useEffect(() => {
fetchData(pagination);
}, []);
}, [fetchData, pagination]);
const handlePageChange = async (pagination) => {
await fetchData(pagination);

View File

@ -1,11 +1,25 @@
import { Button, DatePicker, Form, Input, message, Table, Tag } from "antd";
import { useForm } from "antd/es/form/Form";
import Column from "antd/es/table/Column";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import axiosInstance from "../../api/axios";
import { selectUserId, selectUserRole } from "../../features/auth/authSlice";
import dayjs from "dayjs";
import { PageResult, Pagination } from "types/common";
interface ApprovalVO {
reservationId: string;
approvalId: string;
applicantName: string;
applicantTeam: string;
applicantContact: string;
deviceName: string;
startTime: Date;
endTime: Date;
decision: number;
status: string;
}
export default function MyApproval() {
const [approvals, setApprovals] = useState([]);
@ -21,26 +35,35 @@ export default function MyApproval() {
const userId = useSelector(selectUserId);
const userRole = useSelector(selectUserRole);
const fetchData = async (pagination, searchParam) => {
const data = await axiosInstance.get(`/approval/${userId}`, {
params: {
page: pagination.current,
size: pagination.pageSize,
applicantName: searchParam?.applicantName,
deviceName: searchParam?.deviceName,
},
});
const fetchData = useCallback(
async (
pagination: Pagination,
searchParam?: { applicantName: string; deviceName: string }
) => {
const data = await axiosInstance.get<unknown, PageResult<ApprovalVO>>(
`/approval/${userId}`,
{
params: {
page: pagination.current,
size: pagination.pageSize,
applicantName: searchParam?.applicantName,
deviceName: searchParam?.deviceName,
},
}
);
setApprovals(data.records);
setPagination({
...pagination,
total: data.total,
});
};
setApprovals(data.records);
setPagination({
...pagination,
total: data.total,
});
},
[userId]
);
useEffect(() => {
fetchData(pagination);
}, []);
}, [fetchData, pagination]);
const handlePageChange = async (pagination) => {
const values = await form.validateFields();
@ -66,7 +89,7 @@ export default function MyApproval() {
await fetchData(pagination, values);
setEditingRow(null);
message.success("修改成功");
} catch (error) {
} catch {
message.error("修改失败");
}
};

View File

@ -1,14 +1,14 @@
import { Button, Col, Form, Input, message, Row } from "antd";
import { useForm } from "antd/es/form/Form";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import axiosInstance from "../../api/axios";
import { selectUserId } from "../../features/auth/authSlice";
import { UserVo } from "types/model";
export default function UserDetail() {
const [form] = Form.useForm();
const [showPassword, setShowPassword] = useState(false);
const [user, setUser] = useState({
const [user, setUser] = useState<UserVo>({
userId: "",
username: "",
team: "",
@ -17,15 +17,20 @@ export default function UserDetail() {
});
const userId = useSelector(selectUserId);
const fetchUser = async (userId) => {
const user = await axiosInstance.get(`/userdetail/${userId}`);
setUser(user);
form.setFieldsValue(user);
};
const fetchUser = useCallback(
async (userId: string) => {
const user = await axiosInstance.get<unknown, UserVo>(
`/userdetail/${userId}`
);
setUser(user);
form.setFieldsValue(user);
},
[form]
);
useEffect(() => {
fetchUser(userId);
}, []);
}, [fetchUser, userId]);
const handleReset = () => {
form.resetFields();
@ -36,7 +41,7 @@ export default function UserDetail() {
message.error("两次输入的密码不一致");
return;
}
const changedFields = {};
const changedFields: Record<string, string> = {};
for (const key in values) {
if (values[key] !== user[key] && values[key] !== undefined) {
changedFields[key] = values[key];
@ -44,7 +49,10 @@ export default function UserDetail() {
}
delete changedFields.confirmPassword;
const newUser = await axiosInstance.put(`/user/${userId}`, changedFields);
const newUser = await axiosInstance.put<unknown, UserVo>(
`/user/${userId}`,
changedFields
);
setUser(newUser);
form.setFieldsValue(newUser);
message.success("修改成功");

View File

@ -10,21 +10,32 @@ import {
Select,
Space,
} from "antd";
import dayjs from "dayjs";
import dayjs, { Dayjs } from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import axiosInstance, { baseURL } from "../../api/axios";
import { selectUserId } from "../../features/auth/authSlice";
import { UserVo } from "types/model";
interface FormValue {
name: string;
phone: string;
team: string;
}
export default function DeviceDetailModal({ visiable, device, onclose }) {
const [unavailableTimes, setUnavailableTims] = useState([]);
const [unavailableTimes, setUnavailableTimes] = useState([]);
const [form] = Form.useForm();
const userId = useSelector((state) => state.auth.userId);
const userId = useSelector(selectUserId);
const [teams, setTeams] = useState([]);
const [initialValues, setInitialValues] = useState();
const [initialValues, setInitialValues] = useState<FormValue>();
const fetchTeams = async () => {
const data = await axiosInstance.get("/team-label");
const data = await axiosInstance.get<
unknown,
{ label: string; value: string }[]
>("/team-label");
const teams = data.map((item) => ({
label: item.label,
value: item.label,
@ -32,8 +43,10 @@ export default function DeviceDetailModal({ visiable, device, onclose }) {
setTeams(teams);
};
const fetchUser = async () => {
const data = await axiosInstance.get(`/userdetail/${userId}`);
const fetchUser = useCallback(async () => {
const data = await axiosInstance.get<unknown, UserVo>(
`/userdetail/${userId}`
);
const values = {
name: data.name,
phone: data.phone,
@ -41,7 +54,7 @@ export default function DeviceDetailModal({ visiable, device, onclose }) {
};
setInitialValues(values);
form.setFieldsValue(values);
};
}, [userId, form]);
useEffect(() => {
fetchTeams();
@ -49,20 +62,23 @@ export default function DeviceDetailModal({ visiable, device, onclose }) {
useEffect(() => {
const fetchUnavailableTimes = async (id) => {
const data = await axiosInstance.get(`/device/unavailable-times/${id}`);
setUnavailableTims(data);
const data = await axiosInstance.get<
unknown,
{ startTime: Date; endTime: Date }[]
>(`/device/unavailable-times/${id}`);
setUnavailableTimes(data);
};
if (visiable && device?.deviceId) {
fetchUnavailableTimes(device.deviceId);
fetchUser();
}
}, [visiable, device?.deviceId]);
}, [visiable, device?.deviceId, fetchUser]);
const { RangePicker } = DatePicker;
const disabledDate = (current, { from } = {}) => {
const disabledDate = (current: Dayjs, info: { from?: Dayjs } = {}) => {
if (!current) return false;
const { from } = info;
const today = dayjs().startOf("day");
const currentDay = current.startOf("day");

View File

@ -1,10 +1,24 @@
import { Table, Tag } from "antd";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import { useSelector } from "react-redux";
import Column from "antd/es/table/Column";
import dayjs from "dayjs";
import { selectUserId } from "../../features/auth/authSlice";
import { PageResult } from "types/common";
interface UserReservationVO {
reservationId: string;
deviceName: string;
startTime: Date;
endTime: Date;
statusLabel: string;
deviceLeaderName: string;
deviceLeaderContact: string;
deviceAdminName: string;
deviceAdminContact: string;
createdTime: Date;
}
export default function MyReservation() {
const [reservations, setReservations] = useState([]);
@ -16,23 +30,29 @@ export default function MyReservation() {
const userId = useSelector(selectUserId);
const fetchData = async (pagination) => {
const data = await axiosInstance.get(`/reservation/${userId}`, {
params: {
page: pagination.current,
size: pagination.pageSize,
},
});
setReservations(data.records);
setPagination({
...pagination,
total: data.total,
});
};
const fetchData = useCallback(
async (pagination) => {
const data = await axiosInstance.get<
unknown,
PageResult<UserReservationVO>
>(`/reservation/${userId}`, {
params: {
page: pagination.current,
size: pagination.pageSize,
},
});
setReservations(data.records);
setPagination({
...pagination,
total: data.total,
});
},
[userId]
);
useEffect(() => {
fetchData(pagination);
}, []);
}, [fetchData, pagination]);
const handlePageChange = (pagination) => {
fetchData(pagination);

View File

@ -1,8 +1,9 @@
import { Input, Space, Table, Tag } from "antd";
import Column from "antd/es/table/Column";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import axiosInstance from "../../api/axios";
import DeviceDetailModal from "./DeviceDetailModal";
import { PageResult } from "types/common";
const statusColorMap = {
: "green",
@ -11,6 +12,15 @@ const statusColorMap = {
: "gray",
};
interface DeviceVO {
deviceId: string;
name: string;
usageRequirement: string;
location: string;
imagePath: string;
state: string;
}
export default function Reserve() {
const [name, setName] = useState(null);
const [pagination, setPagination] = useState({
@ -20,24 +30,31 @@ export default function Reserve() {
});
const [devices, setDevices] = useState([]);
const fetchData = async (pagination, searchName = name) => {
const data = await axiosInstance.get("/device", {
params: {
page: pagination.current,
size: pagination.pageSize,
name: searchName,
},
});
const fetchData = useCallback(
async (pagination, searchName = name) => {
const data = await axiosInstance.get<unknown, PageResult<DeviceVO>>(
"/device",
{
params: {
page: pagination.current,
size: pagination.pageSize,
name: searchName,
},
}
);
setDevices(data.records);
setPagination({
...pagination,
total: data.total,
});
},
[name]
);
setDevices(data.records);
setPagination({
...pagination,
total: data.total,
});
};
useEffect(() => {
fetchData(pagination);
}, []);
}, [fetchData, pagination]);
const handlePageChange = (pagination) => {
fetchData(pagination);
@ -74,7 +91,7 @@ export default function Reserve() {
title="使用要求"
key="usageRequirement"
dataIndex="usageRequirement"
ellipsis="true"
ellipsis={true}
/>
<Column title="位置" key="location" dataIndex="location" />
<Column

7
src/types/axios.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
import "axios";
declare module "axios" {
export interface AxiosRequestConfig {
skipInterceptor?: boolean;
}
}

12
src/types/common.ts Normal file
View File

@ -0,0 +1,12 @@
export interface PageResult<T> {
records: T[];
total: number;
size: number;
current: number;
}
export interface Pagination {
current: number;
pageSize: number;
total?: number;
}

15
src/types/model.ts Normal file
View File

@ -0,0 +1,15 @@
export interface Team {
id: string;
name: string;
size: number;
}
export interface UserVo {
userId: string;
username: string;
team: string;
teamId?: string;
name: string;
phone: string;
roleId?: string;
}

1
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />