koa-boot-runtime 1.0.0
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/aiToolRegistry.d.ts +32 -0
- package/dist/aiToolRegistry.d.ts.map +1 -0
- package/dist/aiToolRegistry.js +41 -0
- package/dist/aiToolRegistry.js.map +1 -0
- package/dist/build/routes.d.ts +3 -0
- package/dist/build/routes.d.ts.map +1 -0
- package/dist/build/routes.js +4055 -0
- package/dist/build/routes.js.map +1 -0
- package/dist/build/swagger.json +6752 -0
- package/dist/common/decorators/index.d.ts +2 -0
- package/dist/common/decorators/index.d.ts.map +1 -0
- package/dist/common/decorators/index.js +18 -0
- package/dist/common/decorators/index.js.map +1 -0
- package/dist/common/decorators/validation.d.ts +33 -0
- package/dist/common/decorators/validation.d.ts.map +1 -0
- package/dist/common/decorators/validation.js +215 -0
- package/dist/common/decorators/validation.js.map +1 -0
- package/dist/common/dto.d.ts +17 -0
- package/dist/common/dto.d.ts.map +1 -0
- package/dist/common/dto.js +28 -0
- package/dist/common/dto.js.map +1 -0
- package/dist/common/enums/base.d.ts +14 -0
- package/dist/common/enums/base.d.ts.map +1 -0
- package/dist/common/enums/base.js +14 -0
- package/dist/common/enums/base.js.map +1 -0
- package/dist/common/enums/index.d.ts +8 -0
- package/dist/common/enums/index.d.ts.map +1 -0
- package/dist/common/enums/index.js +24 -0
- package/dist/common/enums/index.js.map +1 -0
- package/dist/common/enums/system.d.ts +14 -0
- package/dist/common/enums/system.d.ts.map +1 -0
- package/dist/common/enums/system.js +14 -0
- package/dist/common/enums/system.js.map +1 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +25 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/paginate.d.ts +49 -0
- package/dist/common/paginate.d.ts.map +1 -0
- package/dist/common/paginate.js +47 -0
- package/dist/common/paginate.js.map +1 -0
- package/dist/common/types/index.d.ts +8 -0
- package/dist/common/types/index.d.ts.map +1 -0
- package/dist/common/types/index.js +18 -0
- package/dist/common/types/index.js.map +1 -0
- package/dist/common/types/pagination.d.ts +76 -0
- package/dist/common/types/pagination.d.ts.map +1 -0
- package/dist/common/types/pagination.js +29 -0
- package/dist/common/types/pagination.js.map +1 -0
- package/dist/common/types/request.d.ts +66 -0
- package/dist/common/types/request.d.ts.map +1 -0
- package/dist/common/types/request.js +4 -0
- package/dist/common/types/request.js.map +1 -0
- package/dist/common/types/response.d.ts +109 -0
- package/dist/common/types/response.d.ts.map +1 -0
- package/dist/common/types/response.js +50 -0
- package/dist/common/types/response.js.map +1 -0
- package/dist/common/types/sort.d.ts +71 -0
- package/dist/common/types/sort.d.ts.map +1 -0
- package/dist/common/types/sort.js +46 -0
- package/dist/common/types/sort.js.map +1 -0
- package/dist/config/database.d.ts +12 -0
- package/dist/config/database.d.ts.map +1 -0
- package/dist/config/database.js +24 -0
- package/dist/config/database.js.map +1 -0
- package/dist/config/index.d.ts +144 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +180 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/ioc.d.ts +6 -0
- package/dist/config/ioc.d.ts.map +1 -0
- package/dist/config/ioc.js +29 -0
- package/dist/config/ioc.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +3 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +52 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/errorHandler.d.ts +3 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +40 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/logger.d.ts +3 -0
- package/dist/middleware/logger.d.ts.map +1 -0
- package/dist/middleware/logger.js +13 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware/operationLogger.d.ts +11 -0
- package/dist/middleware/operationLogger.d.ts.map +1 -0
- package/dist/middleware/operationLogger.js +155 -0
- package/dist/middleware/operationLogger.js.map +1 -0
- package/dist/middleware/permission.d.ts +23 -0
- package/dist/middleware/permission.d.ts.map +1 -0
- package/dist/middleware/permission.js +153 -0
- package/dist/middleware/permission.js.map +1 -0
- package/dist/middleware/validate.d.ts +7 -0
- package/dist/middleware/validate.d.ts.map +1 -0
- package/dist/middleware/validate.js +53 -0
- package/dist/middleware/validate.js.map +1 -0
- package/dist/middlewares.d.ts +15 -0
- package/dist/middlewares.d.ts.map +1 -0
- package/dist/middlewares.js +24 -0
- package/dist/middlewares.js.map +1 -0
- package/dist/registerRoutes.d.ts +15 -0
- package/dist/registerRoutes.d.ts.map +1 -0
- package/dist/registerRoutes.js +83 -0
- package/dist/registerRoutes.js.map +1 -0
- package/dist/system/department/department.controller.d.ts +46 -0
- package/dist/system/department/department.controller.d.ts.map +1 -0
- package/dist/system/department/department.controller.js +203 -0
- package/dist/system/department/department.controller.js.map +1 -0
- package/dist/system/department/department.model.d.ts +33 -0
- package/dist/system/department/department.model.d.ts.map +1 -0
- package/dist/system/department/department.model.js +171 -0
- package/dist/system/department/department.model.js.map +1 -0
- package/dist/system/department/department.service.d.ts +40 -0
- package/dist/system/department/department.service.d.ts.map +1 -0
- package/dist/system/department/department.service.js +99 -0
- package/dist/system/department/department.service.js.map +1 -0
- package/dist/system/dictItem/dictItem.controller.d.ts +42 -0
- package/dist/system/dictItem/dictItem.controller.d.ts.map +1 -0
- package/dist/system/dictItem/dictItem.controller.js +167 -0
- package/dist/system/dictItem/dictItem.controller.js.map +1 -0
- package/dist/system/dictItem/dictItem.model.d.ts +38 -0
- package/dist/system/dictItem/dictItem.model.d.ts.map +1 -0
- package/dist/system/dictItem/dictItem.model.js +180 -0
- package/dist/system/dictItem/dictItem.model.js.map +1 -0
- package/dist/system/dictItem/dictItem.service.d.ts +33 -0
- package/dist/system/dictItem/dictItem.service.d.ts.map +1 -0
- package/dist/system/dictItem/dictItem.service.js +97 -0
- package/dist/system/dictItem/dictItem.service.js.map +1 -0
- package/dist/system/dictType/dictType.controller.d.ts +47 -0
- package/dist/system/dictType/dictType.controller.d.ts.map +1 -0
- package/dist/system/dictType/dictType.controller.js +174 -0
- package/dist/system/dictType/dictType.controller.js.map +1 -0
- package/dist/system/dictType/dictType.model.d.ts +31 -0
- package/dist/system/dictType/dictType.model.d.ts.map +1 -0
- package/dist/system/dictType/dictType.model.js +127 -0
- package/dist/system/dictType/dictType.model.js.map +1 -0
- package/dist/system/dictType/dictType.service.d.ts +27 -0
- package/dist/system/dictType/dictType.service.d.ts.map +1 -0
- package/dist/system/dictType/dictType.service.js +74 -0
- package/dist/system/dictType/dictType.service.js.map +1 -0
- package/dist/system/employee/employee.controller.d.ts +16 -0
- package/dist/system/employee/employee.controller.d.ts.map +1 -0
- package/dist/system/employee/employee.controller.js +111 -0
- package/dist/system/employee/employee.controller.js.map +1 -0
- package/dist/system/employee/employee.model.d.ts +34 -0
- package/dist/system/employee/employee.model.d.ts.map +1 -0
- package/dist/system/employee/employee.model.js +186 -0
- package/dist/system/employee/employee.model.js.map +1 -0
- package/dist/system/employee/employee.service.d.ts +16 -0
- package/dist/system/employee/employee.service.d.ts.map +1 -0
- package/dist/system/employee/employee.service.js +49 -0
- package/dist/system/employee/employee.service.js.map +1 -0
- package/dist/system/fileUpload/fileUpload.controller.d.ts +35 -0
- package/dist/system/fileUpload/fileUpload.controller.d.ts.map +1 -0
- package/dist/system/fileUpload/fileUpload.controller.js +228 -0
- package/dist/system/fileUpload/fileUpload.controller.js.map +1 -0
- package/dist/system/fileUpload/fileUpload.model.d.ts +13 -0
- package/dist/system/fileUpload/fileUpload.model.d.ts.map +1 -0
- package/dist/system/fileUpload/fileUpload.model.js +71 -0
- package/dist/system/fileUpload/fileUpload.model.js.map +1 -0
- package/dist/system/fileUpload/fileUpload.service.d.ts +29 -0
- package/dist/system/fileUpload/fileUpload.service.d.ts.map +1 -0
- package/dist/system/fileUpload/fileUpload.service.js +61 -0
- package/dist/system/fileUpload/fileUpload.service.js.map +1 -0
- package/dist/system/loginLog/loginLog.controller.d.ts +21 -0
- package/dist/system/loginLog/loginLog.controller.d.ts.map +1 -0
- package/dist/system/loginLog/loginLog.controller.js +149 -0
- package/dist/system/loginLog/loginLog.controller.js.map +1 -0
- package/dist/system/loginLog/loginLog.model.d.ts +26 -0
- package/dist/system/loginLog/loginLog.model.d.ts.map +1 -0
- package/dist/system/loginLog/loginLog.model.js +150 -0
- package/dist/system/loginLog/loginLog.model.js.map +1 -0
- package/dist/system/loginLog/loginLog.service.d.ts +24 -0
- package/dist/system/loginLog/loginLog.service.d.ts.map +1 -0
- package/dist/system/loginLog/loginLog.service.js +87 -0
- package/dist/system/loginLog/loginLog.service.js.map +1 -0
- package/dist/system/menu/menu.controller.d.ts +46 -0
- package/dist/system/menu/menu.controller.d.ts.map +1 -0
- package/dist/system/menu/menu.controller.js +203 -0
- package/dist/system/menu/menu.controller.js.map +1 -0
- package/dist/system/menu/menu.model.d.ts +45 -0
- package/dist/system/menu/menu.model.d.ts.map +1 -0
- package/dist/system/menu/menu.model.js +254 -0
- package/dist/system/menu/menu.model.js.map +1 -0
- package/dist/system/menu/menu.service.d.ts +40 -0
- package/dist/system/menu/menu.service.d.ts.map +1 -0
- package/dist/system/menu/menu.service.js +101 -0
- package/dist/system/menu/menu.service.js.map +1 -0
- package/dist/system/operationLog/operationLog.controller.d.ts +34 -0
- package/dist/system/operationLog/operationLog.controller.d.ts.map +1 -0
- package/dist/system/operationLog/operationLog.controller.js +126 -0
- package/dist/system/operationLog/operationLog.controller.js.map +1 -0
- package/dist/system/operationLog/operationLog.model.d.ts +38 -0
- package/dist/system/operationLog/operationLog.model.d.ts.map +1 -0
- package/dist/system/operationLog/operationLog.model.js +224 -0
- package/dist/system/operationLog/operationLog.model.js.map +1 -0
- package/dist/system/operationLog/operationLog.service.d.ts +46 -0
- package/dist/system/operationLog/operationLog.service.d.ts.map +1 -0
- package/dist/system/operationLog/operationLog.service.js +109 -0
- package/dist/system/operationLog/operationLog.service.js.map +1 -0
- package/dist/system/permission/permission.controller.d.ts +18 -0
- package/dist/system/permission/permission.controller.d.ts.map +1 -0
- package/dist/system/permission/permission.controller.js +160 -0
- package/dist/system/permission/permission.controller.js.map +1 -0
- package/dist/system/permission/permission.model.d.ts +39 -0
- package/dist/system/permission/permission.model.d.ts.map +1 -0
- package/dist/system/permission/permission.model.js +220 -0
- package/dist/system/permission/permission.model.js.map +1 -0
- package/dist/system/permission/permission.service.d.ts +40 -0
- package/dist/system/permission/permission.service.d.ts.map +1 -0
- package/dist/system/permission/permission.service.js +105 -0
- package/dist/system/permission/permission.service.js.map +1 -0
- package/dist/system/role/role.controller.d.ts +16 -0
- package/dist/system/role/role.controller.d.ts.map +1 -0
- package/dist/system/role/role.controller.js +123 -0
- package/dist/system/role/role.controller.js.map +1 -0
- package/dist/system/role/role.model.d.ts +25 -0
- package/dist/system/role/role.model.d.ts.map +1 -0
- package/dist/system/role/role.model.js +133 -0
- package/dist/system/role/role.model.js.map +1 -0
- package/dist/system/role/role.service.d.ts +17 -0
- package/dist/system/role/role.service.d.ts.map +1 -0
- package/dist/system/role/role.service.js +50 -0
- package/dist/system/role/role.service.js.map +1 -0
- package/dist/system/roleMenu/roleMenu.controller.d.ts +26 -0
- package/dist/system/roleMenu/roleMenu.controller.d.ts.map +1 -0
- package/dist/system/roleMenu/roleMenu.controller.js +83 -0
- package/dist/system/roleMenu/roleMenu.controller.js.map +1 -0
- package/dist/system/roleMenu/roleMenu.model.d.ts +35 -0
- package/dist/system/roleMenu/roleMenu.model.d.ts.map +1 -0
- package/dist/system/roleMenu/roleMenu.model.js +56 -0
- package/dist/system/roleMenu/roleMenu.model.js.map +1 -0
- package/dist/system/roleMenu/roleMenu.service.d.ts +35 -0
- package/dist/system/roleMenu/roleMenu.service.d.ts.map +1 -0
- package/dist/system/roleMenu/roleMenu.service.js +77 -0
- package/dist/system/roleMenu/roleMenu.service.js.map +1 -0
- package/dist/system/rolePermission/rolePermission.controller.d.ts +36 -0
- package/dist/system/rolePermission/rolePermission.controller.d.ts.map +1 -0
- package/dist/system/rolePermission/rolePermission.controller.js +115 -0
- package/dist/system/rolePermission/rolePermission.controller.js.map +1 -0
- package/dist/system/rolePermission/rolePermission.model.d.ts +45 -0
- package/dist/system/rolePermission/rolePermission.model.d.ts.map +1 -0
- package/dist/system/rolePermission/rolePermission.model.js +87 -0
- package/dist/system/rolePermission/rolePermission.model.js.map +1 -0
- package/dist/system/rolePermission/rolePermission.service.d.ts +50 -0
- package/dist/system/rolePermission/rolePermission.service.d.ts.map +1 -0
- package/dist/system/rolePermission/rolePermission.service.js +110 -0
- package/dist/system/rolePermission/rolePermission.service.js.map +1 -0
- package/dist/system/user/user.controller.d.ts +66 -0
- package/dist/system/user/user.controller.d.ts.map +1 -0
- package/dist/system/user/user.controller.js +322 -0
- package/dist/system/user/user.controller.js.map +1 -0
- package/dist/system/user/user.model.d.ts +58 -0
- package/dist/system/user/user.model.d.ts.map +1 -0
- package/dist/system/user/user.model.js +225 -0
- package/dist/system/user/user.model.js.map +1 -0
- package/dist/system/user/user.service.d.ts +73 -0
- package/dist/system/user/user.service.d.ts.map +1 -0
- package/dist/system/user/user.service.js +388 -0
- package/dist/system/user/user.service.js.map +1 -0
- package/dist/system/userRole/userRole.controller.d.ts +33 -0
- package/dist/system/userRole/userRole.controller.d.ts.map +1 -0
- package/dist/system/userRole/userRole.controller.js +231 -0
- package/dist/system/userRole/userRole.controller.js.map +1 -0
- package/dist/system/userRole/userRole.model.d.ts +14 -0
- package/dist/system/userRole/userRole.model.d.ts.map +1 -0
- package/dist/system/userRole/userRole.model.js +58 -0
- package/dist/system/userRole/userRole.model.js.map +1 -0
- package/dist/system/userRole/userRole.service.d.ts +29 -0
- package/dist/system/userRole/userRole.service.d.ts.map +1 -0
- package/dist/system/userRole/userRole.service.js +135 -0
- package/dist/system/userRole/userRole.service.js.map +1 -0
- package/dist/systemServices.d.ts +23 -0
- package/dist/systemServices.d.ts.map +1 -0
- package/dist/systemServices.js +40 -0
- package/dist/systemServices.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +70 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/aiClient.d.ts +55 -0
- package/dist/utils/aiClient.d.ts.map +1 -0
- package/dist/utils/aiClient.js +59 -0
- package/dist/utils/aiClient.js.map +1 -0
- package/dist/utils/banner.d.ts +10 -0
- package/dist/utils/banner.d.ts.map +1 -0
- package/dist/utils/banner.js +40 -0
- package/dist/utils/banner.js.map +1 -0
- package/dist/utils/crypto.d.ts +49 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/crypto.js +113 -0
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/dataScope.d.ts +41 -0
- package/dist/utils/dataScope.d.ts.map +1 -0
- package/dist/utils/dataScope.js +130 -0
- package/dist/utils/dataScope.js.map +1 -0
- package/dist/utils/date.d.ts +48 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +145 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/emailClient.d.ts +15 -0
- package/dist/utils/emailClient.d.ts.map +1 -0
- package/dist/utils/emailClient.js +71 -0
- package/dist/utils/emailClient.js.map +1 -0
- package/dist/utils/jwt.d.ts +10 -0
- package/dist/utils/jwt.d.ts.map +1 -0
- package/dist/utils/jwt.js +31 -0
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/logger.d.ts +34 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +108 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/ossClient.d.ts +38 -0
- package/dist/utils/ossClient.d.ts.map +1 -0
- package/dist/utils/ossClient.js +92 -0
- package/dist/utils/ossClient.js.map +1 -0
- package/dist/utils/permissionSync.d.ts +10 -0
- package/dist/utils/permissionSync.d.ts.map +1 -0
- package/dist/utils/permissionSync.js +11 -0
- package/dist/utils/permissionSync.js.map +1 -0
- package/dist/utils/redisClient.d.ts +91 -0
- package/dist/utils/redisClient.d.ts.map +1 -0
- package/dist/utils/redisClient.js +246 -0
- package/dist/utils/redisClient.js.map +1 -0
- package/dist/utils/sequence.d.ts +53 -0
- package/dist/utils/sequence.d.ts.map +1 -0
- package/dist/utils/sequence.js +109 -0
- package/dist/utils/sequence.js.map +1 -0
- package/dist/utils/smsClient.d.ts +15 -0
- package/dist/utils/smsClient.d.ts.map +1 -0
- package/dist/utils/smsClient.js +115 -0
- package/dist/utils/smsClient.js.map +1 -0
- package/dist/utils/supabaseClient.d.ts +5 -0
- package/dist/utils/supabaseClient.d.ts.map +1 -0
- package/dist/utils/supabaseClient.js +17 -0
- package/dist/utils/supabaseClient.js.map +1 -0
- package/dist/utils/unipushClient.d.ts +12 -0
- package/dist/utils/unipushClient.d.ts.map +1 -0
- package/dist/utils/unipushClient.js +109 -0
- package/dist/utils/unipushClient.js.map +1 -0
- package/dist/utils/validator.d.ts +74 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +173 -0
- package/dist/utils/validator.js.map +1 -0
- package/dist/utils/wecom.d.ts +20 -0
- package/dist/utils/wecom.d.ts.map +1 -0
- package/dist/utils/wecom.js +126 -0
- package/dist/utils/wecom.js.map +1 -0
- package/package.json +84 -0
- package/templates/schema.system.prisma +283 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 格式化日期为指定模式
|
|
3
|
+
*
|
|
4
|
+
* 支持的占位符:
|
|
5
|
+
* YYYY - 四位年份
|
|
6
|
+
* MM - 两位月份 (01-12)
|
|
7
|
+
* DD - 两位日期 (01-31)
|
|
8
|
+
* HH - 两位小时 (00-23)
|
|
9
|
+
* mm - 两位分钟 (00-59)
|
|
10
|
+
* ss - 两位秒数 (00-59)
|
|
11
|
+
* SSS - 三位毫秒
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatDate(date: Date | string | number, pattern?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* 获取相对时间描述(如 "3分钟前"、"2小时前")
|
|
16
|
+
*/
|
|
17
|
+
export declare function timeAgo(date: Date | string | number): string;
|
|
18
|
+
/**
|
|
19
|
+
* 增减天数
|
|
20
|
+
*/
|
|
21
|
+
export declare function addDays(date: Date | string | number, days: number): Date;
|
|
22
|
+
/**
|
|
23
|
+
* 计算两个日期之间的天数差(绝对值)
|
|
24
|
+
*/
|
|
25
|
+
export declare function diffDays(date1: Date | string | number, date2: Date | string | number): number;
|
|
26
|
+
/**
|
|
27
|
+
* 获取当天起始时间 (00:00:00.000)
|
|
28
|
+
*/
|
|
29
|
+
export declare function startOfDay(date?: Date | string | number): Date;
|
|
30
|
+
/**
|
|
31
|
+
* 获取当天结束时间 (23:59:59.999)
|
|
32
|
+
*/
|
|
33
|
+
export declare function endOfDay(date?: Date | string | number): Date;
|
|
34
|
+
/**
|
|
35
|
+
* 判断是否为同一天
|
|
36
|
+
*/
|
|
37
|
+
export declare function isSameDay(date1: Date | string | number, date2: Date | string | number): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 判断日期是否在指定范围内
|
|
40
|
+
*/
|
|
41
|
+
export declare function isInRange(date: Date | string | number, start: Date | string | number, end: Date | string | number): boolean;
|
|
42
|
+
/** 格式化为 YYYY-MM-DD */
|
|
43
|
+
export declare function formatDateShort(date?: Date | string | number): string;
|
|
44
|
+
/** 格式化为 YYYY-MM-DD HH:mm:ss */
|
|
45
|
+
export declare function formatDateTime(date?: Date | string | number): string;
|
|
46
|
+
/** 格式化为 YYYY-MM-DD HH:mm:ss.SSS */
|
|
47
|
+
export declare function formatDateTimeFull(date?: Date | string | number): string;
|
|
48
|
+
//# sourceMappingURL=date.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/utils/date.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,GAAE,MAA8B,GAAG,MAAM,CAyBxG;AAID;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAoB5D;AAID;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAK7F;AAID;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAAmB,GAAG,IAAI,CAI1E;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAAmB,GAAG,IAAI,CAIxE;AAID;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAQ/F;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAC5B,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAC7B,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAC1B,OAAO,CAKT;AAID,sBAAsB;AACtB,wBAAgB,eAAe,CAAC,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAAmB,GAAG,MAAM,CAEjF;AAED,+BAA+B;AAC/B,wBAAgB,cAAc,CAAC,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAAmB,GAAG,MAAM,CAEhF;AAED,mCAAmC;AACnC,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAAmB,GAAG,MAAM,CAEpF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============ 日期格式化工具 ============
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.formatDate = formatDate;
|
|
5
|
+
exports.timeAgo = timeAgo;
|
|
6
|
+
exports.addDays = addDays;
|
|
7
|
+
exports.diffDays = diffDays;
|
|
8
|
+
exports.startOfDay = startOfDay;
|
|
9
|
+
exports.endOfDay = endOfDay;
|
|
10
|
+
exports.isSameDay = isSameDay;
|
|
11
|
+
exports.isInRange = isInRange;
|
|
12
|
+
exports.formatDateShort = formatDateShort;
|
|
13
|
+
exports.formatDateTime = formatDateTime;
|
|
14
|
+
exports.formatDateTimeFull = formatDateTimeFull;
|
|
15
|
+
/**
|
|
16
|
+
* 格式化日期为指定模式
|
|
17
|
+
*
|
|
18
|
+
* 支持的占位符:
|
|
19
|
+
* YYYY - 四位年份
|
|
20
|
+
* MM - 两位月份 (01-12)
|
|
21
|
+
* DD - 两位日期 (01-31)
|
|
22
|
+
* HH - 两位小时 (00-23)
|
|
23
|
+
* mm - 两位分钟 (00-59)
|
|
24
|
+
* ss - 两位秒数 (00-59)
|
|
25
|
+
* SSS - 三位毫秒
|
|
26
|
+
*/
|
|
27
|
+
function formatDate(date, pattern = 'YYYY-MM-DD HH:mm:ss') {
|
|
28
|
+
const d = date instanceof Date ? date : new Date(date);
|
|
29
|
+
if (isNaN(d.getTime())) {
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
const pad = (n, len = 2) => String(n).padStart(len, '0');
|
|
33
|
+
const tokens = {
|
|
34
|
+
YYYY: String(d.getFullYear()),
|
|
35
|
+
MM: pad(d.getMonth() + 1),
|
|
36
|
+
DD: pad(d.getDate()),
|
|
37
|
+
HH: pad(d.getHours()),
|
|
38
|
+
mm: pad(d.getMinutes()),
|
|
39
|
+
ss: pad(d.getSeconds()),
|
|
40
|
+
SSS: pad(d.getMilliseconds(), 3),
|
|
41
|
+
};
|
|
42
|
+
let result = pattern;
|
|
43
|
+
// 先替换长 token 再替换短 token,避免 SSS 被 SS 匹配
|
|
44
|
+
for (const key of Object.keys(tokens).sort((a, b) => b.length - a.length)) {
|
|
45
|
+
result = result.replace(key, tokens[key]);
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
// ============ 相对时间 ============
|
|
50
|
+
/**
|
|
51
|
+
* 获取相对时间描述(如 "3分钟前"、"2小时前")
|
|
52
|
+
*/
|
|
53
|
+
function timeAgo(date) {
|
|
54
|
+
const d = date instanceof Date ? date : new Date(date);
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
const diff = now - d.getTime();
|
|
57
|
+
if (diff < 0)
|
|
58
|
+
return '刚刚';
|
|
59
|
+
const seconds = Math.floor(diff / 1000);
|
|
60
|
+
const minutes = Math.floor(seconds / 60);
|
|
61
|
+
const hours = Math.floor(minutes / 60);
|
|
62
|
+
const days = Math.floor(hours / 24);
|
|
63
|
+
const months = Math.floor(days / 30);
|
|
64
|
+
const years = Math.floor(months / 12);
|
|
65
|
+
if (years > 0)
|
|
66
|
+
return `${years}年前`;
|
|
67
|
+
if (months > 0)
|
|
68
|
+
return `${months}个月前`;
|
|
69
|
+
if (days > 0)
|
|
70
|
+
return `${days}天前`;
|
|
71
|
+
if (hours > 0)
|
|
72
|
+
return `${hours}小时前`;
|
|
73
|
+
if (minutes > 0)
|
|
74
|
+
return `${minutes}分钟前`;
|
|
75
|
+
return '刚刚';
|
|
76
|
+
}
|
|
77
|
+
// ============ 日期计算 ============
|
|
78
|
+
/**
|
|
79
|
+
* 增减天数
|
|
80
|
+
*/
|
|
81
|
+
function addDays(date, days) {
|
|
82
|
+
const d = new Date(date instanceof Date ? date : new Date(date));
|
|
83
|
+
d.setDate(d.getDate() + days);
|
|
84
|
+
return d;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 计算两个日期之间的天数差(绝对值)
|
|
88
|
+
*/
|
|
89
|
+
function diffDays(date1, date2) {
|
|
90
|
+
const d1 = date1 instanceof Date ? date1 : new Date(date1);
|
|
91
|
+
const d2 = date2 instanceof Date ? date2 : new Date(date2);
|
|
92
|
+
const diff = Math.abs(d1.getTime() - d2.getTime());
|
|
93
|
+
return Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
94
|
+
}
|
|
95
|
+
// ============ 日期边界 ============
|
|
96
|
+
/**
|
|
97
|
+
* 获取当天起始时间 (00:00:00.000)
|
|
98
|
+
*/
|
|
99
|
+
function startOfDay(date = new Date()) {
|
|
100
|
+
const d = new Date(date instanceof Date ? date : new Date(date));
|
|
101
|
+
d.setHours(0, 0, 0, 0);
|
|
102
|
+
return d;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 获取当天结束时间 (23:59:59.999)
|
|
106
|
+
*/
|
|
107
|
+
function endOfDay(date = new Date()) {
|
|
108
|
+
const d = new Date(date instanceof Date ? date : new Date(date));
|
|
109
|
+
d.setHours(23, 59, 59, 999);
|
|
110
|
+
return d;
|
|
111
|
+
}
|
|
112
|
+
// ============ 判断 ============
|
|
113
|
+
/**
|
|
114
|
+
* 判断是否为同一天
|
|
115
|
+
*/
|
|
116
|
+
function isSameDay(date1, date2) {
|
|
117
|
+
const d1 = date1 instanceof Date ? date1 : new Date(date1);
|
|
118
|
+
const d2 = date2 instanceof Date ? date2 : new Date(date2);
|
|
119
|
+
return (d1.getFullYear() === d2.getFullYear() &&
|
|
120
|
+
d1.getMonth() === d2.getMonth() &&
|
|
121
|
+
d1.getDate() === d2.getDate());
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 判断日期是否在指定范围内
|
|
125
|
+
*/
|
|
126
|
+
function isInRange(date, start, end) {
|
|
127
|
+
const ts = new Date(date instanceof Date ? date : new Date(date)).getTime();
|
|
128
|
+
const s = new Date(start instanceof Date ? start : new Date(start)).getTime();
|
|
129
|
+
const e = new Date(end instanceof Date ? end : new Date(end)).getTime();
|
|
130
|
+
return ts >= s && ts <= e;
|
|
131
|
+
}
|
|
132
|
+
// ============ 快捷格式化 ============
|
|
133
|
+
/** 格式化为 YYYY-MM-DD */
|
|
134
|
+
function formatDateShort(date = new Date()) {
|
|
135
|
+
return formatDate(date, 'YYYY-MM-DD');
|
|
136
|
+
}
|
|
137
|
+
/** 格式化为 YYYY-MM-DD HH:mm:ss */
|
|
138
|
+
function formatDateTime(date = new Date()) {
|
|
139
|
+
return formatDate(date, 'YYYY-MM-DD HH:mm:ss');
|
|
140
|
+
}
|
|
141
|
+
/** 格式化为 YYYY-MM-DD HH:mm:ss.SSS */
|
|
142
|
+
function formatDateTimeFull(date = new Date()) {
|
|
143
|
+
return formatDate(date, 'YYYY-MM-DD HH:mm:ss.SSS');
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=date.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/utils/date.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** 校验 SMTP 配置是否完整(不抛出,返回缺失项说明;供调用方决定是否跳过) */
|
|
2
|
+
export declare function isEmailConfigured(): {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
reason?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* 发送单封邮件
|
|
8
|
+
* @param to 接收邮箱
|
|
9
|
+
* @param subject 邮件主题
|
|
10
|
+
* @param html 邮件正文(HTML 富文本)
|
|
11
|
+
*/
|
|
12
|
+
export declare function sendEmail(to: string, subject: string, html: string): Promise<void>;
|
|
13
|
+
/** 批量发送邮件(逐条发送;SMTP 无批量接口) */
|
|
14
|
+
export declare function sendEmailBatch(emails: string[], subject: string, html: string): Promise<number>;
|
|
15
|
+
//# sourceMappingURL=emailClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emailClient.d.ts","sourceRoot":"","sources":["../../src/utils/emailClient.ts"],"names":[],"mappings":"AAQA,6CAA6C;AAC7C,wBAAgB,iBAAiB,IAAI;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAMpE;AAoBD;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxF;AAED,8BAA8B;AAC9B,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYrG"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isEmailConfigured = isEmailConfigured;
|
|
7
|
+
exports.sendEmail = sendEmail;
|
|
8
|
+
exports.sendEmailBatch = sendEmailBatch;
|
|
9
|
+
// SMTP 邮件发送工具(V6.2):外部通知方式选择 EXTERNAL_NOTIFY_CHANNEL=email 时使用
|
|
10
|
+
// 依赖 nodemailer(标准 SMTP 协议,支持阿里云/腾讯云/网易等企业邮箱或自建 SMTP 服务)
|
|
11
|
+
const nodemailer_1 = __importDefault(require("nodemailer"));
|
|
12
|
+
const config_1 = __importDefault(require("../config"));
|
|
13
|
+
const logger_1 = require("./logger");
|
|
14
|
+
let transporter = null;
|
|
15
|
+
/** 校验 SMTP 配置是否完整(不抛出,返回缺失项说明;供调用方决定是否跳过) */
|
|
16
|
+
function isEmailConfigured() {
|
|
17
|
+
const mail = config_1.default.email;
|
|
18
|
+
if (!mail.host)
|
|
19
|
+
return { ok: false, reason: 'SMTP 服务器 EMAIL_SMTP_HOST 未配置' };
|
|
20
|
+
if (!mail.user || !mail.pass)
|
|
21
|
+
return { ok: false, reason: 'SMTP 账号/授权码 EMAIL_SMTP_USER / EMAIL_SMTP_PASS 未配置' };
|
|
22
|
+
if (!mail.from)
|
|
23
|
+
return { ok: false, reason: '发件人 EMAIL_FROM 未配置' };
|
|
24
|
+
return { ok: true };
|
|
25
|
+
}
|
|
26
|
+
/** 获取或初始化 SMTP 客户端(单例) */
|
|
27
|
+
function getTransporter() {
|
|
28
|
+
if (transporter)
|
|
29
|
+
return transporter;
|
|
30
|
+
const mail = config_1.default.email;
|
|
31
|
+
if (!mail.host || !mail.user || !mail.pass) {
|
|
32
|
+
throw new Error('SMTP 配置不完整,请检查 EMAIL_SMTP_HOST / EMAIL_SMTP_USER / EMAIL_SMTP_PASS');
|
|
33
|
+
}
|
|
34
|
+
transporter = nodemailer_1.default.createTransport({
|
|
35
|
+
host: mail.host,
|
|
36
|
+
port: mail.port,
|
|
37
|
+
// true = 465 端口 SSL/TLS(默认);false = 587 端口 STARTTLS
|
|
38
|
+
secure: mail.secure,
|
|
39
|
+
auth: { user: mail.user, pass: mail.pass },
|
|
40
|
+
});
|
|
41
|
+
logger_1.logger.info(`[EMAIL] SMTP 客户端已初始化(${mail.host}:${mail.port} secure=${mail.secure})`);
|
|
42
|
+
return transporter;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 发送单封邮件
|
|
46
|
+
* @param to 接收邮箱
|
|
47
|
+
* @param subject 邮件主题
|
|
48
|
+
* @param html 邮件正文(HTML 富文本)
|
|
49
|
+
*/
|
|
50
|
+
async function sendEmail(to, subject, html) {
|
|
51
|
+
const mail = config_1.default.email;
|
|
52
|
+
const tr = getTransporter();
|
|
53
|
+
await tr.sendMail({ from: mail.from, to, subject, html });
|
|
54
|
+
}
|
|
55
|
+
/** 批量发送邮件(逐条发送;SMTP 无批量接口) */
|
|
56
|
+
async function sendEmailBatch(emails, subject, html) {
|
|
57
|
+
let sent = 0;
|
|
58
|
+
for (const email of emails) {
|
|
59
|
+
if (!email)
|
|
60
|
+
continue;
|
|
61
|
+
try {
|
|
62
|
+
await sendEmail(email, subject, html);
|
|
63
|
+
sent++;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
logger_1.logger.warn(`[EMAIL] ${email} 发送失败:`, e.message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return sent;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=emailClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emailClient.js","sourceRoot":"","sources":["../../src/utils/emailClient.ts"],"names":[],"mappings":";;;;;AASA,8CAMC;AA0BD,8BAIC;AAGD,wCAYC;AA5DD,+DAA+D;AAC/D,yDAAyD;AACzD,4DAAqD;AACrD,uDAA+B;AAC/B,qCAAkC;AAElC,IAAI,WAAW,GAAuB,IAAI,CAAC;AAE3C,6CAA6C;AAC7C,SAAgB,iBAAiB;IAC/B,MAAM,IAAI,GAAG,gBAAM,CAAC,KAAK,CAAC;IAC1B,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;IAC7E,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mDAAmD,EAAE,CAAC;IAChH,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IACnE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,0BAA0B;AAC1B,SAAS,cAAc;IACrB,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,MAAM,IAAI,GAAG,gBAAM,CAAC,KAAK,CAAC;IAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;IACD,WAAW,GAAG,oBAAU,CAAC,eAAe,CAAC;QACvC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,oDAAoD;QACpD,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;KAC3C,CAAC,CAAC;IACH,eAAM,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACrF,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,SAAS,CAAC,EAAU,EAAE,OAAe,EAAE,IAAY;IACvE,MAAM,IAAI,GAAG,gBAAM,CAAC,KAAK,CAAC;IAC1B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,8BAA8B;AACvB,KAAK,UAAU,cAAc,CAAC,MAAgB,EAAE,OAAe,EAAE,IAAY;IAClF,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACtC,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,eAAM,CAAC,IAAI,CAAC,WAAW,KAAK,QAAQ,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface JwtPayload {
|
|
2
|
+
id: string;
|
|
3
|
+
username: string;
|
|
4
|
+
/** 用户拥有的角色编码列表(通过 sys_user_roles 关联获取) */
|
|
5
|
+
roles: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function signToken(payload: JwtPayload): string;
|
|
8
|
+
export declare function verifyToken(token: string): JwtPayload | null;
|
|
9
|
+
export declare function decodeToken(token: string): JwtPayload | null;
|
|
10
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAErD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAM5D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAM5D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.signToken = signToken;
|
|
7
|
+
exports.verifyToken = verifyToken;
|
|
8
|
+
exports.decodeToken = decodeToken;
|
|
9
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
10
|
+
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
|
|
11
|
+
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';
|
|
12
|
+
function signToken(payload) {
|
|
13
|
+
return jsonwebtoken_1.default.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
|
|
14
|
+
}
|
|
15
|
+
function verifyToken(token) {
|
|
16
|
+
try {
|
|
17
|
+
return jsonwebtoken_1.default.verify(token, JWT_SECRET);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function decodeToken(token) {
|
|
24
|
+
try {
|
|
25
|
+
return jsonwebtoken_1.default.decode(token);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":";;;;;AAYA,8BAEC;AAED,kCAMC;AAED,kCAMC;AA9BD,gEAA2C;AAE3C,MAAM,UAAU,GAAW,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,sCAAsC,CAAC;AAC5F,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC;AAS1D,SAAgB,SAAS,CAAC,OAAmB;IAC3C,OAAO,sBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,cAAuB,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAe,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,CAAe,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare enum LogLevel {
|
|
2
|
+
DEBUG = 0,
|
|
3
|
+
INFO = 1,
|
|
4
|
+
WARN = 2,
|
|
5
|
+
ERROR = 3,
|
|
6
|
+
SILENT = 4
|
|
7
|
+
}
|
|
8
|
+
export interface LoggerOptions {
|
|
9
|
+
/** 最低输出等级,低于此等级的日志不输出 */
|
|
10
|
+
level: LogLevel;
|
|
11
|
+
/** 是否在日志前输出时间戳 */
|
|
12
|
+
timestamp: boolean;
|
|
13
|
+
/** 是否输出调用位置(文件名:行号) */
|
|
14
|
+
caller: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class Logger {
|
|
17
|
+
private options;
|
|
18
|
+
private context;
|
|
19
|
+
constructor(context?: string, options?: Partial<LoggerOptions>);
|
|
20
|
+
/** 创建子 logger(带上下文名称) */
|
|
21
|
+
child(context: string): Logger;
|
|
22
|
+
/** 设置最低日志等级 */
|
|
23
|
+
setLevel(level: LogLevel): void;
|
|
24
|
+
private log;
|
|
25
|
+
debug(message: string, ...args: unknown[]): void;
|
|
26
|
+
info(message: string, ...args: unknown[]): void;
|
|
27
|
+
warn(message: string, ...args: unknown[]): void;
|
|
28
|
+
error(message: string, ...args: unknown[]): void;
|
|
29
|
+
/** 记录请求耗时 */
|
|
30
|
+
logRequest(method: string, url: string, status: number, duration: number): void;
|
|
31
|
+
}
|
|
32
|
+
/** 全局默认 Logger 实例 */
|
|
33
|
+
export declare const logger: Logger;
|
|
34
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAIA,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;IACT,MAAM,IAAI;CACX;AAID,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,KAAK,EAAE,QAAQ,CAAC;IAChB,kBAAkB;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,uBAAuB;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AAkCD,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,MAAc,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAKrE,yBAAyB;IACzB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAI9B,eAAe;IACf,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAM/B,OAAO,CAAC,GAAG;IAkCX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAIhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMhD,aAAa;IACb,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAIhF;AAID,qBAAqB;AACrB,eAAO,MAAM,MAAM,QAAoB,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = exports.Logger = exports.LogLevel = void 0;
|
|
4
|
+
const date_1 = require("./date");
|
|
5
|
+
// ============ 日志等级 ============
|
|
6
|
+
var LogLevel;
|
|
7
|
+
(function (LogLevel) {
|
|
8
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
9
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
10
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
11
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
12
|
+
LogLevel[LogLevel["SILENT"] = 4] = "SILENT";
|
|
13
|
+
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
|
14
|
+
const DEFAULT_OPTIONS = {
|
|
15
|
+
level: process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG,
|
|
16
|
+
timestamp: true,
|
|
17
|
+
caller: false,
|
|
18
|
+
};
|
|
19
|
+
// ============ 颜色(终端 ANSI) ============
|
|
20
|
+
const COLORS = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
dim: '\x1b[2m',
|
|
23
|
+
bright: '\x1b[1m',
|
|
24
|
+
fg: {
|
|
25
|
+
gray: '\x1b[90m',
|
|
26
|
+
cyan: '\x1b[36m',
|
|
27
|
+
green: '\x1b[32m',
|
|
28
|
+
yellow: '\x1b[33m',
|
|
29
|
+
red: '\x1b[31m',
|
|
30
|
+
magenta: '\x1b[35m',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
const LEVEL_STYLES = {
|
|
34
|
+
[LogLevel.DEBUG]: { label: 'DEBUG', color: COLORS.fg.cyan },
|
|
35
|
+
[LogLevel.INFO]: { label: 'INFO ', color: COLORS.fg.green },
|
|
36
|
+
[LogLevel.WARN]: { label: 'WARN ', color: COLORS.fg.yellow },
|
|
37
|
+
[LogLevel.ERROR]: { label: 'ERROR', color: COLORS.fg.red },
|
|
38
|
+
[LogLevel.SILENT]: { label: '', color: '' },
|
|
39
|
+
};
|
|
40
|
+
// ============ Logger 类 ============
|
|
41
|
+
class Logger {
|
|
42
|
+
options;
|
|
43
|
+
context;
|
|
44
|
+
constructor(context = 'App', options) {
|
|
45
|
+
this.context = context;
|
|
46
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
47
|
+
}
|
|
48
|
+
/** 创建子 logger(带上下文名称) */
|
|
49
|
+
child(context) {
|
|
50
|
+
return new Logger(`${this.context}:${context}`, this.options);
|
|
51
|
+
}
|
|
52
|
+
/** 设置最低日志等级 */
|
|
53
|
+
setLevel(level) {
|
|
54
|
+
this.options.level = level;
|
|
55
|
+
}
|
|
56
|
+
// ---- 核心输出 ----
|
|
57
|
+
log(level, message, ...args) {
|
|
58
|
+
if (level < this.options.level)
|
|
59
|
+
return;
|
|
60
|
+
const style = LEVEL_STYLES[level];
|
|
61
|
+
const parts = [];
|
|
62
|
+
// 时间戳
|
|
63
|
+
if (this.options.timestamp) {
|
|
64
|
+
parts.push(`${COLORS.fg.gray}${(0, date_1.formatDateTimeFull)()}${COLORS.reset}`);
|
|
65
|
+
}
|
|
66
|
+
// 等级
|
|
67
|
+
parts.push(`${style.color}${style.label}${COLORS.reset}`);
|
|
68
|
+
// 上下文
|
|
69
|
+
parts.push(`${COLORS.fg.magenta}[${this.context}]${COLORS.reset}`);
|
|
70
|
+
// 消息
|
|
71
|
+
parts.push(message);
|
|
72
|
+
const output = parts.join(' ');
|
|
73
|
+
const rest = args.length > 0 ? ' ' + args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ') : '';
|
|
74
|
+
if (level >= LogLevel.ERROR) {
|
|
75
|
+
console.error(output + rest);
|
|
76
|
+
}
|
|
77
|
+
else if (level >= LogLevel.WARN) {
|
|
78
|
+
console.warn(output + rest);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(output + rest);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// ---- 公开方法 ----
|
|
85
|
+
debug(message, ...args) {
|
|
86
|
+
this.log(LogLevel.DEBUG, message, ...args);
|
|
87
|
+
}
|
|
88
|
+
info(message, ...args) {
|
|
89
|
+
this.log(LogLevel.INFO, message, ...args);
|
|
90
|
+
}
|
|
91
|
+
warn(message, ...args) {
|
|
92
|
+
this.log(LogLevel.WARN, message, ...args);
|
|
93
|
+
}
|
|
94
|
+
error(message, ...args) {
|
|
95
|
+
this.log(LogLevel.ERROR, message, ...args);
|
|
96
|
+
}
|
|
97
|
+
// ---- 便捷方法 ----
|
|
98
|
+
/** 记录请求耗时 */
|
|
99
|
+
logRequest(method, url, status, duration) {
|
|
100
|
+
const level = status >= 500 ? LogLevel.ERROR : status >= 400 ? LogLevel.WARN : LogLevel.INFO;
|
|
101
|
+
this.log(level, `${method} ${url} ${status} - ${duration}ms`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.Logger = Logger;
|
|
105
|
+
// ============ 默认导出 ============
|
|
106
|
+
/** 全局默认 Logger 实例 */
|
|
107
|
+
exports.logger = new Logger('App');
|
|
108
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import OSS from 'ali-oss';
|
|
2
|
+
/** 获取或初始化 OSS 客户端(单例) */
|
|
3
|
+
export declare function getOssClient(): OSS;
|
|
4
|
+
/**
|
|
5
|
+
* 构建 OSS 存储路径:uploads/YYYY-MM/{timestamp36}{random4}_{originalName}
|
|
6
|
+
* 路径唯一性由时间戳保证,原始文件名保留可读性。
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildOssPath(originalName: string): string;
|
|
9
|
+
interface UploadResult {
|
|
10
|
+
/** OSS 访问 URL */
|
|
11
|
+
url: string;
|
|
12
|
+
/** OSS 返回的文件 ETag(内容哈希),用作 fileNo */
|
|
13
|
+
etag: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 上传文件到 OSS
|
|
17
|
+
* @param fileBuffer 文件二进制内容
|
|
18
|
+
* @param ossPath OSS 存储路径
|
|
19
|
+
* @param mimeType MIME 类型
|
|
20
|
+
* @returns { url, etag } — etag 即 OSS 返回的唯一标识,去除首尾引号后作为 fileNo
|
|
21
|
+
*/
|
|
22
|
+
export declare function uploadToOss(fileBuffer: Buffer, ossPath: string, mimeType: string): Promise<UploadResult>;
|
|
23
|
+
/**
|
|
24
|
+
* 从 OSS 获取文件内容
|
|
25
|
+
*/
|
|
26
|
+
export declare function getFromOss(ossPath: string): Promise<Buffer>;
|
|
27
|
+
/**
|
|
28
|
+
* 从 OSS 删除文件
|
|
29
|
+
*/
|
|
30
|
+
export declare function deleteFromOss(ossPath: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* 解析 URL 中的 OSS 路径
|
|
33
|
+
* 例如 https://bucket.oss-cn-hangzhou.aliyuncs.com/uploads/2026-07/file.pdf
|
|
34
|
+
* → uploads/2026-07/file.pdf
|
|
35
|
+
*/
|
|
36
|
+
export declare function extractOssPath(url: string): string | null;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=ossClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ossClient.d.ts","sourceRoot":"","sources":["../../src/utils/ossClient.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,SAAS,CAAC;AAM1B,yBAAyB;AACzB,wBAAgB,YAAY,IAAI,GAAG,CAqBlC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,UAAU,YAAY;IACpB,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAWvB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIjE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getOssClient = getOssClient;
|
|
7
|
+
exports.buildOssPath = buildOssPath;
|
|
8
|
+
exports.uploadToOss = uploadToOss;
|
|
9
|
+
exports.getFromOss = getFromOss;
|
|
10
|
+
exports.deleteFromOss = deleteFromOss;
|
|
11
|
+
exports.extractOssPath = extractOssPath;
|
|
12
|
+
const ali_oss_1 = __importDefault(require("ali-oss"));
|
|
13
|
+
const config_1 = __importDefault(require("../config"));
|
|
14
|
+
const logger_1 = require("./logger");
|
|
15
|
+
let client = null;
|
|
16
|
+
/** 获取或初始化 OSS 客户端(单例) */
|
|
17
|
+
function getOssClient() {
|
|
18
|
+
if (client)
|
|
19
|
+
return client;
|
|
20
|
+
const oss = config_1.default.oss;
|
|
21
|
+
if (!oss.accessKeyId || !oss.accessKeySecret || !oss.bucket) {
|
|
22
|
+
logger_1.logger.warn('[OSS] 未配置完整参数,OSS 功能不可用');
|
|
23
|
+
throw new Error('OSS 配置不完整,请检查环境变量');
|
|
24
|
+
}
|
|
25
|
+
client = new ali_oss_1.default({
|
|
26
|
+
accessKeyId: oss.accessKeyId,
|
|
27
|
+
accessKeySecret: oss.accessKeySecret,
|
|
28
|
+
bucket: oss.bucket,
|
|
29
|
+
endpoint: oss.endpoint,
|
|
30
|
+
region: oss.region,
|
|
31
|
+
secure: true,
|
|
32
|
+
});
|
|
33
|
+
logger_1.logger.info(`[OSS] 客户端已初始化 → bucket=${oss.bucket}, endpoint=${oss.endpoint}`);
|
|
34
|
+
return client;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 构建 OSS 存储路径:uploads/YYYY-MM/{timestamp36}{random4}_{originalName}
|
|
38
|
+
* 路径唯一性由时间戳保证,原始文件名保留可读性。
|
|
39
|
+
*/
|
|
40
|
+
function buildOssPath(originalName) {
|
|
41
|
+
const now = new Date();
|
|
42
|
+
const ym = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
|
|
43
|
+
const uniq = Date.now().toString(36) + Math.random().toString(36).substring(2, 6);
|
|
44
|
+
return `uploads/${ym}/${uniq}_${originalName}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 上传文件到 OSS
|
|
48
|
+
* @param fileBuffer 文件二进制内容
|
|
49
|
+
* @param ossPath OSS 存储路径
|
|
50
|
+
* @param mimeType MIME 类型
|
|
51
|
+
* @returns { url, etag } — etag 即 OSS 返回的唯一标识,去除首尾引号后作为 fileNo
|
|
52
|
+
*/
|
|
53
|
+
async function uploadToOss(fileBuffer, ossPath, mimeType) {
|
|
54
|
+
const ossClient = getOssClient();
|
|
55
|
+
const result = await ossClient.put(ossPath, fileBuffer, {
|
|
56
|
+
mime: mimeType,
|
|
57
|
+
});
|
|
58
|
+
// ETag 格式如 "5B3C1A2D...",去除首尾双引号
|
|
59
|
+
const rawEtag = result.res?.headers?.etag || '';
|
|
60
|
+
const etag = rawEtag.replace(/^"|"$/g, '');
|
|
61
|
+
return { url: result.url, etag };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 从 OSS 获取文件内容
|
|
65
|
+
*/
|
|
66
|
+
async function getFromOss(ossPath) {
|
|
67
|
+
const ossClient = getOssClient();
|
|
68
|
+
const result = await ossClient.get(ossPath);
|
|
69
|
+
return Buffer.from(result.content);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 从 OSS 删除文件
|
|
73
|
+
*/
|
|
74
|
+
async function deleteFromOss(ossPath) {
|
|
75
|
+
const ossClient = getOssClient();
|
|
76
|
+
await ossClient.delete(ossPath);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 解析 URL 中的 OSS 路径
|
|
80
|
+
* 例如 https://bucket.oss-cn-hangzhou.aliyuncs.com/uploads/2026-07/file.pdf
|
|
81
|
+
* → uploads/2026-07/file.pdf
|
|
82
|
+
*/
|
|
83
|
+
function extractOssPath(url) {
|
|
84
|
+
try {
|
|
85
|
+
const parsed = new URL(url);
|
|
86
|
+
return parsed.pathname.startsWith('/') ? parsed.pathname.substring(1) : parsed.pathname;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=ossClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ossClient.js","sourceRoot":"","sources":["../../src/utils/ossClient.ts"],"names":[],"mappings":"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"}
|