完成流水线控制器重构和相关功能改进
This commit is contained in:
@@ -3,4 +3,5 @@ export { ProjectController } from './project/index.ts';
|
|||||||
export { UserController } from './user/index.ts';
|
export { UserController } from './user/index.ts';
|
||||||
export { AuthController } from './auth/index.ts';
|
export { AuthController } from './auth/index.ts';
|
||||||
export { DeploymentController } from './deployment/index.ts';
|
export { DeploymentController } from './deployment/index.ts';
|
||||||
export { PipelineController } from './pipeline/index.ts'
|
export { PipelineController } from './pipeline/index.ts';
|
||||||
|
export { StepController } from './step/index.ts'
|
||||||
|
|||||||
@@ -1,22 +1,175 @@
|
|||||||
import type { Context } from 'koa';
|
import type { Context } from 'koa';
|
||||||
import { Controller, Get, Post } from '../../decorators/route.ts';
|
import { Controller, Get, Post, Put, Delete } from '../../decorators/route.ts';
|
||||||
import prisma from '../../libs/db.ts';
|
import prisma from '../../libs/db.ts';
|
||||||
|
import { log } from '../../libs/logger.ts';
|
||||||
|
import { BusinessError } from '../../middlewares/exception.ts';
|
||||||
|
import {
|
||||||
|
createPipelineSchema,
|
||||||
|
updatePipelineSchema,
|
||||||
|
pipelineIdSchema,
|
||||||
|
listPipelinesQuerySchema
|
||||||
|
} from './schema.ts';
|
||||||
|
|
||||||
@Controller('/pipelines')
|
@Controller('/pipelines')
|
||||||
export class PipelineController {
|
export class PipelineController {
|
||||||
@Get('/:id')
|
// GET /api/pipelines - 获取流水线列表
|
||||||
async get(ctx: Context) {
|
@Get('')
|
||||||
const id = ctx.params.id;
|
async list(ctx: Context) {
|
||||||
const pipeline = await prisma.pipeline.findUnique({
|
const query = listPipelinesQuerySchema.parse(ctx.query);
|
||||||
where: {
|
|
||||||
id: id,
|
const whereCondition: any = {
|
||||||
|
valid: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果提供了项目ID参数
|
||||||
|
if (query?.projectId) {
|
||||||
|
whereCondition.projectId = query.projectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipelines = await prisma.pipeline.findMany({
|
||||||
|
where: whereCondition,
|
||||||
|
include: {
|
||||||
|
steps: {
|
||||||
|
where: {
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
order: 'asc',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return pipelines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/pipelines/:id - 获取单个流水线
|
||||||
|
@Get('/:id')
|
||||||
|
async get(ctx: Context) {
|
||||||
|
const { id } = pipelineIdSchema.parse(ctx.params);
|
||||||
|
|
||||||
|
const pipeline = await prisma.pipeline.findFirst({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
steps: {
|
||||||
|
where: {
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
order: 'asc',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pipeline) {
|
||||||
|
throw new BusinessError('流水线不存在', 3001, 404);
|
||||||
|
}
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST /api/pipelines - 创建流水线
|
||||||
@Post('')
|
@Post('')
|
||||||
async create(ctx: Context) {
|
async create(ctx: Context) {
|
||||||
|
const validatedData = createPipelineSchema.parse(ctx.request.body);
|
||||||
|
|
||||||
|
const pipeline = await prisma.pipeline.create({
|
||||||
|
data: {
|
||||||
|
name: validatedData.name,
|
||||||
|
description: validatedData.description || '',
|
||||||
|
projectId: validatedData.projectId,
|
||||||
|
createdBy: 'system',
|
||||||
|
updatedBy: 'system',
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('pipeline', 'Created new pipeline: %s', pipeline.name);
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /api/pipelines/:id - 更新流水线
|
||||||
|
@Put('/:id')
|
||||||
|
async update(ctx: Context) {
|
||||||
|
const { id } = pipelineIdSchema.parse(ctx.params);
|
||||||
|
const validatedData = updatePipelineSchema.parse(ctx.request.body);
|
||||||
|
|
||||||
|
// 检查流水线是否存在
|
||||||
|
const existingPipeline = await prisma.pipeline.findFirst({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!existingPipeline) {
|
||||||
|
throw new BusinessError('流水线不存在', 3001, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只更新提供的字段
|
||||||
|
const updateData: any = {
|
||||||
|
updatedBy: 'system',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (validatedData.name !== undefined) {
|
||||||
|
updateData.name = validatedData.name;
|
||||||
|
}
|
||||||
|
if (validatedData.description !== undefined) {
|
||||||
|
updateData.description = validatedData.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipeline = await prisma.pipeline.update({
|
||||||
|
where: { id },
|
||||||
|
data: updateData,
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('pipeline', 'Updated pipeline: %s', pipeline.name);
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /api/pipelines/:id - 删除流水线(软删除)
|
||||||
|
@Delete('/:id')
|
||||||
|
async destroy(ctx: Context) {
|
||||||
|
const { id } = pipelineIdSchema.parse(ctx.params);
|
||||||
|
|
||||||
|
// 检查流水线是否存在
|
||||||
|
const existingPipeline = await prisma.pipeline.findFirst({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!existingPipeline) {
|
||||||
|
throw new BusinessError('流水线不存在', 3001, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 软删除:将 valid 设置为 0
|
||||||
|
await prisma.pipeline.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
valid: 0,
|
||||||
|
updatedBy: 'system',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 同时软删除关联的步骤
|
||||||
|
await prisma.step.updateMany({
|
||||||
|
where: { pipelineId: id },
|
||||||
|
data: {
|
||||||
|
valid: 0,
|
||||||
|
updatedBy: 'system',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('pipeline', 'Deleted pipeline: %s', existingPipeline.name);
|
||||||
|
|
||||||
|
// RESTful 删除成功返回 204 No Content
|
||||||
|
ctx.status = 204;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
apps/server/controllers/pipeline/schema.ts
Normal file
34
apps/server/controllers/pipeline/schema.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
// 定义验证架构
|
||||||
|
export const createPipelineSchema = z.object({
|
||||||
|
name: z.string({
|
||||||
|
message: '流水线名称必须是字符串',
|
||||||
|
}).min(1, { message: '流水线名称不能为空' }).max(100, { message: '流水线名称不能超过100个字符' }),
|
||||||
|
|
||||||
|
description: z.string({
|
||||||
|
message: '流水线描述必须是字符串',
|
||||||
|
}).max(500, { message: '流水线描述不能超过500个字符' }).optional(),
|
||||||
|
|
||||||
|
projectId: z.number({
|
||||||
|
message: '项目ID必须是数字',
|
||||||
|
}).int().positive({ message: '项目ID必须是正整数' }).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updatePipelineSchema = z.object({
|
||||||
|
name: z.string({
|
||||||
|
message: '流水线名称必须是字符串',
|
||||||
|
}).min(1, { message: '流水线名称不能为空' }).max(100, { message: '流水线名称不能超过100个字符' }).optional(),
|
||||||
|
|
||||||
|
description: z.string({
|
||||||
|
message: '流水线描述必须是字符串',
|
||||||
|
}).max(500, { message: '流水线描述不能超过500个字符' }).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const pipelineIdSchema = z.object({
|
||||||
|
id: z.coerce.number().int().positive({ message: '流水线 ID 必须是正整数' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const listPipelinesQuerySchema = z.object({
|
||||||
|
projectId: z.coerce.number().int().positive({ message: '项目ID必须是正整数' }).optional(),
|
||||||
|
}).optional();
|
||||||
13
apps/server/controllers/pipeline/types.ts
Normal file
13
apps/server/controllers/pipeline/types.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { z } from 'zod';
|
||||||
|
import type {
|
||||||
|
createPipelineSchema,
|
||||||
|
updatePipelineSchema,
|
||||||
|
pipelineIdSchema,
|
||||||
|
listPipelinesQuerySchema
|
||||||
|
} from './schema.js';
|
||||||
|
|
||||||
|
// TypeScript 类型
|
||||||
|
export type CreatePipelineInput = z.infer<typeof createPipelineSchema>;
|
||||||
|
export type UpdatePipelineInput = z.infer<typeof updatePipelineSchema>;
|
||||||
|
export type PipelineIdParams = z.infer<typeof pipelineIdSchema>;
|
||||||
|
export type ListPipelinesQuery = z.infer<typeof listPipelinesQuerySchema>;
|
||||||
234
apps/server/controllers/step/index.ts
Normal file
234
apps/server/controllers/step/index.ts
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
import type { Context } from 'koa';
|
||||||
|
import prisma from '../../libs/db.ts';
|
||||||
|
import { log } from '../../libs/logger.ts';
|
||||||
|
import { BusinessError } from '../../middlewares/exception.ts';
|
||||||
|
import { Controller, Get, Post, Put, Delete } from '../../decorators/route.ts';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
// 定义验证架构
|
||||||
|
const createStepSchema = z.object({
|
||||||
|
name: z.string({
|
||||||
|
message: '步骤名称必须是字符串',
|
||||||
|
}).min(1, { message: '步骤名称不能为空' }).max(100, { message: '步骤名称不能超过100个字符' }),
|
||||||
|
|
||||||
|
description: z.string({
|
||||||
|
message: '步骤描述必须是字符串',
|
||||||
|
}).max(500, { message: '步骤描述不能超过500个字符' }).optional(),
|
||||||
|
|
||||||
|
order: z.number({
|
||||||
|
message: '步骤顺序必须是数字',
|
||||||
|
}).int().min(0, { message: '步骤顺序必须是非负整数' }),
|
||||||
|
|
||||||
|
script: z.string({
|
||||||
|
message: '脚本命令必须是字符串',
|
||||||
|
}).min(1, { message: '脚本命令不能为空' }),
|
||||||
|
|
||||||
|
pipelineId: z.number({
|
||||||
|
message: '流水线ID必须是数字',
|
||||||
|
}).int().positive({ message: '流水线ID必须是正整数' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateStepSchema = z.object({
|
||||||
|
name: z.string({
|
||||||
|
message: '步骤名称必须是字符串',
|
||||||
|
}).min(1, { message: '步骤名称不能为空' }).max(100, { message: '步骤名称不能超过100个字符' }).optional(),
|
||||||
|
|
||||||
|
description: z.string({
|
||||||
|
message: '步骤描述必须是字符串',
|
||||||
|
}).max(500, { message: '步骤描述不能超过500个字符' }).optional(),
|
||||||
|
|
||||||
|
order: z.number({
|
||||||
|
message: '步骤顺序必须是数字',
|
||||||
|
}).int().min(0, { message: '步骤顺序必须是非负整数' }).optional(),
|
||||||
|
|
||||||
|
script: z.string({
|
||||||
|
message: '脚本命令必须是字符串',
|
||||||
|
}).min(1, { message: '脚本命令不能为空' }).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const stepIdSchema = z.object({
|
||||||
|
id: z.coerce.number().int().positive({ message: '步骤 ID 必须是正整数' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const listStepsQuerySchema = z.object({
|
||||||
|
pipelineId: z.coerce.number().int().positive({ message: '流水线ID必须是正整数' }).optional(),
|
||||||
|
page: z.coerce.number().int().min(1, { message: '页码必须大于0' }).optional().default(1),
|
||||||
|
limit: z.coerce.number().int().min(1, { message: '每页数量必须大于0' }).max(100, { message: '每页数量不能超过100' }).optional().default(10),
|
||||||
|
}).optional();
|
||||||
|
|
||||||
|
// TypeScript 类型
|
||||||
|
type CreateStepInput = z.infer<typeof createStepSchema>;
|
||||||
|
type UpdateStepInput = z.infer<typeof updateStepSchema>;
|
||||||
|
type StepIdParams = z.infer<typeof stepIdSchema>;
|
||||||
|
type ListStepsQuery = z.infer<typeof listStepsQuerySchema>;
|
||||||
|
|
||||||
|
@Controller('/steps')
|
||||||
|
export class StepController {
|
||||||
|
// GET /api/steps - 获取步骤列表
|
||||||
|
@Get('')
|
||||||
|
async list(ctx: Context) {
|
||||||
|
const query = listStepsQuerySchema.parse(ctx.query);
|
||||||
|
|
||||||
|
const whereCondition: any = {
|
||||||
|
valid: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果提供了流水线ID参数
|
||||||
|
if (query?.pipelineId) {
|
||||||
|
whereCondition.pipelineId = query.pipelineId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [total, steps] = await Promise.all([
|
||||||
|
prisma.step.count({ where: whereCondition }),
|
||||||
|
prisma.step.findMany({
|
||||||
|
where: whereCondition,
|
||||||
|
skip: query ? (query.page - 1) * query.limit : 0,
|
||||||
|
take: query?.limit,
|
||||||
|
orderBy: {
|
||||||
|
order: 'asc',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: steps,
|
||||||
|
pagination: {
|
||||||
|
page: query?.page || 1,
|
||||||
|
limit: query?.limit || 10,
|
||||||
|
total,
|
||||||
|
totalPages: Math.ceil(total / (query?.limit || 10)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/steps/:id - 获取单个步骤
|
||||||
|
@Get(':id')
|
||||||
|
async show(ctx: Context) {
|
||||||
|
const { id } = stepIdSchema.parse(ctx.params);
|
||||||
|
|
||||||
|
const step = await prisma.step.findFirst({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!step) {
|
||||||
|
throw new BusinessError('步骤不存在', 2001, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /api/steps - 创建步骤
|
||||||
|
@Post('')
|
||||||
|
async create(ctx: Context) {
|
||||||
|
const validatedData = createStepSchema.parse(ctx.request.body);
|
||||||
|
|
||||||
|
// 检查关联的流水线是否存在
|
||||||
|
const pipeline = await prisma.pipeline.findFirst({
|
||||||
|
where: {
|
||||||
|
id: validatedData.pipelineId,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pipeline) {
|
||||||
|
throw new BusinessError('关联的流水线不存在', 2002, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const step = await prisma.step.create({
|
||||||
|
data: {
|
||||||
|
name: validatedData.name,
|
||||||
|
description: validatedData.description || '',
|
||||||
|
order: validatedData.order,
|
||||||
|
script: validatedData.script,
|
||||||
|
pipelineId: validatedData.pipelineId,
|
||||||
|
createdBy: 'system',
|
||||||
|
updatedBy: 'system',
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('step', 'Created new step: %s', step.name);
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /api/steps/:id - 更新步骤
|
||||||
|
@Put(':id')
|
||||||
|
async update(ctx: Context) {
|
||||||
|
const { id } = stepIdSchema.parse(ctx.params);
|
||||||
|
const validatedData = updateStepSchema.parse(ctx.request.body);
|
||||||
|
|
||||||
|
// 检查步骤是否存在
|
||||||
|
const existingStep = await prisma.step.findFirst({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!existingStep) {
|
||||||
|
throw new BusinessError('步骤不存在', 2001, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只更新提供的字段
|
||||||
|
const updateData: any = {
|
||||||
|
updatedBy: 'system',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (validatedData.name !== undefined) {
|
||||||
|
updateData.name = validatedData.name;
|
||||||
|
}
|
||||||
|
if (validatedData.description !== undefined) {
|
||||||
|
updateData.description = validatedData.description;
|
||||||
|
}
|
||||||
|
if (validatedData.order !== undefined) {
|
||||||
|
updateData.order = validatedData.order;
|
||||||
|
}
|
||||||
|
if (validatedData.script !== undefined) {
|
||||||
|
updateData.script = validatedData.script;
|
||||||
|
}
|
||||||
|
|
||||||
|
const step = await prisma.step.update({
|
||||||
|
where: { id },
|
||||||
|
data: updateData,
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('step', 'Updated step: %s', step.name);
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /api/steps/:id - 删除步骤(软删除)
|
||||||
|
@Delete(':id')
|
||||||
|
async destroy(ctx: Context) {
|
||||||
|
const { id } = stepIdSchema.parse(ctx.params);
|
||||||
|
|
||||||
|
// 检查步骤是否存在
|
||||||
|
const existingStep = await prisma.step.findFirst({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
valid: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!existingStep) {
|
||||||
|
throw new BusinessError('步骤不存在', 2001, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 软删除:将 valid 设置为 0
|
||||||
|
await prisma.step.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
valid: 0,
|
||||||
|
updatedBy: 'system',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('step', 'Deleted step: %s', existingStep.name);
|
||||||
|
|
||||||
|
// RESTful 删除成功返回 204 No Content
|
||||||
|
ctx.status = 204;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,8 @@ import {
|
|||||||
UserController,
|
UserController,
|
||||||
AuthController,
|
AuthController,
|
||||||
DeploymentController,
|
DeploymentController,
|
||||||
PipelineController
|
PipelineController,
|
||||||
|
StepController
|
||||||
} from '../controllers/index.ts';
|
} from '../controllers/index.ts';
|
||||||
import { log } from '../libs/logger.ts';
|
import { log } from '../libs/logger.ts';
|
||||||
|
|
||||||
@@ -41,7 +42,8 @@ export class Router implements Middleware {
|
|||||||
UserController,
|
UserController,
|
||||||
AuthController,
|
AuthController,
|
||||||
DeploymentController,
|
DeploymentController,
|
||||||
PipelineController
|
PipelineController,
|
||||||
|
StepController
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 输出注册的路由信息
|
// 输出注册的路由信息
|
||||||
|
|||||||
Binary file not shown.
@@ -60,9 +60,8 @@ model Pipeline {
|
|||||||
model Step {
|
model Step {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
name String
|
name String
|
||||||
description String?
|
|
||||||
order Int
|
order Int
|
||||||
status String?
|
script String // 执行的脚本命令
|
||||||
valid Int @default(1)
|
valid Int @default(1)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|||||||
@@ -11,21 +11,21 @@
|
|||||||
"preview": "rsbuild preview"
|
"preview": "rsbuild preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@arco-design/web-react": "^2.66.4",
|
"@arco-design/web-react": "^2.66.8",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"react": "^18.2.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router": "^7.8.0",
|
"react-router": "^7.8.0",
|
||||||
"zustand": "^5.0.8"
|
"zustand": "^5.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@arco-plugins/unplugin-react": "2.0.0-beta.5",
|
"@arco-plugins/unplugin-react": "2.0.0-beta.5",
|
||||||
"@rsbuild/core": "^1.4.13",
|
"@rsbuild/core": "^1.6.7",
|
||||||
"@rsbuild/plugin-less": "^1.4.0",
|
"@rsbuild/plugin-less": "^1.5.0",
|
||||||
"@rsbuild/plugin-react": "^1.3.4",
|
"@rsbuild/plugin-react": "^1.4.2",
|
||||||
"@rsbuild/plugin-svgr": "^1.2.2",
|
"@rsbuild/plugin-svgr": "^1.2.2",
|
||||||
"@tailwindcss/postcss": "^4.1.11",
|
"@tailwindcss/postcss": "^4.1.11",
|
||||||
"@types/react": "^18.3.24",
|
"@types/react": "^18.3.24",
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ export default {
|
|||||||
plugins: {
|
plugins: {
|
||||||
'@tailwindcss/postcss': {},
|
'@tailwindcss/postcss': {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ArcoDesignPlugin } from '@arco-plugins/unplugin-react';
|
import { ArcoDesignPlugin } from '@arco-plugins/unplugin-react';
|
||||||
import { defineConfig } from '@rsbuild/core';
|
import { defineConfig } from '@rsbuild/core';
|
||||||
import { pluginReact } from '@rsbuild/plugin-react';
|
|
||||||
import { pluginLess } from '@rsbuild/plugin-less';
|
import { pluginLess } from '@rsbuild/plugin-less';
|
||||||
|
import { pluginReact } from '@rsbuild/plugin-react';
|
||||||
import { pluginSvgr } from '@rsbuild/plugin-svgr';
|
import { pluginSvgr } from '@rsbuild/plugin-svgr';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
import React, { useEffect } from 'react';
|
import type React from 'react';
|
||||||
|
import { useEffect, useCallback } from 'react';
|
||||||
|
|
||||||
export function useAsyncEffect(
|
export function useAsyncEffect(
|
||||||
effect: () => Promise<void>,
|
effect: () => Promise<void | (() => void)>,
|
||||||
deps: React.DependencyList,
|
deps: React.DependencyList,
|
||||||
) {
|
) {
|
||||||
|
const callback = useCallback(effect, [...deps]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
effect();
|
const cleanupPromise = callback();
|
||||||
}, [...deps]);
|
return () => {
|
||||||
|
if (cleanupPromise instanceof Promise) {
|
||||||
|
cleanupPromise.then(cleanup => cleanup && cleanup());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [callback]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import App from '@pages/App';
|
import App from '@pages/App';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
import { BrowserRouter } from 'react-router';
|
import { BrowserRouter } from 'react-router';
|
||||||
import { useGlobalStore } from './stores/global';
|
import { useGlobalStore } from './stores/global';
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Route, Routes, Navigate } from 'react-router';
|
import Env from '@pages/env';
|
||||||
import Home from '@pages/home';
|
import Home from '@pages/home';
|
||||||
import Login from '@pages/login';
|
import Login from '@pages/login';
|
||||||
import ProjectList from '@pages/project/list';
|
|
||||||
import ProjectDetail from '@pages/project/detail';
|
import ProjectDetail from '@pages/project/detail';
|
||||||
import Env from '@pages/env';
|
import ProjectList from '@pages/project/list';
|
||||||
|
import { Navigate, Route, Routes } from 'react-router';
|
||||||
|
|
||||||
import '@styles/index.css';
|
import '@styles/index.css';
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|||||||
9
apps/web/src/pages/env/index.tsx
vendored
9
apps/web/src/pages/env/index.tsx
vendored
@@ -1,12 +1,5 @@
|
|||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
function Env() {
|
function Env() {
|
||||||
const [env, setEnv] = useState([]);
|
return <div>env page</div>;
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
env page
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Env;
|
export default Env;
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import {
|
|||||||
IconMenuUnfold,
|
IconMenuUnfold,
|
||||||
IconRobot,
|
IconRobot,
|
||||||
} from '@arco-design/web-react/icon';
|
} from '@arco-design/web-react/icon';
|
||||||
import { useState } from 'react';
|
|
||||||
import Logo from '@assets/images/logo.svg?react';
|
import Logo from '@assets/images/logo.svg?react';
|
||||||
|
import { loginService } from '@pages/login/service';
|
||||||
|
import { useState } from 'react';
|
||||||
import { Link, Outlet } from 'react-router';
|
import { Link, Outlet } from 'react-router';
|
||||||
import { useGlobalStore } from '../../stores/global';
|
import { useGlobalStore } from '../../stores/global';
|
||||||
import { loginService } from '@pages/login/service';
|
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Button } from '@arco-design/web-react';
|
import { Button } from '@arco-design/web-react';
|
||||||
import Gitea from '@assets/images/gitea.svg?react';
|
import Gitea from '@assets/images/gitea.svg?react';
|
||||||
import { loginService } from './service';
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useNavigate, useSearchParams } from 'react-router';
|
import { useNavigate, useSearchParams } from 'react-router';
|
||||||
|
import { loginService } from './service';
|
||||||
|
|
||||||
function Login() {
|
function Login() {
|
||||||
const [ searchParams ] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const authCode = searchParams.get('code');
|
const authCode = searchParams.get('code');
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { net } from '@shared';
|
|
||||||
import type { AuthURLResponse, AuthLoginResponse } from './types';
|
|
||||||
import type { NavigateFunction } from 'react-router';
|
|
||||||
import { Message, Notification } from '@arco-design/web-react';
|
import { Message, Notification } from '@arco-design/web-react';
|
||||||
|
import { net } from '@shared';
|
||||||
|
import type { NavigateFunction } from 'react-router';
|
||||||
import { useGlobalStore } from '../../stores/global';
|
import { useGlobalStore } from '../../stores/global';
|
||||||
|
import type { AuthLoginResponse, AuthURLResponse } from './types';
|
||||||
|
|
||||||
class LoginService {
|
class LoginService {
|
||||||
async getAuthUrl() {
|
async getAuthUrl() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { List, Tag, Space } from '@arco-design/web-react';
|
import { List, Space, Tag } from '@arco-design/web-react';
|
||||||
|
|
||||||
// 部署记录类型定义
|
// 部署记录类型定义
|
||||||
interface DeployRecord {
|
interface DeployRecord {
|
||||||
@@ -76,9 +76,7 @@ function DeployRecordItem({
|
|||||||
<Space size="medium" wrap>
|
<Space size="medium" wrap>
|
||||||
<span className="text-sm text-gray-500">
|
<span className="text-sm text-gray-500">
|
||||||
分支:{' '}
|
分支:{' '}
|
||||||
<span className="font-medium text-gray-700">
|
<span className="font-medium text-gray-700">{item.branch}</span>
|
||||||
{item.branch}
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
<span className="text-sm text-gray-500">
|
<span className="text-sm text-gray-500">
|
||||||
环境: {getEnvTag(item.env)}
|
环境: {getEnvTag(item.env)}
|
||||||
|
|||||||
@@ -1,23 +1,35 @@
|
|||||||
import { Typography, Tag, Switch, Button } from '@arco-design/web-react';
|
import { Button, Switch, Tag, Typography } from '@arco-design/web-react';
|
||||||
import { IconDragArrow, IconEdit, IconDelete } from '@arco-design/web-react/icon';
|
import {
|
||||||
|
IconDelete,
|
||||||
|
IconDragArrow,
|
||||||
|
IconEdit,
|
||||||
|
} from '@arco-design/web-react/icon';
|
||||||
import { useSortable } from '@dnd-kit/sortable';
|
import { useSortable } from '@dnd-kit/sortable';
|
||||||
import { CSS } from '@dnd-kit/utilities';
|
import { CSS } from '@dnd-kit/utilities';
|
||||||
|
|
||||||
// 流水线步骤类型定义
|
// 流水线步骤类型定义(更新为与后端一致)
|
||||||
interface PipelineStep {
|
interface PipelineStep {
|
||||||
id: string;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
script: string;
|
description?: string;
|
||||||
|
order: number;
|
||||||
|
script: string; // 执行的脚本命令
|
||||||
|
valid: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdBy: string;
|
||||||
|
updatedBy: string;
|
||||||
|
pipelineId: number;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PipelineStepItemProps {
|
interface PipelineStepItemProps {
|
||||||
step: PipelineStep;
|
step: PipelineStep;
|
||||||
index: number;
|
index: number;
|
||||||
pipelineId: string;
|
pipelineId: number;
|
||||||
onToggle: (pipelineId: string, stepId: string, enabled: boolean) => void;
|
onToggle: (pipelineId: number, stepId: number, enabled: boolean) => void;
|
||||||
onEdit: (pipelineId: string, step: PipelineStep) => void;
|
onEdit: (pipelineId: number, step: PipelineStep) => void;
|
||||||
onDelete: (pipelineId: string, stepId: string) => void;
|
onDelete: (pipelineId: number, stepId: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PipelineStepItem({
|
function PipelineStepItem({
|
||||||
@@ -79,6 +91,9 @@ function PipelineStepItem({
|
|||||||
</Tag>
|
</Tag>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{step.description && (
|
||||||
|
<div className="text-gray-600 text-sm mb-2">{step.description}</div>
|
||||||
|
)}
|
||||||
<div className="bg-gray-900 text-green-400 p-3 rounded font-mono text-sm">
|
<div className="bg-gray-900 text-green-400 p-3 rounded font-mono text-sm">
|
||||||
<pre className="whitespace-pre-wrap break-words">{step.script}</pre>
|
<pre className="whitespace-pre-wrap break-words">{step.script}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,50 +1,49 @@
|
|||||||
import {
|
import {
|
||||||
Typography,
|
|
||||||
Tabs,
|
|
||||||
Button,
|
Button,
|
||||||
List,
|
|
||||||
Tag,
|
|
||||||
Space,
|
|
||||||
Input,
|
|
||||||
Card,
|
Card,
|
||||||
Switch,
|
|
||||||
Modal,
|
|
||||||
Form,
|
|
||||||
Message,
|
|
||||||
Collapse,
|
|
||||||
Dropdown,
|
Dropdown,
|
||||||
|
Empty,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
List,
|
||||||
Menu,
|
Menu,
|
||||||
|
Message,
|
||||||
|
Modal,
|
||||||
|
Switch,
|
||||||
|
Tabs,
|
||||||
|
Tag,
|
||||||
|
Typography,
|
||||||
} from '@arco-design/web-react';
|
} from '@arco-design/web-react';
|
||||||
import type { Project } from '../types';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { useParams } from 'react-router';
|
|
||||||
import { useAsyncEffect } from '../../../hooks/useAsyncEffect';
|
|
||||||
import { detailService } from './service';
|
|
||||||
import {
|
import {
|
||||||
|
IconCopy,
|
||||||
|
IconDelete,
|
||||||
|
IconEdit,
|
||||||
|
IconMore,
|
||||||
IconPlayArrow,
|
IconPlayArrow,
|
||||||
IconPlus,
|
IconPlus,
|
||||||
IconEdit,
|
|
||||||
IconDelete,
|
|
||||||
IconMore,
|
|
||||||
IconCopy,
|
|
||||||
} from '@arco-design/web-react/icon';
|
} from '@arco-design/web-react/icon';
|
||||||
import DeployRecordItem from './components/DeployRecordItem';
|
import type { DragEndEvent } from '@dnd-kit/core';
|
||||||
import PipelineStepItem from './components/PipelineStepItem';
|
|
||||||
import {
|
import {
|
||||||
DndContext,
|
|
||||||
closestCenter,
|
closestCenter,
|
||||||
|
DndContext,
|
||||||
KeyboardSensor,
|
KeyboardSensor,
|
||||||
PointerSensor,
|
PointerSensor,
|
||||||
useSensor,
|
useSensor,
|
||||||
useSensors,
|
useSensors,
|
||||||
} from '@dnd-kit/core';
|
} from '@dnd-kit/core';
|
||||||
import type { DragEndEvent } from '@dnd-kit/core';
|
|
||||||
import {
|
import {
|
||||||
|
arrayMove,
|
||||||
SortableContext,
|
SortableContext,
|
||||||
sortableKeyboardCoordinates,
|
sortableKeyboardCoordinates,
|
||||||
verticalListSortingStrategy,
|
verticalListSortingStrategy,
|
||||||
arrayMove,
|
|
||||||
} from '@dnd-kit/sortable';
|
} from '@dnd-kit/sortable';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useParams } from 'react-router';
|
||||||
|
import { useAsyncEffect } from '../../../hooks/useAsyncEffect';
|
||||||
|
import type { Project } from '../types';
|
||||||
|
import DeployRecordItem from './components/DeployRecordItem';
|
||||||
|
import PipelineStepItem from './components/PipelineStepItem';
|
||||||
|
import { detailService } from './service';
|
||||||
|
|
||||||
// 部署记录类型定义
|
// 部署记录类型定义
|
||||||
interface DeployRecord {
|
interface DeployRecord {
|
||||||
@@ -56,23 +55,35 @@ interface DeployRecord {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 流水线步骤类型定义
|
// 流水线步骤类型定义(更新为与后端一致)
|
||||||
interface PipelineStep {
|
interface PipelineStep {
|
||||||
id: string;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
script: string;
|
description?: string;
|
||||||
|
order: number;
|
||||||
|
script: string; // 执行的脚本命令
|
||||||
|
valid: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdBy: string;
|
||||||
|
updatedBy: string;
|
||||||
|
pipelineId: number;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 流水线类型定义
|
// 流水线类型定义
|
||||||
interface Pipeline {
|
interface Pipeline {
|
||||||
id: string;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
enabled: boolean;
|
valid: number;
|
||||||
steps: PipelineStep[];
|
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
createdBy: string;
|
||||||
|
updatedBy: string;
|
||||||
|
projectId?: number;
|
||||||
|
steps?: PipelineStep[];
|
||||||
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProjectDetailPage() {
|
function ProjectDetailPage() {
|
||||||
@@ -83,65 +94,21 @@ function ProjectDetailPage() {
|
|||||||
useSensor(PointerSensor),
|
useSensor(PointerSensor),
|
||||||
useSensor(KeyboardSensor, {
|
useSensor(KeyboardSensor, {
|
||||||
coordinateGetter: sortableKeyboardCoordinates,
|
coordinateGetter: sortableKeyboardCoordinates,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
const [selectedRecordId, setSelectedRecordId] = useState<number>(1);
|
const [selectedRecordId, setSelectedRecordId] = useState<number>(1);
|
||||||
const [pipelines, setPipelines] = useState<Pipeline[]>([
|
const [pipelines, setPipelines] = useState<Pipeline[]>([]);
|
||||||
{
|
|
||||||
id: 'pipeline1',
|
|
||||||
name: '前端部署流水线',
|
|
||||||
description: '用于前端项目的构建和部署',
|
|
||||||
enabled: true,
|
|
||||||
createdAt: '2024-09-07 10:00:00',
|
|
||||||
updatedAt: '2024-09-07 14:30:00',
|
|
||||||
steps: [
|
|
||||||
{ id: 'step1', name: '安装依赖', script: 'npm install', enabled: true },
|
|
||||||
{ id: 'step2', name: '运行测试', script: 'npm test', enabled: true },
|
|
||||||
{
|
|
||||||
id: 'step3',
|
|
||||||
name: '构建项目',
|
|
||||||
script: 'npm run build',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'pipeline2',
|
|
||||||
name: 'Docker部署流水线',
|
|
||||||
description: '用于容器化部署的流水线',
|
|
||||||
enabled: true,
|
|
||||||
createdAt: '2024-09-06 16:20:00',
|
|
||||||
updatedAt: '2024-09-07 09:15:00',
|
|
||||||
steps: [
|
|
||||||
{ id: 'step1', name: '安装依赖', script: 'npm install', enabled: true },
|
|
||||||
{
|
|
||||||
id: 'step2',
|
|
||||||
name: '构建镜像',
|
|
||||||
script: 'docker build -t $PROJECT_NAME:$BUILD_NUMBER .',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'step3',
|
|
||||||
name: 'K8s部署',
|
|
||||||
script: 'kubectl apply -f deployment.yaml',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const [editModalVisible, setEditModalVisible] = useState(false);
|
const [editModalVisible, setEditModalVisible] = useState(false);
|
||||||
const [selectedPipelineId, setSelectedPipelineId] = useState<string>(
|
const [selectedPipelineId, setSelectedPipelineId] = useState<number>(0);
|
||||||
pipelines.length > 0 ? pipelines[0].id : '',
|
|
||||||
);
|
|
||||||
const [editingStep, setEditingStep] = useState<PipelineStep | null>(null);
|
const [editingStep, setEditingStep] = useState<PipelineStep | null>(null);
|
||||||
const [editingPipelineId, setEditingPipelineId] = useState<string | null>(
|
const [editingPipelineId, setEditingPipelineId] = useState<number | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const [pipelineModalVisible, setPipelineModalVisible] = useState(false);
|
const [pipelineModalVisible, setPipelineModalVisible] = useState(false);
|
||||||
const [editingPipeline, setEditingPipeline] = useState<Pipeline | null>(null);
|
const [editingPipeline, setEditingPipeline] = useState<Pipeline | null>(null);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [pipelineForm] = Form.useForm();
|
const [pipelineForm] = Form.useForm();
|
||||||
const [deployRecords, setDeployRecords] = useState<DeployRecord[]>([
|
const [deployRecords, _setDeployRecords] = useState<DeployRecord[]>([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
branch: 'main',
|
branch: 'main',
|
||||||
@@ -158,14 +125,7 @@ function ProjectDetailPage() {
|
|||||||
status: 'running',
|
status: 'running',
|
||||||
createdAt: '2024-09-07 13:45:12',
|
createdAt: '2024-09-07 13:45:12',
|
||||||
},
|
},
|
||||||
{
|
// 移除了 ID 为 3 的部署记录,避免可能的冲突
|
||||||
id: 3,
|
|
||||||
branch: 'feature/user-auth',
|
|
||||||
env: 'development',
|
|
||||||
commit: '3a7d9f2b1',
|
|
||||||
status: 'failed',
|
|
||||||
createdAt: '2024-09-07 12:20:45',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
branch: 'main',
|
branch: 'main',
|
||||||
@@ -181,6 +141,29 @@ function ProjectDetailPage() {
|
|||||||
if (id) {
|
if (id) {
|
||||||
const project = await detailService.getProject(id);
|
const project = await detailService.getProject(id);
|
||||||
setDetail(project);
|
setDetail(project);
|
||||||
|
|
||||||
|
// 获取项目的所有流水线
|
||||||
|
try {
|
||||||
|
const pipelineData = await detailService.getPipelines(Number(id));
|
||||||
|
// 转换数据结构,添加enabled字段
|
||||||
|
const transformedPipelines = pipelineData.map((pipeline) => ({
|
||||||
|
...pipeline,
|
||||||
|
description: pipeline.description || '', // 确保description不为undefined
|
||||||
|
enabled: pipeline.valid === 1, // 根据valid字段设置enabled
|
||||||
|
steps:
|
||||||
|
pipeline.steps?.map((step) => ({
|
||||||
|
...step,
|
||||||
|
enabled: step.valid === 1, // 根据valid字段设置enabled
|
||||||
|
})) || [],
|
||||||
|
}));
|
||||||
|
setPipelines(transformedPipelines);
|
||||||
|
if (transformedPipelines.length > 0) {
|
||||||
|
setSelectedPipelineId(transformedPipelines[0].id);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取流水线数据失败:', error);
|
||||||
|
Message.error('获取流水线数据失败');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -211,16 +194,7 @@ function ProjectDetailPage() {
|
|||||||
'[2024-09-07 13:47:05] 构建镜像: docker build -t app:develop .',
|
'[2024-09-07 13:47:05] 构建镜像: docker build -t app:develop .',
|
||||||
'[2024-09-07 13:48:20] 🔄 正在推送镜像...',
|
'[2024-09-07 13:48:20] 🔄 正在推送镜像...',
|
||||||
],
|
],
|
||||||
3: [
|
// 移除了 ID 为 3 的模拟数据,避免可能的冲突
|
||||||
'[2024-09-07 12:20:45] 开始构建...',
|
|
||||||
'[2024-09-07 12:20:46] 拉取代码: git clone https://github.com/user/repo.git',
|
|
||||||
'[2024-09-07 12:20:48] 切换分支: git checkout feature/user-auth',
|
|
||||||
'[2024-09-07 12:20:49] 安装依赖: npm install',
|
|
||||||
'[2024-09-07 12:21:35] 运行测试: npm test',
|
|
||||||
'[2024-09-07 12:21:50] ❌ 测试失败',
|
|
||||||
'[2024-09-07 12:21:51] Error: Authentication test failed',
|
|
||||||
'[2024-09-07 12:21:51] ❌ 构建失败',
|
|
||||||
],
|
|
||||||
4: [
|
4: [
|
||||||
'[2024-09-07 10:15:30] 开始构建...',
|
'[2024-09-07 10:15:30] 开始构建...',
|
||||||
'[2024-09-07 10:15:31] 拉取代码: git clone https://github.com/user/repo.git',
|
'[2024-09-07 10:15:31] 拉取代码: git clone https://github.com/user/repo.git',
|
||||||
@@ -256,46 +230,109 @@ function ProjectDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 删除流水线
|
// 删除流水线
|
||||||
const handleDeletePipeline = (pipelineId: string) => {
|
const handleDeletePipeline = async (pipelineId: number) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '确认删除',
|
title: '确认删除',
|
||||||
content:
|
content:
|
||||||
'确定要删除这个流水线吗?此操作不可撤销,将同时删除该流水线下的所有步骤。',
|
'确定要删除这个流水线吗?此操作不可撤销,将同时删除该流水线下的所有步骤。',
|
||||||
onOk: () => {
|
onOk: async () => {
|
||||||
setPipelines((prev) => {
|
try {
|
||||||
const newPipelines = prev.filter((pipeline) => pipeline.id !== pipelineId);
|
// 从数据库删除流水线
|
||||||
// 如果删除的是当前选中的流水线,选中第一个或清空选择
|
await detailService.deletePipeline(pipelineId);
|
||||||
if (selectedPipelineId === pipelineId) {
|
|
||||||
setSelectedPipelineId(newPipelines.length > 0 ? newPipelines[0].id : '');
|
// 更新本地状态
|
||||||
}
|
setPipelines((prev) => {
|
||||||
return newPipelines;
|
const newPipelines = prev.filter(
|
||||||
});
|
(pipeline) => pipeline.id !== pipelineId,
|
||||||
Message.success('流水线删除成功');
|
);
|
||||||
|
// 如果删除的是当前选中的流水线,选中第一个或清空选择
|
||||||
|
if (selectedPipelineId === pipelineId) {
|
||||||
|
setSelectedPipelineId(
|
||||||
|
newPipelines.length > 0 ? newPipelines[0].id : 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newPipelines;
|
||||||
|
});
|
||||||
|
Message.success('流水线删除成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除流水线失败:', error);
|
||||||
|
Message.error('删除流水线失败');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 复制流水线
|
// 复制流水线
|
||||||
const handleCopyPipeline = (pipeline: Pipeline) => {
|
const handleCopyPipeline = async (pipeline: Pipeline) => {
|
||||||
const newPipeline: Pipeline = {
|
Modal.confirm({
|
||||||
...pipeline,
|
title: '确认复制',
|
||||||
id: `pipeline_${Date.now()}`,
|
content: '确定要复制这个流水线吗?',
|
||||||
name: `${pipeline.name} - 副本`,
|
onOk: async () => {
|
||||||
createdAt: new Date().toLocaleString(),
|
try {
|
||||||
updatedAt: new Date().toLocaleString(),
|
// 创建新的流水线
|
||||||
steps: pipeline.steps.map((step) => ({
|
const newPipelineData = await detailService.createPipeline({
|
||||||
...step,
|
name: `${pipeline.name} - 副本`,
|
||||||
id: `step_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
description: pipeline.description || '',
|
||||||
})),
|
projectId: pipeline.projectId,
|
||||||
};
|
});
|
||||||
setPipelines((prev) => [...prev, newPipeline]);
|
|
||||||
// 自动选中新复制的流水线
|
// 复制步骤
|
||||||
setSelectedPipelineId(newPipeline.id);
|
if (pipeline.steps && pipeline.steps.length > 0) {
|
||||||
Message.success('流水线复制成功');
|
for (const step of pipeline.steps) {
|
||||||
|
await detailService.createStep({
|
||||||
|
name: step.name,
|
||||||
|
description: step.description,
|
||||||
|
order: step.order,
|
||||||
|
script: step.script,
|
||||||
|
pipelineId: newPipelineData.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新获取流水线数据以确保步骤已创建
|
||||||
|
if (pipeline.projectId) {
|
||||||
|
const pipelineData = await detailService.getPipelines(
|
||||||
|
pipeline.projectId,
|
||||||
|
);
|
||||||
|
// 转换数据结构,添加enabled字段
|
||||||
|
const transformedPipelines = pipelineData.map((p) => ({
|
||||||
|
...p,
|
||||||
|
description: p.description || '', // 确保description不为undefined
|
||||||
|
enabled: p.valid === 1, // 根据valid字段设置enabled
|
||||||
|
steps:
|
||||||
|
p.steps?.map((step) => ({
|
||||||
|
...step,
|
||||||
|
enabled: step.valid === 1, // 根据valid字段设置enabled
|
||||||
|
})) || [],
|
||||||
|
}));
|
||||||
|
setPipelines(transformedPipelines);
|
||||||
|
setSelectedPipelineId(newPipelineData.id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有步骤,直接更新状态
|
||||||
|
setPipelines((prev) => [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
...newPipelineData,
|
||||||
|
description: newPipelineData.description || '',
|
||||||
|
enabled: newPipelineData.valid === 1,
|
||||||
|
steps: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
setSelectedPipelineId(newPipelineData.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message.success('流水线复制成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('复制流水线失败:', error);
|
||||||
|
Message.error('复制流水线失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换流水线启用状态
|
// 切换流水线启用状态
|
||||||
const handleTogglePipeline = (pipelineId: string, enabled: boolean) => {
|
const handleTogglePipeline = async (pipelineId: number, enabled: boolean) => {
|
||||||
|
// 在数据库中更新流水线状态(这里简化处理,实际可能需要添加enabled字段到数据库)
|
||||||
setPipelines((prev) =>
|
setPipelines((prev) =>
|
||||||
prev.map((pipeline) =>
|
prev.map((pipeline) =>
|
||||||
pipeline.id === pipelineId ? { ...pipeline, enabled } : pipeline,
|
pipeline.id === pipelineId ? { ...pipeline, enabled } : pipeline,
|
||||||
@@ -308,42 +345,58 @@ function ProjectDetailPage() {
|
|||||||
try {
|
try {
|
||||||
const values = await pipelineForm.validate();
|
const values = await pipelineForm.validate();
|
||||||
if (editingPipeline) {
|
if (editingPipeline) {
|
||||||
setPipelines((prev) => [
|
// 更新现有流水线
|
||||||
...prev.map((pipeline) =>
|
const updatedPipeline = await detailService.updatePipeline(
|
||||||
|
editingPipeline.id,
|
||||||
|
{
|
||||||
|
name: values.name,
|
||||||
|
description: values.description,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 更新本地状态
|
||||||
|
setPipelines((prev) =>
|
||||||
|
prev.map((pipeline) =>
|
||||||
pipeline.id === editingPipeline.id
|
pipeline.id === editingPipeline.id
|
||||||
? {
|
? {
|
||||||
...pipeline,
|
...updatedPipeline,
|
||||||
name: values.name,
|
description: updatedPipeline.description || '',
|
||||||
description: values.description,
|
enabled: updatedPipeline.valid === 1,
|
||||||
updatedAt: new Date().toLocaleString(),
|
steps: pipeline.steps || [], // 保持步骤不变
|
||||||
}
|
}
|
||||||
: pipeline,
|
: pipeline,
|
||||||
),
|
),
|
||||||
]);
|
);
|
||||||
Message.success('流水线更新成功');
|
Message.success('流水线更新成功');
|
||||||
} else {
|
} else {
|
||||||
const newPipeline: Pipeline = {
|
// 创建新流水线
|
||||||
id: `pipeline_${Date.now()}`,
|
const newPipeline = await detailService.createPipeline({
|
||||||
name: values.name,
|
name: values.name,
|
||||||
description: values.description,
|
description: values.description || '',
|
||||||
enabled: true,
|
projectId: Number(id),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新本地状态
|
||||||
|
const pipelineWithDefaults = {
|
||||||
|
...newPipeline,
|
||||||
|
description: newPipeline.description || '',
|
||||||
|
enabled: newPipeline.valid === 1,
|
||||||
steps: [],
|
steps: [],
|
||||||
createdAt: new Date().toLocaleString(),
|
|
||||||
updatedAt: new Date().toLocaleString(),
|
|
||||||
};
|
};
|
||||||
setPipelines((prev) => [...prev, newPipeline]);
|
setPipelines((prev) => [...prev, pipelineWithDefaults]);
|
||||||
// 自动选中新创建的流水线
|
// 自动选中新创建的流水线
|
||||||
setSelectedPipelineId(newPipeline.id);
|
setSelectedPipelineId(newPipeline.id);
|
||||||
Message.success('流水线创建成功');
|
Message.success('流水线创建成功');
|
||||||
}
|
}
|
||||||
setPipelineModalVisible(false);
|
setPipelineModalVisible(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('表单验证失败:', error);
|
console.error('保存流水线失败:', error);
|
||||||
|
Message.error('保存流水线失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加新步骤
|
// 添加新步骤
|
||||||
const handleAddStep = (pipelineId: string) => {
|
const handleAddStep = (pipelineId: number) => {
|
||||||
setEditingStep(null);
|
setEditingStep(null);
|
||||||
setEditingPipelineId(pipelineId);
|
setEditingPipelineId(pipelineId);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
@@ -351,7 +404,7 @@ function ProjectDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 编辑步骤
|
// 编辑步骤
|
||||||
const handleEditStep = (pipelineId: string, step: PipelineStep) => {
|
const handleEditStep = (pipelineId: number, step: PipelineStep) => {
|
||||||
setEditingStep(step);
|
setEditingStep(step);
|
||||||
setEditingPipelineId(pipelineId);
|
setEditingPipelineId(pipelineId);
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
@@ -362,40 +415,55 @@ function ProjectDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 删除步骤
|
// 删除步骤
|
||||||
const handleDeleteStep = (pipelineId: string, stepId: string) => {
|
const handleDeleteStep = async (pipelineId: number, stepId: number) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '确认删除',
|
title: '确认删除',
|
||||||
content: '确定要删除这个流水线步骤吗?此操作不可撤销。',
|
content: '确定要删除这个流水线步骤吗?此操作不可撤销。',
|
||||||
onOk: () => {
|
onOk: async () => {
|
||||||
setPipelines((prev) =>
|
try {
|
||||||
prev.map((pipeline) =>
|
// 从数据库删除步骤
|
||||||
pipeline.id === pipelineId
|
await detailService.deleteStep(stepId);
|
||||||
? {
|
|
||||||
...pipeline,
|
// 更新本地状态
|
||||||
steps: pipeline.steps.filter((step) => step.id !== stepId),
|
setPipelines((prev) =>
|
||||||
}
|
prev.map((pipeline) =>
|
||||||
: pipeline,
|
pipeline.id === pipelineId
|
||||||
),
|
? {
|
||||||
);
|
...pipeline,
|
||||||
Message.success('步骤删除成功');
|
steps:
|
||||||
|
pipeline.steps?.filter((step) => step.id !== stepId) ||
|
||||||
|
[],
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
: pipeline,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Message.success('步骤删除成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除步骤失败:', error);
|
||||||
|
Message.error('删除步骤失败');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换步骤启用状态
|
// 切换步骤启用状态
|
||||||
const handleToggleStep = (
|
const handleToggleStep = async (
|
||||||
pipelineId: string,
|
pipelineId: number,
|
||||||
stepId: string,
|
stepId: number,
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
) => {
|
) => {
|
||||||
|
// 在数据库中更新步骤状态(这里简化处理,实际可能需要添加enabled字段到数据库)
|
||||||
setPipelines((prev) =>
|
setPipelines((prev) =>
|
||||||
prev.map((pipeline) =>
|
prev.map((pipeline) =>
|
||||||
pipeline.id === pipelineId
|
pipeline.id === pipelineId
|
||||||
? {
|
? {
|
||||||
...pipeline,
|
...pipeline,
|
||||||
steps: pipeline.steps.map((step) =>
|
steps:
|
||||||
step.id === stepId ? { ...step, enabled } : step,
|
pipeline.steps?.map((step) =>
|
||||||
),
|
step.id === stepId ? { ...step, enabled } : step,
|
||||||
|
) || [],
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
}
|
}
|
||||||
: pipeline,
|
: pipeline,
|
||||||
),
|
),
|
||||||
@@ -403,7 +471,7 @@ function ProjectDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 拖拽结束处理
|
// 拖拽结束处理
|
||||||
const handleDragEnd = (event: DragEndEvent) => {
|
const handleDragEnd = async (event: DragEndEvent) => {
|
||||||
const { active, over } = event;
|
const { active, over } = event;
|
||||||
|
|
||||||
if (!over || active.id === over.id) {
|
if (!over || active.id === over.id) {
|
||||||
@@ -411,20 +479,25 @@ function ProjectDetailPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedPipelineId) {
|
if (selectedPipelineId) {
|
||||||
|
// 更新步骤顺序到数据库(简化处理,实际应该更新所有步骤的order字段)
|
||||||
setPipelines((prev) =>
|
setPipelines((prev) =>
|
||||||
prev.map((pipeline) => {
|
prev.map((pipeline) => {
|
||||||
if (pipeline.id === selectedPipelineId) {
|
if (pipeline.id === selectedPipelineId) {
|
||||||
const oldIndex = pipeline.steps.findIndex((step) => step.id === active.id);
|
const oldIndex =
|
||||||
const newIndex = pipeline.steps.findIndex((step) => step.id === over.id);
|
pipeline.steps?.findIndex((step) => step.id === active.id) || 0;
|
||||||
|
const newIndex =
|
||||||
|
pipeline.steps?.findIndex((step) => step.id === over.id) || 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...pipeline,
|
...pipeline,
|
||||||
steps: arrayMove(pipeline.steps, oldIndex, newIndex),
|
steps: pipeline.steps
|
||||||
updatedAt: new Date().toLocaleString(),
|
? arrayMove(pipeline.steps, oldIndex, newIndex)
|
||||||
|
: [],
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return pipeline;
|
return pipeline;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
Message.success('步骤顺序调整成功');
|
Message.success('步骤顺序调整成功');
|
||||||
}
|
}
|
||||||
@@ -435,36 +508,52 @@ function ProjectDetailPage() {
|
|||||||
try {
|
try {
|
||||||
const values = await form.validate();
|
const values = await form.validate();
|
||||||
if (editingStep && editingPipelineId) {
|
if (editingStep && editingPipelineId) {
|
||||||
|
// 更新现有步骤
|
||||||
|
const updatedStep = await detailService.updateStep(editingStep.id, {
|
||||||
|
name: values.name,
|
||||||
|
script: values.script,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新本地状态
|
||||||
setPipelines((prev) =>
|
setPipelines((prev) =>
|
||||||
prev.map((pipeline) =>
|
prev.map((pipeline) =>
|
||||||
pipeline.id === editingPipelineId
|
pipeline.id === editingPipelineId
|
||||||
? {
|
? {
|
||||||
...pipeline,
|
...pipeline,
|
||||||
steps: pipeline.steps.map((step) =>
|
steps:
|
||||||
step.id === editingStep.id
|
pipeline.steps?.map((step) =>
|
||||||
? { ...step, name: values.name, script: values.script }
|
step.id === editingStep.id
|
||||||
: step,
|
? { ...updatedStep, enabled: step.enabled }
|
||||||
),
|
: step,
|
||||||
updatedAt: new Date().toLocaleString(),
|
) || [],
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
}
|
}
|
||||||
: pipeline,
|
: pipeline,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
Message.success('步骤更新成功');
|
Message.success('步骤更新成功');
|
||||||
} else if (editingPipelineId) {
|
} else if (editingPipelineId) {
|
||||||
const newStep: PipelineStep = {
|
// 创建新步骤
|
||||||
id: `step_${Date.now()}`,
|
const newStep = await detailService.createStep({
|
||||||
name: values.name,
|
name: values.name,
|
||||||
script: values.script,
|
script: values.script,
|
||||||
enabled: true,
|
order:
|
||||||
};
|
pipelines.find((p) => p.id === editingPipelineId)?.steps?.length ||
|
||||||
|
0,
|
||||||
|
pipelineId: editingPipelineId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新本地状态
|
||||||
setPipelines((prev) =>
|
setPipelines((prev) =>
|
||||||
prev.map((pipeline) =>
|
prev.map((pipeline) =>
|
||||||
pipeline.id === editingPipelineId
|
pipeline.id === editingPipelineId
|
||||||
? {
|
? {
|
||||||
...pipeline,
|
...pipeline,
|
||||||
steps: [...pipeline.steps, newStep],
|
steps: [
|
||||||
updatedAt: new Date().toLocaleString(),
|
...(pipeline.steps || []),
|
||||||
|
{ ...newStep, enabled: true },
|
||||||
|
],
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
}
|
}
|
||||||
: pipeline,
|
: pipeline,
|
||||||
),
|
),
|
||||||
@@ -473,7 +562,8 @@ function ProjectDetailPage() {
|
|||||||
}
|
}
|
||||||
setEditModalVisible(false);
|
setEditModalVisible(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('表单验证失败:', error);
|
console.error('保存步骤失败:', error);
|
||||||
|
Message.error('保存步骤失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -498,7 +588,7 @@ function ProjectDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 渲染部署记录项
|
// 渲染部署记录项
|
||||||
const renderDeployRecordItem = (item: DeployRecord, index: number) => {
|
const renderDeployRecordItem = (item: DeployRecord, _index: number) => {
|
||||||
const isSelected = item.id === selectedRecordId;
|
const isSelected = item.id === selectedRecordId;
|
||||||
return (
|
return (
|
||||||
<DeployRecordItem
|
<DeployRecordItem
|
||||||
@@ -538,12 +628,18 @@ function ProjectDetailPage() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full overflow-y-auto">
|
<div className="h-full overflow-y-auto">
|
||||||
<List
|
{deployRecords.length > 0 ? (
|
||||||
className="bg-white rounded-lg border"
|
<List
|
||||||
dataSource={deployRecords}
|
className="bg-white rounded-lg border"
|
||||||
render={renderDeployRecordItem}
|
dataSource={deployRecords}
|
||||||
split={true}
|
render={renderDeployRecordItem}
|
||||||
/>
|
split={true}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-12">
|
||||||
|
<Empty description="暂无部署记录" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -621,7 +717,9 @@ function ProjectDetailPage() {
|
|||||||
<Typography.Title
|
<Typography.Title
|
||||||
heading={6}
|
heading={6}
|
||||||
className={`!m-0 ${
|
className={`!m-0 ${
|
||||||
isSelected ? 'text-blue-600' : 'text-gray-900'
|
isSelected
|
||||||
|
? 'text-blue-600'
|
||||||
|
: 'text-gray-900'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{pipeline.name}
|
{pipeline.name}
|
||||||
@@ -647,14 +745,18 @@ function ProjectDetailPage() {
|
|||||||
<Menu>
|
<Menu>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="edit"
|
key="edit"
|
||||||
onClick={() => handleEditPipeline(pipeline)}
|
onClick={() =>
|
||||||
|
handleEditPipeline(pipeline)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<IconEdit className="mr-2" />
|
<IconEdit className="mr-2" />
|
||||||
编辑流水线
|
编辑流水线
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="copy"
|
key="copy"
|
||||||
onClick={() => handleCopyPipeline(pipeline)}
|
onClick={() =>
|
||||||
|
handleCopyPipeline(pipeline)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<IconCopy className="mr-2" />
|
<IconCopy className="mr-2" />
|
||||||
复制流水线
|
复制流水线
|
||||||
@@ -684,8 +786,14 @@ function ProjectDetailPage() {
|
|||||||
<div className="text-sm text-gray-500">
|
<div className="text-sm text-gray-500">
|
||||||
<div>{pipeline.description}</div>
|
<div>{pipeline.description}</div>
|
||||||
<div className="flex items-center justify-between mt-2">
|
<div className="flex items-center justify-between mt-2">
|
||||||
<span>共 {pipeline.steps.length} 个步骤</span>
|
<span>
|
||||||
<span>{pipeline.updatedAt}</span>
|
共 {pipeline.steps?.length || 0} 个步骤
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{new Date(
|
||||||
|
pipeline.updatedAt,
|
||||||
|
).toLocaleString()}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -695,8 +803,9 @@ function ProjectDetailPage() {
|
|||||||
|
|
||||||
{pipelines.length === 0 && (
|
{pipelines.length === 0 && (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
|
<Empty description="暂无流水线" />
|
||||||
<Typography.Text type="secondary">
|
<Typography.Text type="secondary">
|
||||||
暂无流水线,点击上方"新建流水线"按钮开始创建
|
点击上方"新建流水线"按钮开始创建
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -706,9 +815,12 @@ function ProjectDetailPage() {
|
|||||||
|
|
||||||
{/* 右侧流水线步骤详情 */}
|
{/* 右侧流水线步骤详情 */}
|
||||||
<div className="col-span-3 bg-white rounded-lg border h-full overflow-hidden">
|
<div className="col-span-3 bg-white rounded-lg border h-full overflow-hidden">
|
||||||
{selectedPipelineId && pipelines.find(p => p.id === selectedPipelineId) ? (
|
{selectedPipelineId &&
|
||||||
|
pipelines.find((p) => p.id === selectedPipelineId) ? (
|
||||||
(() => {
|
(() => {
|
||||||
const selectedPipeline = pipelines.find(p => p.id === selectedPipelineId)!;
|
const selectedPipeline = pipelines.find(
|
||||||
|
(p) => p.id === selectedPipelineId,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="p-4 border-b bg-gray-50">
|
<div className="p-4 border-b bg-gray-50">
|
||||||
@@ -717,8 +829,12 @@ function ProjectDetailPage() {
|
|||||||
<Typography.Title heading={5} className="!m-0">
|
<Typography.Title heading={5} className="!m-0">
|
||||||
{selectedPipeline.name} - 流水线步骤
|
{selectedPipeline.name} - 流水线步骤
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
<Typography.Text type="secondary" className="text-sm">
|
<Typography.Text
|
||||||
{selectedPipeline.description} · 共 {selectedPipeline.steps.length} 个步骤
|
type="secondary"
|
||||||
|
className="text-sm"
|
||||||
|
>
|
||||||
|
{selectedPipeline.description} · 共{' '}
|
||||||
|
{selectedPipeline.steps?.length || 0} 个步骤
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@@ -738,11 +854,15 @@ function ProjectDetailPage() {
|
|||||||
onDragEnd={handleDragEnd}
|
onDragEnd={handleDragEnd}
|
||||||
>
|
>
|
||||||
<SortableContext
|
<SortableContext
|
||||||
items={selectedPipeline.steps.map(step => step.id)}
|
items={
|
||||||
|
selectedPipeline.steps?.map(
|
||||||
|
(step) => step.id,
|
||||||
|
) || []
|
||||||
|
}
|
||||||
strategy={verticalListSortingStrategy}
|
strategy={verticalListSortingStrategy}
|
||||||
>
|
>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{selectedPipeline.steps.map((step, index) => (
|
{selectedPipeline.steps?.map((step, index) => (
|
||||||
<PipelineStepItem
|
<PipelineStepItem
|
||||||
key={step.id}
|
key={step.id}
|
||||||
step={step}
|
step={step}
|
||||||
@@ -754,10 +874,11 @@ function ProjectDetailPage() {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{selectedPipeline.steps.length === 0 && (
|
{selectedPipeline.steps?.length === 0 && (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
|
<Empty description="暂无步骤" />
|
||||||
<Typography.Text type="secondary">
|
<Typography.Text type="secondary">
|
||||||
暂无步骤,点击上方"添加步骤"按钮开始配置
|
点击上方"添加步骤"按钮开始配置
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -770,9 +891,7 @@ function ProjectDetailPage() {
|
|||||||
})()
|
})()
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center h-full">
|
<div className="flex items-center justify-center h-full">
|
||||||
<Typography.Text type="secondary">
|
<Empty description="请选择流水线" />
|
||||||
请选择左侧的流水线查看详细步骤
|
|
||||||
</Typography.Text>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,125 @@
|
|||||||
import { net, type APIResponse } from '@shared';
|
import { type APIResponse, net } from '@shared';
|
||||||
import type { Project } from '../types';
|
import type { Pipeline, Project, Step } from '../types';
|
||||||
|
|
||||||
class DetailService {
|
class DetailService {
|
||||||
async getProject(id: string) {
|
async getProject(id: string) {
|
||||||
const { code, data } = await net.request<APIResponse<Project>>({
|
const { data } = await net.request<APIResponse<Project>>({
|
||||||
url: `/api/projects/${id}`,
|
url: `/api/projects/${id}`,
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取项目的所有流水线
|
||||||
|
async getPipelines(projectId: number) {
|
||||||
|
const { data } = await net.request<APIResponse<Pipeline[]>>({
|
||||||
|
url: `/api/pipelines?projectId=${projectId}`,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建流水线
|
||||||
|
async createPipeline(
|
||||||
|
pipeline: Omit<
|
||||||
|
Pipeline,
|
||||||
|
| 'id'
|
||||||
|
| 'createdAt'
|
||||||
|
| 'updatedAt'
|
||||||
|
| 'createdBy'
|
||||||
|
| 'updatedBy'
|
||||||
|
| 'valid'
|
||||||
|
| 'steps'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const { data } = await net.request<APIResponse<Pipeline>>({
|
||||||
|
url: '/api/pipelines',
|
||||||
|
method: 'POST',
|
||||||
|
data: pipeline,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新流水线
|
||||||
|
async updatePipeline(
|
||||||
|
id: number,
|
||||||
|
pipeline: Partial<
|
||||||
|
Omit<
|
||||||
|
Pipeline,
|
||||||
|
| 'id'
|
||||||
|
| 'createdAt'
|
||||||
|
| 'updatedAt'
|
||||||
|
| 'createdBy'
|
||||||
|
| 'updatedBy'
|
||||||
|
| 'valid'
|
||||||
|
| 'steps'
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const { data } = await net.request<APIResponse<Pipeline>>({
|
||||||
|
url: `/api/pipelines/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data: pipeline,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除流水线
|
||||||
|
async deletePipeline(id: number) {
|
||||||
|
const { data } = await net.request<APIResponse<null>>({
|
||||||
|
url: `/api/pipelines/${id}`,
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取流水线的所有步骤
|
||||||
|
async getSteps(pipelineId: number) {
|
||||||
|
const { data } = await net.request<APIResponse<Step[]>>({
|
||||||
|
url: `/api/steps?pipelineId=${pipelineId}`,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建步骤
|
||||||
|
async createStep(
|
||||||
|
step: Omit<
|
||||||
|
Step,
|
||||||
|
'id' | 'createdAt' | 'updatedAt' | 'createdBy' | 'updatedBy' | 'valid'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const { data } = await net.request<APIResponse<Step>>({
|
||||||
|
url: '/api/steps',
|
||||||
|
method: 'POST',
|
||||||
|
data: step,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新步骤
|
||||||
|
async updateStep(
|
||||||
|
id: number,
|
||||||
|
step: Partial<
|
||||||
|
Omit<
|
||||||
|
Step,
|
||||||
|
'id' | 'createdAt' | 'updatedAt' | 'createdBy' | 'updatedBy' | 'valid'
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const { data } = await net.request<APIResponse<Step>>({
|
||||||
|
url: `/api/steps/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data: step,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除步骤
|
||||||
|
async deleteStep(id: number) {
|
||||||
|
const { data } = await net.request<APIResponse<null>>({
|
||||||
|
url: `/api/steps/${id}`,
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const detailService = new DetailService();
|
export const detailService = new DetailService();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Modal, Form, Input, Button, Message } from '@arco-design/web-react';
|
import { Button, Form, Input, Message, Modal } from '@arco-design/web-react';
|
||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { Project } from '../types';
|
|
||||||
import { projectService } from '../service';
|
import { projectService } from '../service';
|
||||||
|
import type { Project } from '../types';
|
||||||
|
|
||||||
interface CreateProjectModalProps {
|
interface CreateProjectModalProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
@@ -9,7 +9,11 @@ interface CreateProjectModalProps {
|
|||||||
onSuccess: (newProject: Project) => void;
|
onSuccess: (newProject: Project) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateProjectModal({ visible, onCancel, onSuccess }: CreateProjectModalProps) {
|
function CreateProjectModal({
|
||||||
|
visible,
|
||||||
|
onCancel,
|
||||||
|
onSuccess,
|
||||||
|
}: CreateProjectModalProps) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
@@ -46,17 +50,18 @@ function CreateProjectModal({ visible, onCancel, onSuccess }: CreateProjectModal
|
|||||||
<Button key="cancel" onClick={handleCancel}>
|
<Button key="cancel" onClick={handleCancel}>
|
||||||
取消
|
取消
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button key="submit" type="primary" loading={loading} onClick={handleSubmit}>
|
<Button
|
||||||
|
key="submit"
|
||||||
|
type="primary"
|
||||||
|
loading={loading}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
创建
|
创建
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
style={{ width: 500 }}
|
style={{ width: 500 }}
|
||||||
>
|
>
|
||||||
<Form
|
<Form form={form} layout="vertical" autoComplete="off">
|
||||||
form={form}
|
|
||||||
layout="vertical"
|
|
||||||
autoComplete="off"
|
|
||||||
>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="项目名称"
|
label="项目名称"
|
||||||
field="name"
|
field="name"
|
||||||
@@ -71,9 +76,7 @@ function CreateProjectModal({ visible, onCancel, onSuccess }: CreateProjectModal
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
label="项目描述"
|
label="项目描述"
|
||||||
field="description"
|
field="description"
|
||||||
rules={[
|
rules={[{ maxLength: 200, message: '项目描述不能超过200个字符' }]}
|
||||||
{ maxLength: 200, message: '项目描述不能超过200个字符' },
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
placeholder="请输入项目描述(可选)"
|
placeholder="请输入项目描述(可选)"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Modal, Form, Input, Button, Message } from '@arco-design/web-react';
|
import { Button, Form, Input, Message, Modal } from '@arco-design/web-react';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import type { Project } from '../types';
|
|
||||||
import { projectService } from '../service';
|
import { projectService } from '../service';
|
||||||
|
import type { Project } from '../types';
|
||||||
|
|
||||||
interface EditProjectModalProps {
|
interface EditProjectModalProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
@@ -10,7 +10,12 @@ interface EditProjectModalProps {
|
|||||||
onSuccess: (updatedProject: Project) => void;
|
onSuccess: (updatedProject: Project) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditProjectModal({ visible, project, onCancel, onSuccess }: EditProjectModalProps) {
|
function EditProjectModal({
|
||||||
|
visible,
|
||||||
|
project,
|
||||||
|
onCancel,
|
||||||
|
onSuccess,
|
||||||
|
}: EditProjectModalProps) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
@@ -59,17 +64,18 @@ function EditProjectModal({ visible, project, onCancel, onSuccess }: EditProject
|
|||||||
<Button key="cancel" onClick={handleCancel}>
|
<Button key="cancel" onClick={handleCancel}>
|
||||||
取消
|
取消
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button key="submit" type="primary" loading={loading} onClick={handleSubmit}>
|
<Button
|
||||||
|
key="submit"
|
||||||
|
type="primary"
|
||||||
|
loading={loading}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
保存
|
保存
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
style={{ width: 500 }}
|
style={{ width: 500 }}
|
||||||
>
|
>
|
||||||
<Form
|
<Form form={form} layout="vertical" autoComplete="off">
|
||||||
form={form}
|
|
||||||
layout="vertical"
|
|
||||||
autoComplete="off"
|
|
||||||
>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="项目名称"
|
label="项目名称"
|
||||||
field="name"
|
field="name"
|
||||||
@@ -84,9 +90,7 @@ function EditProjectModal({ visible, project, onCancel, onSuccess }: EditProject
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
label="项目描述"
|
label="项目描述"
|
||||||
field="description"
|
field="description"
|
||||||
rules={[
|
rules={[{ maxLength: 200, message: '项目描述不能超过200个字符' }]}
|
||||||
{ maxLength: 200, message: '项目描述不能超过200个字符' },
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
placeholder="请输入项目描述"
|
placeholder="请输入项目描述"
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
import {
|
import {
|
||||||
Card,
|
|
||||||
Tag,
|
|
||||||
Avatar,
|
Avatar,
|
||||||
Space,
|
|
||||||
Typography,
|
|
||||||
Button,
|
Button,
|
||||||
Tooltip,
|
Card,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Menu,
|
Menu,
|
||||||
Modal,
|
Modal,
|
||||||
|
Space,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
} from '@arco-design/web-react';
|
} from '@arco-design/web-react';
|
||||||
import {
|
import {
|
||||||
IconBranch,
|
IconBranch,
|
||||||
IconCalendar,
|
IconCalendar,
|
||||||
IconCloud,
|
IconCloud,
|
||||||
|
IconDelete,
|
||||||
IconEdit,
|
IconEdit,
|
||||||
IconMore,
|
IconMore,
|
||||||
IconDelete,
|
|
||||||
} from '@arco-design/web-react/icon';
|
} from '@arco-design/web-react/icon';
|
||||||
import type { Project } from '../../types';
|
|
||||||
import IconGitea from '@assets/images/gitea.svg?react';
|
import IconGitea from '@assets/images/gitea.svg?react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
import type { Project } from '../../types';
|
||||||
|
|
||||||
const { Text, Paragraph } = Typography;
|
const { Text, Paragraph } = Typography;
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Grid, Typography, Button, Message } from '@arco-design/web-react';
|
import { Button, Grid, Message, Typography } from '@arco-design/web-react';
|
||||||
import { IconPlus } from '@arco-design/web-react/icon';
|
import { IconPlus } from '@arco-design/web-react/icon';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { Project } from '../types';
|
|
||||||
import { useAsyncEffect } from '../../../hooks/useAsyncEffect';
|
import { useAsyncEffect } from '../../../hooks/useAsyncEffect';
|
||||||
import { projectService } from './service';
|
import type { Project } from '../types';
|
||||||
import ProjectCard from './components/ProjectCard';
|
|
||||||
import EditProjectModal from './components/EditProjectModal';
|
|
||||||
import CreateProjectModal from './components/CreateProjectModal';
|
import CreateProjectModal from './components/CreateProjectModal';
|
||||||
|
import EditProjectModal from './components/EditProjectModal';
|
||||||
|
import ProjectCard from './components/ProjectCard';
|
||||||
|
import { projectService } from './service';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ function ProjectPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEditSuccess = (updatedProject: Project) => {
|
const handleEditSuccess = (updatedProject: Project) => {
|
||||||
setProjects(prev =>
|
setProjects((prev) =>
|
||||||
prev.map(p => p.id === updatedProject.id ? updatedProject : p)
|
prev.map((p) => (p.id === updatedProject.id ? updatedProject : p)),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ function ProjectPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateSuccess = (newProject: Project) => {
|
const handleCreateSuccess = (newProject: Project) => {
|
||||||
setProjects(prev => [newProject, ...prev]);
|
setProjects((prev) => [newProject, ...prev]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateCancel = () => {
|
const handleCreateCancel = () => {
|
||||||
@@ -52,7 +52,7 @@ function ProjectPage() {
|
|||||||
const handleDeleteProject = async (project: Project) => {
|
const handleDeleteProject = async (project: Project) => {
|
||||||
try {
|
try {
|
||||||
await projectService.delete(project.id);
|
await projectService.delete(project.id);
|
||||||
setProjects(prev => prev.filter(p => p.id !== project.id));
|
setProjects((prev) => prev.filter((p) => p.id !== project.id));
|
||||||
Message.success('项目删除成功');
|
Message.success('项目删除成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('删除项目失败:', error);
|
console.error('删除项目失败:', error);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { net, type APIResponse } from '@shared';
|
import { type APIResponse, net } from '@shared';
|
||||||
import type { Project } from '../types';
|
import type { Project } from '../types';
|
||||||
|
|
||||||
|
|
||||||
class ProjectService {
|
class ProjectService {
|
||||||
async list(params?: ProjectQueryParams) {
|
async list(params?: ProjectQueryParams) {
|
||||||
const { data } = await net.request<APIResponse<ProjectListResponse>>({
|
const { data } = await net.request<APIResponse<ProjectListResponse>>({
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
enum BuildStatus {
|
enum BuildStatus {
|
||||||
Idle = "Pending",
|
Idle = 'Pending',
|
||||||
Running = "Running",
|
Running = 'Running',
|
||||||
Stopped = "Stopped",
|
Stopped = 'Stopped',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Project {
|
export interface Project {
|
||||||
@@ -16,3 +16,32 @@ export interface Project {
|
|||||||
updatedBy: string;
|
updatedBy: string;
|
||||||
status: BuildStatus;
|
status: BuildStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 流水线步骤类型定义
|
||||||
|
export interface Step {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
order: number;
|
||||||
|
script: string; // 执行的脚本命令
|
||||||
|
valid: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdBy: string;
|
||||||
|
updatedBy: string;
|
||||||
|
pipelineId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 流水线类型定义
|
||||||
|
export interface Pipeline {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
valid: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdBy: string;
|
||||||
|
updatedBy: string;
|
||||||
|
projectId?: number;
|
||||||
|
steps?: Step[];
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import axios, { Axios, type AxiosRequestConfig } from 'axios';
|
import axios, { type Axios, type AxiosRequestConfig } from 'axios';
|
||||||
|
|
||||||
class Net {
|
class Net {
|
||||||
private readonly instance: Axios;
|
private readonly instance: Axios;
|
||||||
@@ -18,7 +18,7 @@ class Net {
|
|||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
console.log('error', error)
|
console.log('error', error);
|
||||||
if (error.status === 401 && error.config.url !== '/api/auth/info') {
|
if (error.status === 401 && error.config.url !== '/api/auth/info') {
|
||||||
window.location.href = '/login';
|
window.location.href = '/login';
|
||||||
return;
|
return;
|
||||||
@@ -29,8 +29,16 @@ class Net {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async request<T>(config: AxiosRequestConfig): Promise<T> {
|
async request<T>(config: AxiosRequestConfig): Promise<T> {
|
||||||
const { data } = await this.instance.request<T>(config);
|
try {
|
||||||
return data;
|
const response = await this.instance.request<T>(config);
|
||||||
|
if (!response || !response.data) {
|
||||||
|
throw new Error('Invalid response');
|
||||||
|
}
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Request failed:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { net, type APIResponse } from '@shared';
|
import { type APIResponse, net } from '@shared';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
@import 'tailwindcss';
|
@import "tailwindcss";
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@pages/*": ["./src/pages/*"],
|
"@pages/*": ["./src/pages/*"],
|
||||||
"@styles/*": ["./src/styles/*"],
|
"@styles/*": ["./src/styles/*"],
|
||||||
"@assets/*": ["./src/assets/*"],
|
"@assets/*": ["./src/assets/*"],
|
||||||
|
|||||||
442
pnpm-lock.yaml
generated
442
pnpm-lock.yaml
generated
@@ -79,57 +79,57 @@ importers:
|
|||||||
apps/web:
|
apps/web:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@arco-design/web-react':
|
'@arco-design/web-react':
|
||||||
specifier: ^2.66.4
|
specifier: ^2.66.8
|
||||||
version: 2.66.5(@types/react@18.3.24)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 2.66.8(@types/react@18.3.27)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||||
'@dnd-kit/core':
|
'@dnd-kit/core':
|
||||||
specifier: ^6.3.1
|
specifier: ^6.3.1
|
||||||
version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.3.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||||
'@dnd-kit/sortable':
|
'@dnd-kit/sortable':
|
||||||
specifier: ^10.0.0
|
specifier: ^10.0.0
|
||||||
version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)
|
||||||
'@dnd-kit/utilities':
|
'@dnd-kit/utilities':
|
||||||
specifier: ^3.2.2
|
specifier: ^3.2.2
|
||||||
version: 3.2.2(react@18.3.1)
|
version: 3.2.2(react@19.2.0)
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.11.0
|
specifier: ^1.11.0
|
||||||
version: 1.11.0
|
version: 1.11.0
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^19.0.0
|
||||||
version: 18.3.1
|
version: 19.2.0
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^18.2.0
|
specifier: ^19.0.0
|
||||||
version: 18.3.1(react@18.3.1)
|
version: 19.2.0(react@19.2.0)
|
||||||
react-router:
|
react-router:
|
||||||
specifier: ^7.8.0
|
specifier: ^7.8.0
|
||||||
version: 7.8.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 7.8.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||||
zustand:
|
zustand:
|
||||||
specifier: ^5.0.8
|
specifier: ^5.0.8
|
||||||
version: 5.0.8(@types/react@18.3.24)(react@18.3.1)
|
version: 5.0.8(@types/react@18.3.27)(react@19.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@arco-plugins/unplugin-react':
|
'@arco-plugins/unplugin-react':
|
||||||
specifier: 2.0.0-beta.5
|
specifier: 2.0.0-beta.5
|
||||||
version: 2.0.0-beta.5(@rspack/core@1.5.0(@swc/helpers@0.5.17))
|
version: 2.0.0-beta.5(@rspack/core@1.6.4(@swc/helpers@0.5.17))
|
||||||
'@rsbuild/core':
|
'@rsbuild/core':
|
||||||
specifier: ^1.4.13
|
specifier: ^1.6.7
|
||||||
version: 1.5.1
|
version: 1.6.7
|
||||||
'@rsbuild/plugin-less':
|
'@rsbuild/plugin-less':
|
||||||
specifier: ^1.4.0
|
specifier: ^1.5.0
|
||||||
version: 1.5.0(@rsbuild/core@1.5.1)
|
version: 1.5.0(@rsbuild/core@1.6.7)
|
||||||
'@rsbuild/plugin-react':
|
'@rsbuild/plugin-react':
|
||||||
specifier: ^1.3.4
|
specifier: ^1.4.2
|
||||||
version: 1.3.5(@rsbuild/core@1.5.1)
|
version: 1.4.2(@rsbuild/core@1.6.7)
|
||||||
'@rsbuild/plugin-svgr':
|
'@rsbuild/plugin-svgr':
|
||||||
specifier: ^1.2.2
|
specifier: ^1.2.2
|
||||||
version: 1.2.2(@rsbuild/core@1.5.1)(typescript@5.9.2)
|
version: 1.2.2(@rsbuild/core@1.6.7)(typescript@5.9.2)
|
||||||
'@tailwindcss/postcss':
|
'@tailwindcss/postcss':
|
||||||
specifier: ^4.1.11
|
specifier: ^4.1.11
|
||||||
version: 4.1.12
|
version: 4.1.12
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.3.24
|
specifier: ^18.3.24
|
||||||
version: 18.3.24
|
version: 18.3.27
|
||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: ^18.3.7
|
specifier: ^18.3.7
|
||||||
version: 18.3.7(@types/react@18.3.24)
|
version: 18.3.7(@types/react@18.3.27)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4.1.11
|
specifier: ^4.1.11
|
||||||
version: 4.1.12
|
version: 4.1.12
|
||||||
@@ -150,8 +150,8 @@ packages:
|
|||||||
'@arco-design/color@0.4.0':
|
'@arco-design/color@0.4.0':
|
||||||
resolution: {integrity: sha512-s7p9MSwJgHeL8DwcATaXvWT3m2SigKpxx4JA1BGPHL4gfvaQsmQfrLBDpjOJFJuJ2jG2dMt3R3P8Pm9E65q18g==}
|
resolution: {integrity: sha512-s7p9MSwJgHeL8DwcATaXvWT3m2SigKpxx4JA1BGPHL4gfvaQsmQfrLBDpjOJFJuJ2jG2dMt3R3P8Pm9E65q18g==}
|
||||||
|
|
||||||
'@arco-design/web-react@2.66.5':
|
'@arco-design/web-react@2.66.8':
|
||||||
resolution: {integrity: sha512-ity0kG+B6pmuJ2/Zh3wUtBV78XxWmRtGEwazL8f4KAjoQpMkisgLMXibUpAGfcqph3vycNFq4yHgHujjgwrJMQ==}
|
resolution: {integrity: sha512-V2XDTqeSFq4g6Yk0tSEFO4SMPZ04cGNF6dKfFBM9drEpmj91cU1n9+rd3gmmtcJ2f3SOqbr0itnUsqBWGQ4PvQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16'
|
react: '>=16'
|
||||||
react-dom: '>=16'
|
react-dom: '>=16'
|
||||||
@@ -307,14 +307,14 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16.8.0'
|
react: '>=16.8.0'
|
||||||
|
|
||||||
'@emnapi/core@1.4.5':
|
'@emnapi/core@1.7.1':
|
||||||
resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==}
|
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
|
||||||
|
|
||||||
'@emnapi/runtime@1.4.5':
|
'@emnapi/runtime@1.7.1':
|
||||||
resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==}
|
resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}
|
||||||
|
|
||||||
'@emnapi/wasi-threads@1.0.4':
|
'@emnapi/wasi-threads@1.1.0':
|
||||||
resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==}
|
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.25.9':
|
'@esbuild/aix-ppc64@0.25.9':
|
||||||
resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==}
|
resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==}
|
||||||
@@ -503,26 +503,26 @@ packages:
|
|||||||
resolution: {integrity: sha512-LBSu5K0qAaaQcXX/0WIB9PGDevyCxxpnc1uq13vV/CgObaVxuis5hKl3Eboq/8gcb6ebnkAStW9NB/Em2eYyFA==}
|
resolution: {integrity: sha512-LBSu5K0qAaaQcXX/0WIB9PGDevyCxxpnc1uq13vV/CgObaVxuis5hKl3Eboq/8gcb6ebnkAStW9NB/Em2eYyFA==}
|
||||||
engines: {node: '>= 20'}
|
engines: {node: '>= 20'}
|
||||||
|
|
||||||
'@module-federation/error-codes@0.18.0':
|
'@module-federation/error-codes@0.21.4':
|
||||||
resolution: {integrity: sha512-Woonm8ehyVIUPXChmbu80Zj6uJkC0dD9SJUZ/wOPtO8iiz/m+dkrOugAuKgoiR6qH4F+yorWila954tBz4uKsQ==}
|
resolution: {integrity: sha512-ClpL5MereWNXh+EgDjz7w4RrC1JlisQTvXDa1gLxpviHafzNDfdViVmuhi9xXVuj+EYo8KU70Y999KHhk9424Q==}
|
||||||
|
|
||||||
'@module-federation/runtime-core@0.18.0':
|
'@module-federation/runtime-core@0.21.4':
|
||||||
resolution: {integrity: sha512-ZyYhrDyVAhUzriOsVfgL6vwd+5ebYm595Y13KeMf6TKDRoUHBMTLGQ8WM4TDj8JNsy7LigncK8C03fn97of0QQ==}
|
resolution: {integrity: sha512-SGpmoOLGNxZofpTOk6Lxb2ewaoz5wMi93AFYuuJB04HTVcngEK+baNeUZ2D/xewrqNIJoMY6f5maUjVfIIBPUA==}
|
||||||
|
|
||||||
'@module-federation/runtime-tools@0.18.0':
|
'@module-federation/runtime-tools@0.21.4':
|
||||||
resolution: {integrity: sha512-fSga9o4t1UfXNV/Kh6qFvRyZpPp3EHSPRISNeyT8ZoTpzDNiYzhtw0BPUSSD8m6C6XQh2s/11rI4g80UY+d+hA==}
|
resolution: {integrity: sha512-RzFKaL0DIjSmkn76KZRfzfB6dD07cvID84950jlNQgdyoQFUGkqD80L6rIpVCJTY/R7LzR3aQjHnoqmq4JPo3w==}
|
||||||
|
|
||||||
'@module-federation/runtime@0.18.0':
|
'@module-federation/runtime@0.21.4':
|
||||||
resolution: {integrity: sha512-+C4YtoSztM7nHwNyZl6dQKGUVJdsPrUdaf3HIKReg/GQbrt9uvOlUWo2NXMZ8vDAnf/QRrpSYAwXHmWDn9Obaw==}
|
resolution: {integrity: sha512-wgvGqryurVEvkicufJmTG0ZehynCeNLklv8kIk5BLIsWYSddZAE+xe4xov1kgH5fIJQAoQNkRauFFjVNlHoAkA==}
|
||||||
|
|
||||||
'@module-federation/sdk@0.18.0':
|
'@module-federation/sdk@0.21.4':
|
||||||
resolution: {integrity: sha512-Lo/Feq73tO2unjmpRfyyoUkTVoejhItXOk/h5C+4cistnHbTV8XHrW/13fD5e1Iu60heVdAhhelJd6F898Ve9A==}
|
resolution: {integrity: sha512-tzvhOh/oAfX++6zCDDxuvioHY4Jurf8vcfoCbKFxusjmyKr32GPbwFDazUP+OPhYCc3dvaa9oWU6X/qpUBLfJw==}
|
||||||
|
|
||||||
'@module-federation/webpack-bundler-runtime@0.18.0':
|
'@module-federation/webpack-bundler-runtime@0.21.4':
|
||||||
resolution: {integrity: sha512-TEvErbF+YQ+6IFimhUYKK3a5wapD90d90sLsNpcu2kB3QGT7t4nIluE25duXuZDVUKLz86tEPrza/oaaCWTpvQ==}
|
resolution: {integrity: sha512-dusmR3uPnQh9u9ChQo3M+GLOuGFthfvnh7WitF/a1eoeTfRmXqnMFsXtZCUK+f/uXf+64874Zj/bhAgbBcVHZA==}
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@1.0.3':
|
'@napi-rs/wasm-runtime@1.0.7':
|
||||||
resolution: {integrity: sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==}
|
resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==}
|
||||||
|
|
||||||
'@prisma/client@6.15.0':
|
'@prisma/client@6.15.0':
|
||||||
resolution: {integrity: sha512-wR2LXUbOH4cL/WToatI/Y2c7uzni76oNFND7+23ypLllBmIS8e3ZHhO+nud9iXSXKFt1SoM3fTZvHawg63emZw==}
|
resolution: {integrity: sha512-wR2LXUbOH4cL/WToatI/Y2c7uzni76oNFND7+23ypLllBmIS8e3ZHhO+nud9iXSXKFt1SoM3fTZvHawg63emZw==}
|
||||||
@@ -554,8 +554,8 @@ packages:
|
|||||||
'@prisma/get-platform@6.15.0':
|
'@prisma/get-platform@6.15.0':
|
||||||
resolution: {integrity: sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==}
|
resolution: {integrity: sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==}
|
||||||
|
|
||||||
'@rsbuild/core@1.5.1':
|
'@rsbuild/core@1.6.7':
|
||||||
resolution: {integrity: sha512-ScXC3nm1drXDyT9OahHxXJ8Tg+1oE5IN2+ZwJzNl0cLJD8Jmbjl4zMUN7zZdRPqjaTCz67IAjws+HN+PSKHBaw==}
|
resolution: {integrity: sha512-V0INbMrT/LwyhzKmvpupe2oSvPFWaivz7sdriFRp381BJvD0d2pYcq9iRW91bxgMRX78MgTzFYAu868hMAzoSw==}
|
||||||
engines: {node: '>=18.12.0'}
|
engines: {node: '>=18.12.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -564,8 +564,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@rsbuild/core': 1.x
|
'@rsbuild/core': 1.x
|
||||||
|
|
||||||
'@rsbuild/plugin-react@1.3.5':
|
'@rsbuild/plugin-react@1.4.2':
|
||||||
resolution: {integrity: sha512-L/GoHgJV4j+EQbI4KOhe5EscM0OHgnSat1eR0Nt5P3JZxpJV2ryO5Yfx5jElPWOkYZZCuk+EWhHWDQ4CkeC5BQ==}
|
resolution: {integrity: sha512-2rJb5mOuqVof2aDq4SbB1E65+0n1vjhAADipC88jvZRNuTOulg79fh7R4tsCiBMI4VWq46gSpwekiK8G5bq6jg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@rsbuild/core': 1.x
|
'@rsbuild/core': 1.x
|
||||||
|
|
||||||
@@ -574,60 +574,60 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@rsbuild/core': 1.x
|
'@rsbuild/core': 1.x
|
||||||
|
|
||||||
'@rspack/binding-darwin-arm64@1.5.0':
|
'@rspack/binding-darwin-arm64@1.6.4':
|
||||||
resolution: {integrity: sha512-7909YLNnKf0BYxiCpCWOk13WyWS4493Kxk1NQwy9KPLY9ydQExk84KVsix2NuNBaI8Pnk3aVLBPJiSNXtHLjnA==}
|
resolution: {integrity: sha512-qD2C5xwdY2qKEXTZiPJQx1L1kELapOc0AaZDqcAyzXs30d1qTKpx6PdyW3HN+gueKovyWZwMMYfz6RxcMCnaDQ==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@rspack/binding-darwin-x64@1.5.0':
|
'@rspack/binding-darwin-x64@1.6.4':
|
||||||
resolution: {integrity: sha512-poGuQsGKCMQqSswgrz8X+frqMVTdmtzUDyvi/p9BLwW+2DwWgmywU8jwE+BYtjfWp1tErBSTlLxmEPQTdcIQgQ==}
|
resolution: {integrity: sha512-IHceyLDxeubqIrGz4gUqJavnygTij4vtDDE2Fkgobz7hkTJwGtD5mxBKbVNRqGvhrasVw0h9rEjR7tdbDSiUhQ==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@rspack/binding-linux-arm64-gnu@1.5.0':
|
'@rspack/binding-linux-arm64-gnu@1.6.4':
|
||||||
resolution: {integrity: sha512-Bvmk8h3tRhN9UgOtH+vK0SgFM3qEO36eJz7oddOl4lJQxBf2GNA87bGtkMtX+AVPz/PUn7r82uWxrlVNQHAbFg==}
|
resolution: {integrity: sha512-Ldpoz2wWnBaL2+XKLIOyCZMkAkd4pk/L24EVgma3SpRtwgenLEr10bQupvwGAK5OLkjayslOTZmRiAv0FH5o/w==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rspack/binding-linux-arm64-musl@1.5.0':
|
'@rspack/binding-linux-arm64-musl@1.6.4':
|
||||||
resolution: {integrity: sha512-bH7UwkbACDYT37YnN9kkhaF9niFFK9ndcdNvYFFr1oUT4W9Ie3V9b41EXijqp3pyh0mDSeeLPFY0aEx1t3e7Pw==}
|
resolution: {integrity: sha512-3fLMSDK5yMjKmx7iFbYG3P3A0xNdtmNu09v5P6hzq65tkJ3dflIt3p8DvtOTURtuSgQZV2A1LDd9hpIXdnigqA==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rspack/binding-linux-x64-gnu@1.5.0':
|
'@rspack/binding-linux-x64-gnu@1.6.4':
|
||||||
resolution: {integrity: sha512-xZ5dwNrE5KtpQyMd9israpJTcTQ3UYUUq23fTcNc79xE5aspkGixDFAYoql4YkhO0O+JWRmdSaFAn6jD+IQWQA==}
|
resolution: {integrity: sha512-5YzXUKLnaiqND05CDgkKE0WNRtC1ulkVncYs78xPikonzZmgVXa8eRaTPOZC6ZjpLR0eTsg+MSesLUsPUu27hA==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rspack/binding-linux-x64-musl@1.5.0':
|
'@rspack/binding-linux-x64-musl@1.6.4':
|
||||||
resolution: {integrity: sha512-mv65jYvcyYPkPZJ9kjSvTAcH0o7C5jfICWCQcMmN1tCGD3b8gmf9GqSZ8e+W/JkuvrJ05qTo/PvEq9nhu+pNIg==}
|
resolution: {integrity: sha512-KcSFla8a9bXG1mmV5oQ1R5h/dSXfd41/qHOsNuLqho2UCX8CVh4dezUA153dj7p1S4yOhTy6VZZi6C1szweE9A==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rspack/binding-wasm32-wasi@1.5.0':
|
'@rspack/binding-wasm32-wasi@1.6.4':
|
||||||
resolution: {integrity: sha512-8rVpl6xfaAFJgo1wCd+emksfl+/8nlehrtkmjY9bj79Ou+kp07L9e1B+UU0jfs8e7aLPntQuF68kzLHwYLzWIQ==}
|
resolution: {integrity: sha512-mfFJbDJkRy5I1iW3m0JlWbc0X8pjVd+GRUz5nhbccwEhSQOc27ao3evf7XPU4aaDxud1B3UEqYiRcRmtm1BrjA==}
|
||||||
cpu: [wasm32]
|
cpu: [wasm32]
|
||||||
|
|
||||||
'@rspack/binding-win32-arm64-msvc@1.5.0':
|
'@rspack/binding-win32-arm64-msvc@1.6.4':
|
||||||
resolution: {integrity: sha512-dWSmNm+GR6WSkOwbhlUcot4Oqwyon+1PRZ9E0vIMFHKGvESf9CQjgHAX0QE9G0kJmRM5x3I16J4x44Kw3W/98Q==}
|
resolution: {integrity: sha512-QtIqxsfeTSS1lwfaPGrPFfJ9ir/3aWZv5t3iAgYj/CNUA8MTKWt4vQKcco7NRIGK4ZLMI+dgJBFtvd/lUDMQsw==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rspack/binding-win32-ia32-msvc@1.5.0':
|
'@rspack/binding-win32-ia32-msvc@1.6.4':
|
||||||
resolution: {integrity: sha512-YtOrFEkwhO3Y3sY6Jq0OOYPY7NBTNYuwJ6epTgzPEDGs2cBnwZfzhq0jmD/koWtv1L9+twX95vKosBdauF0tNA==}
|
resolution: {integrity: sha512-HXEWGDllgh0jFwjGhkGcLqb0dzXbc/rA8vQr2JcSdC41p1DTzLgO215jWdKSIvzCzhyPh3VeQkXk76hjFB2cLQ==}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rspack/binding-win32-x64-msvc@1.5.0':
|
'@rspack/binding-win32-x64-msvc@1.6.4':
|
||||||
resolution: {integrity: sha512-V4fcPVYWJgDkIkSsFwmUdwC9lkL8+1dzDOwyTWe6KW2MYHF2D148WPHNyVVE6gum12TShpbIsh0j4NiiMhkMtw==}
|
resolution: {integrity: sha512-MAO5rOnGYoeuT2LPn/P7JVJCi3d78XoXgOq3tkGh6qXhvhkjsBRtYluWCzACXQpXfFHEWYd7uT5yHoZgxiVuoA==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rspack/binding@1.5.0':
|
'@rspack/binding@1.6.4':
|
||||||
resolution: {integrity: sha512-UGXQmwEu2gdO+tnGv2q4rOWJdWioy6dlLXeZOLYAZVh3mrfKJhZWtDEygX9hCdE5thWNRTlEvx30QQchJAszIQ==}
|
resolution: {integrity: sha512-vUxc/zUdsCuyysOvP4CTdIYxsZPb2jIXST5vrLABiTPIaHpXZ0hVdgKif2XPJwJeuCVS6w25xvyPN0mBCU0MvQ==}
|
||||||
|
|
||||||
'@rspack/core@1.5.0':
|
'@rspack/core@1.6.4':
|
||||||
resolution: {integrity: sha512-eEtiKV+CUcAtnt1K+eiHDzmBXQcNM8CfCXOzr0+gHGp4w4Zks2B8RF36sYD03MM2bg8VRXXsf0MicQ8FvRMCOg==}
|
resolution: {integrity: sha512-5F1+MQD8rfbFbUHnaiZe4jqOu9pnSb+PliqQvi0lj+uvpMpcS3sJDIs/mz6P1u87lfkfBXChIT4zSLAzeOgMWw==}
|
||||||
engines: {node: '>=18.12.0'}
|
engines: {node: '>=18.12.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@swc/helpers': '>=0.5.1'
|
'@swc/helpers': '>=0.5.1'
|
||||||
@@ -635,12 +635,11 @@ packages:
|
|||||||
'@swc/helpers':
|
'@swc/helpers':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/lite-tapable@1.0.1':
|
'@rspack/lite-tapable@1.1.0':
|
||||||
resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==}
|
resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==}
|
||||||
engines: {node: '>=16.0.0'}
|
|
||||||
|
|
||||||
'@rspack/plugin-react-refresh@1.4.3':
|
'@rspack/plugin-react-refresh@1.5.3':
|
||||||
resolution: {integrity: sha512-wZx4vWgy5oMEvgyNGd/oUKcdnKaccYWHCRkOqTdAPJC3WcytxhTX+Kady8ERurSBiLyQpoMiU3Iyd+F1Y2Arbw==}
|
resolution: {integrity: sha512-VOnQMf3YOHkTqJ0+BJbrYga4tQAWNwoAnkgwRauXB4HOyCc5wLfBs9DcOFla/2usnRT3Sq6CMVhXmdPobwAoTA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react-refresh: '>=0.10.0 <1.0.0'
|
react-refresh: '>=0.10.0 <1.0.0'
|
||||||
webpack-hot-middleware: 2.x
|
webpack-hot-middleware: 2.x
|
||||||
@@ -826,8 +825,8 @@ packages:
|
|||||||
'@tsconfig/node22@22.0.2':
|
'@tsconfig/node22@22.0.2':
|
||||||
resolution: {integrity: sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA==}
|
resolution: {integrity: sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA==}
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.0':
|
'@tybys/wasm-util@0.10.1':
|
||||||
resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==}
|
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||||
|
|
||||||
'@types/accepts@1.3.7':
|
'@types/accepts@1.3.7':
|
||||||
resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==}
|
resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==}
|
||||||
@@ -894,8 +893,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': ^18.0.0
|
'@types/react': ^18.0.0
|
||||||
|
|
||||||
'@types/react@18.3.24':
|
'@types/react@18.3.27':
|
||||||
resolution: {integrity: sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==}
|
resolution: {integrity: sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==}
|
||||||
|
|
||||||
'@types/send@0.17.5':
|
'@types/send@0.17.5':
|
||||||
resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==}
|
resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==}
|
||||||
@@ -1050,8 +1049,8 @@ packages:
|
|||||||
copy-to@2.0.1:
|
copy-to@2.0.1:
|
||||||
resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==}
|
resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==}
|
||||||
|
|
||||||
core-js@3.45.1:
|
core-js@3.46.0:
|
||||||
resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==}
|
resolution: {integrity: sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==}
|
||||||
|
|
||||||
cosmiconfig@8.3.6:
|
cosmiconfig@8.3.6:
|
||||||
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
|
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
|
||||||
@@ -1084,8 +1083,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
|
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
|
||||||
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||||
|
|
||||||
csstype@3.1.3:
|
csstype@3.2.3:
|
||||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||||
|
|
||||||
dateformat@4.6.3:
|
dateformat@4.6.3:
|
||||||
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
|
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
|
||||||
@@ -1367,6 +1366,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==}
|
resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
jiti@2.6.1:
|
||||||
|
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
joycon@3.1.1:
|
joycon@3.1.1:
|
||||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -1699,10 +1702,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
|
||||||
|
|
||||||
react-dom@18.3.1:
|
react-dom@19.2.0:
|
||||||
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
|
resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^18.3.1
|
react: ^19.2.0
|
||||||
|
|
||||||
react-focus-lock@2.13.6:
|
react-focus-lock@2.13.6:
|
||||||
resolution: {integrity: sha512-ehylFFWyYtBKXjAO9+3v8d0i+cnc1trGS0vlTGhzFW1vbFXVUTmR8s2tt/ZQG8x5hElg6rhENlLG1H3EZK0Llg==}
|
resolution: {integrity: sha512-ehylFFWyYtBKXjAO9+3v8d0i+cnc1trGS0vlTGhzFW1vbFXVUTmR8s2tt/ZQG8x5hElg6rhENlLG1H3EZK0Llg==}
|
||||||
@@ -1719,8 +1722,8 @@ packages:
|
|||||||
react-is@18.3.1:
|
react-is@18.3.1:
|
||||||
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
||||||
|
|
||||||
react-refresh@0.17.0:
|
react-refresh@0.18.0:
|
||||||
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
react-router@7.8.2:
|
react-router@7.8.2:
|
||||||
@@ -1739,8 +1742,8 @@ packages:
|
|||||||
react: '>=16.6.0'
|
react: '>=16.6.0'
|
||||||
react-dom: '>=16.6.0'
|
react-dom: '>=16.6.0'
|
||||||
|
|
||||||
react@18.3.1:
|
react@19.2.0:
|
||||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
readdirp@4.1.2:
|
readdirp@4.1.2:
|
||||||
@@ -1774,8 +1777,8 @@ packages:
|
|||||||
safer-buffer@2.1.2:
|
safer-buffer@2.1.2:
|
||||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||||
|
|
||||||
scheduler@0.23.2:
|
scheduler@0.27.0:
|
||||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||||
|
|
||||||
scroll-into-view-if-needed@2.2.31:
|
scroll-into-view-if-needed@2.2.31:
|
||||||
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
|
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
|
||||||
@@ -1991,7 +1994,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
color: 3.2.1
|
color: 3.2.1
|
||||||
|
|
||||||
'@arco-design/web-react@2.66.5(@types/react@18.3.24)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@arco-design/web-react@2.66.8(@types/react@18.3.27)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@arco-design/color': 0.4.0
|
'@arco-design/color': 0.4.0
|
||||||
'@babel/runtime': 7.28.3
|
'@babel/runtime': 7.28.3
|
||||||
@@ -2001,20 +2004,20 @@ snapshots:
|
|||||||
dayjs: 1.11.15
|
dayjs: 1.11.15
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
number-precision: 1.6.0
|
number-precision: 1.6.0
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.0(react@19.2.0)
|
||||||
react-focus-lock: 2.13.6(@types/react@18.3.24)(react@18.3.1)
|
react-focus-lock: 2.13.6(@types/react@18.3.27)(react@19.2.0)
|
||||||
react-is: 18.3.1
|
react-is: 18.3.1
|
||||||
react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
react-transition-group: 4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||||
resize-observer-polyfill: 1.5.1
|
resize-observer-polyfill: 1.5.1
|
||||||
scroll-into-view-if-needed: 2.2.31
|
scroll-into-view-if-needed: 2.2.31
|
||||||
shallowequal: 1.1.0
|
shallowequal: 1.1.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/react'
|
- '@types/react'
|
||||||
|
|
||||||
'@arco-plugins/unplugin-react@2.0.0-beta.5(@rspack/core@1.5.0(@swc/helpers@0.5.17))':
|
'@arco-plugins/unplugin-react@2.0.0-beta.5(@rspack/core@1.6.4(@swc/helpers@0.5.17))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rspack/core': 1.5.0(@swc/helpers@0.5.17)
|
'@rspack/core': 1.6.4(@swc/helpers@0.5.17)
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
|
|
||||||
'@babel/code-frame@7.27.1':
|
'@babel/code-frame@7.27.1':
|
||||||
@@ -2154,43 +2157,43 @@ snapshots:
|
|||||||
'@biomejs/cli-win32-x64@2.0.6':
|
'@biomejs/cli-win32-x64@2.0.6':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@dnd-kit/accessibility@3.1.1(react@18.3.1)':
|
'@dnd-kit/accessibility@3.1.1(react@19.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@dnd-kit/core@6.3.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/accessibility': 3.1.1(react@18.3.1)
|
'@dnd-kit/accessibility': 3.1.1(react@19.2.0)
|
||||||
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
|
'@dnd-kit/utilities': 3.2.2(react@19.2.0)
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.0(react@19.2.0)
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
'@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/core': 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@dnd-kit/core': 6.3.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||||
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
|
'@dnd-kit/utilities': 3.2.2(react@19.2.0)
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/utilities@3.2.2(react@18.3.1)':
|
'@dnd-kit/utilities@3.2.2(react@19.2.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@emnapi/core@1.4.5':
|
'@emnapi/core@1.7.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emnapi/wasi-threads': 1.0.4
|
'@emnapi/wasi-threads': 1.1.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@emnapi/runtime@1.4.5':
|
'@emnapi/runtime@1.7.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@emnapi/wasi-threads@1.0.4':
|
'@emnapi/wasi-threads@1.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
@@ -2311,36 +2314,36 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@module-federation/error-codes@0.18.0': {}
|
'@module-federation/error-codes@0.21.4': {}
|
||||||
|
|
||||||
'@module-federation/runtime-core@0.18.0':
|
'@module-federation/runtime-core@0.21.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@module-federation/error-codes': 0.18.0
|
'@module-federation/error-codes': 0.21.4
|
||||||
'@module-federation/sdk': 0.18.0
|
'@module-federation/sdk': 0.21.4
|
||||||
|
|
||||||
'@module-federation/runtime-tools@0.18.0':
|
'@module-federation/runtime-tools@0.21.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@module-federation/runtime': 0.18.0
|
'@module-federation/runtime': 0.21.4
|
||||||
'@module-federation/webpack-bundler-runtime': 0.18.0
|
'@module-federation/webpack-bundler-runtime': 0.21.4
|
||||||
|
|
||||||
'@module-federation/runtime@0.18.0':
|
'@module-federation/runtime@0.21.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@module-federation/error-codes': 0.18.0
|
'@module-federation/error-codes': 0.21.4
|
||||||
'@module-federation/runtime-core': 0.18.0
|
'@module-federation/runtime-core': 0.21.4
|
||||||
'@module-federation/sdk': 0.18.0
|
'@module-federation/sdk': 0.21.4
|
||||||
|
|
||||||
'@module-federation/sdk@0.18.0': {}
|
'@module-federation/sdk@0.21.4': {}
|
||||||
|
|
||||||
'@module-federation/webpack-bundler-runtime@0.18.0':
|
'@module-federation/webpack-bundler-runtime@0.21.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@module-federation/runtime': 0.18.0
|
'@module-federation/runtime': 0.21.4
|
||||||
'@module-federation/sdk': 0.18.0
|
'@module-federation/sdk': 0.21.4
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@1.0.3':
|
'@napi-rs/wasm-runtime@1.0.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emnapi/core': 1.4.5
|
'@emnapi/core': 1.7.1
|
||||||
'@emnapi/runtime': 1.4.5
|
'@emnapi/runtime': 1.7.1
|
||||||
'@tybys/wasm-util': 0.10.0
|
'@tybys/wasm-util': 0.10.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@prisma/client@6.15.0(prisma@6.15.0(typescript@5.9.2))(typescript@5.9.2)':
|
'@prisma/client@6.15.0(prisma@6.15.0(typescript@5.9.2))(typescript@5.9.2)':
|
||||||
@@ -2378,32 +2381,32 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/debug': 6.15.0
|
'@prisma/debug': 6.15.0
|
||||||
|
|
||||||
'@rsbuild/core@1.5.1':
|
'@rsbuild/core@1.6.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rspack/core': 1.5.0(@swc/helpers@0.5.17)
|
'@rspack/core': 1.6.4(@swc/helpers@0.5.17)
|
||||||
'@rspack/lite-tapable': 1.0.1
|
'@rspack/lite-tapable': 1.1.0
|
||||||
'@swc/helpers': 0.5.17
|
'@swc/helpers': 0.5.17
|
||||||
core-js: 3.45.1
|
core-js: 3.46.0
|
||||||
jiti: 2.5.1
|
jiti: 2.6.1
|
||||||
|
|
||||||
'@rsbuild/plugin-less@1.5.0(@rsbuild/core@1.5.1)':
|
'@rsbuild/plugin-less@1.5.0(@rsbuild/core@1.6.7)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rsbuild/core': 1.5.1
|
'@rsbuild/core': 1.6.7
|
||||||
deepmerge: 4.3.1
|
deepmerge: 4.3.1
|
||||||
reduce-configs: 1.1.1
|
reduce-configs: 1.1.1
|
||||||
|
|
||||||
'@rsbuild/plugin-react@1.3.5(@rsbuild/core@1.5.1)':
|
'@rsbuild/plugin-react@1.4.2(@rsbuild/core@1.6.7)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rsbuild/core': 1.5.1
|
'@rsbuild/core': 1.6.7
|
||||||
'@rspack/plugin-react-refresh': 1.4.3(react-refresh@0.17.0)
|
'@rspack/plugin-react-refresh': 1.5.3(react-refresh@0.18.0)
|
||||||
react-refresh: 0.17.0
|
react-refresh: 0.18.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- webpack-hot-middleware
|
- webpack-hot-middleware
|
||||||
|
|
||||||
'@rsbuild/plugin-svgr@1.2.2(@rsbuild/core@1.5.1)(typescript@5.9.2)':
|
'@rsbuild/plugin-svgr@1.2.2(@rsbuild/core@1.6.7)(typescript@5.9.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rsbuild/core': 1.5.1
|
'@rsbuild/core': 1.6.7
|
||||||
'@rsbuild/plugin-react': 1.3.5(@rsbuild/core@1.5.1)
|
'@rsbuild/plugin-react': 1.4.2(@rsbuild/core@1.6.7)
|
||||||
'@svgr/core': 8.1.0(typescript@5.9.2)
|
'@svgr/core': 8.1.0(typescript@5.9.2)
|
||||||
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))
|
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))
|
||||||
'@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))(typescript@5.9.2)
|
'@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))(typescript@5.9.2)
|
||||||
@@ -2414,66 +2417,66 @@ snapshots:
|
|||||||
- typescript
|
- typescript
|
||||||
- webpack-hot-middleware
|
- webpack-hot-middleware
|
||||||
|
|
||||||
'@rspack/binding-darwin-arm64@1.5.0':
|
'@rspack/binding-darwin-arm64@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-darwin-x64@1.5.0':
|
'@rspack/binding-darwin-x64@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-linux-arm64-gnu@1.5.0':
|
'@rspack/binding-linux-arm64-gnu@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-linux-arm64-musl@1.5.0':
|
'@rspack/binding-linux-arm64-musl@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-linux-x64-gnu@1.5.0':
|
'@rspack/binding-linux-x64-gnu@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-linux-x64-musl@1.5.0':
|
'@rspack/binding-linux-x64-musl@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-wasm32-wasi@1.5.0':
|
'@rspack/binding-wasm32-wasi@1.6.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@napi-rs/wasm-runtime': 1.0.3
|
'@napi-rs/wasm-runtime': 1.0.7
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-win32-arm64-msvc@1.5.0':
|
'@rspack/binding-win32-arm64-msvc@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-win32-ia32-msvc@1.5.0':
|
'@rspack/binding-win32-ia32-msvc@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding-win32-x64-msvc@1.5.0':
|
'@rspack/binding-win32-x64-msvc@1.6.4':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rspack/binding@1.5.0':
|
'@rspack/binding@1.6.4':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@rspack/binding-darwin-arm64': 1.5.0
|
'@rspack/binding-darwin-arm64': 1.6.4
|
||||||
'@rspack/binding-darwin-x64': 1.5.0
|
'@rspack/binding-darwin-x64': 1.6.4
|
||||||
'@rspack/binding-linux-arm64-gnu': 1.5.0
|
'@rspack/binding-linux-arm64-gnu': 1.6.4
|
||||||
'@rspack/binding-linux-arm64-musl': 1.5.0
|
'@rspack/binding-linux-arm64-musl': 1.6.4
|
||||||
'@rspack/binding-linux-x64-gnu': 1.5.0
|
'@rspack/binding-linux-x64-gnu': 1.6.4
|
||||||
'@rspack/binding-linux-x64-musl': 1.5.0
|
'@rspack/binding-linux-x64-musl': 1.6.4
|
||||||
'@rspack/binding-wasm32-wasi': 1.5.0
|
'@rspack/binding-wasm32-wasi': 1.6.4
|
||||||
'@rspack/binding-win32-arm64-msvc': 1.5.0
|
'@rspack/binding-win32-arm64-msvc': 1.6.4
|
||||||
'@rspack/binding-win32-ia32-msvc': 1.5.0
|
'@rspack/binding-win32-ia32-msvc': 1.6.4
|
||||||
'@rspack/binding-win32-x64-msvc': 1.5.0
|
'@rspack/binding-win32-x64-msvc': 1.6.4
|
||||||
|
|
||||||
'@rspack/core@1.5.0(@swc/helpers@0.5.17)':
|
'@rspack/core@1.6.4(@swc/helpers@0.5.17)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@module-federation/runtime-tools': 0.18.0
|
'@module-federation/runtime-tools': 0.21.4
|
||||||
'@rspack/binding': 1.5.0
|
'@rspack/binding': 1.6.4
|
||||||
'@rspack/lite-tapable': 1.0.1
|
'@rspack/lite-tapable': 1.1.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@swc/helpers': 0.5.17
|
'@swc/helpers': 0.5.17
|
||||||
|
|
||||||
'@rspack/lite-tapable@1.0.1': {}
|
'@rspack/lite-tapable@1.1.0': {}
|
||||||
|
|
||||||
'@rspack/plugin-react-refresh@1.4.3(react-refresh@0.17.0)':
|
'@rspack/plugin-react-refresh@1.5.3(react-refresh@0.18.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
error-stack-parser: 2.1.4
|
error-stack-parser: 2.1.4
|
||||||
html-entities: 2.6.0
|
html-entities: 2.6.0
|
||||||
react-refresh: 0.17.0
|
react-refresh: 0.18.0
|
||||||
|
|
||||||
'@standard-schema/spec@1.0.0': {}
|
'@standard-schema/spec@1.0.0': {}
|
||||||
|
|
||||||
@@ -2638,7 +2641,7 @@ snapshots:
|
|||||||
|
|
||||||
'@tsconfig/node22@22.0.2': {}
|
'@tsconfig/node22@22.0.2': {}
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.0':
|
'@tybys/wasm-util@0.10.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
@@ -2723,14 +2726,14 @@ snapshots:
|
|||||||
|
|
||||||
'@types/range-parser@1.2.7': {}
|
'@types/range-parser@1.2.7': {}
|
||||||
|
|
||||||
'@types/react-dom@18.3.7(@types/react@18.3.24)':
|
'@types/react-dom@18.3.7(@types/react@18.3.27)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.24
|
'@types/react': 18.3.27
|
||||||
|
|
||||||
'@types/react@18.3.24':
|
'@types/react@18.3.27':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/prop-types': 15.7.15
|
'@types/prop-types': 15.7.15
|
||||||
csstype: 3.1.3
|
csstype: 3.2.3
|
||||||
|
|
||||||
'@types/send@0.17.5':
|
'@types/send@0.17.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2888,7 +2891,7 @@ snapshots:
|
|||||||
|
|
||||||
copy-to@2.0.1: {}
|
copy-to@2.0.1: {}
|
||||||
|
|
||||||
core-js@3.45.1: {}
|
core-js@3.46.0: {}
|
||||||
|
|
||||||
cosmiconfig@8.3.6(typescript@5.9.2):
|
cosmiconfig@8.3.6(typescript@5.9.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2927,7 +2930,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
css-tree: 2.2.1
|
css-tree: 2.2.1
|
||||||
|
|
||||||
csstype@3.1.3: {}
|
csstype@3.2.3: {}
|
||||||
|
|
||||||
dateformat@4.6.3: {}
|
dateformat@4.6.3: {}
|
||||||
|
|
||||||
@@ -2964,7 +2967,7 @@ snapshots:
|
|||||||
dom-helpers@5.2.1:
|
dom-helpers@5.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.3
|
'@babel/runtime': 7.28.3
|
||||||
csstype: 3.1.3
|
csstype: 3.2.3
|
||||||
|
|
||||||
dom-serializer@2.0.0:
|
dom-serializer@2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3205,6 +3208,8 @@ snapshots:
|
|||||||
|
|
||||||
jiti@2.5.1: {}
|
jiti@2.5.1: {}
|
||||||
|
|
||||||
|
jiti@2.6.1: {}
|
||||||
|
|
||||||
joycon@3.1.1: {}
|
joycon@3.1.1: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
@@ -3521,55 +3526,52 @@ snapshots:
|
|||||||
defu: 6.1.4
|
defu: 6.1.4
|
||||||
destr: 2.0.5
|
destr: 2.0.5
|
||||||
|
|
||||||
react-clientside-effect@1.2.8(react@18.3.1):
|
react-clientside-effect@1.2.8(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.3
|
'@babel/runtime': 7.28.3
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
|
|
||||||
react-dom@18.3.1(react@18.3.1):
|
react-dom@19.2.0(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
react: 19.2.0
|
||||||
react: 18.3.1
|
scheduler: 0.27.0
|
||||||
scheduler: 0.23.2
|
|
||||||
|
|
||||||
react-focus-lock@2.13.6(@types/react@18.3.24)(react@18.3.1):
|
react-focus-lock@2.13.6(@types/react@18.3.27)(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.3
|
'@babel/runtime': 7.28.3
|
||||||
focus-lock: 1.3.6
|
focus-lock: 1.3.6
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
react-clientside-effect: 1.2.8(react@18.3.1)
|
react-clientside-effect: 1.2.8(react@19.2.0)
|
||||||
use-callback-ref: 1.3.3(@types/react@18.3.24)(react@18.3.1)
|
use-callback-ref: 1.3.3(@types/react@18.3.27)(react@19.2.0)
|
||||||
use-sidecar: 1.1.3(@types/react@18.3.24)(react@18.3.1)
|
use-sidecar: 1.1.3(@types/react@18.3.27)(react@19.2.0)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.24
|
'@types/react': 18.3.27
|
||||||
|
|
||||||
react-is@16.13.1: {}
|
react-is@16.13.1: {}
|
||||||
|
|
||||||
react-is@18.3.1: {}
|
react-is@18.3.1: {}
|
||||||
|
|
||||||
react-refresh@0.17.0: {}
|
react-refresh@0.18.0: {}
|
||||||
|
|
||||||
react-router@7.8.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
react-router@7.8.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
cookie: 1.0.2
|
cookie: 1.0.2
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
set-cookie-parser: 2.7.1
|
set-cookie-parser: 2.7.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.0(react@19.2.0)
|
||||||
|
|
||||||
react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
react-transition-group@4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.3
|
'@babel/runtime': 7.28.3
|
||||||
dom-helpers: 5.2.1
|
dom-helpers: 5.2.1
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.0(react@19.2.0)
|
||||||
|
|
||||||
react@18.3.1:
|
react@19.2.0: {}
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
|
|
||||||
readdirp@4.1.2: {}
|
readdirp@4.1.2: {}
|
||||||
|
|
||||||
@@ -3589,9 +3591,7 @@ snapshots:
|
|||||||
|
|
||||||
safer-buffer@2.1.2: {}
|
safer-buffer@2.1.2: {}
|
||||||
|
|
||||||
scheduler@0.23.2:
|
scheduler@0.27.0: {}
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
|
|
||||||
scroll-into-view-if-needed@2.2.31:
|
scroll-into-view-if-needed@2.2.31:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3729,20 +3729,20 @@ snapshots:
|
|||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
|
|
||||||
use-callback-ref@1.3.3(@types/react@18.3.24)(react@18.3.1):
|
use-callback-ref@1.3.3(@types/react@18.3.27)(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.24
|
'@types/react': 18.3.27
|
||||||
|
|
||||||
use-sidecar@1.1.3(@types/react@18.3.24)(react@18.3.1):
|
use-sidecar@1.1.3(@types/react@18.3.27)(react@19.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-node-es: 1.1.0
|
detect-node-es: 1.1.0
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.24
|
'@types/react': 18.3.27
|
||||||
|
|
||||||
vary@1.1.2: {}
|
vary@1.1.2: {}
|
||||||
|
|
||||||
@@ -3756,9 +3756,9 @@ snapshots:
|
|||||||
|
|
||||||
zod@4.1.5: {}
|
zod@4.1.5: {}
|
||||||
|
|
||||||
zustand@5.0.8(@types/react@18.3.24)(react@18.3.1):
|
zustand@5.0.8(@types/react@18.3.27)(react@19.2.0):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.24
|
'@types/react': 18.3.27
|
||||||
react: 18.3.1
|
react: 19.2.0
|
||||||
|
|
||||||
zx@8.8.2: {}
|
zx@8.8.2: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user