From ee1c5e73f8aa0ca82f46329dca3b038a7b7a20aa Mon Sep 17 00:00:00 2001 From: ggchinazhangwei <30527844+ggchinazhangwei@users.noreply.github.com> Date: Thu, 4 Dec 2025 11:46:24 +0800 Subject: [PATCH] Update index.tsx --- src/pages/user/index.tsx | 498 ++++++++++++++++++++++++++------------- 1 file changed, 328 insertions(+), 170 deletions(-) diff --git a/src/pages/user/index.tsx b/src/pages/user/index.tsx index 961f8f6..9a991a0 100644 --- a/src/pages/user/index.tsx +++ b/src/pages/user/index.tsx @@ -1,194 +1,352 @@ -import React, { useMemo, useState, useCallback } from "react"; -import { Controlled } from "react-codemirror2"; -import { Button, message } from "antd"; -import { saveAs } from "file-saver"; -import Logo from "@/assets/logo.png"; -import styles from "./index.less"; -import { isDev, useGetRect } from "utils/tool"; -import { SaveOutlined } from "@ant-design/icons"; -import { useHotkeys } from "react-hotkeys-hook"; -require("codemirror/mode/xml/xml"); -require("codemirror/mode/javascript/javascript"); +import React, { useMemo, useState, useCallback, useEffect } from "react"; +import { Button, message, Table, Space, Tag, Input, Modal, Form, Select } from "antd"; +import { SearchOutlined, PlusOutlined, EditOutlined, DeleteOutlined, SaveOutlined } from "@ant-design/icons"; +import type { ColumnsType } from "antd/es/table"; +import styles from "./index.module.less"; -const serverUrl = isDev ? "http://localhost:3000" : "http://localhost:3000"; +const { Search } = Input; +const { Option } = Select; -const defaultHtml = ` - - - - - Document - - - -
- -

- (H5编辑器)H5-Dooring是一款功能强大,开源免费的H5可视化页面配置解决方案, - 致力于提供一套简单方便、专业可靠、无限可能的H5落地页最佳实践。 -

-
- - -`; +interface UserData { + id: string; + username: string; + email: string; + phone: string; + status: "active" | "inactive" | "suspended"; + createTime: string; + lastLoginTime: string; +} -export default function CodeEditor() { - const [htmlContent, setHtmlContent] = useState(defaultHtml); - const [cursorPosition, setCursorPosition] = useState({ line: 1, ch: 1 }); - const [isUpdated, setIsUpdated] = useState(false); +const defaultUsers: UserData[] = [ + { + id: "1", + username: "admin", + email: "admin@example.com", + phone: "13800138000", + status: "active", + createTime: "2024-01-01 10:00:00", + lastLoginTime: "2024-01-15 14:30:00", + }, + { + id: "2", + username: "user001", + email: "user001@example.com", + phone: "13800138001", + status: "active", + createTime: "2024-01-02 11:00:00", + lastLoginTime: "2024-01-14 09:20:00", + }, + { + id: "3", + username: "user002", + email: "user002@example.com", + phone: "13800138002", + status: "inactive", + createTime: "2024-01-03 12:00:00", + lastLoginTime: "2024-01-10 16:45:00", + }, +]; - const rect = useGetRect(); +export default function UserPage() { + const [users, setUsers] = useState(defaultUsers); + const [loading, setLoading] = useState(false); + const [searchText, setSearchText] = useState(""); + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isModalVisible, setIsModalVisible] = useState(false); + const [editingUser, setEditingUser] = useState(null); + const [form] = Form.useForm(); - // 计算高度 - const contentHeight = useMemo(() => { - const baseHeight = rect.height - 42 - 1; // 减去顶部高度和滚动条防溢出 - return Math.max(baseHeight, 694); // 最小高度为 694 - }, [rect.height]); + // 过滤用户列表 + const filteredUsers = useMemo(() => { + if (!searchText) return users; + return users.filter( + (user) => + user.username.toLowerCase().includes(searchText.toLowerCase()) || + user.email.toLowerCase().includes(searchText.toLowerCase()) || + user.phone.includes(searchText) + ); + }, [users, searchText]); - const phoneHeight = 694; // 固定高度,避免大屏幕问题 - const iframeHeight = phoneHeight - 30 - 24; // 上边距 30,上下 padding 各 12 - - // 保存页面 - const savePage = useCallback( - (content?: string) => { - const contentToSave = content ?? htmlContent; - fetch(`${serverUrl}/dooring/render`, { - method: "POST", - body: contentToSave, - }).then(() => { - message.success("已保存"); - setIsUpdated((prev) => !prev); // 触发重新渲染 - }); - }, - [htmlContent] + // 表格列定义 + const columns: ColumnsType = useMemo( + () => [ + { + title: "用户名", + dataIndex: "username", + key: "username", + width: 150, + }, + { + title: "邮箱", + dataIndex: "email", + key: "email", + width: 200, + }, + { + title: "手机号", + dataIndex: "phone", + key: "phone", + width: 150, + }, + { + title: "状态", + dataIndex: "status", + key: "status", + width: 120, + render: (status: string) => { + const statusMap = { + active: { color: "green", text: "活跃" }, + inactive: { color: "default", text: "未激活" }, + suspended: { color: "red", text: "已暂停" }, + }; + const statusInfo = statusMap[status as keyof typeof statusMap] || statusMap.inactive; + return {statusInfo.text}; + }, + }, + { + title: "创建时间", + dataIndex: "createTime", + key: "createTime", + width: 180, + }, + { + title: "最后登录", + dataIndex: "lastLoginTime", + key: "lastLoginTime", + width: 180, + }, + { + title: "操作", + key: "action", + width: 200, + fixed: "right", + render: (_, record) => ( + + + + + ), + }, + ], + [] ); - // 下载 HTML 文件 - const downloadHtml = useCallback(() => { - const file = new File([htmlContent], `${Date.now()}.html`, { - type: "text/html;charset=utf-8", + // 编辑用户 + const handleEdit = useCallback((user: UserData) => { + setEditingUser(user); + form.setFieldsValue(user); + setIsModalVisible(true); + }, [form]); + + // 删除用户 + const handleDelete = useCallback((id: string) => { + Modal.confirm({ + title: "确认删除", + content: "确定要删除这个用户吗?", + onOk: () => { + setUsers((prev) => prev.filter((user) => user.id !== id)); + message.success("删除成功"); + }, }); - saveAs(file); - }, [htmlContent]); + }, []); - const downloadcss = useCallback(() => { - const file = new File([htmlContent], `${Date.now()}.html`, { - type: "text/css;charset=utf-8", - }); - saveAs(file); - }, [htmlContent]); - - // 快捷键保存 - useHotkeys( - "ctrl+s", - (event) => { - savePage(); - event.preventDefault(); - }, - [savePage] - ); - - // CodeMirror 编辑器事件处理 - const handleCodeChange = ( - _editor: CodeMirror.Editor, - _data: CodeMirror.EditorChange, - value: string - ) => { - setHtmlContent(value); - }; - - const handleCursorChange = ( - _editor: CodeMirror.Editor, - position: CodeMirror.Position - ) => { - setCursorPosition(position); - }; - - const handleEditorKeyDown = (editor: CodeMirror.Editor, event: KeyboardEvent) => { - if (event.ctrlKey && event.key === "s") { - savePage(editor.getValue()); - event.preventDefault(); + // 保存用户 + const handleSave = useCallback(async () => { + try { + const values = await form.validateFields(); + if (editingUser) { + // 更新用户 + setUsers((prev) => + prev.map((user) => + user.id === editingUser.id ? { ...user, ...values } : user + ) + ); + message.success("更新成功"); + } else { + // 新增用户 + const newUser: UserData = { + id: Date.now().toString(), + ...values, + createTime: new Date().toLocaleString("zh-CN"), + lastLoginTime: "-", + }; + setUsers((prev) => [...prev, newUser]); + message.success("创建成功"); + } + setIsModalVisible(false); + setEditingUser(null); + form.resetFields(); + } catch (error) { + console.error("表单验证失败:", error); } - }; + }, [editingUser, form]); - // CodeMirror 渲染 - const codeMirrorRender = useMemo(() => ( - - ), [htmlContent]); + // 取消编辑 + const handleCancel = useCallback(() => { + setIsModalVisible(false); + setEditingUser(null); + form.resetFields(); + }, [form]); + + // 批量删除 + const handleBatchDelete = useCallback(() => { + if (selectedRowKeys.length === 0) { + message.warning("请选择要删除的用户"); + return; + } + Modal.confirm({ + title: "确认删除", + content: `确定要删除选中的 ${selectedRowKeys.length} 个用户吗?`, + onOk: () => { + setUsers((prev) => prev.filter((user) => !selectedRowKeys.includes(user.id))); + setSelectedRowKeys([]); + message.success("删除成功"); + }, + }); + }, [selectedRowKeys]); + + // 行选择配置 + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; return (
{/* Header */}
-
-
- - Dooring-强大的h5编辑器 - -
-
| 在线代码编辑器
+
+

用户管理

+

可管理所有用户的账号信息

- - - -
-
- - {/* 内容区域 */} -
- {/* 代码编辑器 */} -
- {codeMirrorRender} -
- - {/* 预览区域 */} -
- + style={{ marginRight: "10px" }} + > + 新增用户 + +
+ + {/* 搜索栏 */} +
+ } + size="large" + value={searchText} + onChange={(e) => setSearchText(e.target.value)} + style={{ width: 400 }} + /> +
+ + {/* 表格区域 */} +
+ `共 ${total} 条`, + }} + /> + + + {/* 编辑/新增弹窗 */} + +
+ + + + + + + + + + + + + +
); -} \ No newline at end of file +} +