feat: create isMobile dereactor

This commit is contained in:
louis 2024-03-21 15:03:07 +08:00
parent 414f0d54d6
commit 77247c140c
9 changed files with 139 additions and 57 deletions

View File

@ -89,9 +89,9 @@
"ioredis": "^5.3.2", "ioredis": "^5.3.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mathjs": "^12.4.0", "mathjs": "^12.4.0",
"minio": "^7.1.3",
"mysql2": "^3.9.1", "mysql2": "^3.9.1",
"nanoid": "^3.3.7", "nanoid": "^3.3.7",
"nestjs-minio": "^2.5.4",
"nodemailer": "^6.9.9", "nodemailer": "^6.9.9",
"passport": "^0.7.0", "passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0", "passport-google-oauth20": "^2.0.0",

View File

@ -134,15 +134,15 @@ dependencies:
mathjs: mathjs:
specifier: ^12.4.0 specifier: ^12.4.0
version: 12.4.0 version: 12.4.0
minio:
specifier: ^7.1.3
version: 7.1.3
mysql2: mysql2:
specifier: ^3.9.1 specifier: ^3.9.1
version: 3.9.1 version: 3.9.1
nanoid: nanoid:
specifier: ^3.3.7 specifier: ^3.3.7
version: 3.3.7 version: 3.3.7
nestjs-minio:
specifier: ^2.5.4
version: 2.5.4(@nestjs/common@10.3.3)(@nestjs/core@10.3.3)
nodemailer: nodemailer:
specifier: ^6.9.9 specifier: ^6.9.9
version: 6.9.9 version: 6.9.9
@ -1733,7 +1733,7 @@ packages:
object-assign: 4.1.1 object-assign: 4.1.1
open: 8.4.0 open: 8.4.0
proxy-middleware: 0.15.0 proxy-middleware: 0.15.0
send: 0.18.0 send: 1.0.0-beta.2
serve-index: 1.9.1 serve-index: 1.9.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -5406,6 +5406,17 @@ packages:
dependencies: dependencies:
ms: 2.0.0 ms: 2.0.0
/debug@3.1.0:
resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: true
/debug@4.3.4: /debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
@ -6380,8 +6391,8 @@ packages:
resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==}
dev: false dev: false
/fast-xml-parser@4.3.5: /fast-xml-parser@4.3.6:
resolution: {integrity: sha512-sWvP1Pl8H03B8oFJpFR3HE31HUfwtX7Rlf9BNsvdpujD4n7WMhfmu8h9wOV2u+c1k0ZilTADhPqypzx2J690ZQ==} resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==}
hasBin: true hasBin: true
dependencies: dependencies:
strnum: 1.0.5 strnum: 1.0.5
@ -7572,7 +7583,7 @@ packages:
resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
dependencies: dependencies:
which-typed-array: 1.1.14 which-typed-array: 1.1.15
dev: false dev: false
/is-unicode-supported@0.1.0: /is-unicode-supported@0.1.0:
@ -8818,12 +8829,6 @@ packages:
dependencies: dependencies:
mime-db: 1.52.0 mime-db: 1.52.0
/mime@1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
hasBin: true
dev: true
/mime@2.6.0: /mime@2.6.0:
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
engines: {node: '>=4.0.0'} engines: {node: '>=4.0.0'}
@ -8914,7 +8919,7 @@ packages:
block-stream2: 2.1.0 block-stream2: 2.1.0
browser-or-node: 2.1.1 browser-or-node: 2.1.1
buffer-crc32: 0.2.13 buffer-crc32: 0.2.13
fast-xml-parser: 4.3.5 fast-xml-parser: 4.3.6
ipaddr.js: 2.1.0 ipaddr.js: 2.1.0
json-stream: 1.0.0 json-stream: 1.0.0
lodash: 4.17.21 lodash: 4.17.21
@ -9468,6 +9473,17 @@ packages:
/neo-async@2.6.2: /neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
/nestjs-minio@2.5.4(@nestjs/common@10.3.3)(@nestjs/core@10.3.3):
resolution: {integrity: sha512-b99fCEjK1Kt7cNDfANrfhckQiYC10mKoVqfdwUJQaVCWMKTm2E8Kb7oiPIyWyjcVP6RERn5oUMPmf/rZLJEr3A==}
peerDependencies:
'@nestjs/common': '>7.0.0'
'@nestjs/core': '>7.0.0'
dependencies:
'@nestjs/common': 10.3.3(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.1)(rxjs@7.8.1)
'@nestjs/core': 10.3.3(@nestjs/common@10.3.3)(@nestjs/websockets@10.3.3)(reflect-metadata@0.2.1)(rxjs@7.8.1)
minio: 7.1.3
dev: false
/next-tick@1.1.0: /next-tick@1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: true dev: true
@ -10933,19 +10949,18 @@ packages:
dependencies: dependencies:
lru-cache: 6.0.0 lru-cache: 6.0.0
/send@0.18.0: /send@1.0.0-beta.2:
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} resolution: {integrity: sha512-k1yHu/FNK745PULKdsGpQ+bVSXYNwSk+bWnYzbxGZbt5obZc0JKDVANsCRuJD1X/EG15JtP9eZpwxkhUxIYEcg==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.10'}
dependencies: dependencies:
debug: 2.6.9 debug: 3.1.0
depd: 2.0.0
destroy: 1.2.0 destroy: 1.2.0
encodeurl: 1.0.2 encodeurl: 1.0.2
escape-html: 1.0.3 escape-html: 1.0.3
etag: 1.8.1 etag: 1.8.1
fresh: 0.5.2 fresh: 0.5.2
http-errors: 2.0.0 http-errors: 2.0.0
mime: 1.6.0 mime-types: 2.1.35
ms: 2.1.3 ms: 2.1.3
on-finished: 2.4.1 on-finished: 2.4.1
range-parser: 1.2.1 range-parser: 1.2.1
@ -12202,7 +12217,7 @@ packages:
is-arguments: 1.1.1 is-arguments: 1.1.1
is-generator-function: 1.0.10 is-generator-function: 1.0.10
is-typed-array: 1.1.13 is-typed-array: 1.1.13
which-typed-array: 1.1.14 which-typed-array: 1.1.15
dev: false dev: false
/utility@1.18.0: /utility@1.18.0:
@ -12392,8 +12407,8 @@ packages:
tr46: 0.0.3 tr46: 0.0.3
webidl-conversions: 3.0.1 webidl-conversions: 3.0.1
/which-typed-array@1.1.14: /which-typed-array@1.1.15:
resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
dependencies: dependencies:
available-typed-arrays: 1.0.7 available-typed-arrays: 1.0.7

View File

@ -3,7 +3,15 @@ import type { ExecutionContext } from '@nestjs/common';
import { createParamDecorator } from '@nestjs/common'; import { createParamDecorator } from '@nestjs/common';
import type { FastifyRequest } from 'fastify'; import type { FastifyRequest } from 'fastify';
import { getIp } from '~/utils/ip.util'; import { getIp, getIsMobile } from '~/utils/ip.util';
/**
* IP
*/
export const IsMobile = createParamDecorator((_, context: ExecutionContext) => {
const request = context.switchToHttp().getRequest<FastifyRequest>();
return getIsMobile(request);
});
/** /**
* IP * IP

View File

@ -2,7 +2,7 @@ import { Body, Controller, Headers, Post, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiResult } from '~/common/decorators/api-result.decorator'; import { ApiResult } from '~/common/decorators/api-result.decorator';
import { Ip } from '~/common/decorators/http.decorator'; import { Ip, IsMobile } from '~/common/decorators/http.decorator';
import { UserService } from '../user/user.service'; import { UserService } from '../user/user.service';
@ -32,9 +32,12 @@ export class AuthController {
async login( async login(
@Body() dto: LoginDto, @Body() dto: LoginDto,
@Ip() ip: string, @Ip() ip: string,
@IsMobile() isMobile: boolean,
@Headers('user-agent') ua: string @Headers('user-agent') ua: string
): Promise<LoginToken> { ): Promise<LoginToken> {
if(!isMobile){
await this.captchaService.checkImgCaptcha(dto.captchaId, dto.verifyCode); await this.captchaService.checkImgCaptcha(dto.captchaId, dto.verifyCode);
}
const token = await this.authService.login(dto.username, dto.password, ip, ua); const token = await this.authService.login(dto.username, dto.password, ip, ua);
return { token }; return { token };
} }
@ -43,6 +46,11 @@ export class AuthController {
@ApiSecurityAuth() @ApiSecurityAuth()
@ApiOperation({ summary: '屏幕解锁使用密码和token' }) @ApiOperation({ summary: '屏幕解锁使用密码和token' })
@ApiResult({ type: LoginToken }) @ApiResult({ type: LoginToken })
async unlock(@Body() dto: LoginDto, @AuthUser() user: IAuthUser): Promise<Boolean> { async unlock(@Body() dto: LoginDto, @AuthUser() user: IAuthUser): Promise<Boolean> {
await this.authService.unlock(user.uid, dto.password); await this.authService.unlock(user.uid, dto.password);
return true; return true;

View File

@ -13,7 +13,7 @@ export class LoginDto {
@MinLength(6) @MinLength(6)
password: string; password: string;
@ApiProperty({ description: '验证码标识' }) @ApiProperty({ description: '验证码标识,手机端不需要' })
@IsOptional() @IsOptional()
captchaId: string; captchaId: string;

View File

@ -55,10 +55,12 @@ export class MaterialsInOutDto {
quantity: number; quantity: number;
@ApiProperty({ description: '单价' }) @ApiProperty({ description: '单价' })
@IsOptional()
@IsNumber() @IsNumber()
unitPrice: number; unitPrice: number;
@ApiProperty({ description: '金额' }) @ApiProperty({ description: '金额' })
@IsOptional()
@IsNumber() @IsNumber()
amount: number; amount: number;

View File

@ -1,41 +1,22 @@
import { basename, extname } from 'node:path';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { ConfigKeyPaths } from '~/config'; import { ConfigKeyPaths } from '~/config';
import { import { generateRandomValue } from '~/utils';
NETDISK_COPY_SUFFIX,
NETDISK_DELIMITER,
NETDISK_HANDLE_MAX_ITEM,
NETDISK_LIMIT
} from '~/constants/oss.constant';
import { AccountInfo } from '~/modules/user/user.model';
import { UserService } from '~/modules/user/user.service';
import { fileRename, generateRandomValue } from '~/utils';
import { SFileInfo, SFileInfoDetail, SFileList } from './manage.class'; import { SFileInfo, SFileInfoDetail, SFileList } from './manage.class';
import { FileOpItem } from './manage.dto';
import * as Minio from 'Minio'; import * as Minio from 'Minio';
import { InjectMinio } from 'nestjs-minio';
import { Client } from 'minio';
@Injectable() @Injectable()
export class NetDiskManageService { export class NetDiskManageService {
private get ossConfig() { private get ossConfig() {
return this.configService.get('oss', { infer: true }); return this.configService.get('oss', { infer: true });
} }
private minioClient: Minio.Client; constructor(
constructor(private configService: ConfigService<ConfigKeyPaths>) { private configService: ConfigService<ConfigKeyPaths>,
this.minioClient = new Minio.Client({ @InjectMinio() private readonly minioClient: Client
endPoint: this.ossConfig.domain, ) {}
port: this.ossConfig.port,
useSSL: this.ossConfig.useSSL,
accessKey: this.ossConfig.accessKey,
secretKey: this.ossConfig.secretKey
});
}
/** /**
* *
* @param prefix * @param prefix

View File

@ -1,5 +1,5 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { RouterModule } from '@nestjs/core'; import { RouterModule } from '@nestjs/core';
import { UserModule } from '../user/user.module'; import { UserModule } from '../user/user.module';
@ -9,6 +9,22 @@ import { NetDiskOverviewController } from './overview/overview.controller';
import { NetDiskOverviewService } from './overview/overview.service'; import { NetDiskOverviewService } from './overview/overview.service';
import { MinioService } from './minio/minio.service'; import { MinioService } from './minio/minio.service';
import { NetDiskManageService } from './manager/manage.service'; import { NetDiskManageService } from './manager/manage.service';
import { NestMinioModule } from 'nestjs-minio';
// const getMinioConfig = () => {
// const configService = new ConfigService();
// const endPoint = configService.get<string>('MINIO_ENDPOINT', 'localhost');
// const accessKey = configService.get<string>('MINIO_ACCESSKEY', 'accessKey');
// const secretKey = configService.get<string>('MINIO_SECRET_KEY', 'secretKey');
// return NestMinioModule.register({
// isGlobal: true,
// endPoint,
// port: 9000,
// accessKey,
// secretKey,
// useSSL: false
// });
// };
@Module({ @Module({
imports: [ imports: [
@ -18,9 +34,56 @@ import { NetDiskManageService } from './manager/manage.service';
path: 'netdisk', path: 'netdisk',
module: NetdiskModule module: NetdiskModule
} }
]) ]),
// getMinioConfig()
NestMinioModule.registerAsync({
inject: [ConfigService],
isGlobal: true,
useFactory: async (configService: ConfigService) => {
const ossConfig = configService.get('oss');
return {
endPoint: ossConfig.domain,
port: ossConfig.port,
useSSL: ossConfig.useSSL,
accessKey: ossConfig.accessKey,
secretKey: ossConfig.secretKey
};
}
// endPoint: 'play.min.io',
// port: 9000,
// useSSL: true,
// accessKey: 'Q3AM3UQ867SPQQA43P2F',
// secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG'
})
], ],
controllers: [NetDiskManageController, NetDiskOverviewController], controllers: [NetDiskManageController, NetDiskOverviewController],
providers: [NetDiskManageService, NetDiskOverviewService, MinioService] providers: [NetDiskManageService, NetDiskOverviewService, MinioService]
}) })
export class NetdiskModule {} export class NetdiskModule {}
// TypeOrmModule.forRootAsync({
// inject: [ConfigService],
// useFactory: (configService: ConfigService<ConfigKeyPaths>) => {
// let loggerOptions: LoggerOptions = env('DB_LOGGING') as 'all';
// try {
// // 解析成 js 数组 ['error']
// loggerOptions = JSON.parse(loggerOptions);
// } catch {
// // ignore
// }
// return {
// ...configService.get<IDatabaseConfig>('database'),
// autoLoadEntities: true,
// logging: loggerOptions,
// logger: new TypeORMLogger(loggerOptions)
// };
// },
// // dataSource receives the configured DataSourceOptions
// // and returns a Promise<DataSource>.
// dataSourceFactory: async options => {
// const dataSource = await new DataSource(options).initialize();
// return dataSource;
// }
// })
// ],

View File

@ -25,6 +25,11 @@ function isLAN(ip: string) {
); );
} }
// 是否来自手机的请求
export function getIsMobile(request: FastifyRequest | IncomingMessage): boolean {
return request.headers['user-agent'].includes('Dart');
}
export function getIp(request: FastifyRequest | IncomingMessage) { export function getIp(request: FastifyRequest | IncomingMessage) {
const req = request as any; const req = request as any;