Przeglądaj źródła

✨ feat(classroom): add classroom data entity and schema

- 创建ClassroomData实体,包含教室号、训练日期等基本信息
- 定义ClassroomDataSchema数据验证模型
- 添加CreateClassroomDataDto和UpdateClassroomDataDto数据传输对象

✨ feat(submission): add submission records entity and schema

- 创建SubmissionRecords实体,记录用户提交的交易数据
- 定义SubmissionRecordsSchema数据验证模型
- 添加CreateSubmissionRecordsDto和UpdateSubmissionRecordsDto数据传输对象
- 包含成绩、收益金额、收益率等交易相关字段
yourname 5 miesięcy temu
rodzic
commit
b024517e75

+ 80 - 0
src/server/modules/classroom/classroom-data.entity.ts

@@ -0,0 +1,80 @@
+import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
+import { z } from '@hono/zod-openapi';
+
+@Entity('classroom_data')
+export class ClassroomData {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'classroom_no', type: 'varchar', length: 255, nullable: true, comment: '教室号' })
+  classroomNo!: string | null;
+
+  @Column({ name: 'training_date', type: 'timestamp', nullable: true, comment: '训练日期' })
+  trainingDate!: Date | null;
+
+  @Column({ name: 'holding_stock', type: 'varchar', length: 255, nullable: true, comment: '持股' })
+  holdingStock!: string | null;
+
+  @Column({ name: 'holding_cash', type: 'varchar', length: 255, nullable: true, comment: '持币' })
+  holdingCash!: string | null;
+
+  @Column({ name: 'price', type: 'varchar', length: 255, nullable: true, comment: '价格' })
+  price!: string | null;
+
+  @Column({ name: 'code', type: 'varchar', length: 255, nullable: true, comment: '代码' })
+  code!: string | null;
+
+  @Column({ name: 'status', type: 'varchar', length: 255, nullable: true, comment: '状态' })
+  status!: string | null;
+
+  @Column({ name: 'spare', type: 'varchar', length: 255, nullable: true, comment: '备用' })
+  spare!: string | null;
+
+  @Column({ name: 'submit_user', type: 'varchar', length: 255, nullable: true, comment: '提交用户' })
+  submitUser!: string | null;
+
+  @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
+  createdAt!: Date;
+
+  @Column({ name: 'updated_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' })
+  updatedAt!: Date;
+}
+
+export const ClassroomDataSchema = z.object({
+  id: z.number().int().positive().openapi({ description: '数据ID', example: 1 }),
+  classroomNo: z.string().max(255).nullable().openapi({ description: '教室号', example: 'test01' }),
+  trainingDate: z.date().nullable().openapi({ description: '训练日期', example: '2025-05-21T08:00:00Z' }),
+  holdingStock: z.string().max(255).nullable().openapi({ description: '持股', example: '100股' }),
+  holdingCash: z.string().max(255).nullable().openapi({ description: '持币', example: '10000元' }),
+  price: z.string().max(255).nullable().openapi({ description: '价格', example: '15.68' }),
+  code: z.string().max(255).nullable().openapi({ description: '代码', example: '001339' }),
+  status: z.string().max(255).nullable().openapi({ description: '状态', example: '1' }),
+  spare: z.string().max(255).nullable().openapi({ description: '备用', example: '' }),
+  submitUser: z.string().max(255).nullable().openapi({ description: '提交用户', example: '' }),
+  createdAt: z.date().openapi({ description: '创建时间', example: '2025-05-21T16:44:36Z' }),
+  updatedAt: z.date().openapi({ description: '更新时间', example: '2025-05-21T21:22:06Z' })
+});
+
+export const CreateClassroomDataDto = z.object({
+  classroomNo: z.string().max(255).nullable().openapi({ description: '教室号', example: 'test01' }),
+  trainingDate: z.date().nullable().openapi({ description: '训练日期', example: '2025-05-21T08:00:00Z' }),
+  holdingStock: z.string().max(255).nullable().openapi({ description: '持股', example: '100股' }),
+  holdingCash: z.string().max(255).nullable().openapi({ description: '持币', example: '10000元' }),
+  price: z.string().max(255).nullable().openapi({ description: '价格', example: '15.68' }),
+  code: z.string().max(255).nullable().openapi({ description: '代码', example: '001339' }),
+  status: z.string().max(255).nullable().openapi({ description: '状态', example: '1' }),
+  spare: z.string().max(255).nullable().openapi({ description: '备用', example: '' }),
+  submitUser: z.string().max(255).nullable().openapi({ description: '提交用户', example: '' })
+});
+
+export const UpdateClassroomDataDto = z.object({
+  classroomNo: z.string().max(255).nullable().openapi({ description: '教室号', example: 'test01' }),
+  trainingDate: z.date().nullable().openapi({ description: '训练日期', example: '2025-05-21T08:00:00Z' }),
+  holdingStock: z.string().max(255).nullable().openapi({ description: '持股', example: '100股' }),
+  holdingCash: z.string().max(255).nullable().openapi({ description: '持币', example: '10000元' }),
+  price: z.string().max(255).nullable().openapi({ description: '价格', example: '15.68' }),
+  code: z.string().max(255).nullable().openapi({ description: '代码', example: '001339' }),
+  status: z.string().max(255).nullable().openapi({ description: '状态', example: '1' }),
+  spare: z.string().max(255).nullable().openapi({ description: '备用', example: '' }),
+  submitUser: z.string().max(255).nullable().openapi({ description: '提交用户', example: '' })
+});

+ 116 - 0
src/server/modules/submission/submission-records.entity.ts

@@ -0,0 +1,116 @@
+import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
+import { z } from '@hono/zod-openapi';
+
+@Entity('submission_records')
+export class SubmissionRecords {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'classroom_no', type: 'varchar', length: 255, nullable: true, comment: '教室号' })
+  classroomNo!: string | null;
+
+  @Column({ name: 'user_id', type: 'varchar', length: 255, nullable: true, comment: '用户id' })
+  userId!: string | null;
+
+  @Column({ name: 'nickname', type: 'varchar', length: 255, nullable: true, comment: '昵称' })
+  nickname!: string | null;
+
+  @Column({ name: 'score', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '成绩' })
+  score!: number | null;
+
+  @Column({ name: 'code', type: 'varchar', length: 255, nullable: true, comment: '代码' })
+  code!: string | null;
+
+  @Column({ name: 'training_date', type: 'timestamp', nullable: true, comment: '训练日期' })
+  trainingDate!: Date | null;
+
+  @Column({ name: 'mark', type: 'varchar', length: 255, nullable: true, comment: '标记' })
+  mark!: string | null;
+
+  @Column({ name: 'status', type: 'int', nullable: true, comment: '状态' })
+  status!: number | null;
+
+  @Column({ name: 'holding_stock', type: 'varchar', length: 255, nullable: true, comment: '持股' })
+  holdingStock!: string | null;
+
+  @Column({ name: 'holding_cash', type: 'varchar', length: 255, nullable: true, comment: '持币' })
+  holdingCash!: string | null;
+
+  @Column({ name: 'price', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '价格' })
+  price!: number | null;
+
+  @Column({ name: 'profit_amount', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '收益金额' })
+  profitAmount!: number | null;
+
+  @Column({ name: 'profit_percent', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '收益率' })
+  profitPercent!: number | null;
+
+  @Column({ name: 'total_profit_amount', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '累计收益金额' })
+  totalProfitAmount!: number | null;
+
+  @Column({ name: 'total_profit_percent', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '累计收益率' })
+  totalProfitPercent!: number | null;
+
+  @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
+  createdAt!: Date;
+
+  @Column({ name: 'updated_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' })
+  updatedAt!: Date;
+}
+
+export const SubmissionRecordsSchema = z.object({
+  id: z.number().int().positive().openapi({ description: '数据ID', example: 1 }),
+  classroomNo: z.string().max(255).nullable().openapi({ description: '教室号', example: 'class01' }),
+  userId: z.string().max(255).nullable().openapi({ description: '用户id', example: '1001' }),
+  nickname: z.string().max(255).nullable().openapi({ description: '昵称', example: 'student1' }),
+  score: z.number().nullable().openapi({ description: '成绩', example: 95.5 }),
+  code: z.string().max(255).nullable().openapi({ description: '代码', example: '001339' }),
+  trainingDate: z.date().nullable().openapi({ description: '训练日期', example: '2025-05-21T08:00:00Z' }),
+  mark: z.string().max(255).nullable().openapi({ description: '标记', example: '优秀' }),
+  status: z.number().nullable().openapi({ description: '状态', example: 1 }),
+  holdingStock: z.string().max(255).nullable().openapi({ description: '持股', example: '100股' }),
+  holdingCash: z.string().max(255).nullable().openapi({ description: '持币', example: '10000元' }),
+  price: z.number().nullable().openapi({ description: '价格', example: 15.68 }),
+  profitAmount: z.number().nullable().openapi({ description: '收益金额', example: 500.00 }),
+  profitPercent: z.number().nullable().openapi({ description: '收益率', example: 5.25 }),
+  totalProfitAmount: z.number().nullable().openapi({ description: '累计收益金额', example: 2500.00 }),
+  totalProfitPercent: z.number().nullable().openapi({ description: '累计收益率', example: 12.5 }),
+  createdAt: z.date().openapi({ description: '创建时间', example: '2025-05-21T16:44:36Z' }),
+  updatedAt: z.date().openapi({ description: '更新时间', example: '2025-05-21T21:22:06Z' })
+});
+
+export const CreateSubmissionRecordsDto = z.object({
+  classroomNo: z.string().max(255).nullable().openapi({ description: '教室号', example: 'class01' }),
+  userId: z.string().max(255).nullable().openapi({ description: '用户id', example: '1001' }),
+  nickname: z.string().max(255).nullable().openapi({ description: '昵称', example: 'student1' }),
+  score: z.number().nullable().openapi({ description: '成绩', example: 95.5 }),
+  code: z.string().max(255).nullable().openapi({ description: '代码', example: '001339' }),
+  trainingDate: z.date().nullable().openapi({ description: '训练日期', example: '2025-05-21T08:00:00Z' }),
+  mark: z.string().max(255).nullable().openapi({ description: '标记', example: '优秀' }),
+  status: z.number().nullable().openapi({ description: '状态', example: 1 }),
+  holdingStock: z.string().max(255).nullable().openapi({ description: '持股', example: '100股' }),
+  holdingCash: z.string().max(255).nullable().openapi({ description: '持币', example: '10000元' }),
+  price: z.number().nullable().openapi({ description: '价格', example: 15.68 }),
+  profitAmount: z.number().nullable().openapi({ description: '收益金额', example: 500.00 }),
+  profitPercent: z.number().nullable().openapi({ description: '收益率', example: 5.25 }),
+  totalProfitAmount: z.number().nullable().openapi({ description: '累计收益金额', example: 2500.00 }),
+  totalProfitPercent: z.number().nullable().openapi({ description: '累计收益率', example: 12.5 })
+});
+
+export const UpdateSubmissionRecordsDto = z.object({
+  classroomNo: z.string().max(255).nullable().openapi({ description: '教室号', example: 'class01' }),
+  userId: z.string().max(255).nullable().openapi({ description: '用户id', example: '1001' }),
+  nickname: z.string().max(255).nullable().openapi({ description: '昵称', example: 'student1' }),
+  score: z.number().nullable().openapi({ description: '成绩', example: 95.5 }),
+  code: z.string().max(255).nullable().openapi({ description: '代码', example: '001339' }),
+  trainingDate: z.date().nullable().openapi({ description: '训练日期', example: '2025-05-21T08:00:00Z' }),
+  mark: z.string().max(255).nullable().openapi({ description: '标记', example: '优秀' }),
+  status: z.number().nullable().openapi({ description: '状态', example: 1 }),
+  holdingStock: z.string().max(255).nullable().openapi({ description: '持股', example: '100股' }),
+  holdingCash: z.string().max(255).nullable().openapi({ description: '持币', example: '10000元' }),
+  price: z.number().nullable().openapi({ description: '价格', example: 15.68 }),
+  profitAmount: z.number().nullable().openapi({ description: '收益金额', example: 500.00 }),
+  profitPercent: z.number().nullable().openapi({ description: '收益率', example: 5.25 }),
+  totalProfitAmount: z.number().nullable().openapi({ description: '累计收益金额', example: 2500.00 }),
+  totalProfitPercent: z.number().nullable().openapi({ description: '累计收益率', example: 12.5 })
+});