Przeglądaj źródła

✨ feat(classroom): 优化教室数据管理功能

- 状态字段UI优化:将输入框改为下拉选择器,支持"关闭"和"开放"选项
- 表格显示优化:状态值显示为中文文本而非数字
- 增加用户追踪:添加createdBy和updatedBy字段记录创建者和更新者ID
- 移除冗余字段:删除submitUser字段,使用系统自动记录的用户ID替代

💄 style(table): 优化表格样式

- 添加表格条纹样式,提升可读性
- 移除表头背景色设置,使用默认样式

♻️ refactor(api): 优化教室数据API配置

- 添加用户追踪配置,自动记录创建和更新用户
- 更新数据验证模式,移除submitUser相关配置
yourname 5 miesięcy temu
rodzic
commit
e25131be26

+ 17 - 19
src/client/admin/pages/ClassroomDataPage.tsx

@@ -1,11 +1,13 @@
 import React, { useState, useEffect } from 'react';
-import { Table, Button, Modal, Form, Input, DatePicker, Space, Typography, message } from 'antd';
+import { Table, Button, Modal, Form, Input, DatePicker, Space, Typography, message, Select } from 'antd';
 import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined } from '@ant-design/icons';
 import { classroomDataClient } from '@/client/api';
 import type { InferResponseType, InferRequestType } from 'hono/client';
 import { App } from 'antd';
 import dayjs from 'dayjs';
 
+const { Option } = Select;
+
 const { Title } = Typography;
 
 // 定义类型
@@ -89,9 +91,8 @@ export const ClassroomDataPage: React.FC = () => {
       holdingCash: record.holdingCash || undefined,
       price: record.price || undefined,
       code: record.code || undefined,
-      status: record.status || undefined,
+      status: record.status !== null ? record.status : undefined,
       spare: record.spare || undefined,
-      submitUser: record.submitUser || undefined,
     });
     setIsModalVisible(true);
   };
@@ -194,11 +195,13 @@ export const ClassroomDataPage: React.FC = () => {
       title: '状态',
       dataIndex: 'status',
       key: 'status',
-    },
-    {
-      title: '提交用户',
-      dataIndex: 'submitUser',
-      key: 'submitUser',
+      render: (status: number) => {
+        const statusMap = {
+          0: '关闭',
+          1: '开放'
+        };
+        return statusMap[status as keyof typeof statusMap] || '-';
+      },
     },
     {
       title: '操作',
@@ -259,7 +262,7 @@ export const ClassroomDataPage: React.FC = () => {
         onChange={(p) => setPagination({ ...pagination, current: p.current || 1, pageSize: p.pageSize || 10 })}
         bordered
         scroll={{ x: 'max-content' }}
-        headerCellStyle={{ backgroundColor: '#f9fafb' }}
+        className="ant-table-striped"
         rowClassName={(record, index) => index % 2 === 0 ? 'bg-white' : 'bg-gray-50'}
         rowKey="id"
       />
@@ -327,9 +330,12 @@ export const ClassroomDataPage: React.FC = () => {
           <Form.Item
             name="status"
             label="状态"
-            rules={[{ max: 255, message: '状态不能超过255个字符' }]}
+            rules={[{ required: true, message: '请选择状态' }]}
           >
-            <Input placeholder="请输入状态" />
+            <Select placeholder="请选择状态">
+              <Option value={0}>关闭</Option>
+              <Option value={1}>开放</Option>
+            </Select>
           </Form.Item>
           
           <Form.Item
@@ -339,14 +345,6 @@ export const ClassroomDataPage: React.FC = () => {
           >
             <Input placeholder="请输入备用信息" />
           </Form.Item>
-          
-          <Form.Item
-            name="submitUser"
-            label="提交用户"
-            rules={[{ max: 255, message: '提交用户不能超过255个字符' }]}
-          >
-            <Input placeholder="请输入提交用户" />
-          </Form.Item>
         </Form>
       </Modal>
     </div>

+ 5 - 1
src/server/api/classroom-data/index.ts

@@ -10,7 +10,11 @@ const classroomDataRoutes = createCrudRoutes({
   getSchema: ClassroomDataSchema,
   listSchema: ClassroomDataSchema,
   searchFields: ['classroomNo', 'code'],
-  middleware: [authMiddleware]
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
 });
 
 export default classroomDataRoutes;

+ 10 - 4
src/server/modules/classroom/classroom-data.entity.ts

@@ -45,6 +45,12 @@ export class ClassroomData {
   @Column({ name: 'submit_user', type: 'varchar', length: 255, nullable: true, comment: '提交用户' })
   submitUser!: string | null;
 
+  @Column({ name: 'created_by', type: 'int', nullable: true, comment: '创建用户ID' })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', nullable: true, comment: '更新用户ID' })
+  updatedBy!: number | null;
+
   @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
   createdAt!: Date;
 
@@ -63,6 +69,8 @@ export const ClassroomDataSchema = z.object({
   status: z.nativeEnum(ClassroomStatus).nullable().openapi({ description: '状态', example: ClassroomStatus.OPEN }),
   spare: z.string().max(255).nullable().openapi({ description: '备用', example: '' }),
   submitUser: z.string().max(255).nullable().openapi({ description: '提交用户', example: '' }),
+  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
+  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
   createdAt: z.date().openapi({ description: '创建时间', example: '2025-05-21T16:44:36Z' }),
   updatedAt: z.date().openapi({ description: '更新时间', example: '2025-05-21T21:22:06Z' })
 });
@@ -75,8 +83,7 @@ export const CreateClassroomDataDto = z.object({
   price: z.string().max(255).optional().nullable().openapi({ description: '价格', example: '15.68' }),
   code: z.string().max(255).optional().nullable().openapi({ description: '代码', example: '001339' }),
   status: z.nativeEnum(ClassroomStatus).optional().nullable().openapi({ description: '状态', example: ClassroomStatus.OPEN }),
-  spare: z.string().max(255).optional().nullable().openapi({ description: '备用', example: '' }),
-  submitUser: z.string().max(255).optional().nullable().openapi({ description: '提交用户', example: '' })
+  spare: z.string().max(255).optional().nullable().openapi({ description: '备用', example: '' })
 });
 
 export const UpdateClassroomDataDto = z.object({
@@ -87,6 +94,5 @@ export const UpdateClassroomDataDto = z.object({
   price: z.string().max(255).optional().nullable().openapi({ description: '价格', example: '15.68' }),
   code: z.string().max(255).optional().nullable().openapi({ description: '代码', example: '001339' }),
   status: z.nativeEnum(ClassroomStatus).optional().nullable().openapi({ description: '状态', example: ClassroomStatus.OPEN }),
-  spare: z.string().max(255).optional().nullable().openapi({ description: '备用', example: '' }),
-  submitUser: z.string().max(255).optional().nullable().openapi({ description: '提交用户', example: '' })
+  spare: z.string().max(255).optional().nullable().openapi({ description: '备用', example: '' })
 });