@dofe/infra-shared-services 0.1.1
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.
- package/dist/email/dto/email.dto.d.ts +70 -0
- package/dist/email/dto/email.dto.d.ts.map +1 -0
- package/dist/email/dto/email.dto.js +58 -0
- package/dist/email/dto/email.dto.js.map +1 -0
- package/dist/email/email.module.d.ts +3 -0
- package/dist/email/email.module.d.ts.map +1 -0
- package/dist/email/email.module.js +38 -0
- package/dist/email/email.module.js.map +1 -0
- package/dist/email/email.service.d.ts +61 -0
- package/dist/email/email.service.d.ts.map +1 -0
- package/dist/email/email.service.js +191 -0
- package/dist/email/email.service.js.map +1 -0
- package/dist/email/index.d.ts +5 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +26 -0
- package/dist/email/index.js.map +1 -0
- package/dist/file-storage/bucket-resolver.d.ts +174 -0
- package/dist/file-storage/bucket-resolver.d.ts.map +1 -0
- package/dist/file-storage/bucket-resolver.js +270 -0
- package/dist/file-storage/bucket-resolver.js.map +1 -0
- package/dist/file-storage/file-storage.factory.d.ts +183 -0
- package/dist/file-storage/file-storage.factory.d.ts.map +1 -0
- package/dist/file-storage/file-storage.factory.js +300 -0
- package/dist/file-storage/file-storage.factory.js.map +1 -0
- package/dist/file-storage/file-storage.module.d.ts +49 -0
- package/dist/file-storage/file-storage.module.d.ts.map +1 -0
- package/dist/file-storage/file-storage.module.js +74 -0
- package/dist/file-storage/file-storage.module.js.map +1 -0
- package/dist/file-storage/file-storage.service.d.ts +381 -0
- package/dist/file-storage/file-storage.service.d.ts.map +1 -0
- package/dist/file-storage/file-storage.service.js +598 -0
- package/dist/file-storage/file-storage.service.js.map +1 -0
- package/dist/file-storage/index.d.ts +43 -0
- package/dist/file-storage/index.d.ts.map +1 -0
- package/dist/file-storage/index.js +65 -0
- package/dist/file-storage/index.js.map +1 -0
- package/dist/file-storage/types.d.ts +187 -0
- package/dist/file-storage/types.d.ts.map +1 -0
- package/dist/file-storage/types.js +21 -0
- package/dist/file-storage/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/ip-geo/continent-mapping.d.ts +31 -0
- package/dist/ip-geo/continent-mapping.d.ts.map +1 -0
- package/dist/ip-geo/continent-mapping.js +246 -0
- package/dist/ip-geo/continent-mapping.js.map +1 -0
- package/dist/ip-geo/index.d.ts +33 -0
- package/dist/ip-geo/index.d.ts.map +1 -0
- package/dist/ip-geo/index.js +41 -0
- package/dist/ip-geo/index.js.map +1 -0
- package/dist/ip-geo/ip-geo.module.d.ts +8 -0
- package/dist/ip-geo/ip-geo.module.d.ts.map +1 -0
- package/dist/ip-geo/ip-geo.module.js +34 -0
- package/dist/ip-geo/ip-geo.module.js.map +1 -0
- package/dist/ip-geo/ip-geo.service.d.ts +43 -0
- package/dist/ip-geo/ip-geo.service.d.ts.map +1 -0
- package/dist/ip-geo/ip-geo.service.js +153 -0
- package/dist/ip-geo/ip-geo.service.js.map +1 -0
- package/dist/ip-info/index.d.ts +7 -0
- package/dist/ip-info/index.d.ts.map +1 -0
- package/dist/ip-info/index.js +13 -0
- package/dist/ip-info/index.js.map +1 -0
- package/dist/ip-info/ip-info.client.d.ts +32 -0
- package/dist/ip-info/ip-info.client.d.ts.map +1 -0
- package/dist/ip-info/ip-info.client.js +73 -0
- package/dist/ip-info/ip-info.client.js.map +1 -0
- package/dist/ip-info/ip-info.module.d.ts +3 -0
- package/dist/ip-info/ip-info.module.d.ts.map +1 -0
- package/dist/ip-info/ip-info.module.js +45 -0
- package/dist/ip-info/ip-info.module.js.map +1 -0
- package/dist/ip-info/ip-info.service.d.ts +50 -0
- package/dist/ip-info/ip-info.service.d.ts.map +1 -0
- package/dist/ip-info/ip-info.service.js +177 -0
- package/dist/ip-info/ip-info.service.js.map +1 -0
- package/dist/ocr/index.d.ts +33 -0
- package/dist/ocr/index.d.ts.map +1 -0
- package/dist/ocr/index.js +53 -0
- package/dist/ocr/index.js.map +1 -0
- package/dist/ocr/ocr.module.d.ts +41 -0
- package/dist/ocr/ocr.module.d.ts.map +1 -0
- package/dist/ocr/ocr.module.js +61 -0
- package/dist/ocr/ocr.module.js.map +1 -0
- package/dist/ocr/ocr.service.d.ts +111 -0
- package/dist/ocr/ocr.service.d.ts.map +1 -0
- package/dist/ocr/ocr.service.js +214 -0
- package/dist/ocr/ocr.service.js.map +1 -0
- package/dist/sms/index.d.ts +5 -0
- package/dist/sms/index.d.ts.map +1 -0
- package/dist/sms/index.js +29 -0
- package/dist/sms/index.js.map +1 -0
- package/dist/sms/sms.factory.d.ts +140 -0
- package/dist/sms/sms.factory.d.ts.map +1 -0
- package/dist/sms/sms.factory.js +276 -0
- package/dist/sms/sms.factory.js.map +1 -0
- package/dist/sms/sms.module.d.ts +3 -0
- package/dist/sms/sms.module.d.ts.map +1 -0
- package/dist/sms/sms.module.js +38 -0
- package/dist/sms/sms.module.js.map +1 -0
- package/dist/sms/sms.service.d.ts +139 -0
- package/dist/sms/sms.service.d.ts.map +1 -0
- package/dist/sms/sms.service.js +278 -0
- package/dist/sms/sms.service.js.map +1 -0
- package/dist/sms/types.d.ts +204 -0
- package/dist/sms/types.d.ts.map +1 -0
- package/dist/sms/types.js +44 -0
- package/dist/sms/types.js.map +1 -0
- package/dist/streaming-asr/index.d.ts +45 -0
- package/dist/streaming-asr/index.d.ts.map +1 -0
- package/dist/streaming-asr/index.js +66 -0
- package/dist/streaming-asr/index.js.map +1 -0
- package/dist/streaming-asr/streaming-asr.module.d.ts +37 -0
- package/dist/streaming-asr/streaming-asr.module.d.ts.map +1 -0
- package/dist/streaming-asr/streaming-asr.module.js +59 -0
- package/dist/streaming-asr/streaming-asr.module.js.map +1 -0
- package/dist/streaming-asr/streaming-asr.service.d.ts +276 -0
- package/dist/streaming-asr/streaming-asr.service.d.ts.map +1 -0
- package/dist/streaming-asr/streaming-asr.service.js +1120 -0
- package/dist/streaming-asr/streaming-asr.service.js.map +1 -0
- package/dist/streaming-asr/types.d.ts +194 -0
- package/dist/streaming-asr/types.d.ts.map +1 -0
- package/dist/streaming-asr/types.js +8 -0
- package/dist/streaming-asr/types.js.map +1 -0
- package/dist/system-health/index.d.ts +7 -0
- package/dist/system-health/index.d.ts.map +1 -0
- package/dist/system-health/index.js +25 -0
- package/dist/system-health/index.js.map +1 -0
- package/dist/system-health/system-health.controller.d.ts +43 -0
- package/dist/system-health/system-health.controller.d.ts.map +1 -0
- package/dist/system-health/system-health.controller.js +86 -0
- package/dist/system-health/system-health.controller.js.map +1 -0
- package/dist/system-health/system-health.module.d.ts +3 -0
- package/dist/system-health/system-health.module.d.ts.map +1 -0
- package/dist/system-health/system-health.module.js +29 -0
- package/dist/system-health/system-health.module.js.map +1 -0
- package/dist/system-health/system-health.service.d.ts +14 -0
- package/dist/system-health/system-health.service.d.ts.map +1 -0
- package/dist/system-health/system-health.service.js +87 -0
- package/dist/system-health/system-health.service.js.map +1 -0
- package/dist/uploader/index.d.ts +3 -0
- package/dist/uploader/index.d.ts.map +1 -0
- package/dist/uploader/index.js +8 -0
- package/dist/uploader/index.js.map +1 -0
- package/dist/uploader/uploader.module.d.ts +3 -0
- package/dist/uploader/uploader.module.d.ts.map +1 -0
- package/dist/uploader/uploader.module.js +25 -0
- package/dist/uploader/uploader.module.js.map +1 -0
- package/dist/uploader/uploader.service.d.ts +86 -0
- package/dist/uploader/uploader.service.d.ts.map +1 -0
- package/dist/uploader/uploader.service.js +188 -0
- package/dist/uploader/uploader.service.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.IpInfoService = void 0;
|
|
19
|
+
/**
|
|
20
|
+
* IP Info Service
|
|
21
|
+
*
|
|
22
|
+
* 职责:提供 IP 信息查询服务
|
|
23
|
+
* - IP 地址信息查询(通过 IpInfoClient)
|
|
24
|
+
* - 国家/地区查询
|
|
25
|
+
* - 大洲查询(依赖 CountryCodeService)
|
|
26
|
+
* - 时区查询
|
|
27
|
+
* - 缓存管理
|
|
28
|
+
* - 业务逻辑处理(默认值、特殊地区处理等)
|
|
29
|
+
*
|
|
30
|
+
* 架构:
|
|
31
|
+
* - 使用 IpInfoClient 进行 HTTP 调用(符合架构规范)
|
|
32
|
+
* - 依赖 CountryCodeService(domain 层),因此放置在 infra/shared-services
|
|
33
|
+
*/
|
|
34
|
+
const common_1 = require("@nestjs/common");
|
|
35
|
+
const nest_winston_1 = require("nest-winston");
|
|
36
|
+
const winston_1 = require("winston");
|
|
37
|
+
const config_1 = require("@nestjs/config");
|
|
38
|
+
const infra_redis_1 = require("@dofe/infra-redis");
|
|
39
|
+
const ip_util_1 = __importDefault(require("@dofe/infra-utils/ip.util"));
|
|
40
|
+
const validate_util_1 = __importDefault(require("@dofe/infra-utils/validate.util"));
|
|
41
|
+
const environment_util_1 = __importDefault(require("@dofe/infra-utils/environment.util"));
|
|
42
|
+
const infra_shared_db_1 = require("@dofe/infra-shared-db");
|
|
43
|
+
const ip_info_client_1 = require("./ip-info.client");
|
|
44
|
+
let IpInfoService = class IpInfoService {
|
|
45
|
+
config;
|
|
46
|
+
redis;
|
|
47
|
+
countryCodeService;
|
|
48
|
+
ipInfoClient;
|
|
49
|
+
logger;
|
|
50
|
+
ipInfoConfig;
|
|
51
|
+
ipinfoRedisKey = 'ipinfo';
|
|
52
|
+
constructor(config, redis, countryCodeService, ipInfoClient, logger) {
|
|
53
|
+
this.config = config;
|
|
54
|
+
this.redis = redis;
|
|
55
|
+
this.countryCodeService = countryCodeService;
|
|
56
|
+
this.ipInfoClient = ipInfoClient;
|
|
57
|
+
this.logger = logger;
|
|
58
|
+
this.ipInfoConfig = config.getOrThrow('ipinfo');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 从请求中提取 IP 地址
|
|
62
|
+
*/
|
|
63
|
+
extractIp(req) {
|
|
64
|
+
return ip_util_1.default.extractIp(req);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 获取 IP 信息
|
|
68
|
+
*
|
|
69
|
+
* 业务逻辑:
|
|
70
|
+
* 1. CN 环境返回默认值
|
|
71
|
+
* 2. 本地 IP 返回默认值
|
|
72
|
+
* 3. 检查 Redis 缓存
|
|
73
|
+
* 4. 调用 ipinfo.io API(通过 IpInfoClient)
|
|
74
|
+
* 5. CN IP 替换为 SG(业务需求)
|
|
75
|
+
* 6. 失败时返回默认值
|
|
76
|
+
*/
|
|
77
|
+
async getIpInfo(ip) {
|
|
78
|
+
// 1. CN 环境默认值
|
|
79
|
+
if (environment_util_1.default.getBaseZone() === 'cn') {
|
|
80
|
+
return this.getDefaultIpInfo(ip, 'CN', 'Beijing', 'Asia/Shanghai');
|
|
81
|
+
}
|
|
82
|
+
// 2. 本地 IP 默认值
|
|
83
|
+
if (validate_util_1.default.isBlank(ip) || ip === '127.0.0.1') {
|
|
84
|
+
return this.getDefaultIpInfo(ip, 'SG', 'Singapore', 'Asia/Singapore');
|
|
85
|
+
}
|
|
86
|
+
// 3. 检查缓存
|
|
87
|
+
const cached = await this.redis.getData(this.ipinfoRedisKey, ip);
|
|
88
|
+
if (cached) {
|
|
89
|
+
this.logger.debug('[IpInfoService] Cache hit', { ip });
|
|
90
|
+
return cached;
|
|
91
|
+
}
|
|
92
|
+
// 4. 调用 API(通过 Client)
|
|
93
|
+
try {
|
|
94
|
+
const apiResponse = await this.ipInfoClient.fetchIpInfo(ip, this.ipInfoConfig.token, this.ipInfoConfig.url);
|
|
95
|
+
let ipInfoData = {
|
|
96
|
+
ip: apiResponse.ip,
|
|
97
|
+
country: apiResponse.country,
|
|
98
|
+
region: apiResponse.region,
|
|
99
|
+
city: apiResponse.city,
|
|
100
|
+
loc: apiResponse.loc,
|
|
101
|
+
timezone: apiResponse.timezone,
|
|
102
|
+
org: apiResponse.org,
|
|
103
|
+
};
|
|
104
|
+
this.logger.info('[IpInfoService] IP info fetched', { ipInfoData });
|
|
105
|
+
// 5. 缓存结果
|
|
106
|
+
await this.redis.saveData(this.ipinfoRedisKey, ip, ipInfoData);
|
|
107
|
+
// 6. CN IP 替换为 SG(业务需求)
|
|
108
|
+
if (ipInfoData.country === 'CN') {
|
|
109
|
+
ipInfoData = this.getDefaultIpInfo(ip, 'SG', 'Singapore', 'Asia/Singapore');
|
|
110
|
+
}
|
|
111
|
+
return ipInfoData;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
// 7. 失败时返回默认值
|
|
115
|
+
this.logger.error('[IpInfoService] Failed to fetch IP info', {
|
|
116
|
+
ip,
|
|
117
|
+
error: error.message,
|
|
118
|
+
});
|
|
119
|
+
return this.getDefaultIpInfo(ip, 'SG', 'Singapore', 'Asia/Singapore');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 获取 IP 所属国家
|
|
124
|
+
*/
|
|
125
|
+
async getIpCountry(ip) {
|
|
126
|
+
const ipInfo = await this.getIpInfo(ip);
|
|
127
|
+
return ipInfo.country;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 获取 IP 所属大洲
|
|
131
|
+
*/
|
|
132
|
+
async getContinent(ip) {
|
|
133
|
+
const countryCode = await this.getIpCountry(ip);
|
|
134
|
+
const relations = await this.countryCodeService.loadRelations();
|
|
135
|
+
for (const [continent, countries] of Object.entries(relations)) {
|
|
136
|
+
if (countries.includes(countryCode)) {
|
|
137
|
+
return continent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
this.logger.error('[IpInfoService] Failed to fetch IP continent', {
|
|
141
|
+
ip,
|
|
142
|
+
countryCode,
|
|
143
|
+
});
|
|
144
|
+
return environment_util_1.default.getBaseZone();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 获取 IP 时区
|
|
148
|
+
*/
|
|
149
|
+
async getTimeZone(ip) {
|
|
150
|
+
const ipInfo = await this.getIpInfo(ip);
|
|
151
|
+
return ipInfo.timezone;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 生成默认 IP 信息
|
|
155
|
+
*/
|
|
156
|
+
getDefaultIpInfo(ip, country, city, timezone) {
|
|
157
|
+
return {
|
|
158
|
+
ip,
|
|
159
|
+
country,
|
|
160
|
+
region: city,
|
|
161
|
+
city,
|
|
162
|
+
loc: country === 'CN' ? '39.9042,116.4074' : '1.2897,103.8501',
|
|
163
|
+
timezone,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
exports.IpInfoService = IpInfoService;
|
|
168
|
+
exports.IpInfoService = IpInfoService = __decorate([
|
|
169
|
+
(0, common_1.Injectable)(),
|
|
170
|
+
__param(4, (0, common_1.Inject)(nest_winston_1.WINSTON_MODULE_PROVIDER)),
|
|
171
|
+
__metadata("design:paramtypes", [config_1.ConfigService,
|
|
172
|
+
infra_redis_1.RedisService,
|
|
173
|
+
infra_shared_db_1.CountryCodeService,
|
|
174
|
+
ip_info_client_1.IpInfoClient,
|
|
175
|
+
winston_1.Logger])
|
|
176
|
+
], IpInfoService);
|
|
177
|
+
//# sourceMappingURL=ip-info.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip-info.service.js","sourceRoot":"","sources":["../../src/ip-info/ip-info.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview OCR 服务导出
|
|
3
|
+
*
|
|
4
|
+
* 本模块提供 OCR 文本提取能力的统一封装。
|
|
5
|
+
*
|
|
6
|
+
* @module ocr
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // 导入模块
|
|
11
|
+
* import { OcrModule, OcrService } from '@app/shared-services/ocr';
|
|
12
|
+
*
|
|
13
|
+
* // 在 NestJS 模块中使用
|
|
14
|
+
* @Module({
|
|
15
|
+
* imports: [OcrModule],
|
|
16
|
+
* })
|
|
17
|
+
* export class MyModule {}
|
|
18
|
+
*
|
|
19
|
+
* // 在服务中注入使用
|
|
20
|
+
* @Injectable()
|
|
21
|
+
* class MyService {
|
|
22
|
+
* constructor(private readonly ocrService: OcrService) {}
|
|
23
|
+
*
|
|
24
|
+
* async extractText(fileUrl: string) {
|
|
25
|
+
* const result = await this.ocrService.extractText(fileUrl, 'pdf');
|
|
26
|
+
* return result.text;
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export { OcrModule } from './ocr.module';
|
|
32
|
+
export * from './ocr.service';
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ocr/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview OCR 服务导出
|
|
4
|
+
*
|
|
5
|
+
* 本模块提供 OCR 文本提取能力的统一封装。
|
|
6
|
+
*
|
|
7
|
+
* @module ocr
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // 导入模块
|
|
12
|
+
* import { OcrModule, OcrService } from '@app/shared-services/ocr';
|
|
13
|
+
*
|
|
14
|
+
* // 在 NestJS 模块中使用
|
|
15
|
+
* @Module({
|
|
16
|
+
* imports: [OcrModule],
|
|
17
|
+
* })
|
|
18
|
+
* export class MyModule {}
|
|
19
|
+
*
|
|
20
|
+
* // 在服务中注入使用
|
|
21
|
+
* @Injectable()
|
|
22
|
+
* class MyService {
|
|
23
|
+
* constructor(private readonly ocrService: OcrService) {}
|
|
24
|
+
*
|
|
25
|
+
* async extractText(fileUrl: string) {
|
|
26
|
+
* const result = await this.ocrService.extractText(fileUrl, 'pdf');
|
|
27
|
+
* return result.text;
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
33
|
+
if (k2 === undefined) k2 = k;
|
|
34
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
35
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
36
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
37
|
+
}
|
|
38
|
+
Object.defineProperty(o, k2, desc);
|
|
39
|
+
}) : (function(o, m, k, k2) {
|
|
40
|
+
if (k2 === undefined) k2 = k;
|
|
41
|
+
o[k2] = m[k];
|
|
42
|
+
}));
|
|
43
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
44
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.OcrModule = void 0;
|
|
48
|
+
// 模块导出
|
|
49
|
+
var ocr_module_1 = require("./ocr.module");
|
|
50
|
+
Object.defineProperty(exports, "OcrModule", { enumerable: true, get: function () { return ocr_module_1.OcrModule; } });
|
|
51
|
+
// 服务导出
|
|
52
|
+
__exportStar(require("./ocr.service"), exports);
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ocr/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;;;;;;;;;;;;;;;AAEH,OAAO;AACP,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAElB,OAAO;AACP,gDAA8B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview OCR 服务模块
|
|
3
|
+
*
|
|
4
|
+
* 本模块提供 OCR 文本提取服务的 NestJS 模块配置
|
|
5
|
+
*
|
|
6
|
+
* @module ocr/module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* OCR 服务模块
|
|
10
|
+
*
|
|
11
|
+
* @description 提供文件 OCR 文本提取服务的依赖注入配置。
|
|
12
|
+
*
|
|
13
|
+
* 导出服务:
|
|
14
|
+
* - `OcrService`: OCR 文本提取服务
|
|
15
|
+
*
|
|
16
|
+
* 依赖模块:
|
|
17
|
+
* - `AgentXClientModule`: AgentX 任务客户端模块
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // 在其他模块中导入
|
|
22
|
+
* @Module({
|
|
23
|
+
* imports: [OcrModule],
|
|
24
|
+
* })
|
|
25
|
+
* export class MyModule {}
|
|
26
|
+
*
|
|
27
|
+
* // 在服务中使用
|
|
28
|
+
* @Injectable()
|
|
29
|
+
* class MyService {
|
|
30
|
+
* constructor(private readonly ocrService: OcrService) {}
|
|
31
|
+
*
|
|
32
|
+
* async extractText(fileUrl: string) {
|
|
33
|
+
* const result = await this.ocrService.extractText(fileUrl, 'pdf');
|
|
34
|
+
* return result.text;
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class OcrModule {
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=ocr.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocr.module.d.ts","sourceRoot":"","sources":["../../src/ocr/ocr.module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAKa,SAAS;CAAG"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview OCR 服务模块
|
|
4
|
+
*
|
|
5
|
+
* 本模块提供 OCR 文本提取服务的 NestJS 模块配置
|
|
6
|
+
*
|
|
7
|
+
* @module ocr/module
|
|
8
|
+
*/
|
|
9
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
10
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
11
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
12
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
13
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.OcrModule = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const infra_clients_1 = require("@dofe/infra-clients");
|
|
19
|
+
const ocr_service_1 = require("./ocr.service");
|
|
20
|
+
/**
|
|
21
|
+
* OCR 服务模块
|
|
22
|
+
*
|
|
23
|
+
* @description 提供文件 OCR 文本提取服务的依赖注入配置。
|
|
24
|
+
*
|
|
25
|
+
* 导出服务:
|
|
26
|
+
* - `OcrService`: OCR 文本提取服务
|
|
27
|
+
*
|
|
28
|
+
* 依赖模块:
|
|
29
|
+
* - `AgentXClientModule`: AgentX 任务客户端模块
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // 在其他模块中导入
|
|
34
|
+
* @Module({
|
|
35
|
+
* imports: [OcrModule],
|
|
36
|
+
* })
|
|
37
|
+
* export class MyModule {}
|
|
38
|
+
*
|
|
39
|
+
* // 在服务中使用
|
|
40
|
+
* @Injectable()
|
|
41
|
+
* class MyService {
|
|
42
|
+
* constructor(private readonly ocrService: OcrService) {}
|
|
43
|
+
*
|
|
44
|
+
* async extractText(fileUrl: string) {
|
|
45
|
+
* const result = await this.ocrService.extractText(fileUrl, 'pdf');
|
|
46
|
+
* return result.text;
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
let OcrModule = class OcrModule {
|
|
52
|
+
};
|
|
53
|
+
exports.OcrModule = OcrModule;
|
|
54
|
+
exports.OcrModule = OcrModule = __decorate([
|
|
55
|
+
(0, common_1.Module)({
|
|
56
|
+
imports: [infra_clients_1.AgentXClientModule],
|
|
57
|
+
providers: [ocr_service_1.OcrService],
|
|
58
|
+
exports: [ocr_service_1.OcrService],
|
|
59
|
+
})
|
|
60
|
+
], OcrModule);
|
|
61
|
+
//# sourceMappingURL=ocr.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocr.module.js","sourceRoot":"","sources":["../../src/ocr/ocr.module.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;AAEH,2CAAwC;AACxC,uDAAyD;AACzD,+CAA2C;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAMI,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IALrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,kCAAkB,CAAC;QAC7B,SAAS,EAAE,CAAC,wBAAU,CAAC;QACvB,OAAO,EAAE,CAAC,wBAAU,CAAC;KACtB,CAAC;GACW,SAAS,CAAG"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Logger } from 'winston';
|
|
2
|
+
import { AgentXClient } from '@dofe/infra-clients';
|
|
3
|
+
/**
|
|
4
|
+
* OCR 任务请求参数
|
|
5
|
+
*/
|
|
6
|
+
export interface OcrTaskParams {
|
|
7
|
+
file_url: string;
|
|
8
|
+
mode?: 'basic' | 'advanced' | 'table' | 'handwriting';
|
|
9
|
+
custom_prompt?: string;
|
|
10
|
+
enable_cache?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* OCR 批量任务请求参数
|
|
14
|
+
*/
|
|
15
|
+
export interface OcrBatchTaskParams {
|
|
16
|
+
file_urls: string[];
|
|
17
|
+
mode?: 'basic' | 'advanced' | 'table' | 'handwriting';
|
|
18
|
+
custom_prompt?: string;
|
|
19
|
+
enable_cache?: boolean;
|
|
20
|
+
max_parallel?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* OCR 任务结果
|
|
24
|
+
*/
|
|
25
|
+
export interface OcrTaskResult {
|
|
26
|
+
raw_text?: string;
|
|
27
|
+
text?: string;
|
|
28
|
+
confidence: number;
|
|
29
|
+
pages?: Array<{
|
|
30
|
+
pageNumber: number;
|
|
31
|
+
text: string;
|
|
32
|
+
}>;
|
|
33
|
+
file_type?: string;
|
|
34
|
+
processing_time?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* OCR 结果(对外接口)
|
|
38
|
+
*/
|
|
39
|
+
export interface OcrResult {
|
|
40
|
+
text: string;
|
|
41
|
+
confidence: number;
|
|
42
|
+
pages?: Array<{
|
|
43
|
+
pageNumber: number;
|
|
44
|
+
text: string;
|
|
45
|
+
}>;
|
|
46
|
+
fileType?: string;
|
|
47
|
+
processingTime?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* OCR 服务
|
|
51
|
+
*
|
|
52
|
+
* 封装与 Python OCR 服务的交互,通过 AgentX 任务队列执行
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // 注入服务
|
|
57
|
+
* @Injectable()
|
|
58
|
+
* class MyService {
|
|
59
|
+
* constructor(private readonly ocrService: OcrService) {}
|
|
60
|
+
*
|
|
61
|
+
* async extractText(fileUrl: string) {
|
|
62
|
+
* const result = await this.ocrService.extractText(fileUrl, 'pdf');
|
|
63
|
+
* return result.text;
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare class OcrService {
|
|
69
|
+
private readonly logger;
|
|
70
|
+
private readonly agentxClient;
|
|
71
|
+
constructor(logger: Logger, agentxClient: AgentXClient);
|
|
72
|
+
/**
|
|
73
|
+
* 提取文件文本内容
|
|
74
|
+
*
|
|
75
|
+
* 流程:
|
|
76
|
+
* 1. 创建 OCR 任务
|
|
77
|
+
* 2. 等待任务完成(使用 SSE 或轮询)
|
|
78
|
+
* 3. 返回提取的文本
|
|
79
|
+
*
|
|
80
|
+
* @param fileUrl 文件 URL (必须是可访问的 URL)
|
|
81
|
+
* @param fileType 文件类型 (pdf, docx, doc, png, jpg, jpeg, etc.)
|
|
82
|
+
* @param options 可选参数
|
|
83
|
+
*/
|
|
84
|
+
extractText(fileUrl: string, fileType: string, options?: {
|
|
85
|
+
mode?: 'basic' | 'advanced' | 'table' | 'handwriting';
|
|
86
|
+
custom_prompt?: string;
|
|
87
|
+
enable_cache?: boolean;
|
|
88
|
+
extractPages?: boolean;
|
|
89
|
+
}): Promise<OcrResult>;
|
|
90
|
+
/**
|
|
91
|
+
* 批量提取文件文本
|
|
92
|
+
*
|
|
93
|
+
* @param files 文件列表
|
|
94
|
+
* @param options 可选参数
|
|
95
|
+
*/
|
|
96
|
+
extractTextBatch(files: Array<{
|
|
97
|
+
fileUrl: string;
|
|
98
|
+
fileType: string;
|
|
99
|
+
}>, options?: {
|
|
100
|
+
mode?: 'basic' | 'advanced';
|
|
101
|
+
max_parallel?: number;
|
|
102
|
+
}): Promise<Array<OcrResult | {
|
|
103
|
+
error: string;
|
|
104
|
+
fileUrl: string;
|
|
105
|
+
}>>;
|
|
106
|
+
/**
|
|
107
|
+
* 检查 OCR 服务健康状态
|
|
108
|
+
*/
|
|
109
|
+
healthCheck(): Promise<boolean>;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=ocr.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocr.service.d.ts","sourceRoot":"","sources":["../../src/ocr/ocr.service.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,UAAU;IAEc,OAAO,CAAC,QAAQ,CAAC,MAAM;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADqB,MAAM,EAAE,MAAM,EAC/C,YAAY,EAAE,YAAY;IAG7C;;;;;;;;;;;OAWG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;QACtD,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,GACA,OAAO,CAAC,SAAS,CAAC;IA0ErB;;;;;OAKG;IACG,gBAAgB,CACpB,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,EACnD,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;QAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GACA,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA2EjE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAGtC"}
|