@nest-omni/core 4.1.3-11 → 4.1.3-12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/audit/audit.module.js +17 -0
  2. package/audit/controllers/audit.controller.d.ts +64 -0
  3. package/audit/controllers/audit.controller.js +50 -0
  4. package/audit/decorators/audit-action.decorator.d.ts +74 -0
  5. package/audit/decorators/audit-action.decorator.js +42 -0
  6. package/audit/decorators/entity-audit.decorator.d.ts +10 -1
  7. package/audit/decorators/entity-audit.decorator.js +34 -16
  8. package/audit/decorators/index.d.ts +1 -0
  9. package/audit/decorators/index.js +1 -0
  10. package/audit/entities/audit-action-summary.entity.d.ts +23 -0
  11. package/audit/entities/audit-action-summary.entity.js +101 -0
  12. package/audit/entities/entity-audit-log.entity.d.ts +3 -0
  13. package/audit/entities/entity-audit-log.entity.js +25 -2
  14. package/audit/entities/entity-transaction.entity.d.ts +3 -4
  15. package/audit/entities/entity-transaction.entity.js +10 -3
  16. package/audit/entities/index.d.ts +1 -0
  17. package/audit/entities/index.js +1 -0
  18. package/audit/entities/manual-operation-log.entity.js +8 -1
  19. package/audit/enums/audit.enums.d.ts +1 -10
  20. package/audit/enums/audit.enums.js +7 -17
  21. package/audit/index.d.ts +2 -1
  22. package/audit/index.js +5 -1
  23. package/audit/interceptors/audit-action.interceptor.d.ts +38 -0
  24. package/audit/interceptors/audit-action.interceptor.js +215 -0
  25. package/audit/interceptors/index.d.ts +1 -0
  26. package/audit/interceptors/index.js +1 -0
  27. package/audit/interfaces/audit.interfaces.d.ts +10 -5
  28. package/audit/services/audit-action.service.d.ts +141 -0
  29. package/audit/services/audit-action.service.js +244 -0
  30. package/audit/services/audit-context.service.d.ts +82 -0
  31. package/audit/services/audit-context.service.js +170 -0
  32. package/audit/services/entity-audit.service.d.ts +104 -3
  33. package/audit/services/entity-audit.service.js +306 -9
  34. package/audit/services/index.d.ts +1 -0
  35. package/audit/services/index.js +1 -0
  36. package/audit/services/manual-audit-log.service.d.ts +24 -23
  37. package/audit/services/manual-audit-log.service.js +32 -53
  38. package/audit/services/operation-description.service.d.ts +13 -3
  39. package/audit/services/operation-description.service.js +161 -24
  40. package/audit/services/transaction-audit.service.js +3 -3
  41. package/audit/subscribers/entity-audit.subscriber.d.ts +4 -0
  42. package/audit/subscribers/entity-audit.subscriber.js +47 -0
  43. package/file-upload/controllers/file-access.controller.d.ts +23 -0
  44. package/file-upload/controllers/file-access.controller.js +128 -0
  45. package/file-upload/decorators/csv-data.decorator.d.ts +44 -0
  46. package/file-upload/decorators/csv-data.decorator.js +131 -0
  47. package/file-upload/decorators/excel-data.decorator.d.ts +44 -0
  48. package/file-upload/decorators/excel-data.decorator.js +125 -0
  49. package/file-upload/decorators/file-upload.decorator.d.ts +83 -0
  50. package/file-upload/decorators/file-upload.decorator.js +172 -0
  51. package/file-upload/decorators/index.d.ts +4 -0
  52. package/file-upload/decorators/index.js +20 -0
  53. package/file-upload/decorators/process.decorator.d.ts +40 -0
  54. package/file-upload/decorators/process.decorator.js +52 -0
  55. package/file-upload/dto/create-file.dto.d.ts +24 -0
  56. package/file-upload/dto/create-file.dto.js +112 -0
  57. package/file-upload/dto/find-files.dto.d.ts +15 -0
  58. package/file-upload/dto/find-files.dto.js +76 -0
  59. package/file-upload/dto/index.d.ts +4 -0
  60. package/file-upload/dto/index.js +20 -0
  61. package/file-upload/dto/pagination.dto.d.ts +7 -0
  62. package/file-upload/dto/pagination.dto.js +39 -0
  63. package/file-upload/dto/update-file.dto.d.ts +16 -0
  64. package/file-upload/dto/update-file.dto.js +71 -0
  65. package/file-upload/entities/file-metadata.entity.d.ts +22 -0
  66. package/file-upload/entities/file-metadata.entity.js +84 -0
  67. package/file-upload/entities/file.entity.d.ts +129 -0
  68. package/file-upload/entities/file.entity.js +384 -0
  69. package/file-upload/entities/index.d.ts +2 -0
  70. package/file-upload/entities/index.js +18 -0
  71. package/file-upload/enums/file-type.enum.d.ts +72 -0
  72. package/file-upload/enums/file-type.enum.js +212 -0
  73. package/file-upload/exceptions/file-upload.exception.d.ts +57 -0
  74. package/file-upload/exceptions/file-upload.exception.js +120 -0
  75. package/file-upload/exceptions/index.d.ts +1 -0
  76. package/file-upload/exceptions/index.js +17 -0
  77. package/file-upload/file-upload.module.d.ts +89 -0
  78. package/file-upload/file-upload.module.js +264 -0
  79. package/file-upload/index.d.ts +26 -0
  80. package/file-upload/index.js +59 -0
  81. package/file-upload/interceptors/file-upload.interceptor.d.ts +48 -0
  82. package/file-upload/interceptors/file-upload.interceptor.js +434 -0
  83. package/file-upload/interceptors/index.d.ts +1 -0
  84. package/file-upload/interceptors/index.js +17 -0
  85. package/file-upload/interfaces/custom-file-type.interface.d.ts +72 -0
  86. package/file-upload/interfaces/custom-file-type.interface.js +2 -0
  87. package/file-upload/interfaces/file-buffer.interface.d.ts +72 -0
  88. package/file-upload/interfaces/file-buffer.interface.js +2 -0
  89. package/file-upload/interfaces/file-entity.interface.d.ts +142 -0
  90. package/file-upload/interfaces/file-entity.interface.js +28 -0
  91. package/file-upload/interfaces/file-metadata.interface.d.ts +21 -0
  92. package/file-upload/interfaces/file-metadata.interface.js +2 -0
  93. package/file-upload/interfaces/file-upload-options.interface.d.ts +117 -0
  94. package/file-upload/interfaces/file-upload-options.interface.js +2 -0
  95. package/file-upload/interfaces/index.d.ts +7 -0
  96. package/file-upload/interfaces/index.js +24 -0
  97. package/file-upload/interfaces/storage-provider.interface.d.ts +239 -0
  98. package/file-upload/interfaces/storage-provider.interface.js +2 -0
  99. package/file-upload/interfaces/upload-options.interface.d.ts +19 -0
  100. package/file-upload/interfaces/upload-options.interface.js +2 -0
  101. package/file-upload/providers/index.d.ts +2 -0
  102. package/file-upload/providers/index.js +18 -0
  103. package/file-upload/providers/local-storage.provider.d.ts +98 -0
  104. package/file-upload/providers/local-storage.provider.js +484 -0
  105. package/file-upload/providers/s3-storage.provider.d.ts +87 -0
  106. package/file-upload/providers/s3-storage.provider.js +455 -0
  107. package/file-upload/services/file-signature-validator.service.d.ts +118 -0
  108. package/file-upload/services/file-signature-validator.service.js +376 -0
  109. package/file-upload/services/file.service.d.ts +190 -0
  110. package/file-upload/services/file.service.js +609 -0
  111. package/file-upload/services/index.d.ts +4 -0
  112. package/file-upload/services/index.js +20 -0
  113. package/file-upload/services/malicious-file-detector.service.d.ts +274 -0
  114. package/file-upload/services/malicious-file-detector.service.js +1035 -0
  115. package/file-upload/services/mime-registry.service.d.ts +47 -0
  116. package/file-upload/services/mime-registry.service.js +167 -0
  117. package/file-upload/utils/checksum.util.d.ts +28 -0
  118. package/file-upload/utils/checksum.util.js +65 -0
  119. package/file-upload/utils/dynamic-import.util.d.ts +50 -0
  120. package/file-upload/utils/dynamic-import.util.js +144 -0
  121. package/file-upload/utils/filename.util.d.ts +59 -0
  122. package/file-upload/utils/filename.util.js +184 -0
  123. package/file-upload/utils/filepath.util.d.ts +70 -0
  124. package/file-upload/utils/filepath.util.js +152 -0
  125. package/file-upload/utils/index.d.ts +4 -0
  126. package/file-upload/utils/index.js +20 -0
  127. package/index.d.ts +3 -1
  128. package/index.js +4 -1
  129. package/package.json +4 -5
  130. package/setup/bootstrap.setup.d.ts +1 -0
  131. package/setup/bootstrap.setup.js +1 -0
  132. package/shared/index.d.ts +1 -1
  133. package/shared/index.js +1 -1
  134. package/shared/{serviceRegistryModule.js → service-registry.module.js} +0 -12
  135. package/shared/services/index.d.ts +0 -1
  136. package/shared/services/index.js +0 -1
  137. package/transaction/__tests__/mocks.d.ts +9 -0
  138. package/transaction/__tests__/mocks.js +33 -0
  139. package/transaction/base-service-transaction.d.ts +99 -0
  140. package/transaction/base-service-transaction.js +286 -0
  141. package/transaction/cls-compatibility.service.d.ts +55 -0
  142. package/transaction/cls-compatibility.service.js +127 -0
  143. package/transaction/data-source-registry.d.ts +91 -0
  144. package/transaction/data-source-registry.js +349 -0
  145. package/transaction/database-adapter.d.ts +44 -0
  146. package/transaction/database-adapter.js +240 -0
  147. package/transaction/decorators/entity-datasource.decorator.d.ts +62 -0
  148. package/transaction/decorators/entity-datasource.decorator.js +105 -0
  149. package/transaction/index.d.ts +14 -0
  150. package/transaction/index.js +57 -0
  151. package/transaction/logging-transactional.interceptor.d.ts +18 -0
  152. package/transaction/logging-transactional.interceptor.js +163 -0
  153. package/transaction/transaction-context.service.d.ts +137 -0
  154. package/transaction/transaction-context.service.js +411 -0
  155. package/transaction/transaction-manager.d.ts +230 -0
  156. package/transaction/transaction-manager.js +1001 -0
  157. package/transaction/transaction-synchronization.d.ts +171 -0
  158. package/transaction/transaction-synchronization.js +380 -0
  159. package/transaction/transaction.errors.d.ts +91 -0
  160. package/transaction/transaction.errors.js +206 -0
  161. package/transaction/transaction.module.d.ts +30 -0
  162. package/transaction/transaction.module.js +98 -0
  163. package/transaction/transactional.decorator.d.ts +82 -0
  164. package/transaction/transactional.decorator.js +319 -0
  165. package/transaction/typeorm-module-wrapper.d.ts +96 -0
  166. package/transaction/typeorm-module-wrapper.js +197 -0
  167. package/validators/file-mimetype.validator.d.ts +0 -2
  168. package/validators/file-mimetype.validator.js +4 -6
  169. package/validators/is-exists.validator.d.ts +2 -5
  170. package/validators/is-exists.validator.js +4 -6
  171. package/validators/is-unique.validator.d.ts +2 -5
  172. package/validators/is-unique.validator.js +6 -11
  173. package/shared/services/validator.service.d.ts +0 -3
  174. package/shared/services/validator.service.js +0 -20
  175. /package/shared/{serviceRegistryModule.d.ts → service-registry.module.d.ts} +0 -0
@@ -32,11 +32,12 @@ const audit_context_service_1 = require("./audit-context.service");
32
32
  const audit_strategy_service_1 = require("./audit-strategy.service");
33
33
  const multi_database_service_1 = require("./multi-database.service");
34
34
  const dto_1 = require("../../common/dto");
35
+ const entity_audit_decorator_1 = require("../decorators/entity-audit.decorator");
35
36
  /**
36
37
  * 实体审计服务
37
38
  */
38
39
  let EntityAuditService = class EntityAuditService {
39
- constructor(auditLogRepository, transactionRepository, manualOperationRepository, entityManager, contextService, multiDbService, auditStrategy = new audit_strategy_service_1.DefaultAuditStrategy(), config, auditConnectionName) {
40
+ constructor(auditLogRepository, transactionRepository, manualOperationRepository, entityManager, contextService, multiDbService, auditStrategy = new audit_strategy_service_1.DefaultAuditStrategy(), config, auditConnectionName, actionSummaryRepository) {
40
41
  this.auditLogRepository = auditLogRepository;
41
42
  this.transactionRepository = transactionRepository;
42
43
  this.manualOperationRepository = manualOperationRepository;
@@ -45,6 +46,7 @@ let EntityAuditService = class EntityAuditService {
45
46
  this.multiDbService = multiDbService;
46
47
  this.auditStrategy = auditStrategy;
47
48
  this.config = config;
49
+ this.actionSummaryRepository = actionSummaryRepository;
48
50
  this.auditConnectionName = auditConnectionName || 'default';
49
51
  }
50
52
  /**
@@ -90,6 +92,10 @@ let EntityAuditService = class EntityAuditService {
90
92
  hashChain: ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.security) === null || _b === void 0 ? void 0 : _b.hashChainEnabled)
91
93
  ? yield this.generateHashChain(entityType, entityId, filteredNewValue)
92
94
  : undefined,
95
+ // 新增:审计动作关联字段
96
+ auditActionId: metadata.auditActionId,
97
+ auditActionName: metadata.auditActionName,
98
+ sequenceInAction: metadata.sequenceInAction || 0,
93
99
  });
94
100
  // 保存变更日志
95
101
  const savedLog = yield this.auditLogRepository.save(auditLog);
@@ -338,7 +344,7 @@ let EntityAuditService = class EntityAuditService {
338
344
  /**
339
345
  * 深度差异比较
340
346
  */
341
- deepDiff(oldObj, newObj, path = []) {
347
+ deepDiff(oldObj, newObj, path = [], visited = new WeakSet()) {
342
348
  var _a;
343
349
  const changes = [];
344
350
  const maxDepth = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.maxDiffDepth) || 5;
@@ -358,6 +364,19 @@ let EntityAuditService = class EntityAuditService {
358
364
  }
359
365
  return changes;
360
366
  }
367
+ // 检测循环引用
368
+ if (visited.has(oldObj)) {
369
+ // 检测到循环引用,停止递归
370
+ return changes;
371
+ }
372
+ visited.add(oldObj);
373
+ // 如果newObj也是对象,也加入访问集合
374
+ if (typeof newObj === 'object' && newObj !== null) {
375
+ if (visited.has(newObj)) {
376
+ return changes;
377
+ }
378
+ visited.add(newObj);
379
+ }
361
380
  // 处理数组
362
381
  if (Array.isArray(oldObj)) {
363
382
  if (!Array.isArray(newObj)) {
@@ -379,7 +398,7 @@ let EntityAuditService = class EntityAuditService {
379
398
  return changes;
380
399
  }
381
400
  for (let i = 0; i < oldObj.length; i++) {
382
- changes.push(...this.deepDiff(oldObj[i], newObj[i], [...path, i.toString()]));
401
+ changes.push(...this.deepDiff(oldObj[i], newObj[i], [...path, i.toString()], visited));
383
402
  }
384
403
  return changes;
385
404
  }
@@ -405,7 +424,7 @@ let EntityAuditService = class EntityAuditService {
405
424
  });
406
425
  }
407
426
  else {
408
- changes.push(...this.deepDiff(oldVal, newVal, [...path, key]));
427
+ changes.push(...this.deepDiff(oldVal, newVal, [...path, key], visited));
409
428
  }
410
429
  }
411
430
  return changes;
@@ -522,9 +541,15 @@ let EntityAuditService = class EntityAuditService {
522
541
  });
523
542
  }
524
543
  /**
525
- * 生成描述
544
+ * 生成描述(支持多语言)
545
+ * @param operation 操作类型
546
+ * @param entityType 实体类型
547
+ * @param entityId 实体ID
548
+ * @param changedFields 变更字段列表
549
+ * @param language 语言(默认中文)
550
+ * @param entityClass 实体类(可选,用于获取实体标签)
526
551
  */
527
- generateDescription(operation, entityType, entityId, changedFields) {
552
+ generateDescription(operation, entityType, entityId, changedFields, language = 'zh', entityClass) {
528
553
  const operationText = {
529
554
  [enums_1.AuditOperation.CREATE]: '创建',
530
555
  [enums_1.AuditOperation.UPDATE]: '更新',
@@ -532,10 +557,32 @@ let EntityAuditService = class EntityAuditService {
532
557
  [enums_1.AuditOperation.RESTORE]: '恢复',
533
558
  };
534
559
  const text = operationText[operation] || operation;
560
+ // 尝试获取实体的多语言标签
561
+ let entityLabel = entityType;
562
+ if (entityClass) {
563
+ try {
564
+ entityLabel = (0, entity_audit_decorator_1.getEntityLabel)(entityClass, language);
565
+ }
566
+ catch (error) {
567
+ // 忽略错误,使用默认的 entityType
568
+ }
569
+ }
535
570
  if (operation === enums_1.AuditOperation.UPDATE && changedFields.length > 0) {
536
- return `${text} ${entityType}(${entityId}), 变更字段: ${changedFields.join(', ')}`;
571
+ // 对于更新操作,显示哪些字段发生了变化
572
+ const fieldLabels = changedFields.map(field => {
573
+ if (entityClass) {
574
+ try {
575
+ return (0, entity_audit_decorator_1.getFieldLabel)(entityClass, field, language);
576
+ }
577
+ catch (error) {
578
+ return field;
579
+ }
580
+ }
581
+ return field;
582
+ });
583
+ return `${text}${entityLabel}(${entityId}), 变更字段: ${fieldLabels.join('、')}`;
537
584
  }
538
- return `${text} ${entityType}(${entityId})`;
585
+ return `${text}${entityLabel}(${entityId})`;
539
586
  }
540
587
  /**
541
588
  * 检测冲突
@@ -756,6 +803,254 @@ let EntityAuditService = class EntityAuditService {
756
803
  });
757
804
  });
758
805
  }
806
+ /**
807
+ * 查询审计动作汇总记录
808
+ */
809
+ getAuditActions(options) {
810
+ return __awaiter(this, void 0, void 0, function* () {
811
+ if (!this.actionSummaryRepository) {
812
+ throw new Error('AuditActionSummaryEntity repository not available');
813
+ }
814
+ const { page = 1, limit = 20 } = options;
815
+ const queryBuilder = this.actionSummaryRepository.createQueryBuilder('action');
816
+ // 应用过滤条件
817
+ if (options.userId) {
818
+ queryBuilder.andWhere('action.userId = :userId', { userId: options.userId });
819
+ }
820
+ if (options.username) {
821
+ queryBuilder.andWhere('action.username LIKE :username', { username: `%${options.username}%` });
822
+ }
823
+ if (options.actionName) {
824
+ queryBuilder.andWhere('action.actionName = :actionName', { actionName: options.actionName });
825
+ }
826
+ if (options.success !== undefined) {
827
+ queryBuilder.andWhere('action.success = :success', { success: options.success });
828
+ }
829
+ if (options.startTime && options.endTime) {
830
+ queryBuilder.andWhere('action.createdAt BETWEEN :startTime AND :endTime', {
831
+ startTime: options.startTime,
832
+ endTime: options.endTime,
833
+ });
834
+ }
835
+ // 排序
836
+ queryBuilder.orderBy('action.createdAt', 'DESC');
837
+ // 分页
838
+ const skip = (page - 1) * limit;
839
+ queryBuilder.skip(skip).take(limit);
840
+ const [data, total] = yield queryBuilder.getManyAndCount();
841
+ const pageOptionsDto = new dto_1.PageOptionsDto();
842
+ Object.assign(pageOptionsDto, { page, pageSize: limit });
843
+ const pageMetaDto = new dto_1.PageMetaDto({
844
+ pageOptionsDto,
845
+ itemCount: total,
846
+ });
847
+ return new dto_1.PageDto(data, pageMetaDto);
848
+ });
849
+ }
850
+ /**
851
+ * 查询单个审计动作的详细信息(包含关联的实体变更)
852
+ */
853
+ getAuditActionDetail(actionId) {
854
+ return __awaiter(this, void 0, void 0, function* () {
855
+ if (!this.actionSummaryRepository) {
856
+ throw new Error('AuditActionSummaryEntity repository not available');
857
+ }
858
+ // 查询汇总信息
859
+ const summary = yield this.actionSummaryRepository.findOne({
860
+ where: { id: actionId },
861
+ });
862
+ if (!summary) {
863
+ throw new Error(`Audit action with id ${actionId} not found`);
864
+ }
865
+ // 查询关联的实体变更
866
+ const entityChanges = yield this.auditLogRepository.find({
867
+ where: { auditActionId: actionId },
868
+ order: { sequenceInAction: 'ASC' },
869
+ });
870
+ // 分析每个实体的详细变化
871
+ const detailedChanges = entityChanges.map((change) => {
872
+ const fieldChanges = this.analyzeFieldChanges(change.oldValue || {}, change.newValue || {}, change.operation);
873
+ return {
874
+ id: change.id,
875
+ entityType: change.entityType,
876
+ entityId: change.entityId,
877
+ operation: change.operation,
878
+ operationLabel: this.getOperationLabel(change.operation),
879
+ description: change.description,
880
+ sequenceInAction: change.sequenceInAction,
881
+ createdAt: change.createdAt,
882
+ // 数据快照
883
+ oldValue: change.oldValue,
884
+ newValue: change.newValue,
885
+ // 详细的字段变化分析
886
+ fieldChanges,
887
+ changedFieldsCount: fieldChanges.length,
888
+ changedFields: change.changedFields,
889
+ };
890
+ });
891
+ // 统计信息
892
+ const statistics = {
893
+ totalChanges: entityChanges.length,
894
+ totalFieldChanges: detailedChanges.reduce((sum, c) => sum + c.changedFieldsCount, 0),
895
+ byEntityType: this.groupBy(entityChanges, 'entityType'),
896
+ byOperation: this.groupBy(entityChanges, 'operation'),
897
+ operationSequence: entityChanges.map((c) => ({
898
+ sequence: c.sequenceInAction,
899
+ entityType: c.entityType,
900
+ operation: c.operation,
901
+ })),
902
+ };
903
+ return {
904
+ // 汇总信息
905
+ summary: {
906
+ id: summary.id,
907
+ actionName: summary.actionName,
908
+ operationTemplateKey: summary.operationTemplateKey,
909
+ description: summary.description,
910
+ descriptionParams: summary.descriptionParams,
911
+ success: summary.success,
912
+ errorMessage: summary.errorMessage,
913
+ duration: summary.duration,
914
+ userId: summary.userId,
915
+ username: summary.username,
916
+ requestId: summary.requestId,
917
+ requestIp: summary.requestIp,
918
+ userAgent: summary.userAgent,
919
+ entityChangesCount: summary.entityChangesCount,
920
+ entityTypes: summary.entityTypes,
921
+ operationStats: summary.operationStats,
922
+ createdAt: summary.createdAt,
923
+ metadata: summary.metadata,
924
+ },
925
+ // 原始实体变更记录
926
+ entityChanges,
927
+ // 详细的变化分析
928
+ detailedChanges,
929
+ // 统计信息
930
+ statistics,
931
+ };
932
+ });
933
+ }
934
+ /**
935
+ * 分析字段变化(支持多语言)
936
+ * @param oldValue 旧值
937
+ * @param newValue 新值
938
+ * @param operation 操作类型
939
+ * @param entityClass 实体类(可选,用于获取字段和值的多语言标签)
940
+ * @param language 语言(默认中文)
941
+ */
942
+ analyzeFieldChanges(oldValue, newValue, operation, entityClass, language = 'zh') {
943
+ const changes = [];
944
+ const allFields = new Set([...Object.keys(oldValue), ...Object.keys(newValue)]);
945
+ for (const field of allFields) {
946
+ const oldVal = oldValue[field];
947
+ const newVal = newValue[field];
948
+ let changeType;
949
+ if (operation === enums_1.AuditOperation.CREATE) {
950
+ // 创建操作,所有字段都是新增
951
+ changeType = 'added';
952
+ }
953
+ else if (operation === enums_1.AuditOperation.DELETE) {
954
+ // 删除操作,所有字段都是移除
955
+ changeType = 'removed';
956
+ }
957
+ else {
958
+ // 更新操作,判断字段变化
959
+ if (oldVal === undefined && newVal !== undefined) {
960
+ changeType = 'added';
961
+ }
962
+ else if (oldVal !== undefined && newVal === undefined) {
963
+ changeType = 'removed';
964
+ }
965
+ else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
966
+ changeType = 'modified';
967
+ }
968
+ else {
969
+ changeType = 'unchanged';
970
+ }
971
+ }
972
+ // 跳过未变化的字段(对于UPDATE操作)
973
+ if (changeType === 'unchanged' && operation === enums_1.AuditOperation.UPDATE) {
974
+ continue;
975
+ }
976
+ // 获取字段的多语言标签
977
+ let fieldLabel = field;
978
+ if (entityClass) {
979
+ try {
980
+ fieldLabel = (0, entity_audit_decorator_1.getFieldLabel)(entityClass, field, language);
981
+ }
982
+ catch (error) {
983
+ // 忽略错误,使用原字段名
984
+ }
985
+ }
986
+ // 获取字段值的多语言标签
987
+ let displayOldValue = this.formatDisplayValue(oldVal);
988
+ let displayNewValue = this.formatDisplayValue(newVal);
989
+ if (entityClass) {
990
+ try {
991
+ if (oldVal !== null && oldVal !== undefined) {
992
+ const valueLabel = (0, entity_audit_decorator_1.getFieldValueLabel)(entityClass, field, oldVal, language);
993
+ if (valueLabel !== oldVal) {
994
+ displayOldValue = valueLabel;
995
+ }
996
+ }
997
+ if (newVal !== null && newVal !== undefined) {
998
+ const valueLabel = (0, entity_audit_decorator_1.getFieldValueLabel)(entityClass, field, newVal, language);
999
+ if (valueLabel !== newVal) {
1000
+ displayNewValue = valueLabel;
1001
+ }
1002
+ }
1003
+ }
1004
+ catch (error) {
1005
+ // 忽略错误,使用默认格式化值
1006
+ }
1007
+ }
1008
+ changes.push({
1009
+ field,
1010
+ fieldLabel,
1011
+ oldValue: oldVal,
1012
+ newValue: newVal,
1013
+ changeType,
1014
+ displayOldValue,
1015
+ displayNewValue,
1016
+ });
1017
+ }
1018
+ return changes;
1019
+ }
1020
+ /**
1021
+ * 格式化显示值
1022
+ */
1023
+ formatDisplayValue(value) {
1024
+ if (value === null || value === undefined) {
1025
+ return '';
1026
+ }
1027
+ if (typeof value === 'object') {
1028
+ return JSON.stringify(value);
1029
+ }
1030
+ return String(value);
1031
+ }
1032
+ /**
1033
+ * 获取操作标签
1034
+ */
1035
+ getOperationLabel(operation) {
1036
+ const labels = {
1037
+ [enums_1.AuditOperation.CREATE]: '创建',
1038
+ [enums_1.AuditOperation.UPDATE]: '更新',
1039
+ [enums_1.AuditOperation.DELETE]: '删除',
1040
+ [enums_1.AuditOperation.RESTORE]: '恢复',
1041
+ };
1042
+ return labels[operation] || operation;
1043
+ }
1044
+ /**
1045
+ * 按字段分组统计
1046
+ */
1047
+ groupBy(items, field) {
1048
+ return items.reduce((acc, item) => {
1049
+ const key = item[field];
1050
+ acc[key] = (acc[key] || 0) + 1;
1051
+ return acc;
1052
+ }, {});
1053
+ }
759
1054
  };
760
1055
  exports.EntityAuditService = EntityAuditService;
761
1056
  exports.EntityAuditService = EntityAuditService = __decorate([
@@ -770,10 +1065,12 @@ exports.EntityAuditService = EntityAuditService = __decorate([
770
1065
  __param(7, (0, common_1.Inject)('AUDIT_CONFIG')),
771
1066
  __param(8, (0, common_1.Optional)()),
772
1067
  __param(8, (0, common_1.Inject)('AUDIT_CONNECTION_NAME')),
1068
+ __param(9, (0, common_1.Optional)()),
1069
+ __param(9, (0, typeorm_1.InjectRepository)(entities_1.AuditActionSummaryEntity)),
773
1070
  __metadata("design:paramtypes", [typeorm_2.Repository,
774
1071
  typeorm_2.Repository,
775
1072
  typeorm_2.Repository,
776
1073
  typeorm_2.EntityManager,
777
1074
  audit_context_service_1.AuditContextService,
778
- multi_database_service_1.MultiDatabaseService, Object, Object, String])
1075
+ multi_database_service_1.MultiDatabaseService, Object, Object, String, typeorm_2.Repository])
779
1076
  ], EntityAuditService);
@@ -5,3 +5,4 @@ export * from './transaction-audit.service';
5
5
  export * from './multi-database.service';
6
6
  export * from './operation-description.service';
7
7
  export * from './manual-audit-log.service';
8
+ export * from './audit-action.service';
@@ -21,3 +21,4 @@ __exportStar(require("./transaction-audit.service"), exports);
21
21
  __exportStar(require("./multi-database.service"), exports);
22
22
  __exportStar(require("./operation-description.service"), exports);
23
23
  __exportStar(require("./manual-audit-log.service"), exports);
24
+ __exportStar(require("./audit-action.service"), exports);
@@ -2,20 +2,21 @@ import { Repository, DataSource } from 'typeorm';
2
2
  import { ManualOperationLogEntity, EntityTransactionEntity } from '../entities';
3
3
  import { AuditContextService } from './audit-context.service';
4
4
  import { ManualLogOptions } from '../interfaces';
5
+ import { AuditTransactionStatus } from '../enums';
5
6
  /**
6
7
  * 手动审计日志服务
7
8
  *
8
- * 提供全局静态方法,在任意地方手动记录操作日志
9
+ * 提供标准的依赖注入方式记录操作日志
10
+ * @deprecated 静态方法已废弃,请使用依赖注入方式
9
11
  */
10
12
  export declare class ManualAuditLogService {
11
13
  private readonly manualLogRepository;
12
14
  private readonly transactionRepository;
13
15
  private readonly contextService;
14
16
  private readonly dataSource;
15
- private static instance;
16
17
  constructor(manualLogRepository: Repository<ManualOperationLogEntity>, transactionRepository: Repository<EntityTransactionEntity>, contextService: AuditContextService, dataSource: DataSource);
17
18
  /**
18
- * 全局静态方法:记录操作日志
19
+ * 记录操作日志
19
20
  *
20
21
  * @description
21
22
  * 支持三种记录模式:
@@ -25,7 +26,7 @@ export declare class ManualAuditLogService {
25
26
  *
26
27
  * @example
27
28
  * // 模式1:模板键模式
28
- * await ManualAuditLogService.log({
29
+ * await this.manualAuditLogService.log({
29
30
  * templateKey: 'user.login',
30
31
  * descriptionParams: {
31
32
  * username: 'john.doe',
@@ -35,13 +36,13 @@ export declare class ManualAuditLogService {
35
36
  *
36
37
  * @example
37
38
  * // 模式2:直接描述模式(字符串)
38
- * await ManualAuditLogService.log({
39
+ * await this.manualAuditLogService.log({
39
40
  * description: '用户登录系统',
40
41
  * });
41
42
  *
42
43
  * @example
43
44
  * // 模式2:直接描述模式(多语言)
44
- * await ManualAuditLogService.log({
45
+ * await this.manualAuditLogService.log({
45
46
  * description: {
46
47
  * zh: '用户登录系统',
47
48
  * en: 'User logged in',
@@ -50,7 +51,7 @@ export declare class ManualAuditLogService {
50
51
  *
51
52
  * @example
52
53
  * // 模式3:内联模板模式
53
- * await ManualAuditLogService.log({
54
+ * await this.manualAuditLogService.log({
54
55
  * descriptionTemplate: {
55
56
  * zh: '用户 {username} 在 {time} 登录了系统',
56
57
  * en: 'User {username} logged in at {time}',
@@ -61,52 +62,52 @@ export declare class ManualAuditLogService {
61
62
  * },
62
63
  * });
63
64
  */
64
- static log(options: ManualLogOptions): Promise<ManualOperationLogEntity>;
65
+ log(options: ManualLogOptions): Promise<ManualOperationLogEntity>;
65
66
  /**
66
67
  * 实例方法:记录操作日志
67
68
  */
68
69
  logOperation(options: ManualLogOptions): Promise<ManualOperationLogEntity>;
69
70
  /**
70
- * 静态方法:带事务记录
71
+ * 开始事务
71
72
  *
72
73
  * @example
73
74
  * ```typescript
74
- * const txId = await ManualAuditLogService.beginTransaction('user-123', 'John Doe');
75
+ * const txId = await this.manualAuditLogService.beginTransaction('user-123', 'John Doe');
75
76
  *
76
- * await ManualAuditLogService.log({
77
+ * await this.manualAuditLogService.log({
77
78
  * templateKey: 'order.create',
78
79
  * descriptionParams: { orderId: 'order-1' },
79
80
  * transactionId: txId,
80
81
  * autoCreateTransaction: false,
81
82
  * });
82
83
  *
83
- * await ManualAuditLogService.log({
84
+ * await this.manualAuditLogService.log({
84
85
  * templateKey: 'payment.process',
85
86
  * descriptionParams: { paymentId: 'pay-1' },
86
87
  * transactionId: txId,
87
88
  * autoCreateTransaction: false,
88
89
  * });
89
90
  *
90
- * await ManualAuditLogService.commitTransaction(txId);
91
+ * await this.manualAuditLogService.commitTransaction(txId);
91
92
  * ```
92
93
  */
93
- static beginTransaction(userId?: string, username?: string): Promise<string>;
94
+ beginTransaction(userId?: string, username?: string): Promise<string>;
94
95
  /**
95
- * 静态方法:提交事务
96
+ * 提交事务
96
97
  */
97
- static commitTransaction(transactionId: string): Promise<void>;
98
+ commitTransaction(transactionId: string): Promise<void>;
98
99
  /**
99
- * 静态方法:回滚事务
100
+ * 回滚事务
100
101
  */
101
- static rollbackTransaction(transactionId: string): Promise<void>;
102
+ rollbackTransaction(transactionId: string): Promise<void>;
102
103
  /**
103
104
  * 创建事务
104
105
  */
105
- private createTransaction;
106
+ createTransaction(userId?: string, username?: string): Promise<string>;
106
107
  /**
107
108
  * 更新事务状态
108
109
  */
109
- private updateTransactionStatus;
110
+ updateTransactionStatus(transactionId: string, status: AuditTransactionStatus): Promise<void>;
110
111
  /**
111
112
  * 生成事务ID
112
113
  */
@@ -120,7 +121,7 @@ export declare class ManualAuditLogService {
120
121
  * @example
121
122
  * ```typescript
122
123
  * // 混合使用多种模式
123
- * await ManualAuditLogService.logBatch([
124
+ * await this.manualAuditLogService.logBatch([
124
125
  * {
125
126
  * templateKey: 'product.update',
126
127
  * descriptionParams: { productId: 'p1', field: 'price' },
@@ -138,11 +139,11 @@ export declare class ManualAuditLogService {
138
139
  * ]);
139
140
  * ```
140
141
  */
141
- static logBatch(operations: ManualLogOptions[], sharedTransactionId?: string): Promise<ManualOperationLogEntity[]>;
142
+ logBatch(operations: ManualLogOptions[], sharedTransactionId?: string): Promise<ManualOperationLogEntity[]>;
142
143
  /**
143
144
  * 查询操作日志
144
145
  */
145
- static findLogs(options: {
146
+ findLogs(options: {
146
147
  templateKey?: string;
147
148
  userId?: string;
148
149
  transactionId?: string;