diff --git a/package.json b/package.json
index 80a14188..201a1e8a 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
"only-build:web": "pnpm run -C packages/web build",
"watch:web": "pnpm run -C packages/web watch",
"project:web": "pnpm run -C packages/web build && node tools/copy-files-web2server.js",
- "dev:server": "pnpm run -C packages/server dev",
+ "dev:server": "pnpm run -C packages/server start:dev",
"build:server": "pnpm run -C packages/server build",
"dev:docs": "pnpm run -C packages/docs dev",
"build:docs": "pnpm run -C packages/docs build",
diff --git a/packages/desktop/electron/main/contract.ts b/packages/desktop/electron/main/contract.ts
index fc5ab801..126cfba2 100644
--- a/packages/desktop/electron/main/contract.ts
+++ b/packages/desktop/electron/main/contract.ts
@@ -11,7 +11,7 @@ export const VITE_API_URL = import.meta.env.VITE_API_URL;
// export const WEB_URL = 'http://127.0.0.1:9191/';
// export const VITE_API_URL = 'http://127.0.0.1:9190/';
export const preload = path.join(__dirname, '../preload/index.js');
-
+export const serverPath = path.join(__dirname, '../server/index.js');
export const DIST_ELECTRON = path.join(__dirname, '../');
export const DIST = path.join(DIST_ELECTRON, '../dist');
diff --git a/packages/desktop/electron/main/index.ts b/packages/desktop/electron/main/index.ts
index 9d3794fc..eb328cac 100644
--- a/packages/desktop/electron/main/index.ts
+++ b/packages/desktop/electron/main/index.ts
@@ -1,13 +1,17 @@
import { app, BrowserWindow, shell, ipcMain } from 'electron';
import { release } from 'node:os';
+import { spawn } from 'node:child_process';
import * as mainWin from '../win/mainWin';
import { initTray } from './tray';
import { update } from './update';
import { registerFileProtocol } from './protocol';
import { registerGlobalShortcut, unregisterAllGlobalShortcut } from './globalShortcut';
import { initConfig, getConfig } from '@pear-rec/server/src/config';
+import { serverPath } from './contract';
import './ipcMain';
-import '@pear-rec/server/src';
+
+const appName = app.getPath('exe');
+const serverAppProcess = spawn(appName, [serverPath]);
initConfig();
@@ -16,8 +20,10 @@ initConfig();
// ├─┬ dist-electron
// │ ├─┬ main
// │ │ └── index.js > Electron-Main
-// │ └─┬ preload
-// │ └── index.js > Preload-Scripts
+// │ ├─┬ preload
+// │ │ └── index.js > Preload-Scripts
+// │ └─┬ server
+// │ └── index.js > Server-Scripts
// ├─┬ dist
// │ └── index.html > Electron-Renderer
//
@@ -52,6 +58,7 @@ app.whenReady().then(() => {
});
app.on('will-quit', () => {
+ serverAppProcess?.kill();
unregisterAllGlobalShortcut();
});
diff --git a/packages/desktop/vite.config.ts b/packages/desktop/vite.config.ts
index f3b391e7..d7141380 100644
--- a/packages/desktop/vite.config.ts
+++ b/packages/desktop/vite.config.ts
@@ -5,7 +5,7 @@ import pkg from './package.json';
// https://vitejs.dev/config/
export default defineConfig(({ command }) => {
- rmSync('dist-electron', { recursive: true, force: true });
+ // rmSync('dist-electron', { recursive: true, force: true });
const isServe = command === 'serve';
const isBuild = command === 'build';
diff --git a/packages/server/CHANGELOG.md b/packages/server/CHANGELOG.md
index 69fb4e3d..b42b68c1 100644
--- a/packages/server/CHANGELOG.md
+++ b/packages/server/CHANGELOG.md
@@ -1,5 +1,9 @@
# @pear-rec/server
+## 1.3.0
+
+refactor: 升级 nestjs 架构
+
## 1.2.5
feat: 重置设置
diff --git a/packages/server/README.md b/packages/server/README.md
new file mode 100644
index 00000000..f5aa86c5
--- /dev/null
+++ b/packages/server/README.md
@@ -0,0 +1,73 @@
+
+
+
+
+[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
+[circleci-url]: https://circleci.com/gh/nestjs/nest
+
+ A progressive Node.js framework for building efficient and scalable server-side applications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Description
+
+[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
+
+## Installation
+
+```bash
+$ pnpm install
+```
+
+## Running the app
+
+```bash
+# development
+$ pnpm run start
+
+# watch mode
+$ pnpm run start:dev
+
+# production mode
+$ pnpm run start:prod
+```
+
+## Test
+
+```bash
+# unit tests
+$ pnpm run test
+
+# e2e tests
+$ pnpm run test:e2e
+
+# test coverage
+$ pnpm run test:cov
+```
+
+## Support
+
+Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
+
+## Stay in touch
+
+- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
+- Website - [https://nestjs.com](https://nestjs.com/)
+- Twitter - [@nestframework](https://twitter.com/nestframework)
+
+## License
+
+Nest is [MIT licensed](LICENSE).
diff --git a/packages/server/nest-cli.json b/packages/server/nest-cli.json
new file mode 100644
index 00000000..f9aa683b
--- /dev/null
+++ b/packages/server/nest-cli.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/nest-cli",
+ "collection": "@nestjs/schematics",
+ "sourceRoot": "src",
+ "compilerOptions": {
+ "deleteOutDir": true
+ }
+}
diff --git a/packages/server/package.json b/packages/server/package.json
index 26ef4994..2cba8ec2 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -1,39 +1,44 @@
{
"name": "@pear-rec/server",
- "version": "1.2.4",
- "description": "",
- "main": "dist/index.js",
- "typings": "index.d.ts",
+ "version": "1.3.0",
"scripts": {
- "dev": "nodemon index.ts",
- "build": "rollup -c",
- "watch": "rollup -c --watch",
- "preview": "node dist/index.js"
+ "build": "nest build",
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
+ "start": "nest start",
+ "start:dev": "nest start --watch",
+ "start:debug": "nest start --debug --watch",
+ "start:prod": "node dist/main"
+ },
+ "dependencies": {
+ "@nestjs/common": "^10.0.0",
+ "@nestjs/core": "^10.0.0",
+ "@nestjs/platform-express": "^10.0.0",
+ "@nestjs/serve-static": "^4.0.0",
+ "@nestjs/typeorm": "^10.0.1",
+ "jsonfile": "^6.1.0",
+ "multer": "^1.4.5-lts.1",
+ "reflect-metadata": "^0.1.13",
+ "rxjs": "^7.8.1"
},
- "author": "027xiguapi",
- "license": "Apache-2.0",
"devDependencies": {
- "@rollup/plugin-commonjs": "^25.0.4",
- "@rollup/plugin-json": "^6.0.0",
- "@rollup/plugin-node-resolve": "^15.2.1",
- "@rollup/plugin-typescript": "^11.1.5",
- "@types/cors": "^2.8.14",
+ "@nestjs/cli": "^10.0.0",
+ "@nestjs/schematics": "^10.0.0",
+ "@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
- "@types/node": "^20.6.0",
- "@types/validator": "^13.11.1",
- "nodemon": "^3.0.1",
- "rollup": "^3.29.3",
+ "@types/multer": "^1.4.11",
+ "@types/node": "^20.3.1",
+ "@types/supertest": "^2.0.12",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "@typescript-eslint/parser": "^6.0.0",
+ "eslint": "^8.42.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.0",
+ "prettier": "^3.0.0",
+ "source-map-support": "^0.5.21",
+ "supertest": "^6.3.3",
+ "ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
- "typescript": "^5.2.2"
- },
- "dependencies": {
- "body-parser": "^1.20.2",
- "cors": "^2.8.5",
- "express": "^4.18.2",
- "http-proxy-middleware": "^2.0.6",
- "multer": "1.4.5-lts.1",
- "reflect-metadata": "^0.1.13",
- "sql.js": "^1.8.0",
- "typeorm": "^0.3.17"
+ "tsconfig-paths": "^4.2.0",
+ "typescript": "^5.1.3"
}
}
\ No newline at end of file
diff --git a/packages/server/rollup.config.mjs b/packages/server/rollup.config.mjs
deleted file mode 100644
index 7c9c563d..00000000
--- a/packages/server/rollup.config.mjs
+++ /dev/null
@@ -1,21 +0,0 @@
-import typescript from '@rollup/plugin-typescript';
-import { nodeResolve } from '@rollup/plugin-node-resolve';
-import commonjs from '@rollup/plugin-commonjs';
-import json from '@rollup/plugin-json';
-
-export default {
- input: 'src/index.ts',
- output: {
- file: 'dist/index.js',
- format: 'cjs',
- sourcemap: true,
- },
- context: 'window',
- external: ['typeorm', 'sql.js'],
- plugins: [
- nodeResolve({ preferBuiltins: true }),
- commonjs({ ignoreDynamicRequires: true }),
- json(),
- typescript(),
- ],
-};
diff --git a/packages/server/src/api/index.ts b/packages/server/src/api/index.ts
index ab83dcdc..82281654 100644
--- a/packages/server/src/api/index.ts
+++ b/packages/server/src/api/index.ts
@@ -1,13 +1,7 @@
-import { Application, Request, Response } from 'express';
+// import { initBaiduProxy } from '../proxy/baidu';
+// import { initGoogleProxy } from '../proxy/google';
-import { initLocalApi } from './local';
-import { initPageProxy } from './page';
-import { initBaiduProxy } from '../proxy/baidu';
-import { initGoogleProxy } from '../proxy/google';
-
-export function initApi(app: Application) {
- initLocalApi(app);
- initBaiduProxy(app);
- initGoogleProxy(app);
- initPageProxy(app);
-}
+// export function initApi(app: Application) {
+// initBaiduProxy(app);
+// initGoogleProxy(app);
+// }
diff --git a/packages/server/src/api/local.ts b/packages/server/src/api/local.ts
index 19ebbb26..906179e8 100644
--- a/packages/server/src/api/local.ts
+++ b/packages/server/src/api/local.ts
@@ -4,26 +4,24 @@ import { join, dirname } from 'node:path';
import { Application } from 'express';
import { exec } from 'child_process';
import { getImgsByImgUrl, getAudiosByAudioUrl, getVideosByVideoUrl } from '../util/index';
-import { RecordController } from '../controller/RecordController';
-import { UserController } from '../controller/UserController';
-import { SettingController } from '../controller/SettingController';
+import { RecordsService } from '../records/records.service';
+import { UsersService } from '../users/users.service';
+import { SettingsService } from '../settings/settings.service';
import { PEAR_FILES_PATH } from '../contract';
-const recordController = new RecordController();
-const userController = new UserController();
-const settingController = new SettingController();
+// const usersService = new UsersService();
const storage = multer.diskStorage({
destination: async function (req, file, cb) {
const { type, userId } = req.body;
- const user = await userController._getUserById(userId);
- const setting = await settingController._getSettingByUserId(userId);
+ // const user = await usersService.findOneById(userId);
+ // const setting = await settingController._getSettingByUserId(userId);
try {
- const filePath = join(setting?.filePath || PEAR_FILES_PATH, `${user.uuid}/${type}`);
- if (!fs.existsSync(filePath)) {
- fs.mkdirSync(filePath, { recursive: true });
- }
- cb(null, filePath);
+ // const filePath = join(setting?.filePath || PEAR_FILES_PATH, `${user.uuid}/${type}`);
+ // if (!fs.existsSync(filePath)) {
+ // fs.mkdirSync(filePath, { recursive: true });
+ // }
+ // cb(null, filePath);
} catch (err) {
console.log('saveFile err', err);
}
@@ -45,7 +43,7 @@ const upload = multer({ storage: storage });
export function initLocalApi(app: Application) {
app.post('/saveFile', upload.single('file'), async (req: any, res) => {
- recordController.saveFile(req, res);
+ // recordController.saveFile(req, res);
});
app.get('/getFile', async (req, res) => {
diff --git a/packages/server/src/api/page.ts b/packages/server/src/api/page.ts
deleted file mode 100644
index 17612554..00000000
--- a/packages/server/src/api/page.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import express, { Application, Request, Response } from "express";
-import path from "node:path";
-
-export function initPageProxy(app: Application) {
- app.use(express.static(path.resolve("public")));
-
- app.get("/", (req, res) => {
- res.sendFile(path.resolve("public/index.html"));
- });
-
- app.get("/shotScreen", (req, res) => {
- res.sendFile(path.resolve("public/shotScreen.html"));
- });
-
- app.get("/recorderScreen", (req, res) => {
- res.sendFile(path.resolve("public/recorderScreen.html"));
- });
-
- app.get("/recorderVideo", (req, res) => {
- res.sendFile(path.resolve("public/recorderVideo.html"));
- });
-
- app.get("/recorderAudio", (req, res) => {
- res.sendFile(path.resolve("public/recorderAudio.html"));
- });
-
- app.get("/viewImage", (req, res) => {
- res.sendFile(path.resolve("public/viewImage.html"));
- });
-
- app.get("/viewVideo", (req, res) => {
- res.sendFile(path.resolve("public/viewVideo.html"));
- });
-
- app.get("/setting", (req, res) => {
- res.sendFile(path.resolve("public/setting.html"));
- });
-
- app.get("/clipScreen", (req, res) => {
- res.sendFile(path.resolve("public/clipScreen.html"));
- });
-
- app.get("/editImage", (req, res) => {
- res.sendFile(path.resolve("public/editImage.html"));
- });
-
- app.get("/viewAudio", (req, res) => {
- res.sendFile(path.resolve("public/viewAudio.html"));
- });
-}
diff --git a/packages/server/src/app/app.controller.ts b/packages/server/src/app/app.controller.ts
new file mode 100644
index 00000000..15f0c470
--- /dev/null
+++ b/packages/server/src/app/app.controller.ts
@@ -0,0 +1,199 @@
+import {
+ Controller,
+ Get,
+ Post,
+ StreamableFile,
+ Query,
+ UseInterceptors,
+ Res,
+ UploadedFile,
+} from '@nestjs/common';
+import { join, dirname, basename, extname } from 'node:path';
+import { readdirSync, createReadStream, statSync } from 'node:fs';
+import { FileInterceptor } from '@nestjs/platform-express';
+import { CreateFileDto } from './dto/create-file.dto';
+import { AppService } from './app.service';
+import { Record } from '../records/entity/record.entity';
+import { exec } from 'child_process';
+import type { Response } from 'express';
+
+@Controller()
+export class AppController {
+ constructor(private readonly appService: AppService) {}
+
+ @Post('/upload/file')
+ // @UseInterceptors(FileInterceptor('fileName'))
+ async uploadFile(@UploadedFile() fileDto: CreateFileDto): Promise {
+ return this.appService.uploadFile(fileDto);
+ }
+
+ @Get('/getFile')
+ getFile(@Query() query): StreamableFile {
+ const file = createReadStream(query.url);
+ return new StreamableFile(file);
+ }
+
+ @Get('/audio')
+ getAudio(@Query() query, @Res({ passthrough: true }) res: Response): StreamableFile {
+ const stream = createReadStream(query.url);
+ const stat = statSync(query.url);
+ const fileSize = stat.size;
+ res.set({
+ 'Content-Type': 'audio/mp3',
+ 'Content-Length': fileSize,
+ });
+ return new StreamableFile(stream);
+ }
+
+ @Get('/video')
+ getVideo(@Query() query, @Res({ passthrough: true }) res: Response): StreamableFile {
+ const stream = createReadStream(query.url);
+ const stat = statSync(query.url);
+ const fileSize = stat.size;
+ res.set({
+ 'Content-Length': fileSize,
+ 'Content-Type': 'video/mp4',
+ });
+ return new StreamableFile(stream);
+ }
+
+ @Get('/getImgs')
+ getImgs(@Query() query) {
+ const imgUrl = query.imgUrl;
+ let imgs: any[] = [];
+ let index = 0;
+ let currentIndex = 0;
+ try {
+ const directoryPath = dirname(imgUrl);
+ const files = readdirSync(directoryPath); // 读取目录内容
+ files.forEach((file) => {
+ const filePath = join(directoryPath, file);
+ function isImgFile(filePath: string): boolean {
+ const ext = extname(filePath).toLowerCase();
+ return [
+ '.jpg',
+ '.jpeg',
+ '.jfif',
+ '.pjpeg',
+ '.pjp',
+ '.png',
+ 'apng',
+ '.gif',
+ '.bmp',
+ '.avif',
+ '.webp',
+ '.ico',
+ ].includes(ext);
+ }
+ const port = process.env.PORT || 9190;
+ const protocol = `http://localhost:${port}/getFile?url=`;
+ if (isImgFile(filePath)) {
+ filePath == imgUrl && (currentIndex = index);
+ imgs.push({
+ url: `${protocol}${filePath}`,
+ filePath: filePath,
+ index,
+ });
+ index++;
+ }
+ });
+ } catch (err) {
+ console.log('getImgsByImgUrl', err);
+ }
+ return { imgs, currentIndex };
+ }
+
+ @Get('/getAudios')
+ async getAudios(@Query() query): Promise {
+ const audioUrl = query.audioUrl;
+ const directoryPath = dirname(audioUrl);
+ const files = readdirSync(directoryPath); // 读取目录内容
+ let audios: any[] = [];
+ let index = 0;
+ files.forEach((file) => {
+ const filePath = join(directoryPath, file);
+ const port = process.env.PORT || 9190;
+ const protocol = `http://localhost:${port}/audio?url=`;
+ function isAudioFile(filePath: string): boolean {
+ const ext = extname(filePath).toLowerCase();
+ return [
+ '.mp3',
+ '.wav',
+ '.aac',
+ '.ogg',
+ '.flac',
+ '.aiff',
+ '.aif',
+ '.m4a',
+ '.alac',
+ '.ac3',
+ '.webm',
+ ].includes(ext);
+ }
+ if (isAudioFile(filePath)) {
+ const fileName = basename(filePath);
+ if (filePath == audioUrl) {
+ audios.unshift({
+ url: `${protocol}${filePath}`,
+ name: fileName,
+ cover: './imgs/music.png',
+ });
+ } else {
+ audios.push({
+ url: `${protocol}${filePath}`,
+ name: fileName,
+ cover: './imgs/music.png',
+ });
+ }
+ index++;
+ }
+ });
+
+ return audios;
+ }
+
+ @Get('/getVideos')
+ getVideos(@Query() query) {
+ const videoUrl = query.videoUrl;
+ const directoryPath = dirname(videoUrl);
+ const files = readdirSync(directoryPath);
+ let videos: any[] = [];
+ let index = 0;
+ let currentIndex = 0;
+ files.forEach((file) => {
+ const filePath = join(directoryPath, file);
+ const port = process.env.PORT || 9190;
+ const protocol = `http://localhost:${port}/video?url=`;
+ function isVideoFile(filePath: string): boolean {
+ const ext = extname(filePath).toLowerCase();
+ return ['.mp4', '.mkv', '.avi', '.mov', '.wmv', '.webm'].includes(ext);
+ }
+ if (isVideoFile(filePath)) {
+ const fileName = basename(filePath);
+ filePath == videoUrl && (currentIndex = index);
+ videos.push({
+ url: `${protocol}${filePath}`,
+ index,
+ name: fileName,
+ });
+ index++;
+ }
+ });
+ return { videos, currentIndex };
+ }
+
+ @Get('/getFolder')
+ getFolder(@Query() query): string {
+ const folderPath = query.folderPath;
+ exec(`start "" "${folderPath}"`);
+ return 'ok';
+ }
+
+ @Get('/openFilePath')
+ openFilePath(@Query() query): string {
+ const filePath = query.filePath as string;
+ const folderPath = dirname(filePath);
+ exec(`start "" "${folderPath}"`);
+ return 'ok';
+ }
+}
diff --git a/packages/server/src/app/app.module.ts b/packages/server/src/app/app.module.ts
new file mode 100644
index 00000000..ef45ade6
--- /dev/null
+++ b/packages/server/src/app/app.module.ts
@@ -0,0 +1,49 @@
+import { join } from 'node:path';
+import { Module } from '@nestjs/common';
+import { APP_INTERCEPTOR, APP_FILTER } from '@nestjs/core';
+import { ServeStaticModule } from '@nestjs/serve-static';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { User } from '../users/entity/user.entity';
+import { Record } from '../records/entity/record.entity';
+import { Setting } from '../settings/entity/setting.entity';
+import { DB_PATH } from '../contract';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+import { UsersModule } from '../users/users.module';
+import { RecordsModule } from '../records/records.module';
+import { SettingsModule } from '../settings/settings.module';
+import { ResponseInterceptor } from '../util/response.interceptor';
+import { AllExceptionsFilter } from '../util/exception.filter';
+
+@Module({
+ imports: [
+ ServeStaticModule.forRoot({
+ rootPath: join(__dirname, '../../', 'public'),
+ }),
+ TypeOrmModule.forRoot({
+ type: 'sqljs',
+ location: DB_PATH,
+ autoSave: true,
+ entities: [User, Record, Setting],
+ synchronize: true,
+ logging: true,
+ logger: 'file',
+ }),
+ UsersModule,
+ RecordsModule,
+ SettingsModule,
+ ],
+ controllers: [AppController],
+ providers: [
+ AppService,
+ {
+ provide: APP_INTERCEPTOR,
+ useClass: ResponseInterceptor,
+ },
+ {
+ provide: APP_FILTER,
+ useClass: AllExceptionsFilter,
+ },
+ ],
+})
+export class AppModule {}
diff --git a/packages/server/src/app/app.service.ts b/packages/server/src/app/app.service.ts
new file mode 100644
index 00000000..d1c487d4
--- /dev/null
+++ b/packages/server/src/app/app.service.ts
@@ -0,0 +1,31 @@
+import * as fs from 'fs';
+import * as path from 'path';
+import { Injectable } from '@nestjs/common';
+import { CreateFileDto } from './dto/create-file.dto';
+import { Record } from '../records/entity/record.entity';
+import { RecordsService } from '../records/records.service';
+import { UsersService } from '../users/users.service';
+
+@Injectable()
+export class AppService {
+ constructor(
+ private readonly recordsService: RecordsService,
+ private readonly usersService: UsersService,
+ ) {}
+
+ getHello(): string {
+ return 'Hello World!';
+ }
+
+ async uploadFile(fileDto: CreateFileDto): Promise {
+ const userId = fileDto.userId;
+ const user = await this.usersService.findOne(userId);
+ let record = {
+ filePath: fileDto.path,
+ fileType: fileDto.type,
+ user: user,
+ };
+
+ return this.recordsService.create(record);
+ }
+}
diff --git a/packages/server/src/app/dto/create-file.dto.ts b/packages/server/src/app/dto/create-file.dto.ts
new file mode 100644
index 00000000..2fc04c09
--- /dev/null
+++ b/packages/server/src/app/dto/create-file.dto.ts
@@ -0,0 +1,11 @@
+export class CreateFileDto {
+ file: string;
+
+ fileName: string;
+
+ type: string;
+
+ userId: number;
+
+ path: string;
+}
diff --git a/packages/server/src/config/index.ts b/packages/server/src/config/index.ts
index 93785899..1492a596 100644
--- a/packages/server/src/config/index.ts
+++ b/packages/server/src/config/index.ts
@@ -1,4 +1,4 @@
-import jsonfile from 'jsonfile';
+import * as jsonfile from 'jsonfile';
import * as fs from 'node:fs';
import { v5 as uuidv5 } from 'uuid';
import dayjs from 'dayjs';
diff --git a/packages/server/src/controller/RecordController.ts b/packages/server/src/controller/RecordController.ts
deleted file mode 100644
index 0ac1489e..00000000
--- a/packages/server/src/controller/RecordController.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import { AppDataSource } from '../dataSource';
-import { Record } from '../entity/Record';
-import { UserController } from '../controller/UserController';
-
-const userController = new UserController();
-
-export class RecordController {
- async getRecords(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- let { pageSize = 20, pageNumber = 1 } = req.query;
- const offset = (pageNumber - 1) * pageSize;
- const [records, total] = await recordRepository.findAndCount({
- skip: offset,
- take: pageSize,
- });
- res.json({ code: 0, data: records, total: total });
- }
-
- async createRecord(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- const record = recordRepository.create(req.body);
- recordRepository.save(record);
- res.json({ code: 0, data: record });
- }
-
- async getRecord(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- const record = await recordRepository.findOneBy({ id: req.params.id });
-
- if (!record) {
- return res.json({ code: -1, data: 'record not found' });
- }
-
- res.json({ code: 0, data: record });
- }
-
- async updateRecord(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- const record = await recordRepository.findOneBy({ id: req.params.id });
-
- if (!record) {
- return res.json({ code: -1, data: 'record not found' });
- }
-
- recordRepository.merge(record, req.body);
- await recordRepository.save(record);
- res.json({ code: 0, data: record });
- }
-
- async deleteAllRecord(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- const userId = req.params.userId;
- const records = await recordRepository
- .createQueryBuilder('record')
- .leftJoinAndSelect('record.user', 'user')
- .where('user.id = :id', { id: userId })
- .getMany();
-
- if (!records) {
- return res.json({ code: -1, data: 'record not found' });
- }
-
- await recordRepository.remove(records);
- res.json({ code: 0, data: 'record deleted successfully' });
- }
-
- async deleteRecord(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- const record = await recordRepository.findOneBy({ id: req.params.id });
-
- if (!record) {
- return res.json({ code: -1, data: 'record not found' });
- }
-
- await recordRepository.remove(record);
- res.json({ code: 0, data: 'record deleted successfully' });
- }
-
- async saveFile(req, res) {
- const recordRepository = AppDataSource.getRepository(Record);
- const userId = req.body.userId;
- const user = await userController._getUserById(userId);
- let data = {
- filePath: req.file.path,
- fileType: req.body.type,
- user: user,
- };
- const record = recordRepository.create(data);
- recordRepository.save(record);
- res.json({ code: 0, data: record });
- }
-}
diff --git a/packages/server/src/controller/SettingController.ts b/packages/server/src/controller/SettingController.ts
deleted file mode 100644
index 8f605b50..00000000
--- a/packages/server/src/controller/SettingController.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { AppDataSource } from '../dataSource';
-import { Setting } from '../entity/Setting';
-import { UserController } from '../controller/UserController';
-import { getDefaultConfig, resetConfig, editConfig } from '../config';
-
-const userController = new UserController();
-export class SettingController {
- async getSettings(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const settings = await settingRepository.find();
- res.json({ code: 0, data: settings });
- }
-
- async createSetting(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const setting = settingRepository.create(req.body);
- await settingRepository.save(setting);
- res.json({ code: 0, data: setting });
- }
-
- async getSetting(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const setting = await settingRepository.findOneBy({ id: req.params.id });
-
- if (!setting) {
- return res.json({ code: -1, data: 'setting not found' });
- }
-
- res.json({ code: 0, data: setting });
- }
-
- async getSettingByUserId(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const userId = req.params.userId;
- const setting = await settingRepository
- .createQueryBuilder('setting')
- .leftJoinAndSelect('setting.user', 'user')
- .where('user.id = :id', { id: userId })
- .getOne();
-
- if (!setting) {
- const user = await userController._getUserById(userId);
- const defaultConfig = getDefaultConfig();
- let _setting = {
- isProxy: defaultConfig.isProxy,
- proxyPort: defaultConfig.proxyPort,
- language: defaultConfig.language,
- filePath: defaultConfig.filePath,
- openAtLogin: defaultConfig.openAtLogin,
- serverPath: defaultConfig.serverPath,
- user: user,
- };
- _setting = await settingRepository.save(_setting);
- return res.json({ code: 0, data: _setting });
- }
-
- res.json({ code: 0, data: setting });
- }
-
- async resetSetting(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const setting = await settingRepository.findOneBy({ id: req.params.id });
-
- if (!setting) {
- return res.json({ code: -1, data: 'setting not found' });
- }
- let defaultConfig = getDefaultConfig();
- let _setting = {
- isProxy: defaultConfig.isProxy,
- proxyPort: defaultConfig.proxyPort,
- language: defaultConfig.language,
- filePath: defaultConfig.filePath,
- openAtLogin: defaultConfig.openAtLogin,
- serverPath: defaultConfig.serverPath,
- };
- settingRepository.merge(setting, _setting);
- await settingRepository.save(setting);
- resetConfig();
- res.json({ code: 0, data: setting });
- }
-
- async updateSetting(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const setting = await settingRepository.findOneBy({ id: req.params.id });
-
- if (!setting) {
- return res.json({ code: -1, data: 'setting not found' });
- }
- const _setting = req.body;
- settingRepository.merge(setting, _setting);
- await settingRepository.save(setting);
- for (let key in _setting) {
- let value = _setting[key];
- editConfig(key, value);
- }
- res.json({ code: 0, data: setting });
- }
-
- async deleteSetting(req, res) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const setting = await settingRepository.findOneBy({ id: req.params.id });
-
- if (!setting) {
- return res.json({ code: -1, data: 'setting not found' });
- }
-
- await settingRepository.remove(setting);
- res.json({ code: 0, data: 'setting deleted successfully' });
- }
-
- async _getSettingByUserId(userId) {
- const settingRepository = AppDataSource.getRepository(Setting);
- const setting = await settingRepository
- .createQueryBuilder('setting')
- .leftJoinAndSelect('setting.user', 'user')
- .where('user.id = :id', { id: userId })
- .getOne();
-
- return setting;
- }
-}
diff --git a/packages/server/src/controller/UserController.ts b/packages/server/src/controller/UserController.ts
deleted file mode 100644
index d18aafac..00000000
--- a/packages/server/src/controller/UserController.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { AppDataSource } from '../dataSource';
-import { User } from '../entity/User';
-import { getConfig } from '../config';
-
-export class UserController {
- async getUsers(req, res) {
- const userRepository = AppDataSource.getRepository(User);
- const users = await userRepository.find();
- res.json({ code: 0, data: users });
- }
-
- async createUser(req, res) {
- const userRepository = AppDataSource.getRepository(User);
- const user = userRepository.create(req.body);
- await userRepository.save(user);
- res.json({ code: 0, data: user });
- }
-
- async getUser(req, res) {
- const userRepository = AppDataSource.getRepository(User);
- const user = await userRepository.findOneBy({ id: req.params.id });
-
- if (!user) {
- res.json({ code: -1, data: 'User not found' });
- }
-
- res.json({ code: 0, data: user });
- }
-
- async updateUser(req, res) {
- const userRepository = AppDataSource.getRepository(User);
- const user = await userRepository.findOneBy({ id: req.params.id });
-
- if (!user) {
- res.json({ code: -1, data: 'User not found' });
- }
-
- userRepository.merge(user, req.body);
- await userRepository.save(user);
- res.json({ code: 0, data: user });
- }
-
- async deleteUser(req, res) {
- const userRepository = AppDataSource.getRepository(User);
- const user = await userRepository.findOneBy({ id: req.params.id });
-
- if (!user) {
- res.json({ code: -1, data: 'User not found' });
- }
-
- await userRepository.remove(user);
- res.json({ code: 0, data: 'User deleted successfully' });
- }
-
- async getCurrentUser(req, res) {
- const userRepository = AppDataSource.getRepository(User);
- const config = getConfig();
- const user = await userRepository.findOneBy({ uuid: config.user.uuid });
-
- if (!user) {
- let _user = {
- ...config.user,
- };
- _user = userRepository.create(_user);
- await userRepository.save(_user);
- res.json({ code: 0, data: _user });
- }
-
- res.json({ code: 0, data: user });
- }
-
- async _getUserById(id) {
- const userRepository = AppDataSource.getRepository(User);
- const user = await userRepository.findOneBy({ id: id });
-
- return user;
- }
-}
diff --git a/packages/server/src/dataSource.ts b/packages/server/src/dataSource.ts
deleted file mode 100644
index daba135c..00000000
--- a/packages/server/src/dataSource.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'reflect-metadata';
-import fs from 'node:fs';
-import { dirname } from 'node:path';
-import { DataSource } from 'typeorm';
-import { User } from './entity/User';
-import { Record } from './entity/Record';
-import { Setting } from './entity/Setting';
-import { DB_PATH } from './contract';
-
-const fileDir = dirname(DB_PATH);
-if (!fs.existsSync(fileDir)) {
- fs.mkdirSync(fileDir, { recursive: true });
-}
-
-export const AppDataSource = new DataSource({
- type: 'sqljs',
- location: DB_PATH,
- autoSave: true,
- entities: [User, Record, Setting],
- synchronize: true,
- logging: true,
- logger: 'file',
-});
diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts
deleted file mode 100644
index f2778dbf..00000000
--- a/packages/server/src/index.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import 'reflect-metadata';
-import cors from 'cors';
-import bodyParser from 'body-parser';
-import express, { Request, Response } from 'express';
-import { AppDataSource } from './dataSource';
-import { AppRoutes } from './route/index';
-import { initApi } from './api';
-import { initConfig } from './config';
-import { PORT } from './contract';
-
-export default function initApp() {
- AppDataSource.initialize()
- .then(async (connection) => {
- const app = express();
-
- app.use(cors());
- app.use(bodyParser.json());
- app.use(bodyParser.urlencoded({ extended: true }));
- app.use(function (err, req, res, next) {
- console.error('server:', err.stack);
- res.status(500).send('服务器内部错误');
- });
-
- initConfig();
- initApi(app);
-
- AppRoutes.forEach((route: any) => {
- app[route.method](route.path, (request: Request, response: Response, next: Function) => {
- route
- .action(request, response)
- .then(() => next)
- .catch((err) => next(err));
- });
- });
-
- app.listen(PORT);
-
- console.log(`Express application is up and running on port ${PORT}`);
- })
- .catch((error) => console.log('TypeORM connection error: ', error));
-}
-
-initApp();
diff --git a/packages/server/src/main.ts b/packages/server/src/main.ts
new file mode 100644
index 00000000..7629ff56
--- /dev/null
+++ b/packages/server/src/main.ts
@@ -0,0 +1,50 @@
+import * as fs from 'node:fs';
+import { join } from 'node:path';
+import { NestFactory } from '@nestjs/core';
+import { AppModule } from './app/app.module';
+import { initConfig, getConfig } from './config';
+import { PORT } from './contract';
+import * as multer from 'multer';
+
+async function bootstrap() {
+ initConfig();
+
+ const app = await NestFactory.create(AppModule, { cors: true, bodyParser: false });
+
+ const storage = multer.diskStorage({
+ destination: async function (req, file, cb) {
+ const { type, userId } = req.body;
+ const config = getConfig();
+ const user = config.user;
+ try {
+ const filePath = join(config?.filePath, `${user.uuid}/${type}`);
+ if (!fs.existsSync(filePath)) {
+ fs.mkdirSync(filePath, { recursive: true });
+ }
+ cb(null, filePath);
+ } catch (err) {
+ console.log('saveFile err', err);
+ }
+ },
+ filename: function (req, file, cb) {
+ const fileTypeMap = {
+ ss: 'png',
+ rs: 'webm',
+ ra: 'webm',
+ ei: 'png',
+ };
+ const type = req.body.type;
+ const fileType = fileTypeMap[type] || 'webm';
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
+ const fileName = `${type}-${uniqueSuffix}.${fileType}`;
+ cb(null, fileName);
+ },
+ });
+
+ app.use(multer({ storage }).single('file'));
+
+ await app.listen(PORT);
+
+ console.log(`Server application is up and running on port ${PORT}`);
+}
+bootstrap();
diff --git a/packages/server/src/model/IUser.ts b/packages/server/src/model/IUser.ts
deleted file mode 100644
index db003c08..00000000
--- a/packages/server/src/model/IUser.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export interface IUser {
- id: number;
-
- uuid: string;
-
- userName: string;
-
- userType: string;
-
- createdAt: Date;
-
- createdBy: string;
-
- updatedAt: Date;
-
- updatedBy: string;
-}
diff --git a/packages/server/src/records/dto/create-record.dto.ts b/packages/server/src/records/dto/create-record.dto.ts
new file mode 100644
index 00000000..dd789011
--- /dev/null
+++ b/packages/server/src/records/dto/create-record.dto.ts
@@ -0,0 +1,19 @@
+import { IUser } from '../../users/interfaces/user.interface';
+
+export class CreateRecordDto {
+ filePath: string;
+
+ fileType: string;
+
+ mark?: string;
+
+ user: IUser;
+
+ createdAt?: Date;
+
+ createdBy?: string;
+
+ updatedAt?: Date;
+
+ updatedBy?: string;
+}
diff --git a/packages/server/src/entity/Record.ts b/packages/server/src/records/entity/record.entity.ts
similarity index 57%
rename from packages/server/src/entity/Record.ts
rename to packages/server/src/records/entity/record.entity.ts
index 8812d68e..2da16248 100644
--- a/packages/server/src/entity/Record.ts
+++ b/packages/server/src/records/entity/record.entity.ts
@@ -7,11 +7,13 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
-import { User } from './User';
-import { IRecord } from '../model/IRecord';
+import { User } from '../../users/entity/user.entity';
+import { IUser } from '../../users/interfaces/user.interface';
+// import { IRecord } from '../interfaces/record.interface';
@Entity()
-export class Record implements IRecord {
+export class Record {
+ user: IUser;
@PrimaryGeneratedColumn()
id: number;
@@ -22,20 +24,20 @@ export class Record implements IRecord {
fileType: string;
@Column('varchar', { nullable: true })
- mark: string;
+ mark?: string;
@CreateDateColumn({ nullable: true })
- createdAt: Date;
+ createdAt?: Date;
@Column('varchar', { nullable: true })
- createdBy: string;
+ createdBy?: string;
@UpdateDateColumn({ nullable: true })
- updatedAt: Date;
+ updatedAt?: Date;
@Column('varchar', { nullable: true })
- updatedBy: string;
+ updatedBy?: string;
- @ManyToOne(() => User, (user) => user.records)
- user: User;
+ // @ManyToOne(() => User, (user) => user.records)
+ // user: IUser;
}
diff --git a/packages/server/src/model/IRecord.ts b/packages/server/src/records/interfaces/record.interface.ts
similarity index 69%
rename from packages/server/src/model/IRecord.ts
rename to packages/server/src/records/interfaces/record.interface.ts
index b5aa0712..cb471026 100644
--- a/packages/server/src/model/IRecord.ts
+++ b/packages/server/src/records/interfaces/record.interface.ts
@@ -1,3 +1,5 @@
+import { IUser } from '../../users/interfaces/user.interface';
+
export interface IRecord {
id: number;
@@ -7,6 +9,8 @@ export interface IRecord {
mark: string;
+ user: IUser;
+
createdAt: Date;
createdBy: string;
diff --git a/packages/server/src/records/records.controller.ts b/packages/server/src/records/records.controller.ts
new file mode 100644
index 00000000..1dabff2f
--- /dev/null
+++ b/packages/server/src/records/records.controller.ts
@@ -0,0 +1,39 @@
+import { Controller, Get, Post, Body, Param, Query } from '@nestjs/common';
+import { CreateRecordDto } from './dto/create-record.dto';
+import { RecordsService } from './records.service';
+import { Record } from './entity/record.entity';
+
+@Controller('records')
+export class RecordsController {
+ constructor(private recordsService: RecordsService) {}
+
+ @Post()
+ create(@Body() record: CreateRecordDto): Promise {
+ return this.recordsService.create(record);
+ }
+
+ @Get()
+ findAll(@Query('pageNumber') page = 1, @Query('pageSize') limit = 20): Promise {
+ return this.recordsService.findAll(page, limit);
+ }
+
+ @Get(':id')
+ findOne(@Param('id') id: number): Promise {
+ return this.recordsService.findOne(id);
+ }
+
+ @Post('/edit/:id')
+ update(@Param('id') id: number, @Body() record: CreateRecordDto): Promise {
+ return this.recordsService.update(id, record);
+ }
+
+ @Post('/delete/list')
+ removeList(@Body('ids') ids: number[]): Promise {
+ return this.recordsService.removeList(ids);
+ }
+
+ @Post('/delete/:id')
+ remove(@Param('id') id: number): Promise {
+ return this.recordsService.remove(id);
+ }
+}
diff --git a/packages/server/src/records/records.module.ts b/packages/server/src/records/records.module.ts
new file mode 100644
index 00000000..7ba3a251
--- /dev/null
+++ b/packages/server/src/records/records.module.ts
@@ -0,0 +1,13 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { RecordsController } from './records.controller';
+import { RecordsService } from './records.service';
+import { Record } from './entity/record.entity';
+
+@Module({
+ imports: [TypeOrmModule.forFeature([Record])],
+ controllers: [RecordsController],
+ providers: [RecordsService],
+ exports: [RecordsService],
+})
+export class RecordsModule {}
diff --git a/packages/server/src/records/records.providers.ts b/packages/server/src/records/records.providers.ts
new file mode 100644
index 00000000..56b638a2
--- /dev/null
+++ b/packages/server/src/records/records.providers.ts
@@ -0,0 +1,10 @@
+import { DataSource } from 'typeorm';
+import { Record } from './entity/record.entity';
+
+export const recordProviders = [
+ {
+ provide: 'RECORDS_REPOSITORY',
+ useFactory: (dataSource: DataSource) => dataSource.getRepository(Record),
+ inject: ['DATA_SOURCE'],
+ },
+];
diff --git a/packages/server/src/records/records.service.ts b/packages/server/src/records/records.service.ts
new file mode 100644
index 00000000..f2857296
--- /dev/null
+++ b/packages/server/src/records/records.service.ts
@@ -0,0 +1,45 @@
+import { Injectable } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+import { Record } from './entity/record.entity';
+import { CreateRecordDto } from './dto/create-record.dto';
+
+@Injectable()
+export class RecordsService {
+ constructor(
+ @InjectRepository(Record)
+ private readonly recordRepository: Repository,
+ ) {}
+
+ async create(record: CreateRecordDto): Promise {
+ return await this.recordRepository.save(record);
+ }
+
+ async findAll(pageNumber: number, pageSize: number): Promise {
+ const [records, totalCount] = await this.recordRepository.findAndCount({
+ skip: (pageNumber - 1) * pageSize,
+ take: pageSize,
+ });
+
+ return records;
+ }
+
+ async findOne(id: number): Promise {
+ return await this.recordRepository.findOneBy({ id });
+ }
+
+ async update(id: number, record: CreateRecordDto): Promise {
+ await this.recordRepository.update(id, record);
+ return await this.recordRepository.findOneBy({ id });
+ }
+
+ async remove(id: number): Promise {
+ await this.recordRepository.delete(id);
+ return `${id} is removed`;
+ }
+
+ async removeList(ids: number[]): Promise {
+ await this.recordRepository.delete(ids);
+ return `${ids} is removed`;
+ }
+}
diff --git a/packages/server/src/route/Record.ts b/packages/server/src/route/Record.ts
deleted file mode 100644
index 9f9f5d8c..00000000
--- a/packages/server/src/route/Record.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { RecordController } from '../controller/RecordController';
-
-const recordController = new RecordController();
-
-export const RecordRoutes = [
- {
- path: '/records',
- method: 'get',
- action: recordController.getRecords,
- },
- {
- path: '/addRecord',
- method: 'post',
- action: recordController.createRecord,
- },
- {
- path: '/record/:id',
- method: 'get',
- action: recordController.getRecord,
- },
- {
- path: '/editRecord/:id',
- method: 'post',
- action: recordController.updateRecord,
- },
- {
- path: '/deleteRecord/:id',
- method: 'post',
- action: recordController.deleteRecord,
- },
- {
- path: '/deleteAllRecord',
- method: 'post',
- action: recordController.deleteAllRecord,
- },
-];
diff --git a/packages/server/src/route/Setting.ts b/packages/server/src/route/Setting.ts
deleted file mode 100644
index d9838952..00000000
--- a/packages/server/src/route/Setting.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { SettingController } from '../controller/SettingController';
-
-const settingController = new SettingController();
-
-export const SettingRoutes = [
- {
- path: '/settings',
- method: 'get',
- action: settingController.getSettings,
- },
- {
- path: '/addSetting',
- method: 'post',
- action: settingController.createSetting,
- },
- {
- path: '/setting/:id',
- method: 'get',
- action: settingController.getSetting,
- },
- {
- path: '/getSettingByUserId/:userId',
- method: 'get',
- action: settingController.getSettingByUserId,
- },
- {
- path: '/editSetting/:id',
- method: 'post',
- action: settingController.updateSetting,
- },
- {
- path: '/deleteSettings/:id',
- method: 'get',
- action: settingController.deleteSetting,
- },
- {
- path: '/resetSetting/:id',
- method: 'get',
- action: settingController.resetSetting,
- },
-];
diff --git a/packages/server/src/route/User.ts b/packages/server/src/route/User.ts
deleted file mode 100644
index 8aa206e8..00000000
--- a/packages/server/src/route/User.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { UserController } from "../controller/UserController";
-
-const userController = new UserController();
-
-export const UserRoutes = [
- {
- path: "/users",
- method: "get",
- action: userController.getUsers,
- },
- {
- path: "/addUser",
- method: "post",
- action: userController.createUser,
- },
- {
- path: "/getUser/:id",
- method: "get",
- action: userController.getUser,
- },
- {
- path: "/editUser/:id",
- method: "get",
- action: userController.updateUser,
- },
- {
- path: "/deleteUser/:id",
- method: "get",
- action: userController.deleteUser,
- },
- {
- path: "/getCurrentUser",
- method: "get",
- action: userController.getCurrentUser,
- },
-];
diff --git a/packages/server/src/route/index.ts b/packages/server/src/route/index.ts
deleted file mode 100644
index 467cf24e..00000000
--- a/packages/server/src/route/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { UserRoutes } from './User';
-import { RecordRoutes } from './Record';
-import { SettingRoutes } from './Setting';
-
-/**
- * All application routes.
- */
-export const AppRoutes = [...UserRoutes, ...RecordRoutes, ...SettingRoutes];
diff --git a/packages/server/src/settings/dto/create-setting.dto.ts b/packages/server/src/settings/dto/create-setting.dto.ts
new file mode 100644
index 00000000..e525aab2
--- /dev/null
+++ b/packages/server/src/settings/dto/create-setting.dto.ts
@@ -0,0 +1,27 @@
+import { IUser } from '../../users/interfaces/user.interface';
+
+export class CreateSettingDto {
+ id: number;
+
+ isProxy: boolean;
+
+ proxyPort: number;
+
+ language: string;
+
+ filePath: string;
+
+ openAtLogin: boolean;
+
+ serverPath: string;
+
+ user: IUser;
+
+ createdAt: Date;
+
+ createdBy: string;
+
+ updatedAt: Date;
+
+ updatedBy: string;
+}
diff --git a/packages/server/src/entity/Setting.ts b/packages/server/src/settings/entity/setting.entity.ts
similarity index 77%
rename from packages/server/src/entity/Setting.ts
rename to packages/server/src/settings/entity/setting.entity.ts
index 1d294257..5e9e815a 100644
--- a/packages/server/src/entity/Setting.ts
+++ b/packages/server/src/settings/entity/setting.entity.ts
@@ -7,11 +7,13 @@ import {
UpdateDateColumn,
OneToOne,
} from 'typeorm';
-import { User } from './User';
-import { ISetting } from '../model/ISetting';
+import { User } from '../../users/entity/user.entity';
+import { IUser } from '../../users/interfaces/user.interface';
+import { ISetting } from '../interfaces/setting.interface';
@Entity()
export class Setting implements ISetting {
+ user: IUser;
@PrimaryGeneratedColumn()
id: number;
@@ -51,7 +53,7 @@ export class Setting implements ISetting {
@Column('varchar', { nullable: true })
updatedBy: string;
- @OneToOne(() => User, (user) => user.setting)
- @JoinColumn()
- user: User;
+ // @OneToOne(() => User, (user) => user.setting)
+ // @JoinColumn()
+ // user: IUser;
}
diff --git a/packages/server/src/model/ISetting.ts b/packages/server/src/settings/interfaces/setting.interface.ts
similarity index 76%
rename from packages/server/src/model/ISetting.ts
rename to packages/server/src/settings/interfaces/setting.interface.ts
index e1190c89..bf5d3ef9 100644
--- a/packages/server/src/model/ISetting.ts
+++ b/packages/server/src/settings/interfaces/setting.interface.ts
@@ -1,3 +1,5 @@
+import { IUser } from '../../users/interfaces/user.interface';
+
export interface ISetting {
id: number;
@@ -13,6 +15,8 @@ export interface ISetting {
serverPath: string;
+ user: IUser;
+
createdAt: Date;
createdBy: string;
diff --git a/packages/server/src/settings/settings.controller.ts b/packages/server/src/settings/settings.controller.ts
new file mode 100644
index 00000000..fca6bc98
--- /dev/null
+++ b/packages/server/src/settings/settings.controller.ts
@@ -0,0 +1,39 @@
+import { Controller, Get, Post, Body, Param, UseInterceptors } from '@nestjs/common';
+import { CreateSettingDto } from './dto/create-setting.dto';
+import { SettingsService } from './settings.service';
+import { Setting } from './entity/setting.entity';
+
+@Controller('settings')
+export class SettingsController {
+ constructor(private settingsService: SettingsService) {}
+
+ @Post()
+ create(@Body() record: CreateSettingDto): Promise {
+ return this.settingsService.create(record);
+ }
+
+ @Get()
+ findAll(): Promise {
+ return this.settingsService.findAll();
+ }
+
+ @Get(':id')
+ findOne(@Param('id') id: number): Promise {
+ return this.settingsService.findOne(id);
+ }
+
+ @Post('/edit/:id')
+ update(@Param('id') id: number, @Body() record: CreateSettingDto): Promise {
+ return this.settingsService.update(id, record);
+ }
+
+ @Post('/delete/:id')
+ remove(@Param('id') id: number): Promise {
+ return this.settingsService.remove(id);
+ }
+
+ @Post('/reset/:id')
+ reset(@Param('id') id: number): Promise {
+ return this.settingsService.reset(id);
+ }
+}
diff --git a/packages/server/src/settings/settings.module.ts b/packages/server/src/settings/settings.module.ts
new file mode 100644
index 00000000..94f95b5d
--- /dev/null
+++ b/packages/server/src/settings/settings.module.ts
@@ -0,0 +1,16 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+// import { DatabaseModule } from '../database/database.module';
+import { SettingsController } from './settings.controller';
+import { SettingsService } from './settings.service';
+import { Setting } from './entity/setting.entity';
+// import { settingsProviders } from './settings.providers';
+
+@Module({
+ // imports: [DatabaseModule],
+ imports: [TypeOrmModule.forFeature([Setting])],
+ controllers: [SettingsController],
+ providers: [SettingsService],
+ exports: [SettingsService],
+})
+export class SettingsModule {}
diff --git a/packages/server/src/settings/settings.providers.ts b/packages/server/src/settings/settings.providers.ts
new file mode 100644
index 00000000..3767d143
--- /dev/null
+++ b/packages/server/src/settings/settings.providers.ts
@@ -0,0 +1,10 @@
+import { DataSource } from 'typeorm';
+import { Setting } from './entity/setting.entity';
+
+export const settingsProviders = [
+ {
+ provide: 'SETTINGS_REPOSITORY',
+ useFactory: (dataSource: DataSource) => dataSource.getRepository(Setting),
+ inject: ['DATA_SOURCE'],
+ },
+];
diff --git a/packages/server/src/settings/settings.service.ts b/packages/server/src/settings/settings.service.ts
new file mode 100644
index 00000000..8d8567cd
--- /dev/null
+++ b/packages/server/src/settings/settings.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+import { Setting } from './entity/setting.entity';
+import { getDefaultConfig } from '../config';
+
+@Injectable()
+export class SettingsService {
+ constructor(
+ @InjectRepository(Setting)
+ private readonly settingRepository: Repository,
+ ) {}
+
+ async create(setting: Setting): Promise {
+ return await this.settingRepository.save(setting);
+ }
+
+ async findAll(): Promise {
+ return await this.settingRepository.find();
+ }
+
+ async findOne(id: number): Promise {
+ return await this.settingRepository.findOneBy({ id });
+ }
+
+ async update(id: number, setting: Setting): Promise {
+ await this.settingRepository.update(id, setting);
+ return await this.settingRepository.findOneBy({ id });
+ }
+
+ async remove(id: number): Promise {
+ await this.settingRepository.delete(id);
+ }
+
+ async reset(id: number): Promise {
+ const defaultConfig = getDefaultConfig();
+ let setting = {
+ isProxy: defaultConfig.isProxy,
+ proxyPort: defaultConfig.proxyPort,
+ language: defaultConfig.language,
+ filePath: defaultConfig.filePath,
+ openAtLogin: defaultConfig.openAtLogin,
+ serverPath: defaultConfig.serverPath,
+ };
+ await this.settingRepository.update(id, setting);
+ return await this.settingRepository.findOneBy({ id });
+ }
+}
diff --git a/packages/server/src/users/dto/create-user.dto.ts b/packages/server/src/users/dto/create-user.dto.ts
new file mode 100644
index 00000000..1fa7d5ba
--- /dev/null
+++ b/packages/server/src/users/dto/create-user.dto.ts
@@ -0,0 +1,24 @@
+import { ISetting } from '../../settings/interfaces/setting.interface';
+import { IRecord } from '../../records/interfaces/record.interface';
+
+export class CreateUserDto {
+ id: number;
+
+ uuid: string;
+
+ userName: string;
+
+ userType: string;
+
+ // records: IRecord[];
+
+ // setting: ISetting;
+
+ createdAt: Date;
+
+ createdBy: string;
+
+ updatedAt: Date;
+
+ updatedBy: string;
+}
diff --git a/packages/server/src/entity/User.ts b/packages/server/src/users/entity/user.entity.ts
similarity index 64%
rename from packages/server/src/entity/User.ts
rename to packages/server/src/users/entity/user.entity.ts
index d4560d3a..7a42181b 100644
--- a/packages/server/src/entity/User.ts
+++ b/packages/server/src/users/entity/user.entity.ts
@@ -7,11 +7,11 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
-import { IUser } from '../model/IUser';
-import { Record } from './Record';
-import { Setting } from './Setting';
+import { IUser } from '../interfaces/user.interface';
+import { Record } from '../../records/entity/record.entity';
+import { Setting } from '../../settings/entity/setting.entity';
// import { IRecord } from '../model/IRecord';
-import { ISetting } from '../model/ISetting';
+// import { ISetting } from '../model/ISetting';
@Entity()
export class User implements IUser {
@@ -42,9 +42,9 @@ export class User implements IUser {
@Column('varchar', { nullable: true })
updatedBy: string;
- @OneToMany(() => Record, (record) => record.user)
- records: Record[];
+ // @OneToMany(() => Record, (record) => record.user)
+ // records: Record[];
- @OneToOne(() => Setting, (setting) => setting.user)
- setting: Setting;
+ // @OneToOne(() => Setting, (setting) => setting.user)
+ // setting: Setting;
}
diff --git a/packages/server/src/users/interfaces/user.interface.ts b/packages/server/src/users/interfaces/user.interface.ts
new file mode 100644
index 00000000..2e5c230b
--- /dev/null
+++ b/packages/server/src/users/interfaces/user.interface.ts
@@ -0,0 +1,24 @@
+import { ISetting } from '../../settings/interfaces/setting.interface';
+import { IRecord } from '../../records/interfaces/record.interface';
+
+export interface IUser {
+ id: number;
+
+ uuid: string;
+
+ userName: string;
+
+ userType: string;
+
+ // records: IRecord[];
+
+ // setting: ISetting;
+
+ createdAt: Date;
+
+ createdBy: string;
+
+ updatedAt: Date;
+
+ updatedBy: string;
+}
diff --git a/packages/server/src/users/users.controller.ts b/packages/server/src/users/users.controller.ts
new file mode 100644
index 00000000..50b5750b
--- /dev/null
+++ b/packages/server/src/users/users.controller.ts
@@ -0,0 +1,39 @@
+import { Controller, Get, Post, Body, Param } from '@nestjs/common';
+import { CreateUserDto } from './dto/create-user.dto';
+import { UsersService } from './users.service';
+import { User } from './entity/user.entity';
+
+@Controller('users')
+export class UsersController {
+ constructor(private readonly usersService: UsersService) {}
+
+ @Post()
+ create(@Body() user: User): Promise {
+ return this.usersService.create(user);
+ }
+
+ @Get()
+ findAll(): Promise {
+ return this.usersService.findAll();
+ }
+
+ @Get('/current')
+ findCurrent(): Promise {
+ return this.usersService.findCurrent();
+ }
+
+ @Get(':id')
+ findOne(@Param('id') id: number): Promise {
+ return this.usersService.findOne(id);
+ }
+
+ @Post('/edit/:id')
+ update(@Param('id') id: number, @Body() user: User): Promise {
+ return this.usersService.update(id, user);
+ }
+
+ @Post('/delete/:id')
+ remove(@Param('id') id: number): Promise {
+ return this.usersService.remove(id);
+ }
+}
diff --git a/packages/server/src/users/users.module.ts b/packages/server/src/users/users.module.ts
new file mode 100644
index 00000000..1bd5373b
--- /dev/null
+++ b/packages/server/src/users/users.module.ts
@@ -0,0 +1,13 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { UsersController } from './users.controller';
+import { UsersService } from './users.service';
+import { User } from './entity/user.entity';
+
+@Module({
+ imports: [TypeOrmModule.forFeature([User])],
+ controllers: [UsersController],
+ providers: [UsersService],
+ exports: [UsersService],
+})
+export class UsersModule {}
diff --git a/packages/server/src/users/users.providers.ts b/packages/server/src/users/users.providers.ts
new file mode 100644
index 00000000..3cb0c779
--- /dev/null
+++ b/packages/server/src/users/users.providers.ts
@@ -0,0 +1,10 @@
+import { DataSource } from 'typeorm';
+import { User } from './entity/user.entity';
+
+export const userProviders = [
+ {
+ provide: 'USERS_REPOSITORY',
+ useFactory: (dataSource: DataSource) => dataSource.getRepository(User),
+ inject: ['DATA_SOURCE'],
+ },
+];
diff --git a/packages/server/src/users/users.service.ts b/packages/server/src/users/users.service.ts
new file mode 100644
index 00000000..551610ff
--- /dev/null
+++ b/packages/server/src/users/users.service.ts
@@ -0,0 +1,39 @@
+import { Injectable } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+import { User } from './entity/user.entity';
+import { getConfig } from '../config';
+
+@Injectable()
+export class UsersService {
+ constructor(
+ @InjectRepository(User)
+ private usersRepository: Repository,
+ ) {}
+
+ findAll(): Promise {
+ return this.usersRepository.find();
+ }
+
+ findCurrent(): Promise {
+ const config = getConfig();
+ return this.usersRepository.findOneBy({ uuid: config.user.uuid });
+ }
+
+ findOne(id: number): Promise {
+ return this.usersRepository.findOneBy({ id });
+ }
+
+ async create(user: User): Promise {
+ return await this.usersRepository.save(user);
+ }
+
+ async update(id: number, user: User): Promise {
+ await this.usersRepository.update(id, user);
+ return await this.usersRepository.findOneBy({ id });
+ }
+
+ async remove(id: number): Promise {
+ await this.usersRepository.delete(id);
+ }
+}
diff --git a/packages/server/src/util/exception.filter.ts b/packages/server/src/util/exception.filter.ts
new file mode 100644
index 00000000..7a489a7b
--- /dev/null
+++ b/packages/server/src/util/exception.filter.ts
@@ -0,0 +1,22 @@
+import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
+
+@Catch()
+export class AllExceptionsFilter implements ExceptionFilter {
+ catch(exception: unknown, host: ArgumentsHost) {
+ const ctx = host.switchToHttp();
+ const response = ctx.getResponse();
+
+ let statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
+ let message = 'Internal server error';
+
+ if (exception instanceof HttpException) {
+ statusCode = exception.getStatus();
+ message = exception.message;
+ }
+
+ response.status(statusCode).json({
+ code: -1,
+ message,
+ });
+ }
+}
diff --git a/packages/server/src/util/response.interceptor.ts b/packages/server/src/util/response.interceptor.ts
new file mode 100644
index 00000000..99825a2d
--- /dev/null
+++ b/packages/server/src/util/response.interceptor.ts
@@ -0,0 +1,30 @@
+import {
+ Injectable,
+ NestInterceptor,
+ ExecutionContext,
+ CallHandler,
+ BadGatewayException,
+ StreamableFile,
+} from '@nestjs/common';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { Response } from 'express';
+
+@Injectable()
+export class ResponseInterceptor implements NestInterceptor {
+ intercept(context: ExecutionContext, next: CallHandler): Observable {
+ const response = context.switchToHttp().getResponse();
+
+ return next.handle().pipe(
+ map((data) => {
+ if (data.code === -1) {
+ throw new BadGatewayException(data.message);
+ } else if (data instanceof StreamableFile) {
+ return data;
+ } else {
+ return { code: 0, message: 'Internal server success', data };
+ }
+ }),
+ );
+ }
+}
diff --git a/packages/server/tsconfig.build.json b/packages/server/tsconfig.build.json
new file mode 100644
index 00000000..37816248
--- /dev/null
+++ b/packages/server/tsconfig.build.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "exclude": [
+ "node_modules",
+ "test",
+ "dist",
+ "**/*spec.ts"
+ ]
+}
\ No newline at end of file
diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json
index e8ac29be..000fbb17 100644
--- a/packages/server/tsconfig.json
+++ b/packages/server/tsconfig.json
@@ -1,18 +1,21 @@
{
"compilerOptions": {
- "target": "ES5",
- "experimentalDecorators": true,
+ "module": "commonjs",
+ "declaration": true,
+ "removeComments": true,
"emitDecoratorMetadata": true,
- "esModuleInterop": true,
- "moduleResolution": "Node",
- "outDir": "dist",
- "importHelpers": true,
- "useDefineForClassFields": false,
- },
- "include": [
- "src/**/*.ts"
- ],
- "exclude": [
- "node_modules"
- ]
+ "experimentalDecorators": true,
+ "allowSyntheticDefaultImports": true,
+ "target": "ES2021",
+ "sourceMap": true,
+ "outDir": "./dist",
+ "baseUrl": "./",
+ "incremental": true,
+ "skipLibCheck": true,
+ "strictNullChecks": false,
+ "noImplicitAny": false,
+ "strictBindCallApply": false,
+ "forceConsistentCasingInFileNames": false,
+ "noFallthroughCasesInSwitch": false
+ }
}
\ No newline at end of file
diff --git a/packages/web/src/api/index.ts b/packages/web/src/api/index.ts
index ed507b1b..a8bc4d78 100644
--- a/packages/web/src/api/index.ts
+++ b/packages/web/src/api/index.ts
@@ -4,8 +4,11 @@ export function useApi() {
return {
saveFile: (formData) => {
return request({
- url: `/saveFile`,
+ url: `/upload/file`,
method: 'post',
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
data: formData,
});
},
diff --git a/packages/web/src/api/record.ts b/packages/web/src/api/record.ts
index 7362408b..2e1252ff 100644
--- a/packages/web/src/api/record.ts
+++ b/packages/web/src/api/record.ts
@@ -10,14 +10,17 @@ export function useRecordApi() {
},
deleteRecord: (recordId) => {
return request({
- url: `/deleteRecord/${recordId}`,
+ url: `/records/delete/${recordId}`,
method: 'post',
});
},
- deleteAllRecord: () => {
+ deleteListRecord: (ids) => {
return request({
- url: `/deleteAllRecord`,
+ url: `/records/delete/list`,
method: 'post',
+ data: {
+ ids: JSON.stringify(ids),
+ },
});
},
};
diff --git a/packages/web/src/api/setting.ts b/packages/web/src/api/setting.ts
index 188f20ff..95305619 100644
--- a/packages/web/src/api/setting.ts
+++ b/packages/web/src/api/setting.ts
@@ -4,21 +4,21 @@ export function useSettingApi() {
return {
getSetting: (userId: string) => {
return request({
- url: `/getSettingByUserId/${userId}`,
+ url: `/settings/${userId}`,
method: 'get',
});
},
editSetting: (settingId, data) => {
return request({
- url: `/editSetting/${settingId}`,
+ url: `/settings/edit/${settingId}`,
method: 'post',
data: data,
});
},
- resetSetting: (userId) => {
+ resetSetting: (settingId) => {
return request({
- url: `/resetSetting/${userId}`,
- method: 'get',
+ url: `/settings/reset/${settingId}`,
+ method: 'post',
});
},
};
diff --git a/packages/web/src/api/user.ts b/packages/web/src/api/user.ts
index bfbf1014..c73331bf 100644
--- a/packages/web/src/api/user.ts
+++ b/packages/web/src/api/user.ts
@@ -4,29 +4,9 @@ export function useUserApi() {
return {
getCurrentUser: () => {
return request({
- url: `/getCurrentUser`,
+ url: `/users/current`,
method: 'get',
});
},
- addUser: (data) => {
- return request({
- url: `/addUser`,
- method: 'post',
- data: data,
- });
- },
- editUser: (userId, data) => {
- return request({
- url: `/editUser/${userId}`,
- method: 'post',
- data: data,
- });
- },
- deleteUser: (userId) => {
- return request({
- url: `/deleteUser/${userId}`,
- method: 'post',
- });
- },
};
}
diff --git a/packages/web/src/components/recorderAudio/WaveSurferPlayer.tsx b/packages/web/src/components/recorderAudio/WaveSurferPlayer.tsx
index 7d13e96d..c0614454 100644
--- a/packages/web/src/components/recorderAudio/WaveSurferPlayer.tsx
+++ b/packages/web/src/components/recorderAudio/WaveSurferPlayer.tsx
@@ -1,191 +1,179 @@
-import React, { useState, useRef, useEffect, useCallback } from "react";
-import { useTranslation } from "react-i18next";
-import {
- Button,
- Space,
- Divider,
- Slider,
- Row,
- Col,
- Checkbox,
- Modal,
- message,
-} from "antd";
-import WaveSurfer from "wavesurfer.js";
-import { saveAs } from "file-saver";
-import { useApi } from "../../api";
+import React, { useState, useRef, useEffect, useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Button, Space, Divider, Slider, Row, Col, Checkbox, Modal, message } from 'antd';
+import WaveSurfer from 'wavesurfer.js';
+import { saveAs } from 'file-saver';
+import { useApi } from '../../api';
const useWavesurfer = (containerRef, options) => {
- const [wavesurfer, setWavesurfer] = useState(null);
+ const [wavesurfer, setWavesurfer] = useState(null);
- useEffect(() => {
- if (!containerRef.current) return;
+ useEffect(() => {
+ if (!containerRef.current) return;
- const ws = WaveSurfer.create({
- ...options,
- container: containerRef.current,
- });
+ const ws = WaveSurfer.create({
+ ...options,
+ container: containerRef.current,
+ });
- setWavesurfer(ws);
+ setWavesurfer(ws);
- ws.on("interaction", () => {
- ws.play();
- });
+ ws.on('interaction', () => {
+ ws.play();
+ });
- return () => {
- ws.destroy();
- };
- }, [options, containerRef]);
+ return () => {
+ ws.destroy();
+ };
+ }, [options, containerRef]);
- return wavesurfer;
+ return wavesurfer;
};
const WaveSurferPlayer = (props) => {
- const { t } = useTranslation();
- const api = useApi();
- const containerRef = useRef();
- const [isPlaying, setIsPlaying] = useState(false);
- const [currentTime, setCurrentTime] = useState(0);
- const [scrollbar, setScrollbar] = useState(true);
- const [fillParent, setFillParent] = useState(true);
- const [autoCenter, setAutoCenter] = useState(true);
- const wavesurfer = useWavesurfer(containerRef, props);
-
- const onPlayClick = useCallback(() => {
- wavesurfer.isPlaying() ? wavesurfer.pause() : wavesurfer.play();
- }, [wavesurfer]);
-
- const onDownloadClick = useCallback(async () => {
- const url = wavesurfer.getMediaElement().src;
- const data = await fetch(url);
- const blob = await data.blob();
-
- window.isOffline
- ? saveAs(url, `pear-rec_${+new Date()}.webm`)
- : saveFile(blob);
- }, [wavesurfer]);
-
- async function saveFile(blob) {
- try {
- const formData = new FormData();
- formData.append("type", "ra");
- formData.append("userId", props.user.id);
- formData.append("file", blob);
- const res = (await api.saveFile(formData)) as any;
- if (res.code == 0) {
- if (window.isElectron) {
- window.electronAPI.sendRaCloseWin();
- window.electronAPI.sendVaOpenWin({ audioUrl: res.data.filePath });
- } else {
- Modal.confirm({
- title: "音频已保存,是否查看?",
- content: `${res.data.filePath}`,
- okText: t("modal.ok"),
- cancelText: t("modal.cancel"),
- onOk() {
- window.open(`/viewAudio.html?audioUrl=${res.data.filePath}`);
- },
- });
- }
- }
- } catch (err) {
- message.error("保存失败");
- }
- }
-
- const onRangeChange = useCallback(
- (minPxPerSec) => {
- wavesurfer.zoom(minPxPerSec);
- },
- [wavesurfer],
- );
-
- const onScrollbarChange = useCallback(
- (e) => {
- wavesurfer.setOptions({
- scrollbar: e.target.checked,
- });
- setScrollbar(e.target.checked);
- },
- [wavesurfer],
- );
-
- const onFillParentChange = useCallback(
- (e) => {
- wavesurfer.setOptions({
- fillParent: e.target.checked,
- });
- setFillParent(e.target.checked);
- },
- [wavesurfer],
- );
-
- const onAutoCenterChange = useCallback(
- (e) => {
- wavesurfer.setOptions({
- autoCenter: e.target.checked,
- });
- setAutoCenter(e.target.checked);
- },
- [wavesurfer],
- );
-
- useEffect(() => {
- if (!wavesurfer) return;
-
- setCurrentTime(0);
- setIsPlaying(false);
-
- const subscriptions = [
- wavesurfer.on("play", () => setIsPlaying(true)),
- wavesurfer.on("pause", () => setIsPlaying(false)),
- wavesurfer.on("timeupdate", (currentTime) => setCurrentTime(currentTime)),
- ];
-
- return () => {
- subscriptions.forEach((unsub) => unsub());
- };
- }, [wavesurfer]);
-
- return (
- <>
-
- Zoom:
-
-
-
-
-
- Scroll bar
-
-
- Fill parent
-
-
- Auto center
-
-
-
-
-
-
-
-
-
- Seconds played: {currentTime}
- >
- );
+ const { t } = useTranslation();
+ const api = useApi();
+ const containerRef = useRef();
+ const [isPlaying, setIsPlaying] = useState(false);
+ const [currentTime, setCurrentTime] = useState(0);
+ const [scrollbar, setScrollbar] = useState(true);
+ const [fillParent, setFillParent] = useState(true);
+ const [autoCenter, setAutoCenter] = useState(true);
+ const wavesurfer = useWavesurfer(containerRef, props);
+
+ const onPlayClick = useCallback(() => {
+ wavesurfer.isPlaying() ? wavesurfer.pause() : wavesurfer.play();
+ }, [wavesurfer]);
+
+ const onDownloadClick = useCallback(async () => {
+ const url = wavesurfer.getMediaElement().src;
+ const data = await fetch(url);
+ const blob = await data.blob();
+
+ window.isOffline ? saveAs(url, `pear-rec_${+new Date()}.webm`) : saveFile(blob);
+ }, [wavesurfer]);
+
+ async function saveFile(blob) {
+ try {
+ const formData = new FormData();
+ formData.append('type', 'ra');
+ formData.append('userId', props.user.id);
+ formData.append('file', blob);
+ const res = (await api.saveFile(formData)) as any;
+ if (res.code == 0) {
+ if (window.isElectron) {
+ window.electronAPI.sendRaCloseWin();
+ window.electronAPI.sendVaOpenWin({ audioUrl: res.data.filePath });
+ } else {
+ Modal.confirm({
+ title: '音频已保存,是否查看?',
+ content: `${res.data.filePath}`,
+ okText: t('modal.ok'),
+ cancelText: t('modal.cancel'),
+ onOk() {
+ window.open(`/viewAudio.html?audioUrl=${res.data.filePath}`);
+ },
+ });
+ }
+ }
+ } catch (err) {
+ message.error('保存失败');
+ }
+ }
+
+ const onRangeChange = useCallback(
+ (minPxPerSec) => {
+ wavesurfer.zoom(minPxPerSec);
+ },
+ [wavesurfer],
+ );
+
+ const onScrollbarChange = useCallback(
+ (e) => {
+ wavesurfer.setOptions({
+ scrollbar: e.target.checked,
+ });
+ setScrollbar(e.target.checked);
+ },
+ [wavesurfer],
+ );
+
+ const onFillParentChange = useCallback(
+ (e) => {
+ wavesurfer.setOptions({
+ fillParent: e.target.checked,
+ });
+ setFillParent(e.target.checked);
+ },
+ [wavesurfer],
+ );
+
+ const onAutoCenterChange = useCallback(
+ (e) => {
+ wavesurfer.setOptions({
+ autoCenter: e.target.checked,
+ });
+ setAutoCenter(e.target.checked);
+ },
+ [wavesurfer],
+ );
+
+ useEffect(() => {
+ if (!wavesurfer) return;
+
+ setCurrentTime(0);
+ setIsPlaying(false);
+
+ const subscriptions = [
+ wavesurfer.on('play', () => setIsPlaying(true)),
+ wavesurfer.on('pause', () => setIsPlaying(false)),
+ wavesurfer.on('timeupdate', (currentTime) => setCurrentTime(currentTime)),
+ ];
+
+ return () => {
+ subscriptions.forEach((unsub) => unsub());
+ };
+ }, [wavesurfer]);
+
+ return (
+ <>
+
+ Zoom:
+
+
+
+
+
+ Scroll bar
+
+
+ Fill parent
+
+
+ Auto center
+
+
+
+
+
+
+
+
+
+ Seconds played: {currentTime}
+ >
+ );
};
export default WaveSurferPlayer;
diff --git a/packages/web/src/components/records/RecordsContent.tsx b/packages/web/src/components/records/RecordsContent.tsx
index 597cc8f1..708142da 100644
--- a/packages/web/src/components/records/RecordsContent.tsx
+++ b/packages/web/src/components/records/RecordsContent.tsx
@@ -9,6 +9,7 @@ import {
import { useApi } from '../../api';
import { useRecordApi } from '../../api/record';
import { eventEmitter } from '../../util/bus';
+import Item from 'antd/es/list/Item';
const { Content } = Layout;
const recordApi = useRecordApi();
@@ -23,6 +24,7 @@ const RecordAudioCard = forwardRef(() => {
const [pageNumber, setPageNumber] = useState(1);
const [isMore, setIsMore] = useState(true);
const [filterVal, setFilterVal] = useState('');
+ const [isDelete, setIsDelete] = useState(false);
useEffect(() => {
setPageNumber(1);
@@ -41,14 +43,27 @@ const RecordAudioCard = forwardRef(() => {
filterData();
}, [filterVal]);
+ useEffect(() => {
+ isDelete && deleteListRecord();
+ }, [isDelete]);
+
async function handleDeleteAllRecord() {
- const res = (await recordApi.deleteAllRecord()) as any;
+ setIsDelete(true);
+ }
+
+ async function deleteListRecord() {
+ let ids = [];
+ data.map((item) => {
+ ids.push(item.id);
+ });
+ const res = (await recordApi.deleteListRecord(ids)) as any;
if (res.code == 0) {
const newData = [];
setData(newData);
setList(newData);
window.dispatchEvent(new Event('resize'));
}
+ setIsDelete(false);
}
function handleSearchRecord(filterVal) {