chore: join project

This commit is contained in:
xiaojunnuo
2026-02-28 00:49:02 +08:00
parent e17f381b1f
commit 6163c3f08e
14 changed files with 379 additions and 146 deletions
@@ -2,6 +2,7 @@ import { BaseController, Constants } from '@certd/lib-server';
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { AuthService } from '../../../modules/sys/authority/service/auth-service.js';
import { ProjectService } from '../../../modules/sys/enterprise/service/project-service.js';
import { ProjectMemberService } from '../../../modules/sys/enterprise/service/project-member-service.js';
/**
*/
@@ -10,6 +11,10 @@ import { ProjectService } from '../../../modules/sys/enterprise/service/project-
export class UserProjectController extends BaseController {
@Inject()
service: ProjectService;
@Inject()
projectMemberService: ProjectMemberService;
@Inject()
authService: AuthService;
@@ -17,6 +22,11 @@ export class UserProjectController extends BaseController {
return this.service;
}
/**
* 我的项目
* @param body
* @returns
*/
@Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) {
const userId= this.getUserId();
@@ -24,4 +34,74 @@ export class UserProjectController extends BaseController {
return this.ok(res);
}
/**
*
* @param body 所有项目
* @returns
*/
@Post('/all', { summary: Constants.per.authOnly })
async all(@Body(ALL) body: any) {
const userId= this.getUserId();
const res = await this.service.getAllWithStatus(userId);
return this.ok(res);
}
@Post('/applyJoin', { summary: Constants.per.authOnly })
async applyJoin(@Body(ALL) body: any) {
const userId= this.getUserId();
const res = await this.service.applyJoin({ userId, projectId: body.projectId });
return this.ok(res);
}
@Post('/updateMember', { summary: Constants.per.authOnly })
async updateMember(@Body(ALL) body: any) {
const {projectId} = await this.getProjectUserIdAdmin();
const {status,permission,userId} = body;
const member = await this.projectMemberService.findOne({
where: {
projectId,
userId,
},
});
if (!member) {
throw new Error('成员不存在');
}
const res = await this.projectMemberService.update({
id: member.id,
status,
permission,
});
return this.ok(res);
}
@Post('/approveJoin', { summary: Constants.per.authOnly })
async approveJoin(@Body(ALL) body: any) {
const {projectId} = await this.getProjectUserIdAdmin();
const {status,permission,userId} = body;
const res = await this.service.approveJoin({ userId, projectId: projectId,status,permission });
return this.ok(res);
}
@Post('/delete', { summary: Constants.per.authOnly })
async delete(@Body(ALL) body: any) {
const {projectId} = await this.getProjectUserIdAdmin();
await this.projectMemberService.deleteWhere({
projectId,
userId: this.getUserId(),
});
return this.ok();
}
@Post('/leave', { summary: Constants.per.authOnly })
async leave(@Body(ALL) body: any) {
const {projectId} = body
const userId = this.getUserId();
await this.projectMemberService.deleteWhere({
projectId,
userId,
});
return this.ok();
}
}
@@ -16,6 +16,9 @@ export class ProjectMemberEntity {
@Column({ name: 'permission', comment: '权限' })
permission: string; // read / write / admin
@Column({ name: 'status', comment: '申请状态' })
status: string; // pending / approved / rejected
@Column({
name: 'create_time',
comment: '创建时间',
@@ -34,4 +34,10 @@ export class ProjectEntity {
// user permission read write admin
permission:string
}
export type ProjectMemberItem = {
memberId: number;
status: string;
} & ProjectEntity
@@ -18,7 +18,7 @@ export class ProjectMemberService extends BaseService<ProjectMemberEntity> {
return this.repository;
}
async add(bean: ProjectMemberEntity) {
async add(bean: Partial<ProjectMemberEntity>) {
const {projectId, userId} = bean;
if (!projectId) {
throw new Error('项目ID不能为空');
@@ -38,10 +38,11 @@ export class ProjectMemberService extends BaseService<ProjectMemberEntity> {
return await super.add(bean)
}
async getByUserId(userId: number) {
async getByUserId(userId: number,status?:string) {
return await this.repository.find({
where: {
userId,
status,
},
});
}
@@ -3,7 +3,7 @@ import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { LRUCache } from 'lru-cache';
import { Repository } from 'typeorm';
import { ProjectEntity } from '../entity/project.js';
import { ProjectEntity, ProjectMemberItem } from '../entity/project.js';
import { ProjectMemberService } from './project-member-service.js';
const projectCache = new LRUCache<string, any>({
@@ -65,7 +65,7 @@ export class ProjectService extends BaseService<ProjectEntity> {
async getUserProjects(userId: number) {
const memberList = await this.projectMemberService.getByUserId(userId);
const memberList = await this.projectMemberService.getByUserId(userId,'approved');
const projectIds = memberList.map(item => item.projectId);
const projectList = await this.repository.createQueryBuilder('project')
.where(' project.disabled = false')
@@ -89,6 +89,39 @@ export class ProjectService extends BaseService<ProjectEntity> {
return projectList
}
async getAllWithStatus(userId: number) : Promise<ProjectMemberItem[]> {
let projectList:any = await this.find({
where: {
disabled: false,
userId: 0,
},
})
const projectMemberItemList:ProjectMemberItem[] = projectList
const memberList = await this.projectMemberService.getByUserId(userId);
const memberMap = memberList.reduce((prev, cur) => {
prev[cur.projectId] = cur as any;
return prev;
}, {} as Record<number, ProjectMemberItem>);
projectMemberItemList.forEach(item => {
if (item.adminId === userId) {
item.permission = 'admin';
item.status = 'approved';
item.memberId = userId
} else {
const memberItem :any = memberMap[item.id]
if (memberItem) {
item.permission = memberItem.permission;
item.status = memberItem.status;
item.memberId = memberItem.userId
}
}
})
return projectMemberItemList
}
async checkAdminPermission({ userId, projectId }: { userId: number, projectId: number }) {
return await this.checkPermission({
userId,
@@ -143,8 +176,8 @@ export class ProjectService extends BaseService<ProjectEntity> {
throw new Error('项目已禁用');
}
const member = await this.projectMemberService.getMember(projectId, userId);
if (!member) {
throw new Error(`用户${userId}不是项目${projectId}成员`);
if (!member || member.status !== 'approved') {
throw new Error(`用户${userId}不是项目${projectId}成员`);
}
savedPermission = member.permission;
}
@@ -169,4 +202,50 @@ export class ProjectService extends BaseService<ProjectEntity> {
}
return true
}
async applyJoin({ userId, projectId }: { userId: number, projectId: number }) {
const project = await this.info(projectId);
if (!project) {
throw new Error('项目不存在');
}
if (project.disabled) {
throw new Error('项目已禁用');
}
if (project.adminId === userId) {
throw new Error('申请用户已经是该项目的管理员');
}
const member = await this.projectMemberService.getMember(projectId, userId);
if (member && member.status === 'approved') {
throw new Error('用户已加入项目');
}
if (member){
this.projectMemberService.update({
id: member.id,
status: 'pending',
})
}else{
// 加入项目
await this.projectMemberService.add({
userId,
projectId,
permission: 'read',
status: 'pending',
})
}
}
async approveJoin({ userId, projectId,status,permission }: { userId: number, projectId: number,status:string,permission:string }) {
const member = await this.projectMemberService.getMember(projectId, userId);
if (!member) {
throw new Error('找不到用户的申请记录');
}
await this.projectMemberService.update({
id: member.id,
status: status,
permission,
})
}
}