浏览代码

2025/11/17

quyx@nextosd.com 1 月之前
父节点
当前提交
d6c6345021

+ 5 - 0
new-react-admin-ui/src/App.tsx

@@ -6,6 +6,7 @@ import { ruoyiAuthProvider } from '@/adapters/ruoyiAuthProvider';
 import { LoginPage } from '@/pages/LoginPage';
 import { UserList } from '@/pages/users/UserList';
 import { LabelGenerationList } from '@/pages/generations/LabelGenerationList';
+import { usermanagementsList } from '@/pages/usermanagements/UserManagementsList';
 import { UserEdit } from '@/pages/users/UserEdit';
 import { UserCreate } from '@/pages/users/UserCreate';
 import { RoleList } from '@/pages/roles/RoleList';
@@ -75,6 +76,10 @@ export const App = () => {
           name="label/generations"
           list={LabelGenerationList}
         />
+         <Resource
+          name="label/usermanagements"
+          list={usermanagementsList}
+        />
         
         <CustomRoutes noLayout>
           <Route path="/error" element={<ErrorPage />} />

+ 27 - 0
new-react-admin-ui/src/adapters/ruoyiDataProvider.ts

@@ -399,6 +399,19 @@ export const ruoyiDataProvider: RuoyiDataProvider = {
           data: { ...params.data, id: data.data?.menuId || Date.now() },
         };
       }
+
+      case 'usermanagements': {
+        const requestData = {
+          ...params.data,
+        };
+        const data = await request<Result>(`/system/user`, {
+          method: 'POST',
+          body: JSON.stringify(requestData),
+        });
+        return {
+          data: { ...params.data, id: data.data?.userId || Date.now() },
+        };
+      }
       
 
       
@@ -455,6 +468,20 @@ export const ruoyiDataProvider: RuoyiDataProvider = {
           data: { ...params.data, id: params.data.menuId || params.id },
         };
       }
+
+      case 'usermanagements': {
+        const requestData = {
+          ...params.data,
+        };
+        await request<Result>(`/system/user`, {
+          method: 'PUT',
+          body: JSON.stringify(requestData),
+        });
+        // 确保返回的数据包含id字段
+        return {
+          data: { ...params.data, id: params.data.userId || params.id },
+        };
+      }
       
 
       

+ 0 - 5
new-react-admin-ui/src/pages/generations/LabelGenerationList.tsx

@@ -226,8 +226,6 @@ export const LabelGenerationList = () => {
       };
 
       const response = await dataProvider.getList('label/generations', {
-        pagination: { page: 1, perPage: 100 },
-        sort: { field: 'creationDate', order: 'DESC' },
         filter: queryParams
       });
 
@@ -522,9 +520,6 @@ export const LabelGenerationList = () => {
           rowData={rowData}
           columnDefs={columnDefs}
           domLayout="autoHeight"
-          suppressHorizontalScroll={false}
-          rowHeight={35}
-          headerHeight={35}
         />
       </div>
       

+ 446 - 0
new-react-admin-ui/src/pages/usermanagements/UserManagementsList.tsx

@@ -0,0 +1,446 @@
+"use client";
+import { useMemo, useState, useEffect } from "react";
+import { AgGridReact } from "ag-grid-react";
+import {
+  ClientSideRowModelModule,
+  ColDef,
+  ModuleRegistry,
+  ICellRendererParams,
+  SelectEditorModule,
+  CellStyleModule
+} from "ag-grid-community";
+import "ag-grid-community/styles/ag-theme-alpine.css";
+import { useDataProvider } from 'react-admin';
+
+// 注册必要的模块
+ModuleRegistry.registerModules([
+  ClientSideRowModelModule,
+  SelectEditorModule,
+  CellStyleModule
+]);
+
+export const usermanagementsList = () => {
+  const containerStyle = useMemo(() => ({
+    display: "flex",
+    alignItems: "flex-start",
+    gap: "30px",
+    width: "100%",
+    padding: "8px"
+  }), []);
+
+  const gridStyle = useMemo(() => ({ width: "50%" }), []);
+  const [rowData, setRowData] = useState<any[]>([]);
+  const [, setLoading] = useState<boolean>(true);
+  const [isEditing, setIsEditing] = useState(false);
+  const [isAdding, setIsAdding] = useState(false); 
+  const [editingData, setEditingData] = useState<any>({}); 
+  const [isDeleting, setIsDeleting] = useState<boolean>(false);
+
+  const dataProvider = useDataProvider();
+
+  // 初始化 CSS 样式
+  useEffect(() => {
+    const style = document.createElement('style');
+    style.textContent = `
+     .ag-theme-alpine .header-center .ag-header-cell-label {
+        justify-content: left !important;
+        text-align: center !important;
+      }
+
+      .ag-theme-alpine .header-center.ag-header-group-cell {
+        text-align: center !important;
+      }
+
+      .ag-theme-alpine .header-center.ag-header-group-cell .ag-header-group-cell-label {
+        justify-content: center !important;
+        display: flex !important;
+        width: 100% !important;
+      }
+
+      .ag-header-cell-resize:after {
+        display: none;
+      }
+      
+     .ag-theme-alpine .ag-cell {
+       border-right: 1px solid #dcdcdc;
+       text-align: center;
+       justify-content: left !important;
+     }
+     
+     .ag-theme-alpine .ag-header-cell {
+       border-right: 1px solid #dcdcdc;
+     }
+     
+     .line-group-header {
+       border-right: 1px solid #dcdcdc;
+     }
+     
+     .date-group-header {
+       border-right: 1px solid #dcdcdc !important;
+     }
+
+      /* 操作链接样式 */
+      .action-link {
+        color: #5b9bd5;
+        text-decoration: underline;
+        cursor: pointer;
+      }
+
+      .action-link:hover {
+        color: #004080;
+      }
+
+      /* 新规作成按钮样式 */
+      .new-button {
+        background-color: #000;
+        color: white;
+        border: none;
+        padding: 5px 20px;
+        cursor: pointer;
+        align-self: flex-start;
+      }
+
+      /* 标题样式 */
+      .page-title {
+        font-weight: bold; 
+        font-size: 16px;
+      }
+
+      .user-edit-section {
+        margin-top: 20px; 
+      }
+      .user-edit-title {
+        font-weight: bold;
+        margin-bottom: 8px;
+        display: block;
+        font-size: 16px;
+      }
+      .user-edit-section label {
+        display: inline-block;
+        width: 120px; 
+        background-color: #dcdcdc; 
+        text-align: left; 
+        border: 1px solid #999;
+      }
+      .user-edit-section input {
+        width: 300px;
+        padding: 4px;
+        box-sizing: border-box;
+        border: 1px solid #999;
+      }
+      .user-edit-buttons {
+        margin-top: 25px;
+      }
+      .user-edit-buttons button {
+        margin-right: 30px;
+        padding: 5px 20px;
+        border: none;
+        background-color: #000;
+        color: white;
+        cursor: pointer;
+      }
+      .issue-button {
+        background-color: #000;
+        color: white;
+        border: none;
+        padding: 5px 20px;
+        cursor: pointer;
+      }
+      .loading-indicator {
+        text-align: center;
+        padding: 20px;
+        font-size: 16px;
+      }
+    `;
+    document.head.appendChild(style);
+
+    return () => {
+      document.head.removeChild(style);
+    };
+  }, []);
+
+  // 获取用户列表数据
+  const fetchUserList = async () => {
+    setLoading(true);
+    try {
+      const response = await dataProvider.getList('users', {
+        filter: {}
+      });
+      
+      const formattedData = response.data.map((user: any) => ({
+        userId: user.userId || '',
+        password: user.password || '',
+        userName: user.userName || '',
+        id: user.id || user.userId 
+      }));
+      
+      setRowData(formattedData);
+    } catch (error) {
+      console.error("获取用户列表失败:", error);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  // 组件挂载时获取数据
+  useEffect(() => {
+    fetchUserList();
+  }, [dataProvider]);
+
+  // 编辑操作处理
+  const handleEdit = (data: any) => {
+    setIsEditing(true);
+    setIsAdding(false);
+    setEditingData({...data});
+  };
+
+  // 新增操作处理
+  const handleAdd = () => {
+    setIsAdding(true);
+    setIsEditing(false);
+    setEditingData({
+      userId: '',
+      userName: '',
+      password: ''
+    });
+  };
+
+  // 删除操作处理
+  const handleDelete = async (data: any) => {
+    if (isDeleting) return; 
+    
+    if (window.confirm(`确定要删除用户 ${data.userName} (${data.userId}) 吗?`)) {
+      setIsDeleting(true);
+      try {
+        await dataProvider.delete('users', {
+          id: data.id || data.userId,
+          previousData: data
+        });
+        setRowData(prev => prev.filter(row => row.userId !== data.userId));
+        alert("用户删除成功");
+      } catch (error) {
+        console.error("删除用户失败:", error);
+        alert("删除失败,请重试");
+      } finally {
+        setIsDeleting(false);
+      }
+    }
+  };
+
+  // 取消按钮处理
+  const handleCancel = () => {
+    setIsEditing(false);
+    setIsAdding(false);
+    setEditingData({});
+  };
+
+  // 保存按钮处理
+  const handleSave = async () => {
+    try {
+      const originalUser = rowData.find(row => row.userId === editingData.userId);
+      
+      if (!originalUser) {
+        alert("未找到用户信息");
+        return;
+      }
+
+      const updateParams = {
+        ...originalUser, 
+        ...editingData,
+        id: originalUser.id || originalUser.userId
+      };
+
+      await dataProvider.update('usermanagements', {
+        id: updateParams.id,
+        data: updateParams,
+        previousData: originalUser
+      });
+      
+      alert("用户信息更新成功");
+      setIsEditing(false);
+      fetchUserList(); 
+    } catch (error) {
+      console.error("更新用户失败:", error);
+      alert("更新失败,请重试");
+    }
+  };
+
+  // 保存新增用户
+  const handleAddSave = async () => {
+    try {
+      if (!editingData.userId || !editingData.userName || !editingData.password) {
+        alert("ユーザID、ユーザ名及びパスワードは必須です");
+        return;
+      }
+
+      const newUser = {
+        ...editingData,
+        nickName: editingData.userName,
+        userType: '0',
+        email: '',
+        phonenumber: '',
+        sex: '0',
+        avatar: '',
+        status: '0',
+        delFlag: '0',
+        loginIp: '',
+        createBy: '',
+        updateBy: '',
+        remark: '',
+        id: editingData.userId
+      };
+
+      await dataProvider.create('usermanagements', {
+        data: newUser
+      });
+      
+      alert("用户新增成功");
+      setIsAdding(false);
+      fetchUserList(); 
+    } catch (error) {
+      console.error("新增用户失败:", error);
+      alert("新增失败,请重试");
+    }
+  };
+
+  // 表格列定义
+   const columnDefs: ColDef[] = [
+    {
+      field: "userId",
+      headerClass: "header-center",
+      headerName: "ユーザID",
+      cellRenderer: (params: ICellRendererParams) => (
+        <div style={{ textAlign: 'left' }}>{params.value || ''}</div>
+      ),
+      flex: 1,
+      minWidth: 100,
+    },
+    {
+      field: "userName",
+      headerClass: "header-center",
+      headerName: "ユーザ名",
+      cellRenderer: (params: ICellRendererParams) => (
+        <div style={{ textAlign: 'left' }}>{params.value || ''}</div>
+      ),
+      flex: 1.5,
+      minWidth: 120,
+    },
+    {
+      field: "編集",
+      headerClass: "header-center",
+      headerName: "編集",
+      cellRenderer: (params: ICellRendererParams) => (
+        <div style={{ textAlign: 'left' }}>
+          <span className="action-link" onClick={() => handleEdit(params.data)}>編集</span>
+        </div>
+      ),
+      flex: 0.8,
+      minWidth: 80,
+    },
+    {
+      field: "削除",
+      headerClass: "header-center",
+      headerName: "削除",
+      cellRenderer: (params: ICellRendererParams) => (
+        <div style={{ textAlign: 'left' }}>
+          <span className="action-link" onClick={() => handleDelete(params.data)}>削除</span>
+        </div>
+      ),
+      flex: 0.8,
+      minWidth: 80,
+    },
+  ];
+
+  // 渲染部分
+  return (
+    <div>
+      {!isEditing && !isAdding && (
+        <>
+          <span className="page-title">ユーザ一覧</span>
+          <div style={containerStyle}>
+            <div className="ag-theme-alpine" style={gridStyle}>
+              <AgGridReact
+                rowData={rowData}
+                columnDefs={columnDefs}
+                domLayout="autoHeight"
+              />
+            </div>
+            <button className="new-button" onClick={handleAdd}>
+              新規作成
+            </button>
+          </div>
+        </>
+      )}
+      
+      {/* 编辑表单*/}
+      {isEditing && (
+        <div className="user-edit-section">
+          <span className="user-edit-title">ユーザ編集</span>
+          <label>ユーザID</label>
+          <input 
+              type="text" 
+              value={editingData.userId || ''}
+              onChange={(e) => setEditingData({...editingData, userId: e.target.value})}
+              disabled={!!editingData.userId}
+            />
+          <br/>
+          <label>ユーザ名</label>
+          <input 
+              type="text" 
+              value={editingData.userName || ''}
+              onChange={(e) => setEditingData({...editingData, userName: e.target.value})}
+            />
+          <br/>
+          <label>パスワード</label>
+          <input 
+              type="password" 
+              value={editingData.password || ''}
+              onChange={(e) => setEditingData({...editingData, password: e.target.value})}
+            />
+          <button className="issue-button" style={{ marginLeft: '30px' }}>発行</button>
+          <div className="user-edit-buttons">
+            <button onClick={handleCancel}>キャンセル</button>
+            <button onClick={handleSave}>保存</button>
+          </div>
+        </div>
+      )}
+      
+      {/* 新增表单*/}
+      {isAdding && (
+        <div className="user-edit-section">
+          <span className="user-edit-title">ユーザ編集</span>
+          <label>ユーザID</label>
+          <input 
+              type="text" 
+              value={editingData.userId || ''}
+              onChange={(e) => setEditingData({...editingData, userId: e.target.value})}
+              placeholder=""
+            />
+          <br/>
+          <label>ユーザ名</label>
+          <input 
+              type="text" 
+              value={editingData.userName || ''}
+              onChange={(e) => setEditingData({...editingData, userName: e.target.value})}
+              placeholder=""
+            />
+          <br/>
+          <label>パスワード</label>
+          <input 
+              type="text" 
+              value={editingData.password || ''}
+              onChange={(e) => setEditingData({...editingData, password: e.target.value})}
+              placeholder=""
+            />
+          <button className="issue-button" style={{ marginLeft: '30px' }}>発行</button>
+          <div className="user-edit-buttons">
+            <button onClick={handleCancel}>キャンセル</button>
+            <button onClick={handleAddSave}>保存</button>
+          </div>
+        </div>
+      )}
+    </div>
+  );
+};
+
+export default usermanagementsList;

+ 1 - 1
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -43,7 +43,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </sql>
     
     <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
-		select u.user_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark from sys_user u
+		select u.user_id, u.nick_name, u.user_name, u.email, u.avatar,u.password, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark from sys_user u
 		where u.del_flag = '0'
 		<if test="userId != null and userId != 0">
 			AND u.user_id = #{userId}