[Feature]:我的空间新增分组管理 (#439)
* fix: 问卷列表更多按钮图标优化 * feat: 我的空间新增分组管理 * feat: 我的空间新增分组管理 * feat: 我的空间新增分组管理 * feat: 我的空间新增分组管理 * fix: 修改单元测试 * fix: 修改单元测试 * fix: 修改单元测试 * fix: 修改单元测试 * fix: 修改我的空间验收问题 * fix; 修改我的空间验收问题 * fix: 修改二次验收相关问题 --------- Co-authored-by: dayou <853094838@qq.com>
This commit is contained in:
parent
20f01768cf
commit
12f19559a9
@ -29,6 +29,7 @@ import { SurveyHistory } from './models/surveyHistory.entity';
|
|||||||
import { ResponseSchema } from './models/responseSchema.entity';
|
import { ResponseSchema } from './models/responseSchema.entity';
|
||||||
import { Counter } from './models/counter.entity';
|
import { Counter } from './models/counter.entity';
|
||||||
import { SurveyResponse } from './models/surveyResponse.entity';
|
import { SurveyResponse } from './models/surveyResponse.entity';
|
||||||
|
import { SurveyGroup } from './models/surveyGroup.entity';
|
||||||
import { ClientEncrypt } from './models/clientEncrypt.entity';
|
import { ClientEncrypt } from './models/clientEncrypt.entity';
|
||||||
import { Word } from './models/word.entity';
|
import { Word } from './models/word.entity';
|
||||||
import { MessagePushingTask } from './models/messagePushingTask.entity';
|
import { MessagePushingTask } from './models/messagePushingTask.entity';
|
||||||
@ -78,6 +79,7 @@ import { Logger } from './logger';
|
|||||||
SurveyConf,
|
SurveyConf,
|
||||||
SurveyHistory,
|
SurveyHistory,
|
||||||
SurveyResponse,
|
SurveyResponse,
|
||||||
|
SurveyGroup,
|
||||||
Counter,
|
Counter,
|
||||||
ResponseSchema,
|
ResponseSchema,
|
||||||
ClientEncrypt,
|
ClientEncrypt,
|
||||||
|
11
server/src/models/surveyGroup.entity.ts
Normal file
11
server/src/models/surveyGroup.entity.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Entity, Column } from 'typeorm';
|
||||||
|
import { BaseEntity } from './base.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'surveyGroup' })
|
||||||
|
export class SurveyGroup extends BaseEntity {
|
||||||
|
@Column()
|
||||||
|
ownerId: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name: string;
|
||||||
|
}
|
@ -37,6 +37,9 @@ export class SurveyMeta extends BaseEntity {
|
|||||||
@Column()
|
@Column()
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
groupId: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
curStatus: {
|
curStatus: {
|
||||||
status: RECORD_STATUS;
|
status: RECORD_STATUS;
|
||||||
|
132
server/src/modules/survey/__test/surveyGroup.controller.spec.ts
Normal file
132
server/src/modules/survey/__test/surveyGroup.controller.spec.ts
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { SurveyGroupController } from '../controllers/surveyGroup.controller';
|
||||||
|
import { SurveyGroupService } from '../services/surveyGroup.service';
|
||||||
|
import { SurveyMetaService } from '../services/surveyMeta.service';
|
||||||
|
import { HttpException } from 'src/exceptions/httpException';
|
||||||
|
import { ObjectId } from 'mongodb';
|
||||||
|
import { Logger } from 'src/logger';
|
||||||
|
|
||||||
|
jest.mock('src/guards/authentication.guard');
|
||||||
|
|
||||||
|
describe('SurveyGroupController', () => {
|
||||||
|
let controller: SurveyGroupController;
|
||||||
|
let service: SurveyGroupService;
|
||||||
|
|
||||||
|
const mockService = {
|
||||||
|
create: jest.fn(),
|
||||||
|
findAll: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
remove: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [SurveyGroupController],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: SurveyMetaService,
|
||||||
|
useValue: {
|
||||||
|
countSurveyMetaByGroupId: jest.fn().mockResolvedValue(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: SurveyGroupService,
|
||||||
|
useValue: mockService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: Logger,
|
||||||
|
useValue: {
|
||||||
|
error: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<SurveyGroupController>(SurveyGroupController);
|
||||||
|
service = module.get<SurveyGroupService>(SurveyGroupService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('create', () => {
|
||||||
|
it('should create a survey group', async () => {
|
||||||
|
const result = {
|
||||||
|
_id: new ObjectId(),
|
||||||
|
name: 'Test Group',
|
||||||
|
ownerId: '123',
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
}; // 确保这里返回的对象结构符合预期
|
||||||
|
jest.spyOn(service, 'create').mockResolvedValue(result);
|
||||||
|
|
||||||
|
// 创建模拟的请求对象
|
||||||
|
const req = {
|
||||||
|
user: {
|
||||||
|
_id: '123', // 模拟的用户ID
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(await controller.create({ name: 'Test Group' }, req)).toEqual({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
id: result._id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(service.create).toHaveBeenCalledWith({
|
||||||
|
name: 'Test Group',
|
||||||
|
ownerId: req.user._id.toString(), // 这里用模拟的 req.user._id
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findAll', () => {
|
||||||
|
it('should return a list of survey groups', async () => {
|
||||||
|
const result = { total: 0, notTotal: 0, list: [], allList: [] };
|
||||||
|
jest.spyOn(service, 'findAll').mockResolvedValue(result);
|
||||||
|
const mockReq = { user: { _id: new ObjectId() } };
|
||||||
|
const mockQue = { curPage: 1, pageSize: 10, name: '' };
|
||||||
|
const userId = mockReq.user._id.toString();
|
||||||
|
expect(await controller.findAll(mockReq, mockQue)).toEqual({
|
||||||
|
code: 200,
|
||||||
|
data: result,
|
||||||
|
});
|
||||||
|
expect(service.findAll).toHaveBeenCalledWith(userId, '', 0, 10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('update', () => {
|
||||||
|
it('should update a survey group', async () => {
|
||||||
|
const updatedFields = { name: 'xxx' };
|
||||||
|
const updatedResult = { raw: 'xxx', generatedMaps: [] };
|
||||||
|
const id = '1';
|
||||||
|
jest.spyOn(service, 'update').mockResolvedValue(updatedResult);
|
||||||
|
|
||||||
|
expect(await controller.updateOne(id, updatedFields)).toEqual({
|
||||||
|
code: 200,
|
||||||
|
ret: updatedResult,
|
||||||
|
});
|
||||||
|
expect(service.update).toHaveBeenCalledWith(id, updatedFields);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error on invalid parameter', async () => {
|
||||||
|
const id = '1';
|
||||||
|
const invalidFields: any = {};
|
||||||
|
await expect(controller.updateOne(id, invalidFields)).rejects.toThrow(
|
||||||
|
HttpException,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('remove', () => {
|
||||||
|
it('should remove a survey group', async () => {
|
||||||
|
const id = '1';
|
||||||
|
jest.spyOn(service, 'remove').mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
expect(await controller.remove(id)).toEqual({ code: 200 });
|
||||||
|
expect(service.remove).toHaveBeenCalledWith(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
102
server/src/modules/survey/__test/surveyGroup.service.spec.ts
Normal file
102
server/src/modules/survey/__test/surveyGroup.service.spec.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { SurveyGroupService } from '../services/surveyGroup.service';
|
||||||
|
import { SurveyGroup } from 'src/models/surveyGroup.entity';
|
||||||
|
import { SurveyMeta } from 'src/models/surveyMeta.entity';
|
||||||
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
describe('SurveyGroupService', () => {
|
||||||
|
let service: SurveyGroupService;
|
||||||
|
|
||||||
|
const mockSurveyGroupRepository = {
|
||||||
|
create: jest.fn(),
|
||||||
|
save: jest.fn(),
|
||||||
|
findAndCount: jest.fn(),
|
||||||
|
find: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
delete: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockSurveyMetaRepository = {
|
||||||
|
updateMany: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
SurveyGroupService,
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(SurveyGroup),
|
||||||
|
useValue: mockSurveyGroupRepository,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(SurveyMeta),
|
||||||
|
useValue: mockSurveyMetaRepository,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<SurveyGroupService>(SurveyGroupService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('create', () => {
|
||||||
|
it('should create a survey group', async () => {
|
||||||
|
const createParams = { name: 'Test Group', ownerId: '123' };
|
||||||
|
const mockSavedGroup = { ...createParams, id: '1' };
|
||||||
|
|
||||||
|
mockSurveyGroupRepository.create.mockReturnValue(mockSavedGroup);
|
||||||
|
mockSurveyGroupRepository.save.mockResolvedValue(mockSavedGroup);
|
||||||
|
|
||||||
|
expect(await service.create(createParams)).toEqual(mockSavedGroup);
|
||||||
|
expect(mockSurveyGroupRepository.create).toHaveBeenCalledWith(
|
||||||
|
createParams,
|
||||||
|
);
|
||||||
|
expect(mockSurveyGroupRepository.save).toHaveBeenCalledWith(
|
||||||
|
mockSavedGroup,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findAll', () => {
|
||||||
|
it('should return survey groups', async () => {
|
||||||
|
const list = [{ id: '1', name: 'Test Group', ownerId: '123' }];
|
||||||
|
const total = list.length;
|
||||||
|
|
||||||
|
mockSurveyGroupRepository.findAndCount.mockResolvedValue([list, total]);
|
||||||
|
mockSurveyGroupRepository.find.mockResolvedValue(list);
|
||||||
|
|
||||||
|
const result = await service.findAll('123', '', 0, 10);
|
||||||
|
expect(result).toEqual({ total, list, allList: list });
|
||||||
|
expect(mockSurveyGroupRepository.findAndCount).toHaveBeenCalled();
|
||||||
|
expect(mockSurveyGroupRepository.find).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('update', () => {
|
||||||
|
it('should update a survey group', async () => {
|
||||||
|
const id = '1';
|
||||||
|
const updatedFields = { name: 'Updated Test Group' };
|
||||||
|
|
||||||
|
await service.update(id, updatedFields);
|
||||||
|
expect(mockSurveyGroupRepository.update).toHaveBeenCalledWith(id, {
|
||||||
|
...updatedFields,
|
||||||
|
updatedAt: expect.any(Date),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('remove', () => {
|
||||||
|
it('should remove a survey group', async () => {
|
||||||
|
const id = '1';
|
||||||
|
await service.remove(id);
|
||||||
|
expect(mockSurveyMetaRepository.updateMany).toHaveBeenCalledWith(
|
||||||
|
{ groupId: id },
|
||||||
|
{ $set: { groupId: null } },
|
||||||
|
);
|
||||||
|
expect(mockSurveyGroupRepository.delete).toHaveBeenCalledWith(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -77,6 +77,7 @@ describe('SurveyMetaController', () => {
|
|||||||
survey: {
|
survey: {
|
||||||
title: reqBody.title,
|
title: reqBody.title,
|
||||||
remark: reqBody.remark,
|
remark: reqBody.remark,
|
||||||
|
groupId: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ describe('SurveyMetaService', () => {
|
|||||||
createMethod: params.createMethod,
|
createMethod: params.createMethod,
|
||||||
createFrom: params.createFrom,
|
createFrom: params.createFrom,
|
||||||
workspaceId: params.workspaceId,
|
workspaceId: params.workspaceId,
|
||||||
|
groupId: null,
|
||||||
});
|
});
|
||||||
expect(surveyRepository.save).toHaveBeenCalledWith(newSurvey);
|
expect(surveyRepository.save).toHaveBeenCalledWith(newSurvey);
|
||||||
expect(result).toEqual(newSurvey);
|
expect(result).toEqual(newSurvey);
|
||||||
|
@ -78,7 +78,7 @@ export class SurveyController {
|
|||||||
throw new HttpException('参数错误', EXCEPTION_CODE.PARAMETER_ERROR);
|
throw new HttpException('参数错误', EXCEPTION_CODE.PARAMETER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title, remark, createMethod, createFrom } = value;
|
const { title, remark, createMethod, createFrom, groupId } = value;
|
||||||
|
|
||||||
let surveyType = '',
|
let surveyType = '',
|
||||||
workspaceId = null;
|
workspaceId = null;
|
||||||
@ -100,6 +100,7 @@ export class SurveyController {
|
|||||||
createMethod,
|
createMethod,
|
||||||
createFrom,
|
createFrom,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
groupId,
|
||||||
});
|
});
|
||||||
await this.surveyConfService.createSurveyConf({
|
await this.surveyConfService.createSurveyConf({
|
||||||
surveyId: surveyMeta._id.toString(),
|
surveyId: surveyMeta._id.toString(),
|
||||||
|
145
server/src/modules/survey/controllers/surveyGroup.controller.ts
Normal file
145
server/src/modules/survey/controllers/surveyGroup.controller.ts
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Post,
|
||||||
|
Delete,
|
||||||
|
Body,
|
||||||
|
Param,
|
||||||
|
UseGuards,
|
||||||
|
Request,
|
||||||
|
HttpCode,
|
||||||
|
Query,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { Authentication } from 'src/guards/authentication.guard';
|
||||||
|
import { SurveyMetaService } from 'src/modules/survey/services/surveyMeta.service';
|
||||||
|
import { SurveyGroupService } from '../services/surveyGroup.service';
|
||||||
|
|
||||||
|
import { Logger } from 'src/logger';
|
||||||
|
import { HttpException } from 'src/exceptions/httpException';
|
||||||
|
import { EXCEPTION_CODE } from 'src/enums/exceptionCode';
|
||||||
|
|
||||||
|
import { CreateSurveyGroupDto } from '../dto/createSurveyGroup.dto';
|
||||||
|
import { UpdateSurveyGroupDto } from '../dto/updateSurveyGroup.dto';
|
||||||
|
import { GetGroupListDto } from '../dto/getGroupList.dto';
|
||||||
|
|
||||||
|
@ApiTags('surveyGroup')
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(Authentication)
|
||||||
|
@Controller('api/surveyGroup')
|
||||||
|
export class SurveyGroupController {
|
||||||
|
constructor(
|
||||||
|
private readonly surveyMetaService: SurveyMetaService,
|
||||||
|
private readonly SurveyGroupService: SurveyGroupService,
|
||||||
|
private readonly logger: Logger,
|
||||||
|
) {}
|
||||||
|
@Post()
|
||||||
|
@HttpCode(200)
|
||||||
|
async create(
|
||||||
|
@Body()
|
||||||
|
reqBody: CreateSurveyGroupDto,
|
||||||
|
@Request()
|
||||||
|
req,
|
||||||
|
) {
|
||||||
|
const { error, value } = CreateSurveyGroupDto.validate(reqBody);
|
||||||
|
if (error) {
|
||||||
|
this.logger.error(`createSurveyGroup_parameter error: ${error.message}`);
|
||||||
|
throw new HttpException('参数错误', EXCEPTION_CODE.PARAMETER_ERROR);
|
||||||
|
}
|
||||||
|
const userId = req.user._id.toString();
|
||||||
|
const ret = await this.SurveyGroupService.create({
|
||||||
|
name: value.name,
|
||||||
|
ownerId: userId,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
id: ret._id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@HttpCode(200)
|
||||||
|
async findAll(@Request() req, @Query() queryInfo: GetGroupListDto) {
|
||||||
|
const { value, error } = GetGroupListDto.validate(queryInfo);
|
||||||
|
if (error) {
|
||||||
|
this.logger.error(`GetGroupListDto validate failed: ${error.message}`);
|
||||||
|
throw new HttpException(
|
||||||
|
`参数错误: 请联系管理员`,
|
||||||
|
EXCEPTION_CODE.PARAMETER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const userId = req.user._id.toString();
|
||||||
|
const curPage = Number(value.curPage);
|
||||||
|
const pageSize = Number(value.pageSize);
|
||||||
|
const skip = (curPage - 1) * pageSize;
|
||||||
|
const { total, list, allList } = await this.SurveyGroupService.findAll(
|
||||||
|
userId,
|
||||||
|
value.name,
|
||||||
|
skip,
|
||||||
|
pageSize,
|
||||||
|
);
|
||||||
|
const groupIdList = list.map((item) => item._id.toString());
|
||||||
|
const surveyTotalList = await Promise.all(
|
||||||
|
groupIdList.map((item) => {
|
||||||
|
return this.surveyMetaService.countSurveyMetaByGroupId({
|
||||||
|
groupId: item,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const surveyTotalMap = groupIdList.reduce((pre, cur, index) => {
|
||||||
|
const total = surveyTotalList[index];
|
||||||
|
pre[cur] = total;
|
||||||
|
return pre;
|
||||||
|
}, {});
|
||||||
|
const notTotal = await this.surveyMetaService.countSurveyMetaByGroupId({
|
||||||
|
groupId: null,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
total,
|
||||||
|
list: list.map((item) => {
|
||||||
|
const id = item._id.toString();
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
createdAt: moment(item.createdAt).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
surveyTotal: surveyTotalMap[id] || 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
allList,
|
||||||
|
notTotal,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id')
|
||||||
|
@HttpCode(200)
|
||||||
|
async updateOne(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body()
|
||||||
|
reqBody: UpdateSurveyGroupDto,
|
||||||
|
) {
|
||||||
|
const { error, value } = UpdateSurveyGroupDto.validate(reqBody);
|
||||||
|
if (error) {
|
||||||
|
this.logger.error(`createSurveyGroup_parameter error: ${error.message}`);
|
||||||
|
throw new HttpException('参数错误', EXCEPTION_CODE.PARAMETER_ERROR);
|
||||||
|
}
|
||||||
|
const ret = await this.SurveyGroupService.update(id, value);
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
ret,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
@HttpCode(200)
|
||||||
|
async remove(@Param('id') id: string) {
|
||||||
|
await this.SurveyGroupService.remove(id);
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,7 @@ export class SurveyMetaController {
|
|||||||
title: Joi.string().required(),
|
title: Joi.string().required(),
|
||||||
remark: Joi.string().allow(null, '').default(''),
|
remark: Joi.string().allow(null, '').default(''),
|
||||||
surveyId: Joi.string().required(),
|
surveyId: Joi.string().required(),
|
||||||
|
groupId: Joi.string().allow(null, ''),
|
||||||
}).validate(reqBody, { allowUnknown: true });
|
}).validate(reqBody, { allowUnknown: true });
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -57,6 +58,8 @@ export class SurveyMetaController {
|
|||||||
const survey = req.surveyMeta;
|
const survey = req.surveyMeta;
|
||||||
survey.title = value.title;
|
survey.title = value.title;
|
||||||
survey.remark = value.remark;
|
survey.remark = value.remark;
|
||||||
|
survey.groupId =
|
||||||
|
value.groupId && value.groupId !== '' ? value.groupId : null;
|
||||||
|
|
||||||
await this.surveyMetaService.editSurveyMeta({
|
await this.surveyMetaService.editSurveyMeta({
|
||||||
survey,
|
survey,
|
||||||
@ -86,7 +89,7 @@ export class SurveyMetaController {
|
|||||||
this.logger.error(error.message);
|
this.logger.error(error.message);
|
||||||
throw new HttpException('参数有误', EXCEPTION_CODE.PARAMETER_ERROR);
|
throw new HttpException('参数有误', EXCEPTION_CODE.PARAMETER_ERROR);
|
||||||
}
|
}
|
||||||
const { curPage, pageSize, workspaceId } = value;
|
const { curPage, pageSize, workspaceId, groupId } = value;
|
||||||
let filter = {},
|
let filter = {},
|
||||||
order = {};
|
order = {};
|
||||||
if (value.filter) {
|
if (value.filter) {
|
||||||
@ -120,6 +123,7 @@ export class SurveyMetaController {
|
|||||||
filter,
|
filter,
|
||||||
order,
|
order,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
groupId,
|
||||||
surveyIdList,
|
surveyIdList,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
@ -20,6 +20,9 @@ export class CreateSurveyDto {
|
|||||||
@ApiProperty({ description: '问卷创建在哪个空间下', required: false })
|
@ApiProperty({ description: '问卷创建在哪个空间下', required: false })
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '问卷创建在哪个分组下', required: false })
|
||||||
|
groupId?: string;
|
||||||
|
|
||||||
static validate(data) {
|
static validate(data) {
|
||||||
return Joi.object({
|
return Joi.object({
|
||||||
title: Joi.string().required(),
|
title: Joi.string().required(),
|
||||||
@ -36,6 +39,7 @@ export class CreateSurveyDto {
|
|||||||
otherwise: Joi.allow(null),
|
otherwise: Joi.allow(null),
|
||||||
}),
|
}),
|
||||||
workspaceId: Joi.string().allow(null, ''),
|
workspaceId: Joi.string().allow(null, ''),
|
||||||
|
groupId: Joi.string().allow(null, ''),
|
||||||
}).validate(data);
|
}).validate(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
server/src/modules/survey/dto/createSurveyGroup.dto.ts
Normal file
13
server/src/modules/survey/dto/createSurveyGroup.dto.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import Joi from 'joi';
|
||||||
|
|
||||||
|
export class CreateSurveyGroupDto {
|
||||||
|
@ApiProperty({ description: '分组名称', required: true })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
static validate(data) {
|
||||||
|
return Joi.object({
|
||||||
|
name: Joi.string().required(),
|
||||||
|
}).validate(data);
|
||||||
|
}
|
||||||
|
}
|
21
server/src/modules/survey/dto/getGroupList.dto.ts
Normal file
21
server/src/modules/survey/dto/getGroupList.dto.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import Joi from 'joi';
|
||||||
|
|
||||||
|
export class GetGroupListDto {
|
||||||
|
@ApiProperty({ description: '当前页码', required: true })
|
||||||
|
curPage: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '分页', required: false })
|
||||||
|
pageSize: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '空间名称', required: false })
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
static validate(data: Partial<GetGroupListDto>): Joi.ValidationResult {
|
||||||
|
return Joi.object({
|
||||||
|
curPage: Joi.number().required(),
|
||||||
|
pageSize: Joi.number().allow(null).default(10),
|
||||||
|
name: Joi.string().allow(null, '').optional(),
|
||||||
|
}).validate(data);
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,9 @@ export class GetSurveyListDto {
|
|||||||
@ApiProperty({ description: '空间id', required: false })
|
@ApiProperty({ description: '空间id', required: false })
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '分组id', required: false })
|
||||||
|
groupId?: string;
|
||||||
|
|
||||||
static validate(data) {
|
static validate(data) {
|
||||||
return Joi.object({
|
return Joi.object({
|
||||||
curPage: Joi.number().required(),
|
curPage: Joi.number().required(),
|
||||||
@ -24,6 +27,7 @@ export class GetSurveyListDto {
|
|||||||
filter: Joi.string().allow(null),
|
filter: Joi.string().allow(null),
|
||||||
order: Joi.string().allow(null),
|
order: Joi.string().allow(null),
|
||||||
workspaceId: Joi.string().allow(null, ''),
|
workspaceId: Joi.string().allow(null, ''),
|
||||||
|
groupId: Joi.string().allow(null, ''),
|
||||||
}).validate(data);
|
}).validate(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
server/src/modules/survey/dto/updateSurveyGroup.dto.ts
Normal file
13
server/src/modules/survey/dto/updateSurveyGroup.dto.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import Joi from 'joi';
|
||||||
|
|
||||||
|
export class UpdateSurveyGroupDto {
|
||||||
|
@ApiProperty({ description: '分组名称', required: true })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
static validate(data) {
|
||||||
|
return Joi.object({
|
||||||
|
name: Joi.string().required(),
|
||||||
|
}).validate(data);
|
||||||
|
}
|
||||||
|
}
|
56
server/src/modules/survey/services/surveyGroup.service.ts
Normal file
56
server/src/modules/survey/services/surveyGroup.service.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { MongoRepository } from 'typeorm';
|
||||||
|
|
||||||
|
import { SurveyGroup } from 'src/models/surveyGroup.entity';
|
||||||
|
import { SurveyMeta } from 'src/models/surveyMeta.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SurveyGroupService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(SurveyGroup)
|
||||||
|
private readonly SurveyGroup: MongoRepository<SurveyGroup>,
|
||||||
|
@InjectRepository(SurveyMeta)
|
||||||
|
private surveyMetaRepository: MongoRepository<SurveyMeta>,
|
||||||
|
) {}
|
||||||
|
create(params: { name: string; ownerId: string }) {
|
||||||
|
const newGroup = this.SurveyGroup.create({
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
return this.SurveyGroup.save(newGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll(userId: string, name: string, skip: number, pageSize: number) {
|
||||||
|
const [list, total] = await this.SurveyGroup.findAndCount({
|
||||||
|
skip: skip,
|
||||||
|
take: pageSize,
|
||||||
|
where: name
|
||||||
|
? { name: { $regex: name, $options: 'i' }, ownerId: userId }
|
||||||
|
: { ownerId: userId },
|
||||||
|
order: {
|
||||||
|
createdAt: -1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const allList = await this.SurveyGroup.find({
|
||||||
|
where: { ownerId: userId },
|
||||||
|
select: ['_id', 'name'],
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
total,
|
||||||
|
list,
|
||||||
|
allList,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: string, updatedFields: Partial<SurveyGroup>) {
|
||||||
|
updatedFields.updatedAt = new Date();
|
||||||
|
return this.SurveyGroup.update(id, updatedFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: string) {
|
||||||
|
const query = { groupId: id };
|
||||||
|
const update = { $set: { groupId: null } };
|
||||||
|
await this.surveyMetaRepository.updateMany(query, update);
|
||||||
|
return this.SurveyGroup.delete(id);
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,7 @@ export class SurveyMetaService {
|
|||||||
createMethod: string;
|
createMethod: string;
|
||||||
createFrom: string;
|
createFrom: string;
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
|
groupId?: string;
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
@ -57,6 +58,7 @@ export class SurveyMetaService {
|
|||||||
createFrom,
|
createFrom,
|
||||||
userId,
|
userId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
groupId,
|
||||||
} = params;
|
} = params;
|
||||||
const surveyPath = await this.getNewSurveyPath();
|
const surveyPath = await this.getNewSurveyPath();
|
||||||
const newSurvey = this.surveyRepository.create({
|
const newSurvey = this.surveyRepository.create({
|
||||||
@ -71,6 +73,7 @@ export class SurveyMetaService {
|
|||||||
createMethod,
|
createMethod,
|
||||||
createFrom,
|
createFrom,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
groupId: groupId && groupId !== '' ? groupId : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return await this.surveyRepository.save(newSurvey);
|
return await this.surveyRepository.save(newSurvey);
|
||||||
@ -143,10 +146,18 @@ export class SurveyMetaService {
|
|||||||
filter: Record<string, any>;
|
filter: Record<string, any>;
|
||||||
order: Record<string, any>;
|
order: Record<string, any>;
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
|
groupId?: string;
|
||||||
surveyIdList?: Array<string>;
|
surveyIdList?: Array<string>;
|
||||||
}): Promise<{ data: any[]; count: number }> {
|
}): Promise<{ data: any[]; count: number }> {
|
||||||
const { pageNum, pageSize, userId, username, workspaceId, surveyIdList } =
|
const {
|
||||||
condition;
|
pageNum,
|
||||||
|
pageSize,
|
||||||
|
userId,
|
||||||
|
username,
|
||||||
|
workspaceId,
|
||||||
|
groupId,
|
||||||
|
surveyIdList,
|
||||||
|
} = condition;
|
||||||
const skip = (pageNum - 1) * pageSize;
|
const skip = (pageNum - 1) * pageSize;
|
||||||
try {
|
try {
|
||||||
const query: Record<string, any> = Object.assign(
|
const query: Record<string, any> = Object.assign(
|
||||||
@ -160,6 +171,15 @@ export class SurveyMetaService {
|
|||||||
if (condition.filter['curStatus.status']) {
|
if (condition.filter['curStatus.status']) {
|
||||||
query['subStatus.status'] = RECORD_SUB_STATUS.DEFAULT;
|
query['subStatus.status'] = RECORD_SUB_STATUS.DEFAULT;
|
||||||
}
|
}
|
||||||
|
if (groupId && groupId !== 'all') {
|
||||||
|
query.groupId =
|
||||||
|
groupId === 'nogrouped'
|
||||||
|
? {
|
||||||
|
$exists: true,
|
||||||
|
$eq: null,
|
||||||
|
}
|
||||||
|
: groupId;
|
||||||
|
}
|
||||||
if (workspaceId) {
|
if (workspaceId) {
|
||||||
query.workspaceId = workspaceId;
|
query.workspaceId = workspaceId;
|
||||||
} else {
|
} else {
|
||||||
@ -228,4 +248,21 @@ export class SurveyMetaService {
|
|||||||
});
|
});
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
async countSurveyMetaByGroupId({ groupId }) {
|
||||||
|
const total = await this.surveyRepository.count({
|
||||||
|
groupId,
|
||||||
|
$or: [
|
||||||
|
{ workspaceId: { $exists: false } },
|
||||||
|
{ workspaceId: null },
|
||||||
|
{ workspaceId: '' },
|
||||||
|
],
|
||||||
|
isDeleted: {
|
||||||
|
$ne: true,
|
||||||
|
},
|
||||||
|
'curStatus.status': {
|
||||||
|
$ne: RECORD_STATUS.REMOVED,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return total;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,13 @@ import { SurveyUIController } from './controllers/surveyUI.controller';
|
|||||||
import { CollaboratorController } from './controllers/collaborator.controller';
|
import { CollaboratorController } from './controllers/collaborator.controller';
|
||||||
import { DownloadTaskController } from './controllers/downloadTask.controller';
|
import { DownloadTaskController } from './controllers/downloadTask.controller';
|
||||||
import { SessionController } from './controllers/session.controller';
|
import { SessionController } from './controllers/session.controller';
|
||||||
|
import { SurveyGroupController } from './controllers/surveyGroup.controller';
|
||||||
|
|
||||||
import { SurveyConf } from 'src/models/surveyConf.entity';
|
import { SurveyConf } from 'src/models/surveyConf.entity';
|
||||||
import { SurveyHistory } from 'src/models/surveyHistory.entity';
|
import { SurveyHistory } from 'src/models/surveyHistory.entity';
|
||||||
import { SurveyMeta } from 'src/models/surveyMeta.entity';
|
import { SurveyMeta } from 'src/models/surveyMeta.entity';
|
||||||
import { SurveyResponse } from 'src/models/surveyResponse.entity';
|
import { SurveyResponse } from 'src/models/surveyResponse.entity';
|
||||||
|
import { SurveyGroup } from 'src/models/surveyGroup.entity';
|
||||||
import { Word } from 'src/models/word.entity';
|
import { Word } from 'src/models/word.entity';
|
||||||
import { Collaborator } from 'src/models/collaborator.entity';
|
import { Collaborator } from 'src/models/collaborator.entity';
|
||||||
import { DownloadTask } from 'src/models/downloadTask.entity';
|
import { DownloadTask } from 'src/models/downloadTask.entity';
|
||||||
@ -38,6 +40,7 @@ import { CounterService } from '../surveyResponse/services/counter.service';
|
|||||||
import { FileService } from '../file/services/file.service';
|
import { FileService } from '../file/services/file.service';
|
||||||
import { DownloadTaskService } from './services/downloadTask.service';
|
import { DownloadTaskService } from './services/downloadTask.service';
|
||||||
import { SessionService } from './services/session.service';
|
import { SessionService } from './services/session.service';
|
||||||
|
import { SurveyGroupService } from './services/surveyGroup.service';
|
||||||
import { Session } from 'src/models/session.entity';
|
import { Session } from 'src/models/session.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@ -52,6 +55,7 @@ import { Session } from 'src/models/session.entity';
|
|||||||
Counter,
|
Counter,
|
||||||
DownloadTask,
|
DownloadTask,
|
||||||
Session,
|
Session,
|
||||||
|
SurveyGroup,
|
||||||
]),
|
]),
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
SurveyResponseModule,
|
SurveyResponseModule,
|
||||||
@ -68,6 +72,7 @@ import { Session } from 'src/models/session.entity';
|
|||||||
CollaboratorController,
|
CollaboratorController,
|
||||||
DownloadTaskController,
|
DownloadTaskController,
|
||||||
SessionController,
|
SessionController,
|
||||||
|
SurveyGroupController,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
DataStatisticService,
|
DataStatisticService,
|
||||||
@ -82,6 +87,7 @@ import { Session } from 'src/models/session.entity';
|
|||||||
DownloadTaskService,
|
DownloadTaskService,
|
||||||
FileService,
|
FileService,
|
||||||
SessionService,
|
SessionService,
|
||||||
|
SurveyGroupService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SurveyModule {}
|
export class SurveyModule {}
|
||||||
|
@ -78,3 +78,21 @@ export const getCollaboratorPermissions = (surveyId: string) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createGroup = ({ name }: any) => {
|
||||||
|
return axios.post('surveyGroup', { name })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateGroup = ({ _id, name }: any) => {
|
||||||
|
return axios.post(`/surveyGroup/${_id}`, { name })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getGroupList = (params: any) => {
|
||||||
|
return axios.get('/surveyGroup', {
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteGroup = (id: string) => {
|
||||||
|
return axios.delete(`/surveyGroup/${id}`)
|
||||||
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import axios from './base'
|
import axios from './base'
|
||||||
|
|
||||||
export const getSurveyList = ({ curPage, filter, order, workspaceId }) => {
|
export const getSurveyList = ({ curPage, filter, order, workspaceId, groupId }) => {
|
||||||
return axios.get('/survey/getList', {
|
return axios.get('/survey/getList', {
|
||||||
params: {
|
params: {
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
curPage,
|
curPage,
|
||||||
filter,
|
filter,
|
||||||
order,
|
order,
|
||||||
workspaceId
|
workspaceId,
|
||||||
|
groupId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,25 @@ export const spaceListConfig = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const groupListConfig = {
|
||||||
|
name: {
|
||||||
|
title: '分组名称',
|
||||||
|
key: 'name',
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
surveyTotal: {
|
||||||
|
title: '问卷数',
|
||||||
|
key: 'surveyTotal',
|
||||||
|
width: 150,
|
||||||
|
tip: true
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'createdAt',
|
||||||
|
minWidth: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const fieldConfig = {
|
export const fieldConfig = {
|
||||||
type: {
|
type: {
|
||||||
title: '类型',
|
title: '类型',
|
||||||
@ -92,6 +111,16 @@ export const noSpaceSearchDataConfig = {
|
|||||||
desc: '可以更换条件查询试试',
|
desc: '可以更换条件查询试试',
|
||||||
img: '/imgs/icons/list-empty.webp'
|
img: '/imgs/icons/list-empty.webp'
|
||||||
}
|
}
|
||||||
|
export const noGroupDataConfig = {
|
||||||
|
title: '您还没有创建问卷分组',
|
||||||
|
desc: '赶快点击右上角立即创建问卷分组吧!',
|
||||||
|
img: '/imgs/icons/list-empty.webp'
|
||||||
|
}
|
||||||
|
export const noGroupSearchDataConfig = {
|
||||||
|
title: '没有满足该查询条件的问卷分组哦',
|
||||||
|
desc: '可以更换条件查询试试',
|
||||||
|
img: '/imgs/icons/list-empty.webp'
|
||||||
|
}
|
||||||
export const noSearchDataConfig = {
|
export const noSearchDataConfig = {
|
||||||
title: '没有满足该查询条件的问卷',
|
title: '没有满足该查询条件的问卷',
|
||||||
desc: '可以更换条件查询试试',
|
desc: '可以更换条件查询试试',
|
||||||
|
@ -26,6 +26,19 @@
|
|||||||
/>
|
/>
|
||||||
<p class="form-item-tip">备注仅自己可见</p>
|
<p class="form-item-tip">备注仅自己可见</p>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item prop="groupId" label="问卷分组" v-if="menuType === MenuType.PersonalGroup">
|
||||||
|
<el-select
|
||||||
|
v-model="form.groupId"
|
||||||
|
placeholder="未分组"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in groupAllList"
|
||||||
|
:key="item?._id"
|
||||||
|
:label="item?.name"
|
||||||
|
:value="item?._id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button class="create-btn" type="primary" @click="submit" :loading="!canSubmit">
|
<el-button class="create-btn" type="primary" @click="submit" :loading="!canSubmit">
|
||||||
开始创建
|
开始创建
|
||||||
@ -37,11 +50,13 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, computed, toRefs } from 'vue'
|
import { ref, reactive, computed, toRefs } from 'vue'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
import { createSurvey } from '@/management/api/survey'
|
import { createSurvey } from '@/management/api/survey'
|
||||||
import { SURVEY_TYPE_LIST } from '../types'
|
import { SURVEY_TYPE_LIST } from '../types'
|
||||||
|
import { MenuType, GroupState } from '@/management/utils/workSpace'
|
||||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -53,6 +68,8 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const workSpaceStore = useWorkSpaceStore()
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
|
const { groupAllList, menuType, groupId, workSpaceId } = storeToRefs(workSpaceStore)
|
||||||
|
|
||||||
const ruleForm = ref<any>(null)
|
const ruleForm = ref<any>(null)
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -62,7 +79,8 @@ const state = reactive({
|
|||||||
canSubmit: true,
|
canSubmit: true,
|
||||||
form: {
|
form: {
|
||||||
title: '问卷调研',
|
title: '问卷调研',
|
||||||
remark: '问卷调研'
|
remark: '问卷调研',
|
||||||
|
groupId: groupId.value == GroupState.All || groupId.value == GroupState.Not ? '' : groupId.value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const { rules, canSubmit, form } = toRefs(state)
|
const { rules, canSubmit, form } = toRefs(state)
|
||||||
@ -92,8 +110,8 @@ const submit = () => {
|
|||||||
surveyType: selectType,
|
surveyType: selectType,
|
||||||
...state.form
|
...state.form
|
||||||
}
|
}
|
||||||
if (workSpaceStore.workSpaceId) {
|
if (workSpaceId.value) {
|
||||||
payload.workspaceId = workSpaceStore.workSpaceId
|
payload.workspaceId = workSpaceId.value
|
||||||
}
|
}
|
||||||
const res: any = await createSurvey(payload)
|
const res: any = await createSurvey(payload)
|
||||||
if (res?.code === 200 && res?.data?.id) {
|
if (res?.code === 200 && res?.data?.id) {
|
||||||
|
@ -98,6 +98,8 @@
|
|||||||
:type="modifyType"
|
:type="modifyType"
|
||||||
:visible="showModify"
|
:visible="showModify"
|
||||||
:question-info="questionInfo"
|
:question-info="questionInfo"
|
||||||
|
:group-all-list="groupAllList"
|
||||||
|
:menu-type="menuType"
|
||||||
@on-close-codify="onCloseModify"
|
@on-close-codify="onCloseModify"
|
||||||
/>
|
/>
|
||||||
<CooperModify :modifyId="cooperId" :visible="cooperModify" @on-close-codify="onCooperClose" />
|
<CooperModify :modifyId="cooperId" :visible="cooperModify" @on-close-codify="onCooperClose" />
|
||||||
@ -142,7 +144,7 @@ import {
|
|||||||
|
|
||||||
const surveyListStore = useSurveyListStore()
|
const surveyListStore = useSurveyListStore()
|
||||||
const workSpaceStore = useWorkSpaceStore()
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
const { workSpaceId } = storeToRefs(workSpaceStore)
|
const { workSpaceId, groupAllList, menuType } = storeToRefs(workSpaceStore)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
loading: {
|
loading: {
|
||||||
@ -363,7 +365,6 @@ const onDelete = async (row) => {
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('取消删除')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,6 +372,8 @@ const onDelete = async (row) => {
|
|||||||
if (res.code === CODE_MAP.SUCCESS) {
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
ElMessage.success('删除成功')
|
ElMessage.success('删除成功')
|
||||||
onRefresh()
|
onRefresh()
|
||||||
|
workSpaceStore.getGroupList()
|
||||||
|
workSpaceStore.getSpaceList()
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.errmsg || '删除失败')
|
ElMessage.error(res.errmsg || '删除失败')
|
||||||
}
|
}
|
||||||
@ -409,6 +412,8 @@ const onCloseModify = (type) => {
|
|||||||
questionInfo.value = {}
|
questionInfo.value = {}
|
||||||
if (type === 'update') {
|
if (type === 'update') {
|
||||||
onRefresh()
|
onRefresh()
|
||||||
|
workSpaceStore.getGroupList()
|
||||||
|
workSpaceStore.getSpaceList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onRowClick = (row) => {
|
const onRowClick = (row) => {
|
||||||
|
245
web/src/management/pages/list/components/GroupList.vue
Normal file
245
web/src/management/pages/list/components/GroupList.vue
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
<template>
|
||||||
|
<div class="search">
|
||||||
|
<TextSearch placeholder="请输入分组名称" :value="searchVal" @search="onSearchText" />
|
||||||
|
</div>
|
||||||
|
<div class="list-wrap" v-if="props.total">
|
||||||
|
<el-table
|
||||||
|
v-if="props.total"
|
||||||
|
ref="multipleListTable"
|
||||||
|
class="list-table"
|
||||||
|
:data="data"
|
||||||
|
empty-text="暂无数据"
|
||||||
|
row-key="_id"
|
||||||
|
header-row-class-name="tableview-header"
|
||||||
|
row-class-name="tableview-row"
|
||||||
|
cell-class-name="tableview-cell"
|
||||||
|
v-loading="loading"
|
||||||
|
:height="550"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-table-column column-key="space" width="20" />
|
||||||
|
<el-table-column
|
||||||
|
v-for="field in fieldList"
|
||||||
|
:key="(field as any)?.key"
|
||||||
|
:label="(field as any).title"
|
||||||
|
:column-key="(field as any).key"
|
||||||
|
:width="(field as any).width"
|
||||||
|
:min-width="(field as any).width || (field as any).minWidth"
|
||||||
|
class-name="link"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="(field as any).comp">
|
||||||
|
<component :is="(field as any).comp" type="table" :value="scope.row" />
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span class="cell-span">{{ scope.row[(field as any).key] }}</span>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="操作"
|
||||||
|
:width="200"
|
||||||
|
label-class-name="operation"
|
||||||
|
class-name="table-options"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="space-tool-bar">
|
||||||
|
<ToolBar
|
||||||
|
:data="scope.row"
|
||||||
|
:tool-width="50"
|
||||||
|
:tools="tools"
|
||||||
|
@click="handleClick"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<EmptyIndex :data="!searchVal ? noGroupDataConfig : noGroupSearchDataConfig" />
|
||||||
|
</div>
|
||||||
|
<div class="list-pagination">
|
||||||
|
<el-pagination
|
||||||
|
v-if="props.total"
|
||||||
|
v-model:current-page="curPage"
|
||||||
|
background
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
layout="prev, pager, next"
|
||||||
|
:total="props.total"
|
||||||
|
>
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
<GroupModify
|
||||||
|
v-if="showGroupModify"
|
||||||
|
type="edit"
|
||||||
|
:visible="showGroupModify"
|
||||||
|
@on-close-codify="onCloseModify"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { ElMessageBox } from 'element-plus'
|
||||||
|
import 'element-plus/theme-chalk/src/message-box.scss'
|
||||||
|
import { get, map } from 'lodash-es'
|
||||||
|
import {
|
||||||
|
noGroupDataConfig,
|
||||||
|
noGroupSearchDataConfig,
|
||||||
|
groupListConfig
|
||||||
|
} from '@/management/config/listConfig'
|
||||||
|
import { MenuType } from '@/management/utils/workSpace'
|
||||||
|
import GroupModify from './GroupModify.vue'
|
||||||
|
import TextSearch from '@/management/pages/list/components/TextSearch.vue'
|
||||||
|
import EmptyIndex from '@/management/components/EmptyIndex.vue'
|
||||||
|
import ToolBar from './ToolBar.vue'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
import { useSurveyListStore } from '@/management/stores/surveyList'
|
||||||
|
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
|
const surveyListStore = useSurveyListStore()
|
||||||
|
|
||||||
|
const showGroupModify = ref(false)
|
||||||
|
const props = defineProps({
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
const fields = ['name', 'surveyTotal', 'createdAt']
|
||||||
|
const fieldList = computed(() => {
|
||||||
|
return map(fields, (f) => {
|
||||||
|
return get(groupListConfig, f, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const tools = ref([{
|
||||||
|
key: 'open',
|
||||||
|
label: '进入'
|
||||||
|
}, {
|
||||||
|
key: 'modify',
|
||||||
|
label: '管理'
|
||||||
|
}, {
|
||||||
|
key: 'delete',
|
||||||
|
label: '删除'
|
||||||
|
}])
|
||||||
|
|
||||||
|
const data = computed(() => {
|
||||||
|
return props.data
|
||||||
|
})
|
||||||
|
let searchVal = ref('')
|
||||||
|
let curPage = ref(1)
|
||||||
|
const emitRefresh = (page: number, name: string) => {
|
||||||
|
curPage.value = page
|
||||||
|
emit('refresh', {
|
||||||
|
curPage: page,
|
||||||
|
name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleCurrentChange = async (val: number) => {
|
||||||
|
emitRefresh(val, searchVal.value)
|
||||||
|
}
|
||||||
|
const onSearchText = async (value: string) => {
|
||||||
|
searchVal.value = value
|
||||||
|
emitRefresh(1, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleModify = (id: string) => {
|
||||||
|
workSpaceStore.getGroupDetail(id)
|
||||||
|
showGroupModify.value = true
|
||||||
|
}
|
||||||
|
const handleDelete = (id: string) => {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'删除分组后,属于该分组的问卷将会自动更换到“未分组”下,是否确认本次删除?',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(async () => {
|
||||||
|
await workSpaceStore.deleteGroup(id)
|
||||||
|
await workSpaceStore.getGroupList()
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClick = (key: string, data: any) => {
|
||||||
|
if (key === 'modify') {
|
||||||
|
handleModify(data._id)
|
||||||
|
} else if (key === 'delete') {
|
||||||
|
handleDelete(data._id)
|
||||||
|
} else if(key === 'open') {
|
||||||
|
workSpaceStore.changeMenuType(MenuType.PersonalGroup)
|
||||||
|
workSpaceStore.changeGroup(data._id)
|
||||||
|
surveyListStore.getSurveyList({
|
||||||
|
pageSize: 10,
|
||||||
|
curPage: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCloseModify = () => {
|
||||||
|
showGroupModify.value = false
|
||||||
|
workSpaceStore.getGroupList()
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ onCloseModify })
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.list-pagination {
|
||||||
|
margin-top: 20px;
|
||||||
|
:deep(.el-pagination) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-wrap {
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-table {
|
||||||
|
:deep(.el-table__header) {
|
||||||
|
.tableview-header .el-table__cell {
|
||||||
|
.cell {
|
||||||
|
height: 24px;
|
||||||
|
color: #4a4c5b;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.tableview-row) {
|
||||||
|
.tableview-cell {
|
||||||
|
height: 42px;
|
||||||
|
|
||||||
|
&.link {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell .cell-span {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
119
web/src/management/pages/list/components/GroupModify.vue
Normal file
119
web/src/management/pages/list/components/GroupModify.vue
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
class="base-dialog-root"
|
||||||
|
:model-value="visible"
|
||||||
|
width="40%"
|
||||||
|
:title="formTitle"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
class="base-form-root"
|
||||||
|
ref="ruleForm"
|
||||||
|
:model="formModel"
|
||||||
|
:rules="rules"
|
||||||
|
label-position="top"
|
||||||
|
size="large"
|
||||||
|
@submit.prevent
|
||||||
|
>
|
||||||
|
<el-form-item label="分组名称" prop="name">
|
||||||
|
<el-input v-model="formModel.name" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="onClose">取消</el-button>
|
||||||
|
<el-button type="primary" class="save-btn" @click="onConfirm">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref, shallowRef, onMounted } from 'vue'
|
||||||
|
import { pick as _pick } from 'lodash-es'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
|
import { QOP_MAP } from '@/management/utils/constant'
|
||||||
|
import { type IGroup } from '@/management/utils/workSpace'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
|
const emit = defineEmits(['on-close-codify'])
|
||||||
|
const props = defineProps({
|
||||||
|
type: String,
|
||||||
|
width: String,
|
||||||
|
visible: Boolean
|
||||||
|
})
|
||||||
|
const ruleForm = shallowRef<any>(null)
|
||||||
|
|
||||||
|
const formTitle = computed(() => {
|
||||||
|
return props.type === QOP_MAP.ADD ? '创建分组' : '管理分组'
|
||||||
|
})
|
||||||
|
const formModel = ref<Required<IGroup>>({
|
||||||
|
_id: '',
|
||||||
|
name: ''
|
||||||
|
})
|
||||||
|
const rules = {
|
||||||
|
name: [{ required: true, message: '请输入分组名称', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
const groupDetail = computed(() => {
|
||||||
|
return workSpaceStore.groupDetail
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.type === QOP_MAP.EDIT) {
|
||||||
|
formModel.value = _pick(groupDetail.value as any, ['_id', 'name'])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const onClose = () => {
|
||||||
|
formModel.value = {
|
||||||
|
_id: '',
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
// 清空空间详情
|
||||||
|
workSpaceStore.setGroupDetail(null)
|
||||||
|
emit('on-close-codify')
|
||||||
|
}
|
||||||
|
|
||||||
|
const onConfirm = async () => {
|
||||||
|
ruleForm.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
if (props.type === QOP_MAP.ADD) {
|
||||||
|
try {
|
||||||
|
await handleAdd()
|
||||||
|
emit('on-close-codify')
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error('createGroup status err' + err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await handleUpdate()
|
||||||
|
emit('on-close-codify')
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error('createGroup status err' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpdate = async () => {
|
||||||
|
await workSpaceStore.updateGroup(formModel.value)
|
||||||
|
}
|
||||||
|
const handleAdd = async () => {
|
||||||
|
await workSpaceStore.addGroup({ name: formModel.value.name })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" rel="lang/scss" scoped>
|
||||||
|
.base-form-root {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -21,6 +21,19 @@
|
|||||||
<el-form-item label="备注">
|
<el-form-item label="备注">
|
||||||
<el-input v-model="current.remark" />
|
<el-input v-model="current.remark" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item prop="groupId" label="问卷分组" v-if="menuType === MenuType.PersonalGroup">
|
||||||
|
<el-select
|
||||||
|
v-model="current.groupId"
|
||||||
|
placeholder="未分组"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in groupAllList"
|
||||||
|
:key="item._id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item._id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@ -35,7 +48,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { pick as _pick } from 'lodash-es'
|
import { pick as _pick } from 'lodash-es'
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
@ -43,17 +55,22 @@ import { CODE_MAP } from '@/management/api/base'
|
|||||||
import { updateSurvey, createSurvey } from '@/management/api/survey'
|
import { updateSurvey, createSurvey } from '@/management/api/survey'
|
||||||
import { QOP_MAP } from '@/management/utils/constant'
|
import { QOP_MAP } from '@/management/utils/constant'
|
||||||
|
|
||||||
|
import { MenuType } from '@/management/utils/workSpace'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModifyDialog',
|
name: 'ModifyDialog',
|
||||||
props: {
|
props: {
|
||||||
type: String,
|
type: String,
|
||||||
questionInfo: Object,
|
questionInfo: Object,
|
||||||
width: String,
|
width: String,
|
||||||
visible: Boolean
|
visible: Boolean,
|
||||||
|
groupAllList: Array,
|
||||||
|
menuType: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
QOP_MAP,
|
QOP_MAP,
|
||||||
|
MenuType,
|
||||||
loadingInstance: null,
|
loadingInstance: null,
|
||||||
rules: {
|
rules: {
|
||||||
title: [{ required: true, message: '请输入问卷标题', trigger: 'blur' }]
|
title: [{ required: true, message: '请输入问卷标题', trigger: 'blur' }]
|
||||||
@ -72,7 +89,8 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
getCurrent(val) {
|
getCurrent(val) {
|
||||||
return {
|
return {
|
||||||
..._pick(val, ['title', 'remark'])
|
..._pick(val, ['title', 'remark']),
|
||||||
|
groupId: val.groupId === null ? '' : val.groupId
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClose() {
|
onClose() {
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-menu
|
<el-menu
|
||||||
:default-active="SpaceType.Personal"
|
:default-active="active"
|
||||||
class="el-menu-vertical"
|
class="el-menu-vertical"
|
||||||
ref="menuRef"
|
ref="menuRef"
|
||||||
@select="handleSelect"
|
@select="handleMenu"
|
||||||
|
@open="handleMenu"
|
||||||
|
@close="handleMenu"
|
||||||
>
|
>
|
||||||
<template v-for="(menu, index) in menus" :key="menu.id">
|
<template v-for="(menu, index) in props.menus" :key="menu.id">
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
:class="[index === 0 ? 'bottom' : '', index > 2 ? 'sub-item' : 'main-item']"
|
:class="[index === 0 ? 'bottom' : '', index > 2 ? 'sub-item' : 'main-item', active == menu.id ? 'check-item' : '' ]"
|
||||||
:index="menu.id"
|
:index="menu.id.toString()"
|
||||||
v-if="!menu.children?.length"
|
v-if="!menu.children?.length"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
@ -18,46 +20,65 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item-group v-else>
|
<el-sub-menu v-else :index="menu.id.toString()" :class="[ active == menu.id ? 'check-item' : '' ]">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-menu-item :index="menu.id" class="sub-title main-item">
|
<div class="title-content sub-title main-item">
|
||||||
<div class="title-content">
|
|
||||||
<i :class="['iconfont', menu.icon]"></i>
|
<i :class="['iconfont', menu.icon]"></i>
|
||||||
<span>{{ menu.name }}</span>
|
<span>{{ menu.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-menu-item>
|
|
||||||
</template>
|
</template>
|
||||||
<el-menu-item v-for="item in menu.children" :key="item.id" :index="item.id">
|
<el-menu-item v-for="item in menu.children" :key="item.id" :index="item.id.toString()" :class="[ active == item.id ? 'check-item' : '' ]">
|
||||||
<p>
|
<div class="title-box">
|
||||||
{{ item.name }}
|
<p class="title-text">{{ item.name }}</p>
|
||||||
</p>
|
<p class="title-total">{{ item.total }}</p>
|
||||||
|
</div>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-menu-item-group>
|
</el-sub-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { type MenuItem } from '@/management/utils/workSpace'
|
import { type MenuItem } from '@/management/utils/workSpace'
|
||||||
import { SpaceType } from '@/management/utils/workSpace'
|
import { MenuType } from '@/management/utils/workSpace'
|
||||||
|
|
||||||
const menuRef = ref()
|
const menuRef = ref()
|
||||||
|
const props = withDefaults(
|
||||||
withDefaults(
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
menus: Array<MenuItem>
|
menus: Array<MenuItem>,
|
||||||
|
activeValue: string
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
menus: () => []
|
menus: () => [],
|
||||||
|
activeValue: MenuType.PersonalGroup
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const active = computed({
|
||||||
|
get: () => {
|
||||||
|
return props.activeValue
|
||||||
|
},
|
||||||
|
set: () => {}
|
||||||
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['select'])
|
const emit = defineEmits(['select'])
|
||||||
const handleSelect = (id: string) => {
|
const handleMenu = (id: string) => {
|
||||||
|
active.value = id
|
||||||
emit('select', id)
|
emit('select', id)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.el-sub-menu {
|
||||||
|
:deep(.el-sub-menu__icon-arrow) {
|
||||||
|
transform: rotate(-90deg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-opened {
|
||||||
|
> :deep(.el-sub-menu__title .el-sub-menu__icon-arrow) {
|
||||||
|
transform: rotate(0deg) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.el-menu-vertical {
|
.el-menu-vertical {
|
||||||
border: none;
|
border: none;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
@ -94,10 +115,6 @@ const handleSelect = (id: string) => {
|
|||||||
&.sub-item {
|
&.sub-item {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
&.is-active {
|
|
||||||
// background-color: #F2F4F7;
|
|
||||||
background: #fef6e6 100% !important;
|
|
||||||
}
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f2f4f7;
|
background-color: #f2f4f7;
|
||||||
}
|
}
|
||||||
@ -106,6 +123,27 @@ const handleSelect = (id: string) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title-box {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
width: 80%;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-total {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #92949D;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
:deep(.el-menu-item-group) {
|
:deep(.el-menu-item-group) {
|
||||||
> ul {
|
> ul {
|
||||||
@ -128,4 +166,7 @@ const handleSelect = (id: string) => {
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
color: #faa600 !important;
|
color: #faa600 !important;
|
||||||
}
|
}
|
||||||
|
.check-item {
|
||||||
|
background: #fef6e6 100% !important
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,23 +2,32 @@
|
|||||||
<div class="question-list-root">
|
<div class="question-list-root">
|
||||||
<TopNav></TopNav>
|
<TopNav></TopNav>
|
||||||
<div class="content-wrap">
|
<div class="content-wrap">
|
||||||
<SliderBar :menus="spaceMenus" @select="handleSpaceSelect" />
|
<SliderBar :menus="spaceMenus" :activeValue="activeValue" @select="handleSpaceSelect" />
|
||||||
<div class="list-content">
|
<div class="list-content">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<h2>
|
<h2>
|
||||||
{{ spaceType === SpaceType.Group ? '团队空间' : currentTeamSpace?.name || '问卷列表' }}
|
{{ tableTitle }}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="operation">
|
<div class="operation">
|
||||||
<el-button
|
<el-button
|
||||||
class="btn create-btn"
|
class="btn create-btn"
|
||||||
type="default"
|
type="default"
|
||||||
@click="onSpaceCreate"
|
@click="onSpaceCreate"
|
||||||
v-if="spaceType == SpaceType.Group"
|
v-if="menuType === MenuType.SpaceGroup && !workSpaceId"
|
||||||
>
|
>
|
||||||
<i class="iconfont icon-chuangjian"></i>
|
<i class="iconfont icon-chuangjian"></i>
|
||||||
<span>创建团队空间</span>
|
<span>创建团队空间</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="default" class="btn" @click="onSetGroup" v-if="workSpaceId">
|
<el-button
|
||||||
|
class="btn create-btn"
|
||||||
|
type="default"
|
||||||
|
@click="onGroupCreate"
|
||||||
|
v-if="menuType === MenuType.PersonalGroup && !groupId"
|
||||||
|
>
|
||||||
|
<i class="iconfont icon-chuangjian"></i>
|
||||||
|
<span>创建分组</span>
|
||||||
|
</el-button>
|
||||||
|
<el-button type="default" class="btn" @click="onSetGroup" v-if="workSpaceId && menuType === MenuType.SpaceGroup">
|
||||||
<i class="iconfont icon-shujuliebiao"></i>
|
<i class="iconfont icon-shujuliebiao"></i>
|
||||||
<span>团队管理</span>
|
<span>团队管理</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -26,7 +35,7 @@
|
|||||||
class="btn create-btn"
|
class="btn create-btn"
|
||||||
type="default"
|
type="default"
|
||||||
@click="onCreate"
|
@click="onCreate"
|
||||||
v-if="spaceType !== SpaceType.Group"
|
v-if="workSpaceId || groupId"
|
||||||
>
|
>
|
||||||
<i class="iconfont icon-chuangjian"></i>
|
<i class="iconfont icon-chuangjian"></i>
|
||||||
<span>创建问卷</span>
|
<span>创建问卷</span>
|
||||||
@ -38,7 +47,7 @@
|
|||||||
:data="surveyList"
|
:data="surveyList"
|
||||||
:total="surveyTotal"
|
:total="surveyTotal"
|
||||||
@refresh="fetchSurveyList"
|
@refresh="fetchSurveyList"
|
||||||
v-if="spaceType !== SpaceType.Group"
|
v-if="workSpaceId || groupId"
|
||||||
></BaseList>
|
></BaseList>
|
||||||
<SpaceList
|
<SpaceList
|
||||||
ref="spaceListRef"
|
ref="spaceListRef"
|
||||||
@ -46,17 +55,31 @@
|
|||||||
:loading="spaceLoading"
|
:loading="spaceLoading"
|
||||||
:data="workSpaceList"
|
:data="workSpaceList"
|
||||||
:total="workSpaceListTotal"
|
:total="workSpaceListTotal"
|
||||||
v-if="spaceType === SpaceType.Group"
|
v-if="menuType === MenuType.SpaceGroup && !workSpaceId"
|
||||||
></SpaceList>
|
></SpaceList>
|
||||||
|
<GroupList
|
||||||
|
ref="groupListRef"
|
||||||
|
@refresh="fetchGroupList"
|
||||||
|
:loading="groupLoading"
|
||||||
|
:data="groupList"
|
||||||
|
:total="groupListTotal"
|
||||||
|
v-if="menuType === MenuType.PersonalGroup && !groupId"
|
||||||
|
></GroupList>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SpaceModify
|
<SpaceModify
|
||||||
v-if="showSpaceModify"
|
v-if="showSpaceModify"
|
||||||
:type="modifyType"
|
:type="modifyType"
|
||||||
:visible="showSpaceModify"
|
:visible="showSpaceModify"
|
||||||
@on-close-codify="onCloseModify"
|
@on-close-codify="onCloseSpaceModify"
|
||||||
@update-data="onCloseModifyInTeamWork"
|
@update-data="onCloseModifyInTeamWork"
|
||||||
/>
|
/>
|
||||||
|
<GroupModify
|
||||||
|
v-if="showGroupModify"
|
||||||
|
type="add"
|
||||||
|
:visible="showGroupModify"
|
||||||
|
@on-close-codify="onCloseGroupModify"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -66,10 +89,13 @@ import { storeToRefs } from 'pinia'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import BaseList from './components/BaseList.vue'
|
import BaseList from './components/BaseList.vue'
|
||||||
import SpaceList from './components/SpaceList.vue'
|
import SpaceList from './components/SpaceList.vue'
|
||||||
|
import GroupList from './components/GroupList.vue'
|
||||||
import SliderBar from './components/SliderBar.vue'
|
import SliderBar from './components/SliderBar.vue'
|
||||||
import SpaceModify from './components/SpaceModify.vue'
|
import SpaceModify from './components/SpaceModify.vue'
|
||||||
|
import GroupModify from './components/GroupModify.vue'
|
||||||
import TopNav from '@/management/components/TopNav.vue'
|
import TopNav from '@/management/components/TopNav.vue'
|
||||||
import { SpaceType } from '@/management/utils/workSpace'
|
import { MenuType } from '@/management/utils/workSpace'
|
||||||
|
|
||||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
import { useSurveyListStore } from '@/management/stores/surveyList'
|
import { useSurveyListStore } from '@/management/stores/surveyList'
|
||||||
import { type IWorkspace } from '@/management/utils/workSpace'
|
import { type IWorkspace } from '@/management/utils/workSpace'
|
||||||
@ -78,14 +104,39 @@ const workSpaceStore = useWorkSpaceStore()
|
|||||||
const surveyListStore = useSurveyListStore()
|
const surveyListStore = useSurveyListStore()
|
||||||
|
|
||||||
const { surveyList, surveyTotal } = storeToRefs(surveyListStore)
|
const { surveyList, surveyTotal } = storeToRefs(surveyListStore)
|
||||||
const { spaceMenus, workSpaceId, spaceType, workSpaceList, workSpaceListTotal } =
|
const { spaceMenus, workSpaceId, groupId, menuType, workSpaceList, workSpaceListTotal, groupList, groupListTotal } =
|
||||||
storeToRefs(workSpaceStore)
|
storeToRefs(workSpaceStore)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const tableTitle = computed(() => {
|
||||||
|
if(menuType.value === MenuType.PersonalGroup && !groupId.value) {
|
||||||
|
return '我的空间'
|
||||||
|
} else if (menuType.value === MenuType.SpaceGroup && !workSpaceId.value) {
|
||||||
|
return '团队空间'
|
||||||
|
} else {
|
||||||
|
return currentTeamSpace.value?.name || '问卷列表';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const activeValue = computed(() => {
|
||||||
|
if(workSpaceId.value !== '') {
|
||||||
|
return workSpaceId.value
|
||||||
|
} else if(groupId.value !== '') {
|
||||||
|
return groupId.value
|
||||||
|
} else if(menuType.value === MenuType.PersonalGroup) {
|
||||||
|
return MenuType.PersonalGroup
|
||||||
|
} else if(menuType.value === MenuType.SpaceGroup) {
|
||||||
|
return MenuType.SpaceGroup
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
const spaceListRef = ref<any>(null)
|
const spaceListRef = ref<any>(null)
|
||||||
const spaceLoading = ref(false)
|
const spaceLoading = ref(false)
|
||||||
|
const groupLoading = ref(false)
|
||||||
|
|
||||||
const fetchSpaceList = async (params?: any) => {
|
const fetchSpaceList = async (params?: any) => {
|
||||||
spaceLoading.value = true
|
spaceLoading.value = true
|
||||||
@ -94,24 +145,39 @@ const fetchSpaceList = async (params?: any) => {
|
|||||||
spaceLoading.value = false
|
spaceLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSpaceSelect = (id: SpaceType | string) => {
|
const fetchGroupList = async (params?: any) => {
|
||||||
if (id === spaceType.value || id === workSpaceId.value) {
|
groupLoading.value = true
|
||||||
|
workSpaceStore.changeWorkSpace('')
|
||||||
|
workSpaceStore.getGroupList(params)
|
||||||
|
groupLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSpaceSelect = (id: MenuType | string) => {
|
||||||
|
if (groupId.value === id || workSpaceId.value === id) {
|
||||||
return void 0
|
return void 0
|
||||||
}
|
}
|
||||||
|
let parentMenu = undefined
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case SpaceType.Personal:
|
case MenuType.PersonalGroup:
|
||||||
workSpaceStore.changeSpaceType(SpaceType.Personal)
|
workSpaceStore.changeMenuType(MenuType.PersonalGroup)
|
||||||
workSpaceStore.changeWorkSpace('')
|
workSpaceStore.changeWorkSpace('')
|
||||||
|
fetchGroupList()
|
||||||
break
|
break
|
||||||
case SpaceType.Group:
|
case MenuType.SpaceGroup:
|
||||||
workSpaceStore.changeSpaceType(SpaceType.Group)
|
workSpaceStore.changeMenuType(MenuType.SpaceGroup)
|
||||||
workSpaceStore.changeWorkSpace('')
|
workSpaceStore.changeWorkSpace('')
|
||||||
fetchSpaceList()
|
fetchSpaceList()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
workSpaceStore.changeSpaceType(SpaceType.Teamwork)
|
parentMenu = spaceMenus.value.find((parent: any) => parent.children.find((children: any) => children.id.toString() === id))
|
||||||
workSpaceStore.changeWorkSpace(id)
|
if(parentMenu != undefined) {
|
||||||
|
workSpaceStore.changeMenuType(parentMenu.id)
|
||||||
|
if(parentMenu.id === MenuType.PersonalGroup) {
|
||||||
|
workSpaceStore.changeGroup(id)
|
||||||
|
} else if (parentMenu.id === MenuType.SpaceGroup) {
|
||||||
|
workSpaceStore.changeWorkSpace(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fetchSurveyList()
|
fetchSurveyList()
|
||||||
@ -133,6 +199,7 @@ const fetchSurveyList = async (params?: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
fetchGroupList()
|
||||||
fetchSpaceList()
|
fetchSpaceList()
|
||||||
fetchSurveyList()
|
fetchSurveyList()
|
||||||
})
|
})
|
||||||
@ -168,7 +235,7 @@ const onCloseModifyInTeamWork = (data: IWorkspace) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onCloseModify = (type: string) => {
|
const onCloseSpaceModify = (type: string) => {
|
||||||
showSpaceModify.value = false
|
showSpaceModify.value = false
|
||||||
if (type === 'update' && spaceListRef.value) {
|
if (type === 'update' && spaceListRef.value) {
|
||||||
fetchSpaceList()
|
fetchSpaceList()
|
||||||
@ -179,6 +246,20 @@ const onSpaceCreate = () => {
|
|||||||
modifyType.value = 'add'
|
modifyType.value = 'add'
|
||||||
showSpaceModify.value = true
|
showSpaceModify.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分组
|
||||||
|
|
||||||
|
const showGroupModify = ref<boolean>(false)
|
||||||
|
|
||||||
|
const onCloseGroupModify = () => {
|
||||||
|
showGroupModify.value = false
|
||||||
|
fetchGroupList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onGroupCreate = () => {
|
||||||
|
showGroupModify.value = true
|
||||||
|
}
|
||||||
|
|
||||||
const onCreate = () => {
|
const onCreate = () => {
|
||||||
router.push('/create')
|
router.push('/create')
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import 'element-plus/theme-chalk/src/message.scss'
|
|||||||
|
|
||||||
import { CODE_MAP } from '@/management/api/base'
|
import { CODE_MAP } from '@/management/api/base'
|
||||||
import { getSurveyList as getSurveyListReq } from '@/management/api/survey'
|
import { getSurveyList as getSurveyListReq } from '@/management/api/survey'
|
||||||
|
import { GroupState } from '@/management/utils/workSpace'
|
||||||
import { useWorkSpaceStore } from './workSpace'
|
import { useWorkSpaceStore } from './workSpace'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -150,7 +150,8 @@ export const useSurveyListStore = defineStore('surveyList', () => {
|
|||||||
pageSize: payload?.pageSize || 10, // 默认一页10条
|
pageSize: payload?.pageSize || 10, // 默认一页10条
|
||||||
filter: filterString,
|
filter: filterString,
|
||||||
order: orderString,
|
order: orderString,
|
||||||
workspaceId: workSpaceStore.workSpaceId
|
workspaceId: workSpaceStore.workSpaceId,
|
||||||
|
groupId: workSpaceStore.groupId === GroupState.All ? '' : workSpaceStore.groupId
|
||||||
}
|
}
|
||||||
|
|
||||||
const res: any = await getSurveyListReq(params)
|
const res: any = await getSurveyListReq(params)
|
||||||
|
@ -10,11 +10,16 @@ import {
|
|||||||
updateSpace as updateSpaceReq,
|
updateSpace as updateSpaceReq,
|
||||||
deleteSpace as deleteSpaceReq,
|
deleteSpace as deleteSpaceReq,
|
||||||
getSpaceList as getSpaceListReq,
|
getSpaceList as getSpaceListReq,
|
||||||
getSpaceDetail as getSpaceDetailReq
|
getSpaceDetail as getSpaceDetailReq,
|
||||||
|
createGroup,
|
||||||
|
getGroupList as getGroupListReq,
|
||||||
|
updateGroup as updateGroupReq,
|
||||||
|
deleteGroup as deleteGroupReq
|
||||||
} from '@/management/api/space'
|
} from '@/management/api/space'
|
||||||
|
|
||||||
import { SpaceType } from '@/management/utils/workSpace'
|
import { GroupState, MenuType } from '@/management/utils/workSpace'
|
||||||
import { type SpaceDetail, type SpaceItem, type IWorkspace } from '@/management/utils/workSpace'
|
import { type SpaceDetail, type SpaceItem, type IWorkspace, type IGroup, type GroupItem, } from '@/management/utils/workSpace'
|
||||||
|
|
||||||
|
|
||||||
import { useSurveyListStore } from './surveyList'
|
import { useSurveyListStore } from './surveyList'
|
||||||
|
|
||||||
@ -24,16 +29,18 @@ export const useWorkSpaceStore = defineStore('workSpace', () => {
|
|||||||
{
|
{
|
||||||
icon: 'icon-wodekongjian',
|
icon: 'icon-wodekongjian',
|
||||||
name: '我的空间',
|
name: '我的空间',
|
||||||
id: SpaceType.Personal
|
id: MenuType.PersonalGroup,
|
||||||
|
children: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'icon-tuanduikongjian',
|
icon: 'icon-tuanduikongjian',
|
||||||
name: '团队空间',
|
name: '团队空间',
|
||||||
id: SpaceType.Group,
|
id: MenuType.SpaceGroup,
|
||||||
children: []
|
children: []
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
const spaceType = ref(SpaceType.Personal)
|
const menuType = ref(MenuType.PersonalGroup)
|
||||||
|
const groupId = ref('')
|
||||||
const workSpaceId = ref('')
|
const workSpaceId = ref('')
|
||||||
const spaceDetail = ref<SpaceDetail | null>(null)
|
const spaceDetail = ref<SpaceDetail | null>(null)
|
||||||
const workSpaceList = ref<SpaceItem[]>([])
|
const workSpaceList = ref<SpaceItem[]>([])
|
||||||
@ -50,7 +57,8 @@ export const useWorkSpaceStore = defineStore('workSpace', () => {
|
|||||||
const workSpace = list.map((item: SpaceDetail) => {
|
const workSpace = list.map((item: SpaceDetail) => {
|
||||||
return {
|
return {
|
||||||
id: item._id,
|
id: item._id,
|
||||||
name: item.name
|
name: item.name,
|
||||||
|
total: item.surveyTotal
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
workSpaceList.value = list
|
workSpaceList.value = list
|
||||||
@ -78,12 +86,19 @@ export const useWorkSpaceStore = defineStore('workSpace', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeSpaceType(id: SpaceType) {
|
function changeMenuType(id: MenuType) {
|
||||||
spaceType.value = id
|
menuType.value = id
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeWorkSpace(id: string) {
|
function changeWorkSpace(id: string) {
|
||||||
workSpaceId.value = id
|
workSpaceId.value = id
|
||||||
|
groupId.value = ''
|
||||||
|
surveyListStore.resetSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeGroup(id: string) {
|
||||||
|
groupId.value = id
|
||||||
|
workSpaceId.value = ''
|
||||||
surveyListStore.resetSearch()
|
surveyListStore.resetSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,21 +141,130 @@ export const useWorkSpaceStore = defineStore('workSpace', () => {
|
|||||||
function setSpaceDetail(data: null | SpaceDetail) {
|
function setSpaceDetail(data: null | SpaceDetail) {
|
||||||
spaceDetail.value = data
|
spaceDetail.value = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分组
|
||||||
|
const groupList = ref<GroupItem[]>([])
|
||||||
|
const groupAllList = ref<IGroup[]>([])
|
||||||
|
const groupListTotal = ref(0)
|
||||||
|
const groupDetail = ref<GroupItem | null>(null)
|
||||||
|
async function addGroup(params: IGroup) {
|
||||||
|
const { name } = params
|
||||||
|
const res: any = await createGroup({ name })
|
||||||
|
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.error('createGroup code err' + res.errmsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateGroup(params: Required<IGroup>) {
|
||||||
|
const { _id, name } = params
|
||||||
|
const res: any = await updateGroupReq({ _id, name })
|
||||||
|
|
||||||
|
if (res?.code === CODE_MAP.SUCCESS) {
|
||||||
|
ElMessage.success('更新成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.errmsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getGroupList(params = { curPage: 1 }) {
|
||||||
|
try {
|
||||||
|
const res: any = await getGroupListReq(params)
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
const { list, allList, total, notTotal } = res.data
|
||||||
|
let allTotal = notTotal
|
||||||
|
const group = list.map((item: GroupItem) => {
|
||||||
|
allTotal += item.surveyTotal
|
||||||
|
return {
|
||||||
|
id: item._id,
|
||||||
|
name: item.name,
|
||||||
|
total: item.surveyTotal,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
group.unshift({
|
||||||
|
id: GroupState.All,
|
||||||
|
name: '全部' ,
|
||||||
|
total: allTotal
|
||||||
|
}, {
|
||||||
|
id: GroupState.Not,
|
||||||
|
name: '未分组' ,
|
||||||
|
total: notTotal
|
||||||
|
})
|
||||||
|
allList.unshift({
|
||||||
|
_id: '',
|
||||||
|
name: '未分组'
|
||||||
|
})
|
||||||
|
groupList.value = list
|
||||||
|
groupListTotal.value = total
|
||||||
|
spaceMenus.value[0].children = group
|
||||||
|
groupAllList.value = allList
|
||||||
|
} else {
|
||||||
|
ElMessage.error('getGroupList' + res.errmsg)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error('getGroupList' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGroupDetail(id: string) {
|
||||||
|
try {
|
||||||
|
const data = groupList.value.find((item: GroupItem) => item._id === id)
|
||||||
|
if(data != undefined) {
|
||||||
|
groupDetail.value = data
|
||||||
|
} else {
|
||||||
|
ElMessage.error('groupDetail 未找到分组')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error('groupDetail' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setGroupDetail(data: null | GroupItem) {
|
||||||
|
groupDetail.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteGroup(id: string) {
|
||||||
|
try {
|
||||||
|
const res: any = await deleteGroupReq(id)
|
||||||
|
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.errmsg)
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
ElMessage.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
menuType,
|
||||||
spaceMenus,
|
spaceMenus,
|
||||||
spaceType,
|
groupId,
|
||||||
workSpaceId,
|
workSpaceId,
|
||||||
spaceDetail,
|
spaceDetail,
|
||||||
workSpaceList,
|
workSpaceList,
|
||||||
workSpaceListTotal,
|
workSpaceListTotal,
|
||||||
getSpaceList,
|
getSpaceList,
|
||||||
getSpaceDetail,
|
getSpaceDetail,
|
||||||
changeSpaceType,
|
changeMenuType,
|
||||||
changeWorkSpace,
|
changeWorkSpace,
|
||||||
|
changeGroup,
|
||||||
addSpace,
|
addSpace,
|
||||||
deleteSpace,
|
deleteSpace,
|
||||||
updateSpace,
|
updateSpace,
|
||||||
setSpaceDetail
|
setSpaceDetail,
|
||||||
|
groupList,
|
||||||
|
groupAllList,
|
||||||
|
groupListTotal,
|
||||||
|
groupDetail,
|
||||||
|
addGroup,
|
||||||
|
updateGroup,
|
||||||
|
getGroupList,
|
||||||
|
getGroupDetail,
|
||||||
|
setGroupDetail,
|
||||||
|
deleteGroup
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -7,9 +7,15 @@ export interface MenuItem {
|
|||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
icon?: string
|
icon?: string
|
||||||
|
total?: Number
|
||||||
children?: MenuItem[]
|
children?: MenuItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type IGroup = {
|
||||||
|
_id?: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
export type IWorkspace = {
|
export type IWorkspace = {
|
||||||
_id?: string
|
_id?: string
|
||||||
name: string
|
name: string
|
||||||
@ -29,6 +35,7 @@ export interface SpaceDetail {
|
|||||||
name: string
|
name: string
|
||||||
currentUserId?: string
|
currentUserId?: string
|
||||||
description: string
|
description: string
|
||||||
|
surveyTotal: number
|
||||||
members: IMember[]
|
members: IMember[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,16 +56,30 @@ export interface ICollaborator {
|
|||||||
permissions: Array<number>
|
permissions: Array<number>
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SpaceType {
|
export type GroupItem = {
|
||||||
Personal = 'personal',
|
_id: string,
|
||||||
Group = 'group',
|
name: string,
|
||||||
Teamwork = 'teamwork'
|
createdAt: string
|
||||||
|
updatedAt?: string
|
||||||
|
ownerId: string
|
||||||
|
surveyTotal: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum MenuType {
|
||||||
|
PersonalGroup = 'personalGroup',
|
||||||
|
SpaceGroup = 'spaceGroup',
|
||||||
|
}
|
||||||
|
|
||||||
export enum UserRole {
|
export enum UserRole {
|
||||||
Admin = 'admin',
|
Admin = 'admin',
|
||||||
Member = 'user'
|
Member = 'user'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum GroupState {
|
||||||
|
All = 'all',
|
||||||
|
Not = 'nogrouped'
|
||||||
|
}
|
||||||
|
|
||||||
// 定义角色标签映射对象
|
// 定义角色标签映射对象
|
||||||
export const roleLabels: Record<UserRole, string> = {
|
export const roleLabels: Record<UserRole, string> = {
|
||||||
[UserRole.Admin]: '管理员',
|
[UserRole.Admin]: '管理员',
|
||||||
|
Loading…
Reference in New Issue
Block a user