From eaee821e7271b85b80a25208a9f7da1bf7b36e21 Mon Sep 17 00:00:00 2001 From: Jim__TT <1820452084@qq.com> Date: Thu, 19 Oct 2023 02:13:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=94=90=E7=AE=80:=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=B1=95=E7=A4=BA=EF=BC=8C=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=EF=BC=8C=E5=88=86=E9=A1=B5=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 20 +- src/Login.tsx | 97 +++---- src/api/system/users.ts | 38 +++ src/api/user/userDept.ts | 8 - src/main.tsx | 24 +- src/utils/formatData.ts | 13 + .../user/comps/user-bottom-list/index.scss | 11 + .../user/comps/user-bottom-list/index.tsx | 212 ++++++++------- .../index.scss | 0 .../index.tsx | 28 +- .../user/comps/user-from-modal/index.scss | 3 + .../user/comps/user-from-modal/index.tsx | 244 ++++++++++++++++++ .../user/comps/user-mid-add-button/index.tsx | 12 +- .../user/comps/user-top-search/index.tsx | 95 ++++++- src/view/system/user/index.tsx | 43 ++- 15 files changed, 629 insertions(+), 219 deletions(-) create mode 100644 src/api/system/users.ts delete mode 100644 src/api/user/userDept.ts create mode 100644 src/utils/formatData.ts rename src/view/system/user/comps/{my-dept-tree => user-dept-tree}/index.scss (100%) rename src/view/system/user/comps/{my-dept-tree => user-dept-tree}/index.tsx (84%) create mode 100644 src/view/system/user/comps/user-from-modal/index.scss create mode 100644 src/view/system/user/comps/user-from-modal/index.tsx diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d6c9537..e4efcb5 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -2,17 +2,19 @@ module.exports = { root: true, env: { browser: true, es2020: true }, extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], rules: { - 'react-refresh/only-export-components': [ - 'warn', + "react-refresh/only-export-components": [ + "warn", { allowConstantExport: true }, ], + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-explicit-any": "off", }, -} +}; diff --git a/src/Login.tsx b/src/Login.tsx index 7932d0e..97081da 100644 --- a/src/Login.tsx +++ b/src/Login.tsx @@ -1,60 +1,59 @@ import { Button, Form, Input, Image, message } from "antd"; import React, { useEffect, useState } from "react"; -import './assets/styles/login.scss' +import "./assets/styles/login.scss"; import { getCaptchaApi, loginApi } from "./api/login"; import { useNavigate } from "react-router-dom"; import { setToken } from "./utils/auth"; type Login = { - uuid?: string, - username?: string, - password?: string, - code?: string -} + uuid?: string; + username?: string; + password?: string; + code?: string; +}; export default function Login() { - const [messageApi, contextHolder] = message.useMessage() - const [uuid, setUuid] = useState('') - const [captcha, setCaptcha] = useState('') - const navigate = useNavigate() + const [messageApi, contextHolder] = message.useMessage(); + const [uuid, setUuid] = useState(""); + const [captcha, setCaptcha] = useState(""); + const navigate = useNavigate(); const getCaptcha = async () => { try { - const { code, data } = await getCaptchaApi() + const { code, data } = await getCaptchaApi(); if (code === 1000) { - setUuid(data.uuid) - setCaptcha(data.img) + setUuid(data.uuid); + setCaptcha(data.img); } - } catch(err: any) { - messageApi.error(err) + } catch (err: any) { + messageApi.error(err); } - } + }; const handleLogin = async (values: Login) => { - values.uuid = uuid + values.uuid = uuid; try { - const { code, data, msg } = await loginApi(values) + const { code, data, msg } = await loginApi(values); if (code === 1000) { - setToken(data) - messageApi.success(msg) - navigate('/') - return + setToken(data); + messageApi.success(msg); + navigate("/"); + return; } - messageApi.error(msg) - getCaptcha() - } catch(err: any) { - messageApi.error(err) + messageApi.error(msg); + getCaptcha(); + } catch (err: any) { + messageApi.error(err); } - } + }; const handleLoginFailed = (errorInfo: any) => { console.log(errorInfo); - - } + }; useEffect(() => { - getCaptcha() - }, []) + getCaptcha(); + }, []); return (
{contextHolder} @@ -69,35 +68,41 @@ export default function Login() {

FateVerse

- label='用户名' - name='username' - rules={[{ required: true, message: '请输入用户名' }]} - initialValue='admin' + label="用户名" + name="username" + rules={[{ required: true, message: "请输入用户名" }]} + initialValue="admin" > - label='密码' - name='password' - rules={[{ required: true, message: '请输入密码' }]} - initialValue='123456' + label="密码" + name="password" + rules={[{ required: true, message: "请输入密码" }]} + initialValue="123456" > - label='验证码' - name='code' - rules={[{ required: true, message: '请输入验证码' }]} + label="验证码" + name="code" + rules={[{ required: true, message: "请输入验证码" }]} >
- +
- +
- ) -} \ No newline at end of file + ); +} diff --git a/src/api/system/users.ts b/src/api/system/users.ts new file mode 100644 index 0000000..58ac93d --- /dev/null +++ b/src/api/system/users.ts @@ -0,0 +1,38 @@ +import request from "../../utils/request"; + +interface userListParams { + userName?: string; + phoneNumber?: string; + state?: string; + startTime?: string; + endTime?: string; + pageNum?: number; + pageSize?: number; +} + +export const getDeptTreeApi = () => { + return request({ + url: "/admin/dept", + method: "get", + }); +}; + +export const getUserListApi = (data?: userListParams) => { + const params = data + ? { + userName: data.userName, + phoneNumber: data.phoneNumber, + state: data.state, + startTime: data.startTime, + endTime: data.endTime, + pageNum: data.pageNum, + pageSize: 13, + } + : undefined; + + return request({ + url: "/admin/user", + method: "get", + params, + }); +}; diff --git a/src/api/user/userDept.ts b/src/api/user/userDept.ts deleted file mode 100644 index d6d2939..0000000 --- a/src/api/user/userDept.ts +++ /dev/null @@ -1,8 +0,0 @@ -import request from "../../utils/request"; - -export const getDeptTree = () => { - return request({ - url: "/admin/dept", - method: "get", - }); -}; diff --git a/src/main.tsx b/src/main.tsx index 2f85134..fd8a0d7 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,21 +1,21 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.tsx' -import './index.css' -import { BrowserRouter } from 'react-router-dom' +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App.tsx"; +import "./index.css"; +import { BrowserRouter } from "react-router-dom"; // redux toolkit -import { Provider } from 'react-redux' -import store, { persistor } from './stores/index.ts' -import { PersistGate } from 'redux-persist/integration/react' -ReactDOM.createRoot(document.getElementById('root')!).render( +import { Provider } from "react-redux"; +import store, { persistor } from "./stores/index.ts"; +import { PersistGate } from "redux-persist/integration/react"; +ReactDOM.createRoot(document.getElementById("root")!).render( - + - , -) + +); diff --git a/src/utils/formatData.ts b/src/utils/formatData.ts new file mode 100644 index 0000000..f52325a --- /dev/null +++ b/src/utils/formatData.ts @@ -0,0 +1,13 @@ +export default function FormatData(DataStr: string) { + const dateStr = DataStr; + const date = new Date(dateStr); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + const hours = String(date.getHours()).padStart(2, "0"); + const minutes = String(date.getMinutes()).padStart(2, "0"); + const seconds = String(date.getSeconds()).padStart(2, "0"); + + const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + return formattedDate; +} diff --git a/src/view/system/user/comps/user-bottom-list/index.scss b/src/view/system/user/comps/user-bottom-list/index.scss index e69de29..fc6ac55 100644 --- a/src/view/system/user/comps/user-bottom-list/index.scss +++ b/src/view/system/user/comps/user-bottom-list/index.scss @@ -0,0 +1,11 @@ +.tree-content { + margin: 12px 0 0 12px; + + .ant-table-thead > tr > th { + color: #909399; + text-align: center; + } + .ant-table-tbody > tr > td { + text-align: center; + } +} diff --git a/src/view/system/user/comps/user-bottom-list/index.tsx b/src/view/system/user/comps/user-bottom-list/index.tsx index 2a9ad6a..97e12ee 100644 --- a/src/view/system/user/comps/user-bottom-list/index.tsx +++ b/src/view/system/user/comps/user-bottom-list/index.tsx @@ -1,88 +1,74 @@ -import React, { useState } from "react"; -import { Table, Space } from "antd"; +import React, { useState, useEffect } from "react"; +import { Table, Space, Tag } from "antd"; import { EditOutlined, DeleteOutlined } from "@ant-design/icons"; -const UserBottomList: React.FC = () => { - const [data, setData] = useState([ - { - key: 1, - projectId: "1", - projectName: "http接口管理平台", - create_time: "2023/7/22", - description: "一个用于统一管理", - interface_nums: 8, - member: [ - { - id: 1, - name: "Jim", - role: "阅读", - }, - { - id: 2, - name: "Jack", - role: "编辑", - }, - { - id: 3, - name: "Aurora", - role: "阅读", - }, - { - id: 4, - name: "Tom", - role: "编辑", - }, - ], - }, - { - key: 2, - projectId: "2", - projectName: "低代码平台", - create_time: "2021/3/2", - description: "更高效的开发", - interface_nums: 12, - member: [ - { - id: 1, - name: "qqq", - role: "阅读", - }, - { - id: 2, - name: "bbb", - role: "编辑", - }, - ], - }, - { - key: 3, - projectId: "3", - projectName: "ui组件库", - create_time: "2021/1/1", - description: "漂亮,简洁的ui组件", - interface_nums: 5, - member: [ - { - id: 1, - name: "111", - role: "阅读", - }, - { - id: 2, - name: "2222", - role: "编辑", - }, - { - id: 3, - name: "3333", - role: "阅读", - }, - ], - }, - ]); +import "./index.scss"; +import { getUserListApi } from "../../../../../api/system/users"; + +interface AddButtonClickType { + clickFromChild: (type: string) => void; + searchValues: any; +} +interface QueryParamsType { + userName?: string; + phoneNumber?: string; + state?: string; + startTime?: string; + endTime?: string; + pageNum?: number; + pageSize?: number; +} + +const UserBottomList: React.FC = ({ + clickFromChild, + searchValues, +}) => { + const [currentPage, setCurrentPage] = useState(1); + const [queryParams, setQueryParams] = useState({ + userName: undefined, + phoneNumber: undefined, + state: undefined, + startTime: undefined, + endTime: undefined, + pageNum: undefined, + pageSize: undefined, + }); + const handlePageChange = (page: number) => { + setCurrentPage(page); + setQueryParams({ + ...queryParams, + pageNum: page, + }); + }; + + const handleAddClick = () => { + clickFromChild("FIX"); + }; + + const getUserList = async () => { + try { + const { userName, phoneNumber, state, startTime, endTime } = searchValues; + setQueryParams({ + ...queryParams, + userName, + phoneNumber, + state, + startTime, + endTime, + }); + const { code, data } = await getUserListApi(queryParams); + if (code === 1000) { + setListData(data.rows); + } + } catch (err) { + console.error(err); + } + }; + + const [listData, setListData] = useState([]); const columns = [ { title: "序号", - dataIndex: "Id", + dataIndex: "userId", key: "Id", render: (text: string) => <>{text ? text : "null"}, }, @@ -94,14 +80,14 @@ const UserBottomList: React.FC = () => { }, { title: "用户昵称", - dataIndex: "name", - key: "name", + dataIndex: "nickName", + key: "nikeName", render: (text: string) => <>{text ? text : "null"}, }, { title: "部门", - key: "dept", - dataIndex: "dept", + key: "deptName", + dataIndex: "deptName", render: (text: string) => <>{text ? text : "null"}, }, { @@ -114,7 +100,15 @@ const UserBottomList: React.FC = () => { title: "状态", key: "state", dataIndex: "state", - render: (text: string) => <>{text ? text : "null"}, + render: (text: string) => ( + <> + {text === "0" ? ( + 停用 + ) : ( + 正常 + )} + + ), }, { title: "创建时间", @@ -127,39 +121,43 @@ const UserBottomList: React.FC = () => { key: "operate", dataIndex: "operate", render: () => ( - <> + ), }, ]; + useEffect(() => { + getUserList(); + console.log(searchValues); + }, [searchValues]); + return ( -
+
({ - // onClick: () => { - // // 在这里编写处理点击事件的代码 - // serActiveRowIndex(record.key); - // eventBus.emit("tableRowClick", record); - // }, - // // 根据条件动态设置行样式 - // style: - // activeRowIndex === record.key - // ? { backgroundColor: "#e1eaff" } - // : null, - // })} + pagination={{ + onChange: handlePageChange, + showQuickJumper: true, + showTotal: (total, range) => + `第 ${range[0]}-${range[1]} 条,共 ${total} 条`, + }} /> ); diff --git a/src/view/system/user/comps/my-dept-tree/index.scss b/src/view/system/user/comps/user-dept-tree/index.scss similarity index 100% rename from src/view/system/user/comps/my-dept-tree/index.scss rename to src/view/system/user/comps/user-dept-tree/index.scss diff --git a/src/view/system/user/comps/my-dept-tree/index.tsx b/src/view/system/user/comps/user-dept-tree/index.tsx similarity index 84% rename from src/view/system/user/comps/my-dept-tree/index.tsx rename to src/view/system/user/comps/user-dept-tree/index.tsx index 8bc4766..92982a6 100644 --- a/src/view/system/user/comps/my-dept-tree/index.tsx +++ b/src/view/system/user/comps/user-dept-tree/index.tsx @@ -1,19 +1,24 @@ import React, { useMemo, useState, useEffect } from "react"; import { Input, Tree } from "antd"; import { SearchOutlined } from "@ant-design/icons"; +import { getDeptTreeApi } from "../../../../../api/system/users"; import "./index.scss"; -interface treeDataType { - myTreeData: any[]; -} - -const MyDeptTree: React.FC = (props) => { - console.log("props:", props.myTreeData[0]); - +const MyDeptTree: React.FC = () => { const [expandedKeys, setExpandedKeys] = useState([]); const [searchValue, setSearchValue] = useState(""); const [autoExpandParent, setAutoExpandParent] = useState(true); + const [myData, setMyData] = useState([]); + const getDeptTreeData = async () => { + try { + const res = await getDeptTreeApi(); + setMyData(res.data); + } catch (error) { + console.error(error); + } + }; + const onExpand = (newExpandedKeys: React.Key[]) => { setExpandedKeys(newExpandedKeys); setAutoExpandParent(false); @@ -57,15 +62,16 @@ const MyDeptTree: React.FC = (props) => { if (item.children) { return { title, key: item.deptId, children: loop(item.children) }; } - return { title, key: item.key, }; }); - - return loop(props.myTreeData); - }, [searchValue]); + return loop(myData); + }, [myData]); + useEffect(() => { + getDeptTreeData(); + }, []); return (
diff --git a/src/view/system/user/comps/user-from-modal/index.scss b/src/view/system/user/comps/user-from-modal/index.scss new file mode 100644 index 0000000..e93ce17 --- /dev/null +++ b/src/view/system/user/comps/user-from-modal/index.scss @@ -0,0 +1,3 @@ +.modal-form { + display: flex; +} diff --git a/src/view/system/user/comps/user-from-modal/index.tsx b/src/view/system/user/comps/user-from-modal/index.tsx new file mode 100644 index 0000000..747351a --- /dev/null +++ b/src/view/system/user/comps/user-from-modal/index.tsx @@ -0,0 +1,244 @@ +import { + Modal, + Button, + Form, + Input, + Row, + Col, + Select, + TreeSelect, + Radio, +} from "antd"; +import type { RadioChangeEvent } from "antd"; +import React, { useEffect, useState } from "react"; +import { getDeptTreeApi } from "../../../../../api/system/users"; + +interface ShowModal { + isShowModal: boolean; + clickFromChild: () => void; + modalTitle: string; +} +type FieldType = { + username?: string; + password?: string; + remember?: string; +}; + +const UserFromModal: React.FC = (props) => { + const [deptList, setDeptList] = useState(); + const [value, setValue] = useState(); + const fieldNames = { + label: "deptName", + title: "deptName", + value: "deptName", + key: "deptName", + }; // 用于自定义TreeSelect内容 + + const getDeptTreeData = async () => { + try { + const res = await getDeptTreeApi(); + setDeptList(res.data); + } catch (error) { + console.error(error); + } + }; + + const onChange = (newValue: string) => { + setValue(newValue); + }; + + const handleOk = () => { + props.clickFromChild(); + }; + + const handleCancel = () => { + props.clickFromChild(); + }; + + const onFinish = (values: any) => { + console.log("Success:", values); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log("Failed:", errorInfo); + }; + const [radioValue, setRadioValue] = useState(1); + + const onRadioChange = (e: RadioChangeEvent) => { + setRadioValue(e.target.value); + }; + + useEffect(() => { + getDeptTreeData(); + }, []); + + return ( + <> + +
+ +
+ + label="用户名称" + name="用户名称" + rules={[{ required: true, message: "请输入用户名称" }]} + > + + + + + + label="用户昵称" + name="用户昵称" + rules={[{ required: true, message: "请输入用户昵称" }]} + > + + + + + + label="用户性别" + name="用户性别" + rules={[{ required: false }]} + > + + + + + + label="邮箱" + name="邮箱" + rules={[{ required: false }]} + > + + + + + + label="状态" + name="状态" + rules={[ + { required: false, message: "Please input your password!" }, + ]} + > + + 正常 + 停用 + + + + + + label="岗位" + name="岗位" + rules={[ + { required: false, message: "Please input your password!" }, + ]} + > + + + + + + label="备注" + labelCol={{ span: 3 }} + name="备注" + rules={[ + { required: false, message: "Please input your password!" }, + ]} + > + + + + + + + + ); +}; + +export default UserFromModal; diff --git a/src/view/system/user/comps/user-mid-add-button/index.tsx b/src/view/system/user/comps/user-mid-add-button/index.tsx index 2205c52..ee9b636 100644 --- a/src/view/system/user/comps/user-mid-add-button/index.tsx +++ b/src/view/system/user/comps/user-mid-add-button/index.tsx @@ -3,10 +3,18 @@ import { Button } from "antd"; import { PlusOutlined } from "@ant-design/icons"; import "./index.scss"; -const UserMidAddButton: React.FC = () => { +interface AddButtonClick { + clickFromChild: (type: string) => void; +} + +const UserMidAddButton: React.FC = ({ clickFromChild }) => { + const handleAddClick = () => { + clickFromChild("ADD"); + }; + return (
- diff --git a/src/view/system/user/comps/user-top-search/index.tsx b/src/view/system/user/comps/user-top-search/index.tsx index d71c0c2..94ea529 100644 --- a/src/view/system/user/comps/user-top-search/index.tsx +++ b/src/view/system/user/comps/user-top-search/index.tsx @@ -1,20 +1,85 @@ -import React from "react"; +import React, { useState, useEffect, Children } from "react"; import "./index.scss"; -import { Input, Select, TimePicker, Button } from "antd"; +import { Input, Select, DatePicker, Button } from "antd"; import { SearchOutlined, RedoOutlined } from "@ant-design/icons"; +import FormatData from "../../../../../utils/formatData"; + +interface SearchParamsType { + userName?: string; + phoneNumber?: number; + state?: string; + startTime?: string; + endTime?: string; +} + +interface SearchClick { + clickFromChild: (searchValues: any) => void; +} + +const UserTopSearch: React.FC = ({ clickFromChild }) => { + const [searchValues, setSearchValues] = useState({ + userName: undefined, + phoneNumber: undefined, + state: undefined, + startTime: undefined, + endTime: undefined, + }); + + const handleTimePikerValue = (dates: any[]) => { + setSearchValues({ + ...searchValues, + startTime: FormatData(dates[0].$d), + endTime: FormatData(dates[1].$d), + }); + }; + + const handleInputValues = (e: any) => { + const { name, value } = e.target; + console.log(value); + + setSearchValues({ ...searchValues, [name]: value }); + }; + + const handleSearch = () => { + clickFromChild(searchValues); + }; + const handleReset = () => { + clickFromChild(null); + setSearchValues({ + ...searchValues, + userName: undefined, + phoneNumber: undefined, + state: undefined, + startTime: undefined, + endTime: undefined, + }); + }; + + useEffect(() => { + console.log(searchValues); + }, [searchValues]); -const UserTopSearch: React.FC = () => { return (
用户名称
- +
手机号码
- +
状态
@@ -23,27 +88,37 @@ const UserTopSearch: React.FC = () => { placeholder="用户状态" allowClear options={[ - { value: "正常1", label: "正常" }, - { value: "停用1", label: "停用" }, + { value: "1", label: "正常" }, + { value: "0", label: "停用" }, ]} + value={searchValues.state} + onChange={(value: any) => + setSearchValues({ + ...searchValues, + state: value, + }) + } />
创建时间
- { + handleTimePikerValue(dates as any); + }} />
-
-
+