diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 3faa2987..416c70b7 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -14,6 +14,7 @@ import { AuthModule } from './modules/auth/auth.module'; import { MessageModule } from './modules/message/message.module'; import { FileModule } from './modules/file/file.module'; import { WorkspaceModule } from './modules/workspace/workspace.module'; +import { UpgradeModule } from './modules/upgrade/upgrade.module'; import { join } from 'path'; @@ -100,6 +101,7 @@ import { Logger } from './logger'; MessageModule, FileModule, WorkspaceModule, + UpgradeModule, ], controllers: [AppController], providers: [ diff --git a/server/src/enums/exceptionCode.ts b/server/src/enums/exceptionCode.ts index 6e139ad9..c8979b4c 100644 --- a/server/src/enums/exceptionCode.ts +++ b/server/src/enums/exceptionCode.ts @@ -20,6 +20,7 @@ export enum EXCEPTION_CODE { RESPONSE_OVER_LIMIT = 9003, // 超出限制 RESPONSE_SCHEMA_REMOVED = 9004, // 问卷已删除 RESPONSE_DATA_DECRYPT_ERROR = 9005, // 问卷已删除 + RESPONSE_PAUSING = 9006, // 问卷已暂停 UPLOAD_FILE_ERROR = 5001, // 上传文件错误 } diff --git a/server/src/enums/index.ts b/server/src/enums/index.ts index acaa0e33..0bebf793 100644 --- a/server/src/enums/index.ts +++ b/server/src/enums/index.ts @@ -1,9 +1,14 @@ // 状态类型 export enum RECORD_STATUS { - NEW = 'new', // 新建 + NEW = 'new', // 新建 | 未发布 + PUBLISHED = 'published', // 发布 + CLOSE = 'close', // 关闭 +} + +export const enum RECORD_SUB_STATUS { + DEFAULT = '', // 默认 EDITING = 'editing', // 编辑 PAUSING = 'pausing', // 暂停 - PUBLISHED = 'published', // 发布 REMOVED = 'removed', // 删除 FORCE_REMOVED = 'forceRemoved', // 从回收站删除 } diff --git a/server/src/models/base.entity.ts b/server/src/models/base.entity.ts index 6f30e043..627bec97 100644 --- a/server/src/models/base.entity.ts +++ b/server/src/models/base.entity.ts @@ -1,6 +1,6 @@ import { Column, ObjectIdColumn, BeforeInsert, BeforeUpdate } from 'typeorm'; import { ObjectId } from 'mongodb'; -import { RECORD_STATUS } from '../enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from '../enums'; export class BaseEntity { @ObjectIdColumn() @@ -12,9 +12,15 @@ export class BaseEntity { date: number; }; + @Column() + subStatus: { + status: RECORD_SUB_STATUS; + date: number; + }; + @Column() statusList: Array<{ - status: RECORD_STATUS; + status: RECORD_STATUS | RECORD_SUB_STATUS; date: number; }>; @@ -32,6 +38,10 @@ export class BaseEntity { this.curStatus = curStatus; this.statusList = [curStatus]; } + if (!this.subStatus) { + const subStatus = { status: RECORD_SUB_STATUS.DEFAULT, date: now }; + this.subStatus = subStatus; + } this.createDate = now; this.updateDate = now; } diff --git a/server/src/modules/auth/__test/user.service.spec.ts b/server/src/modules/auth/__test/user.service.spec.ts index e0cdfc19..afb16121 100644 --- a/server/src/modules/auth/__test/user.service.spec.ts +++ b/server/src/modules/auth/__test/user.service.spec.ts @@ -5,7 +5,7 @@ import { UserService } from '../services/user.service'; import { User } from 'src/models/user.entity'; import { HttpException } from 'src/exceptions/httpException'; import { hash256 } from 'src/utils/hash256'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { ObjectId } from 'mongodb'; describe('UserService', () => { @@ -145,7 +145,7 @@ describe('UserService', () => { expect(userRepository.findOne).toHaveBeenCalledWith({ where: { username: username, - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, }); expect(user).toEqual(userInfo); @@ -163,7 +163,7 @@ describe('UserService', () => { expect(findOneSpy).toHaveBeenCalledWith({ where: { username: username, - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, }); expect(user).toBe(null); @@ -184,7 +184,7 @@ describe('UserService', () => { expect(userRepository.findOne).toHaveBeenCalledWith({ where: { _id: new ObjectId(id), - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, }); expect(user).toEqual(userInfo); @@ -202,7 +202,7 @@ describe('UserService', () => { expect(findOneSpy).toHaveBeenCalledWith({ where: { _id: new ObjectId(id), - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, }); expect(user).toBe(null); @@ -228,7 +228,7 @@ describe('UserService', () => { expect(userRepository.find).toHaveBeenCalledWith({ where: { username: new RegExp(username), - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, skip: 0, take: 10, @@ -263,7 +263,7 @@ describe('UserService', () => { _id: { $in: idList.map((id) => new ObjectId(id)), }, - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, select: ['_id', 'username', 'createDate'], }); diff --git a/server/src/modules/auth/services/user.service.ts b/server/src/modules/auth/services/user.service.ts index 03e4f497..ecbe8271 100644 --- a/server/src/modules/auth/services/user.service.ts +++ b/server/src/modules/auth/services/user.service.ts @@ -5,7 +5,7 @@ import { User } from 'src/models/user.entity'; import { HttpException } from 'src/exceptions/httpException'; import { EXCEPTION_CODE } from 'src/enums/exceptionCode'; import { hash256 } from 'src/utils/hash256'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { ObjectId } from 'mongodb'; @Injectable() @@ -53,8 +53,8 @@ export class UserService { const user = await this.userRepository.findOne({ where: { username: username, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }); @@ -66,8 +66,8 @@ export class UserService { const user = await this.userRepository.findOne({ where: { _id: new ObjectId(id), - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }); @@ -79,8 +79,8 @@ export class UserService { const list = await this.userRepository.find({ where: { username: new RegExp(username), - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, skip, @@ -96,8 +96,8 @@ export class UserService { _id: { $in: idList.map((item) => new ObjectId(item)), }, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, select: ['_id', 'username', 'createDate'], diff --git a/server/src/modules/message/__test/messagePushingTask.service.spec.ts b/server/src/modules/message/__test/messagePushingTask.service.spec.ts index 38d8852c..bbb8e20a 100644 --- a/server/src/modules/message/__test/messagePushingTask.service.spec.ts +++ b/server/src/modules/message/__test/messagePushingTask.service.spec.ts @@ -10,7 +10,7 @@ import { MessagePushingLogService } from '../services/messagePushingLog.service' import { CreateMessagePushingTaskDto } from '../dto/createMessagePushingTask.dto'; import { UpdateMessagePushingTaskDto } from '../dto/updateMessagePushingTask.dto'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { MESSAGE_PUSHING_TYPE } from 'src/enums/messagePushing'; import { MESSAGE_PUSHING_HOOK } from 'src/enums/messagePushing'; import { MessagePushingTask } from 'src/models/messagePushingTask.entity'; @@ -121,7 +121,7 @@ describe('MessagePushingTaskService', () => { ownerId: mockOwnerId, surveys: { $all: [surveyId] }, triggerHook: hook, - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, }); }); @@ -146,7 +146,7 @@ describe('MessagePushingTaskService', () => { where: { ownerId: mockOwnerId, _id: new ObjectId(taskId), - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, }); }); @@ -161,8 +161,8 @@ describe('MessagePushingTaskService', () => { pushAddress: 'http://update.example.com', triggerHook: MESSAGE_PUSHING_HOOK.RESPONSE_INSERTED, surveys: ['new survey id'], - curStatus: { - status: RECORD_STATUS.EDITING, + subStatus: { + status: RECORD_SUB_STATUS.EDITING, date: Date.now(), }, }; @@ -211,18 +211,18 @@ describe('MessagePushingTaskService', () => { { ownerId: mockOwnerId, _id: new ObjectId(taskId), - 'curStatus.status': { $ne: RECORD_STATUS.REMOVED }, + 'subStatus.status': { $ne: RECORD_SUB_STATUS.REMOVED }, }, { $set: { - curStatus: { - status: RECORD_STATUS.REMOVED, + subStatus: { + status: RECORD_SUB_STATUS.REMOVED, date: expect.any(Number), }, }, $push: { statusList: { - status: RECORD_STATUS.REMOVED, + status: RECORD_SUB_STATUS.REMOVED, date: expect.any(Number), }, }, diff --git a/server/src/modules/message/dto/updateMessagePushingTask.dto.ts b/server/src/modules/message/dto/updateMessagePushingTask.dto.ts index bf4eb43b..a551a51d 100644 --- a/server/src/modules/message/dto/updateMessagePushingTask.dto.ts +++ b/server/src/modules/message/dto/updateMessagePushingTask.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { MESSAGE_PUSHING_TYPE, MESSAGE_PUSHING_HOOK, @@ -26,4 +26,9 @@ export class UpdateMessagePushingTaskDto { status: RECORD_STATUS; date: number; }; + @ApiProperty({ description: '任务子状态', required: false }) + subStatus?: { + status: RECORD_SUB_STATUS; + date: number; + }; } diff --git a/server/src/modules/message/services/messagePushingTask.service.ts b/server/src/modules/message/services/messagePushingTask.service.ts index 14aef5bf..62a0fb0a 100644 --- a/server/src/modules/message/services/messagePushingTask.service.ts +++ b/server/src/modules/message/services/messagePushingTask.service.ts @@ -6,7 +6,7 @@ import { MESSAGE_PUSHING_HOOK } from 'src/enums/messagePushing'; import { CreateMessagePushingTaskDto } from '../dto/createMessagePushingTask.dto'; import { UpdateMessagePushingTaskDto } from '../dto/updateMessagePushingTask.dto'; import { ObjectId } from 'mongodb'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { MESSAGE_PUSHING_TYPE } from 'src/enums/messagePushing'; import { MessagePushingLogService } from './messagePushingLog.service'; import { httpPost } from 'src/utils/request'; @@ -44,8 +44,8 @@ export class MessagePushingTaskService { ownerId?: string; }): Promise { const where: Record = { - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }; if (surveyId) { @@ -75,8 +75,8 @@ export class MessagePushingTaskService { where: { ownerId, _id: new ObjectId(id), - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }); @@ -103,26 +103,25 @@ export class MessagePushingTaskService { const updatedTask = Object.assign(existingTask, updateData); return await this.messagePushingTaskRepository.save(updatedTask); } - async remove({ id, ownerId }: { id: string; ownerId: string }) { - const curStatus = { - status: RECORD_STATUS.REMOVED, + const subStatus = { + status: RECORD_SUB_STATUS.REMOVED, date: Date.now(), }; return this.messagePushingTaskRepository.updateOne( { ownerId, _id: new ObjectId(id), - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, { $set: { - curStatus, + subStatus, }, $push: { - statusList: curStatus as never, + statusList: subStatus as never, }, }, ); diff --git a/server/src/modules/survey/__test/surveyMeta.controller.spec.ts b/server/src/modules/survey/__test/surveyMeta.controller.spec.ts index b98236d0..936728e1 100644 --- a/server/src/modules/survey/__test/surveyMeta.controller.spec.ts +++ b/server/src/modules/survey/__test/surveyMeta.controller.spec.ts @@ -116,6 +116,9 @@ describe('SurveyMetaController', () => { curStatus: { date: date, }, + subStatus: { + date: date, + }, }, ], }); @@ -132,14 +135,16 @@ describe('SurveyMetaController', () => { createDate: expect.stringMatching( /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, ), - updateDate: expect.stringMatching( - /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, - ), curStatus: expect.objectContaining({ date: expect.stringMatching( /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, ), }), + subStatus: expect.objectContaining({ + date: expect.stringMatching( + /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, + ), + }), }), ]), }, diff --git a/server/src/modules/survey/__test/surveyMeta.service.spec.ts b/server/src/modules/survey/__test/surveyMeta.service.spec.ts index f05502e7..26d3a579 100644 --- a/server/src/modules/survey/__test/surveyMeta.service.spec.ts +++ b/server/src/modules/survey/__test/surveyMeta.service.spec.ts @@ -4,7 +4,7 @@ import { MongoRepository } from 'typeorm'; import { SurveyMeta } from 'src/models/surveyMeta.entity'; import { PluginManagerProvider } from 'src/securityPlugin/pluginManager.provider'; import { XiaojuSurveyPluginManager } from 'src/securityPlugin/pluginManager'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { getRepositoryToken } from '@nestjs/typeorm'; import { HttpException } from 'src/exceptions/httpException'; import { SurveyUtilPlugin } from 'src/securityPlugin/surveyUtilPlugin'; @@ -100,14 +100,18 @@ describe('SurveyMetaService', () => { it('should edit a survey meta and return it if in NEW or EDITING status', async () => { const survey = new SurveyMeta(); survey.curStatus = { status: RECORD_STATUS.PUBLISHED, date: Date.now() }; + survey.subStatus = { + status: RECORD_SUB_STATUS.DEFAULT, + date: Date.now(), + }; survey.statusList = []; jest.spyOn(surveyRepository, 'save').mockResolvedValue(survey); const result = await service.editSurveyMeta(survey); - expect(survey.curStatus.status).toEqual(RECORD_STATUS.EDITING); + expect(survey.subStatus.status).toEqual(RECORD_SUB_STATUS.EDITING); expect(survey.statusList.length).toBe(1); - expect(survey.statusList[0].status).toEqual(RECORD_STATUS.EDITING); + expect(survey.statusList[0].status).toEqual(RECORD_SUB_STATUS.EDITING); expect(surveyRepository.save).toHaveBeenCalledWith(survey); expect(result).toEqual(survey); }); @@ -118,6 +122,10 @@ describe('SurveyMetaService', () => { // 准备假的SurveyMeta对象 const survey = new SurveyMeta(); survey.curStatus = { status: RECORD_STATUS.NEW, date: Date.now() }; + survey.subStatus = { + status: RECORD_SUB_STATUS.DEFAULT, + date: Date.now(), + }; survey.statusList = []; // 模拟save方法 @@ -128,9 +136,9 @@ describe('SurveyMetaService', () => { // 验证结果 expect(result).toBe(survey); - expect(survey.curStatus.status).toBe(RECORD_STATUS.REMOVED); + expect(survey.subStatus.status).toBe(RECORD_SUB_STATUS.REMOVED); expect(survey.statusList.length).toBe(1); - expect(survey.statusList[0].status).toBe(RECORD_STATUS.REMOVED); + expect(survey.statusList[0].status).toBe(RECORD_SUB_STATUS.REMOVED); expect(surveyRepository.save).toHaveBeenCalledTimes(1); expect(surveyRepository.save).toHaveBeenCalledWith(survey); }); @@ -138,7 +146,10 @@ describe('SurveyMetaService', () => { it('should throw exception when survey is already removed', async () => { // 准备假的SurveyMeta对象,其状态已设置为REMOVED const survey = new SurveyMeta(); - survey.curStatus = { status: RECORD_STATUS.REMOVED, date: Date.now() }; + survey.subStatus = { + status: RECORD_SUB_STATUS.REMOVED, + date: Date.now(), + }; // 调用要测试的方法并期待异常 await expect(service.deleteSurveyMeta(survey)).rejects.toThrow( @@ -195,6 +206,10 @@ describe('SurveyMetaService', () => { status: RECORD_STATUS.PUBLISHED, date: expect.any(Number), }, + subStatus: { + status: RECORD_SUB_STATUS.DEFAULT, + date: expect.any(Number), + }, } as unknown as SurveyMeta; jest.spyOn(surveyRepository, 'save').mockResolvedValue(savedSurveyMeta); diff --git a/server/src/modules/survey/controllers/survey.controller.ts b/server/src/modules/survey/controllers/survey.controller.ts index 6976b5c6..69fd4aba 100644 --- a/server/src/modules/survey/controllers/survey.controller.ts +++ b/server/src/modules/survey/controllers/survey.controller.ts @@ -175,6 +175,25 @@ export class SurveyController { }; } + @HttpCode(200) + @Post('/pausingSurvey') + @UseGuards(SurveyGuard) + @SetMetadata('surveyId', 'body.surveyId') + @SetMetadata('surveyPermission', [SURVEY_PERMISSION.SURVEY_CONF_MANAGE]) + @UseGuards(Authentication) + async pausingSurvey(@Request() req) { + const surveyMeta = req.surveyMeta; + + await this.surveyMetaService.pausingSurveyMeta(surveyMeta); + await this.responseSchemaService.pausingResponseSchema({ + surveyPath: surveyMeta.surveyPath, + }); + + return { + code: 200, + }; + } + @Get('/getSurvey') @HttpCode(200) @UseGuards(SurveyGuard) diff --git a/server/src/modules/survey/controllers/surveyMeta.controller.ts b/server/src/modules/survey/controllers/surveyMeta.controller.ts index 3b965222..048fd98a 100644 --- a/server/src/modules/survey/controllers/surveyMeta.controller.ts +++ b/server/src/modules/survey/controllers/surveyMeta.controller.ts @@ -130,8 +130,8 @@ export class SurveyMetaController { item.surveyType = item.questionType || 'normal'; } item.createDate = moment(item.createDate).format(fmt); - item.updateDate = moment(item.updateDate).format(fmt); item.curStatus.date = moment(item.curStatus.date).format(fmt); + item.subStatus.date = moment(item.subStatus.date).format(fmt); const surveyId = item._id.toString(); if (cooperSurveyIdMap[surveyId]) { item.isCollaborated = true; diff --git a/server/src/modules/survey/services/dataStatistic.service.ts b/server/src/modules/survey/services/dataStatistic.service.ts index 0551b432..022f7cab 100644 --- a/server/src/modules/survey/services/dataStatistic.service.ts +++ b/server/src/modules/survey/services/dataStatistic.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { MongoRepository } from 'typeorm'; import { SurveyResponse } from 'src/models/surveyResponse.entity'; +import { RECORD_SUB_STATUS } from 'src/enums'; import moment from 'moment'; import { keyBy } from 'lodash'; @@ -34,8 +35,8 @@ export class DataStatisticService { const dataListMap = keyBy(dataList, 'field'); const where = { pageId: surveyId, - 'curStatus.status': { - $ne: 'removed', + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }; const [surveyResponseList, total] = @@ -124,8 +125,8 @@ export class DataStatisticService { { $match: { pageId: surveyId, - 'curStatus.status': { - $ne: 'removed', + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }, diff --git a/server/src/modules/survey/services/surveyMeta.service.ts b/server/src/modules/survey/services/surveyMeta.service.ts index e44d3b52..69cf8ec8 100644 --- a/server/src/modules/survey/services/surveyMeta.service.ts +++ b/server/src/modules/survey/services/surveyMeta.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { MongoRepository, FindOptionsOrder } from 'typeorm'; import { SurveyMeta } from 'src/models/surveyMeta.entity'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { ObjectId } from 'mongodb'; import { HttpException } from 'src/exceptions/httpException'; import { EXCEPTION_CODE } from 'src/enums/exceptionCode'; @@ -75,33 +75,58 @@ export class SurveyMetaService { return await this.surveyRepository.save(newSurvey); } + async pausingSurveyMeta(survey: SurveyMeta) { + if ( + survey.curStatus.status !== RECORD_STATUS.PUBLISHED || + (survey?.subStatus?.status && + survey?.subStatus?.status != RECORD_SUB_STATUS.EDITING) + ) { + throw new HttpException( + '问卷不能暂停', + EXCEPTION_CODE.SURVEY_STATUS_TRANSFORM_ERROR, + ); + } + const subCurStatus = { + status: RECORD_SUB_STATUS.PAUSING, + date: Date.now(), + }; + survey.subStatus = subCurStatus; + survey.curStatus.status = RECORD_STATUS.PUBLISHED; + if (Array.isArray(survey.statusList)) { + survey.statusList.push(subCurStatus); + } else { + survey.statusList = [subCurStatus]; + } + return this.surveyRepository.save(survey); + } + async editSurveyMeta(survey: SurveyMeta) { if ( survey.curStatus.status !== RECORD_STATUS.NEW && - survey.curStatus.status !== RECORD_STATUS.EDITING + survey.subStatus.status !== RECORD_SUB_STATUS.EDITING ) { const newStatus = { - status: RECORD_STATUS.EDITING, + status: RECORD_SUB_STATUS.EDITING, date: Date.now(), }; - survey.curStatus = newStatus; + survey.subStatus = newStatus; survey.statusList.push(newStatus); } return this.surveyRepository.save(survey); } async deleteSurveyMeta(survey: SurveyMeta) { - if (survey.curStatus.status === RECORD_STATUS.REMOVED) { + if (survey.subStatus.status === RECORD_SUB_STATUS.REMOVED) { throw new HttpException( '问卷已删除,不能重复删除', EXCEPTION_CODE.SURVEY_STATUS_TRANSFORM_ERROR, ); } const newStatusInfo = { - status: RECORD_STATUS.REMOVED, + status: RECORD_SUB_STATUS.REMOVED, date: Date.now(), }; - survey.curStatus = newStatusInfo; + survey.subStatus = newStatusInfo; if (Array.isArray(survey.statusList)) { survey.statusList.push(newStatusInfo); } else { @@ -127,12 +152,15 @@ export class SurveyMetaService { const query: Record = Object.assign( {}, { - 'curStatus.status': { - $ne: 'removed', + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, condition.filter, ); + if (condition.filter['curStatus.status']) { + query['subStatus.status'] = RECORD_SUB_STATUS.DEFAULT; + } if (workspaceId) { query.workspaceId = workspaceId; } else { @@ -162,12 +190,23 @@ export class SurveyMetaService { : ({ createDate: -1, } as FindOptionsOrder); - const [data, count] = await this.surveyRepository.findAndCount({ where: query, skip, take: pageSize, order, + select: [ + '_id', + 'title', + 'remark', + 'surveyType', + 'curStatus', + 'subStatus', + 'createDate', + 'owner', + 'ownerId', + 'workspaceId', + ], }); return { data, count }; } catch (error) { @@ -181,6 +220,10 @@ export class SurveyMetaService { date: Date.now(), }; surveyMeta.curStatus = curStatus; + surveyMeta.subStatus = { + status: RECORD_SUB_STATUS.DEFAULT, + date: Date.now(), + }; if (Array.isArray(surveyMeta.statusList)) { surveyMeta.statusList.push(curStatus); } else { @@ -192,8 +235,8 @@ export class SurveyMetaService { async countSurveyMetaByWorkspaceId({ workspaceId }) { const total = await this.surveyRepository.count({ workspaceId, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }); return total; diff --git a/server/src/modules/surveyResponse/__test/clientEncrypt.service.spec.ts b/server/src/modules/surveyResponse/__test/clientEncrypt.service.spec.ts index 9d2418c6..ff8a941f 100644 --- a/server/src/modules/surveyResponse/__test/clientEncrypt.service.spec.ts +++ b/server/src/modules/surveyResponse/__test/clientEncrypt.service.spec.ts @@ -3,7 +3,7 @@ import { MongoRepository } from 'typeorm'; import { ClientEncryptService } from '../services/clientEncrypt.service'; import { ClientEncrypt } from 'src/models/clientEncrypt.entity'; import { ENCRYPT_TYPE } from 'src/enums/encrypt'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { ObjectId } from 'mongodb'; import { getRepositoryToken } from '@nestjs/typeorm'; @@ -88,8 +88,8 @@ describe('ClientEncryptService', () => { expect(repository.findOne).toHaveBeenCalledWith({ where: { _id: new ObjectId(id), - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }); diff --git a/server/src/modules/surveyResponse/__test/mockResponseSchema.ts b/server/src/modules/surveyResponse/__test/mockResponseSchema.ts index bef78ad8..d07c3fdd 100644 --- a/server/src/modules/surveyResponse/__test/mockResponseSchema.ts +++ b/server/src/modules/surveyResponse/__test/mockResponseSchema.ts @@ -1,5 +1,5 @@ import { ResponseSchema } from 'src/models/responseSchema.entity'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { ObjectId } from 'mongodb'; export const mockResponseSchema: ResponseSchema = { @@ -8,6 +8,10 @@ export const mockResponseSchema: ResponseSchema = { status: RECORD_STATUS.PUBLISHED, date: 1710399368439, }, + subStatus: { + status: RECORD_SUB_STATUS.DEFAULT, + date: 1710399368439, + }, statusList: [ { status: RECORD_STATUS.PUBLISHED, diff --git a/server/src/modules/surveyResponse/__test/responseSchema.controller.spec.ts b/server/src/modules/surveyResponse/__test/responseSchema.controller.spec.ts index 497580df..2119e66b 100644 --- a/server/src/modules/surveyResponse/__test/responseSchema.controller.spec.ts +++ b/server/src/modules/surveyResponse/__test/responseSchema.controller.spec.ts @@ -3,7 +3,7 @@ import { ResponseSchemaController } from '../controllers/responseSchema.controll import { ResponseSchemaService } from '../services/responseScheme.service'; import { HttpException } from 'src/exceptions/httpException'; import { EXCEPTION_CODE } from 'src/enums/exceptionCode'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { ResponseSchema } from 'src/models/responseSchema.entity'; import { Logger } from 'src/logger'; @@ -69,6 +69,7 @@ describe('ResponseSchemaController', () => { const mockResponseSchema = { surveyPath: 'testSurveyPath', curStatus: { status: RECORD_STATUS.PUBLISHED, date: Date.now() }, + subStatus: { status: RECORD_SUB_STATUS.DEFAULT, date: Date.now() }, } as ResponseSchema; jest @@ -97,7 +98,7 @@ describe('ResponseSchemaController', () => { jest .spyOn(responseSchemaService, 'getResponseSchemaByPath') .mockResolvedValue({ - curStatus: { status: RECORD_STATUS.REMOVED }, + subStatus: { status: RECORD_SUB_STATUS.REMOVED }, } as ResponseSchema); await expect(controller.getSchema(mockQueryInfo)).rejects.toThrow( @@ -125,6 +126,9 @@ describe('ResponseSchemaController', () => { curStatus: { status: 'published', }, + subStatus: { + status: '', + }, code: { baseConf: { passwordSwitch: true, @@ -149,6 +153,9 @@ describe('ResponseSchemaController', () => { curStatus: { status: 'published', }, + subStatus: { + status: '', + }, code: { baseConf: { passwordSwitch: true, @@ -172,6 +179,9 @@ describe('ResponseSchemaController', () => { curStatus: { status: 'published', }, + subStatus: { + status: '', + }, code: { baseConf: { passwordSwitch: true, @@ -200,6 +210,9 @@ describe('ResponseSchemaController', () => { curStatus: { status: 'published', }, + subStatus: { + status: '', + }, code: { baseConf: { passwordSwitch: true, @@ -228,6 +241,9 @@ describe('ResponseSchemaController', () => { curStatus: { status: 'published', }, + subStatus: { + status: '', + }, code: { baseConf: { passwordSwitch: true, diff --git a/server/src/modules/surveyResponse/__test/surveyResponse.controller.spec.ts b/server/src/modules/surveyResponse/__test/surveyResponse.controller.spec.ts index b7b1a6eb..55a81096 100644 --- a/server/src/modules/surveyResponse/__test/surveyResponse.controller.spec.ts +++ b/server/src/modules/surveyResponse/__test/surveyResponse.controller.spec.ts @@ -18,7 +18,7 @@ import { HttpException } from 'src/exceptions/httpException'; import { SurveyNotFoundException } from 'src/exceptions/surveyNotFoundException'; import { ResponseSecurityPlugin } from 'src/securityPlugin/responseSecurityPlugin'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { SurveyResponse } from 'src/models/surveyResponse.entity'; import { Logger } from 'src/logger'; import { ResponseSchema } from 'src/models/responseSchema.entity'; @@ -335,6 +335,9 @@ describe('SurveyResponseController', () => { curStatus: { status: RECORD_STATUS.PUBLISHED, }, + subStatus: { + status: RECORD_SUB_STATUS.DEFAULT, + }, code: { baseConf: { passwordSwitch: true, diff --git a/server/src/modules/surveyResponse/__test/surveyResponse.service.spec.ts b/server/src/modules/surveyResponse/__test/surveyResponse.service.spec.ts index f91df266..bf6837c5 100644 --- a/server/src/modules/surveyResponse/__test/surveyResponse.service.spec.ts +++ b/server/src/modules/surveyResponse/__test/surveyResponse.service.spec.ts @@ -77,7 +77,7 @@ describe('SurveyResponseService', () => { expect(surveyResponseRepository.count).toHaveBeenCalledWith({ where: { surveyPath, - 'curStatus.status': { $ne: 'removed' }, + 'subStatus.status': { $ne: 'removed' }, }, }); }); diff --git a/server/src/modules/surveyResponse/controllers/responseSchema.controller.ts b/server/src/modules/surveyResponse/controllers/responseSchema.controller.ts index 8df092bf..13937f66 100644 --- a/server/src/modules/surveyResponse/controllers/responseSchema.controller.ts +++ b/server/src/modules/surveyResponse/controllers/responseSchema.controller.ts @@ -10,7 +10,7 @@ import { import { ResponseSchemaService } from '../services/responseScheme.service'; import { HttpException } from 'src/exceptions/httpException'; import { EXCEPTION_CODE } from 'src/enums/exceptionCode'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { ApiTags } from '@nestjs/swagger'; import Joi from 'joi'; import { Logger } from 'src/logger'; @@ -46,7 +46,7 @@ export class ResponseSchemaController { ); if ( !responseSchema || - responseSchema.curStatus.status === RECORD_STATUS.REMOVED + responseSchema.subStatus.status === RECORD_SUB_STATUS.REMOVED ) { throw new HttpException( '问卷已删除', @@ -82,7 +82,7 @@ export class ResponseSchemaController { // 问卷信息 const schema = await this.responseSchemaService.getResponseSchemaByPath(surveyPath); - if (!schema || schema.curStatus.status === 'removed') { + if (!schema || schema.subStatus.status === RECORD_SUB_STATUS.REMOVED) { throw new SurveyNotFoundException('该问卷不存在,无法提交'); } diff --git a/server/src/modules/surveyResponse/controllers/surveyResponse.controller.ts b/server/src/modules/surveyResponse/controllers/surveyResponse.controller.ts index af8193f3..03600d40 100644 --- a/server/src/modules/surveyResponse/controllers/surveyResponse.controller.ts +++ b/server/src/modules/surveyResponse/controllers/surveyResponse.controller.ts @@ -5,6 +5,7 @@ import { checkSign } from 'src/utils/checkSign'; import { ENCRYPT_TYPE } from 'src/enums/encrypt'; import { EXCEPTION_CODE } from 'src/enums/exceptionCode'; import { getPushingData } from 'src/utils/messagePushing'; +import { RECORD_SUB_STATUS } from 'src/enums'; import { ResponseSchemaService } from '../services/responseScheme.service'; import { CounterService } from '../services/counter.service'; @@ -73,9 +74,18 @@ export class SurveyResponseController { // 查询schema const responseSchema = await this.responseSchemaService.getResponseSchemaByPath(surveyPath); - if (!responseSchema || responseSchema.curStatus.status === 'removed') { + if ( + !responseSchema || + responseSchema.subStatus.status === RECORD_SUB_STATUS.REMOVED + ) { throw new SurveyNotFoundException('该问卷不存在,无法提交'); } + if (responseSchema?.subStatus?.status === RECORD_SUB_STATUS.PAUSING) { + throw new HttpException( + '该问卷已暂停,无法提交', + EXCEPTION_CODE.RESPONSE_PAUSING, + ); + } // 白名单的verifyId校验 const baseConf = responseSchema.code.baseConf; diff --git a/server/src/modules/surveyResponse/services/clientEncrypt.service.ts b/server/src/modules/surveyResponse/services/clientEncrypt.service.ts index 7d204d99..de6883d4 100644 --- a/server/src/modules/surveyResponse/services/clientEncrypt.service.ts +++ b/server/src/modules/surveyResponse/services/clientEncrypt.service.ts @@ -4,7 +4,7 @@ import { MongoRepository } from 'typeorm'; import { ClientEncrypt } from 'src/models/clientEncrypt.entity'; import { ENCRYPT_TYPE } from 'src/enums/encrypt'; import { ObjectId } from 'mongodb'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; @Injectable() export class ClientEncryptService { @@ -38,8 +38,8 @@ export class ClientEncryptService { return this.clientEncryptRepository.findOne({ where: { _id: new ObjectId(id), - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }); @@ -52,8 +52,8 @@ export class ClientEncryptService { }, { $set: { - curStatus: { - status: RECORD_STATUS.REMOVED, + subStatus: { + status: RECORD_SUB_STATUS.REMOVED, date: Date.now(), }, }, diff --git a/server/src/modules/surveyResponse/services/responseScheme.service.ts b/server/src/modules/surveyResponse/services/responseScheme.service.ts index 701192bf..41572438 100644 --- a/server/src/modules/surveyResponse/services/responseScheme.service.ts +++ b/server/src/modules/surveyResponse/services/responseScheme.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { MongoRepository } from 'typeorm'; import { ResponseSchema } from 'src/models/responseSchema.entity'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; @Injectable() export class ResponseSchemaService { @@ -23,12 +23,20 @@ export class ResponseSchemaService { status: RECORD_STATUS.PUBLISHED, date: Date.now(), }; + clientSurvey.subStatus = { + status: RECORD_SUB_STATUS.DEFAULT, + date: Date.now(), + }; return this.responseSchemaRepository.save(clientSurvey); } else { const curStatus = { status: RECORD_STATUS.PUBLISHED, date: Date.now(), }; + const subStatus = { + status: RECORD_SUB_STATUS.DEFAULT, + date: Date.now(), + }; const newClientSurvey = this.responseSchemaRepository.create({ title, surveyPath, @@ -36,6 +44,7 @@ export class ResponseSchemaService { pageId, curStatus, statusList: [curStatus], + subStatus, }); return this.responseSchemaRepository.save(newClientSurvey); } @@ -53,6 +62,26 @@ export class ResponseSchemaService { }); } + async pausingResponseSchema({ surveyPath }) { + const responseSchema = await this.responseSchemaRepository.findOne({ + where: { surveyPath }, + }); + if (responseSchema) { + const subStatus = { + status: RECORD_SUB_STATUS.PAUSING, + date: Date.now(), + }; + responseSchema.subStatus = subStatus; + responseSchema.curStatus.status = RECORD_STATUS.PUBLISHED; + if (Array.isArray(responseSchema.statusList)) { + responseSchema.statusList.push(subStatus); + } else { + responseSchema.statusList = [subStatus]; + } + return this.responseSchemaRepository.save(responseSchema); + } + } + async deleteResponseSchema({ surveyPath }) { const responseSchema = await this.responseSchemaRepository.findOne({ where: { surveyPath }, diff --git a/server/src/modules/surveyResponse/services/surveyResponse.service.ts b/server/src/modules/surveyResponse/services/surveyResponse.service.ts index 59fa3543..f0ad2790 100644 --- a/server/src/modules/surveyResponse/services/surveyResponse.service.ts +++ b/server/src/modules/surveyResponse/services/surveyResponse.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { MongoRepository } from 'typeorm'; import { SurveyResponse } from 'src/models/surveyResponse.entity'; +import { RECORD_SUB_STATUS } from 'src/enums'; @Injectable() export class SurveyResponseService { constructor( @@ -38,8 +39,8 @@ export class SurveyResponseService { const count = await this.surveyResponseRepository.count({ where: { surveyPath, - 'curStatus.status': { - $ne: 'removed', + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, }); diff --git a/server/src/modules/upgrade/controllers/upgrade.controller.ts b/server/src/modules/upgrade/controllers/upgrade.controller.ts new file mode 100644 index 00000000..0fb3f5d3 --- /dev/null +++ b/server/src/modules/upgrade/controllers/upgrade.controller.ts @@ -0,0 +1,18 @@ +import { Controller, Get, HttpCode } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { UpgradeService } from '../services/upgrade.service'; + +@ApiTags('survey') +@Controller('/api/upgrade') +export class UpgradeController { + constructor(private readonly upgradeService: UpgradeService) {} + + @Get('/subStatus') + @HttpCode(200) + async upgradeSubStatus() { + await this.upgradeService.upgradeSubStatus(); + return { + code: 200, + }; + } +} diff --git a/server/src/modules/upgrade/services/upgrade.service.ts b/server/src/modules/upgrade/services/upgrade.service.ts new file mode 100644 index 00000000..45998caa --- /dev/null +++ b/server/src/modules/upgrade/services/upgrade.service.ts @@ -0,0 +1,74 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { MongoRepository } from 'typeorm'; +import { SurveyMeta } from 'src/models/surveyMeta.entity'; +import { ResponseSchema } from 'src/models/ResponseSchema.entity'; +import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; + +@Injectable() +export class UpgradeService { + constructor( + @InjectRepository(SurveyMeta) + private readonly SurveyMeta: MongoRepository, + @InjectRepository(ResponseSchema) + private readonly ResponseSchema: MongoRepository, + ) {} + + async upgradeSubStatus() { + const surveyMetaList = await this.SurveyMeta.find(); + const responseSchemaList = await this.ResponseSchema.find(); + + const callBack = (v: SurveyMeta | ResponseSchema) => { + // 将主状态的REMOVED,EDITING刷到子状态 + // 主状态查一下历史数据删除前最近的状态是“新建”or“已发布 + if ( + v.curStatus.status == (RECORD_SUB_STATUS.REMOVED as any) || + v.curStatus.status == (RECORD_SUB_STATUS.EDITING as any) + ) { + const subStatus = { + status: v.curStatus.status, + date: v.curStatus.date, + }; + v.subStatus = subStatus as any; + console.log('subStatus', subStatus); + if (v.curStatus.status == (RECORD_SUB_STATUS.EDITING as any)) { + v.curStatus.status = RECORD_STATUS.PUBLISHED; + } + if (v.curStatus.status == (RECORD_SUB_STATUS.REMOVED as any)) { + for (let index = v.statusList.length; index > 0; index--) { + const item = v.statusList[index]; + if ( + item?.status == RECORD_STATUS.PUBLISHED || + item?.status == RECORD_STATUS.NEW + ) { + v.curStatus.status = item.status; + break; + } + } + } + return v; + } + if ( + v.curStatus.status == RECORD_STATUS.PUBLISHED || + v.curStatus.status == RECORD_STATUS.NEW + ) { + const subStatus = { + status: RECORD_SUB_STATUS.DEFAULT, + date: v.statusList[0].date, + }; + v.subStatus = subStatus; + } + return v; + }; + + surveyMetaList.map(async (v) => { + const item = callBack(v); + await this.SurveyMeta.save(item); + }); + + responseSchemaList.map(async (v) => { + const item = callBack(v); + await this.ResponseSchema.save(item); + }); + } +} diff --git a/server/src/modules/upgrade/upgrade.module.ts b/server/src/modules/upgrade/upgrade.module.ts new file mode 100644 index 00000000..b183d375 --- /dev/null +++ b/server/src/modules/upgrade/upgrade.module.ts @@ -0,0 +1,39 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ConfigModule } from '@nestjs/config'; + +import { MessageModule } from '../message/message.module'; + +import { UpgradeService } from './services/upgrade.service'; + +import { ResponseSchema } from 'src/models/responseSchema.entity'; +import { Counter } from 'src/models/counter.entity'; +import { SurveyResponse } from 'src/models/surveyResponse.entity'; +import { ClientEncrypt } from 'src/models/clientEncrypt.entity'; +import { Logger } from 'src/logger'; +import { SurveyMeta } from 'src/models/surveyMeta.entity'; + +import { UpgradeController } from './controllers/upgrade.controller'; + +import { AuthModule } from '../auth/auth.module'; +import { WorkspaceModule } from '../workspace/workspace.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([ + ResponseSchema, + Counter, + SurveyResponse, + ClientEncrypt, + SurveyMeta, + ]), + ConfigModule, + MessageModule, + AuthModule, + WorkspaceModule, + ], + controllers: [UpgradeController], + providers: [UpgradeService, Logger], + exports: [UpgradeService], +}) +export class UpgradeModule {} diff --git a/server/src/modules/workspace/_test/workspace.controller.spec.ts b/server/src/modules/workspace/_test/workspace.controller.spec.ts index 9431b6ce..ac5a893d 100644 --- a/server/src/modules/workspace/_test/workspace.controller.spec.ts +++ b/server/src/modules/workspace/_test/workspace.controller.spec.ts @@ -242,11 +242,15 @@ describe('WorkspaceController', () => { describe('getWorkspaceAndMember', () => { it('should return a list of workspaces and members for the user', async () => { - const req = { user: { _id: new ObjectId() } }; - - const workspaceId = new ObjectId(); const userId = new ObjectId(); - const memberList = [{ workspaceId, userId: userId }]; + jest.spyOn(userService, 'getUserListByIds').mockResolvedValue([ + { + _id: userId, + }, + ] as Array); + const req = { user: { _id: userId } }; + const workspaceId = new ObjectId(); + const memberList = [{ workspaceId, userId }]; const workspaces = [{ _id: workspaceId, name: 'Test Workspace' }]; const userList = [{ _id: userId, username: 'Test User' }]; diff --git a/server/src/modules/workspace/services/workspace.service.ts b/server/src/modules/workspace/services/workspace.service.ts index fb097a7a..4c91e666 100644 --- a/server/src/modules/workspace/services/workspace.service.ts +++ b/server/src/modules/workspace/services/workspace.service.ts @@ -6,7 +6,7 @@ import { Workspace } from 'src/models/workspace.entity'; import { SurveyMeta } from 'src/models/surveyMeta.entity'; import { ObjectId } from 'mongodb'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; interface FindAllByIdWithPaginationParams { workspaceIdList: string[]; @@ -56,8 +56,8 @@ export class WorkspaceService { _id: { $in: workspaceIdList.map((item) => new ObjectId(item)), }, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }; @@ -91,8 +91,8 @@ export class WorkspaceService { _id: { $in: workspaceIdList.map((m) => new ObjectId(m)), }, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }; if (name) { @@ -115,7 +115,7 @@ export class WorkspaceService { async delete(id: string) { const newStatus = { - status: RECORD_STATUS.REMOVED, + status: RECORD_SUB_STATUS.REMOVED, date: Date.now(), }; const workspaceRes = await this.workspaceRepository.updateOne( @@ -124,7 +124,7 @@ export class WorkspaceService { }, { $set: { - curStatus: newStatus, + subStatus: newStatus, }, $push: { statusList: newStatus as never, @@ -137,7 +137,7 @@ export class WorkspaceService { }, { $set: { - curStatus: newStatus, + subStatus: newStatus, }, $push: { statusList: newStatus as never, @@ -155,8 +155,8 @@ export class WorkspaceService { return await this.workspaceRepository.find({ where: { ownerId: userId, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, order: { diff --git a/server/src/modules/workspace/services/workspaceMember.service.ts b/server/src/modules/workspace/services/workspaceMember.service.ts index 2f711963..b8485f13 100644 --- a/server/src/modules/workspace/services/workspaceMember.service.ts +++ b/server/src/modules/workspace/services/workspaceMember.service.ts @@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { MongoRepository } from 'typeorm'; import { WorkspaceMember } from 'src/models/workspaceMember.entity'; import { ObjectId } from 'mongodb'; -import { RECORD_STATUS } from 'src/enums'; +import { RECORD_SUB_STATUS } from 'src/enums'; @Injectable() export class WorkspaceMemberService { @@ -94,8 +94,8 @@ export class WorkspaceMemberService { return this.workspaceMemberRepository.find({ where: { workspaceId, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }, select: ['_id', 'createDate', 'curStatus', 'role', 'userId'], @@ -135,8 +135,8 @@ export class WorkspaceMemberService { async countByWorkspaceId({ workspaceId }) { return this.workspaceMemberRepository.count({ workspaceId, - 'curStatus.status': { - $ne: RECORD_STATUS.REMOVED, + 'subStatus.status': { + $ne: RECORD_SUB_STATUS.REMOVED, }, }); } diff --git a/server/src/utils/surveyUtil.ts b/server/src/utils/surveyUtil.ts index a67cf157..d8987a04 100644 --- a/server/src/utils/surveyUtil.ts +++ b/server/src/utils/surveyUtil.ts @@ -20,6 +20,7 @@ export function getFilter(filterList: Array) { 'remark', 'surveyType', 'curStatus.status', + 'subStatus.status', ]; return filterList.reduce( (preItem, curItem) => { diff --git a/web/src/management/api/survey.js b/web/src/management/api/survey.js index 8cbc1444..2174c7c8 100644 --- a/web/src/management/api/survey.js +++ b/web/src/management/api/survey.js @@ -52,3 +52,13 @@ export const deleteSurvey = (surveyId) => { export const updateSurvey = (data) => { return axios.post('/survey/updateMeta', data) } + +export const pausingSurvey= (surveyId) => { + return axios.post('/survey/pausingSurvey', { + surveyId + }) +} + +export const upgradeSubStatus = () => { + return axios.get('/upgrade/subStatus') +} \ No newline at end of file diff --git a/web/src/management/config/listConfig.js b/web/src/management/config/listConfig.js index 8a558651..c095c60a 100644 --- a/web/src/management/config/listConfig.js +++ b/web/src/management/config/listConfig.js @@ -66,7 +66,7 @@ export const fieldConfig = { }, updateDate: { title: '更新时间', - key: 'curStatus.date', + key: 'subStatus.date', minWidth: 200 }, createDate: { @@ -98,14 +98,37 @@ export const noSearchDataConfig = { img: '/imgs/icons/list-empty.webp' } -export const statusMaps = { - new: '未发布', - editing: '修改中', - published: '已发布', - removed: '', - pausing: '' +export const curStatus = { + new: { + value: 'new', + label: '未发布' + }, + published: { + value: 'published', + label: '已发布' + } } +// 子状态 +export const subStatus = { + editing: { + label: '修改中', + value: 'editing' + }, + pausing: { + label: '暂停中', + value: 'pausing' + } +} + +export const statusMaps = { + ...Object.fromEntries(Object.keys(curStatus).map(key => ([key, curStatus[key].label]))), + ...Object.fromEntries(Object.keys(subStatus).map(key => ([key, subStatus[key].label]))) +} + +export const curStatusKey = 'curStatus.status'; +export const subStatusKey = 'subStatus.status'; + // 问卷类型 export const surveyTypeSelect = { label: '问卷类型', @@ -146,29 +169,21 @@ export const curStatusSelect = { value: '', label: '全部状态' }, - { - value: 'new', - label: '未发布' - }, - { - value: 'published', - label: '已发布' - }, - { - value: 'editing', - label: '修改中' - } + curStatus.new, + curStatus.published, + subStatus.editing, + subStatus.pausing ], default: '' } export const selectOptionsDict = Object.freeze({ surveyType: surveyTypeSelect, - 'curStatus.status': curStatusSelect + status: curStatusSelect, }) export const buttonOptionsDict = Object.freeze({ - 'curStatus.date': { + 'subStatus.date': { label: '更新时间', icons: [ { diff --git a/web/src/management/pages/list/components/BaseList.vue b/web/src/management/pages/list/components/BaseList.vue index 49e5ba87..e61c739f 100644 --- a/web/src/management/pages/list/components/BaseList.vue +++ b/web/src/management/pages/list/components/BaseList.vue @@ -42,6 +42,7 @@ @row-click="onRowClick" > + { return data.value.map((item) => { return { ...item, - 'curStatus.date': item.curStatus.date + 'curStatus.date': item.curStatus.date, + 'subStatus.date': item.subStatus.date } }) }) -const filter = computed(() => { - return [ - { - comparator: '', - condition: [ - { - field: 'title', - value: searchVal.value, - comparator: '$regex' - } - ] - }, - { - comparator: '', - condition: [ - { - field: 'curStatus.status', - value: selectValueMap.value['curStatus.status'] - } - ] - }, - { - comparator: '', - condition: [ - { - field: 'surveyType', - value: selectValueMap.value.surveyType - } - ] - } - ] -}) + const order = computed(() => { const formatOrder = Object.entries(buttonValueMap.value) .filter(([, effectValue]) => effectValue) @@ -245,14 +218,8 @@ const order = computed(() => { }) const onRefresh = async () => { - const filterString = JSON.stringify( - filter.value.filter((item) => { - return item.condition[0].value - }) - ) let params = { curPage: currentPage.value, - filter: filterString, order: order.value } if (workSpaceId.value) { @@ -286,6 +253,10 @@ const getToolConfig = (row) => { key: 'release', label: '投放' }, + { + key: subStatus.pausing.value, + label: '暂停' + }, { key: 'cooper', label: '协作' @@ -306,6 +277,10 @@ const getToolConfig = (row) => { if (row.currentPermissions.includes(SurveyPermissions.SurveyManage)) { // 协作人判断权限显示投放按钮 funcList.push( + { + key: subStatus.pausing.value, + label: '暂停' + }, { key: QOP_MAP.EDIT, label: '修改' @@ -339,7 +314,12 @@ const getToolConfig = (row) => { permissionsBtn.splice(-1) funcList = permissionsBtn } - const order = ['edit', 'analysis', 'release', 'delete', 'copy', 'cooper'] + const order = ['edit', 'analysis', 'release', 'pausing', 'delete', 'copy', 'cooper'] + if((row.curStatus.status !== curStatus.published.value && row.curStatus.status !== subStatus.editing.value) || (row.subStatus.status && + row.subStatus.status != subStatus.editing.value)){ + order.splice(3, 1) + funcList = funcList.filter(item => item.key !== subStatus.pausing.value) + } const result = funcList.sort((a, b) => order.indexOf(a.key) - order.indexOf(b.key)) return result @@ -374,6 +354,9 @@ const handleClick = (key, data) => { case 'cooper': onCooper(data) return + case 'pausing': + onPausing(data) + return default: return } @@ -398,6 +381,26 @@ const onDelete = async (row) => { ElMessage.error(res.errmsg || '删除失败') } } + +const onPausing = async (row) => { + try { + await ElMessageBox.confirm('“暂停回收”后问卷将不能填写,是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + } catch (error) { + console.log('取消暂停') + return + } + const res = await pausingSurvey(row._id) + if (res.code === CODE_MAP.SUCCESS) { + ElMessage.success('暂停成功') + onRefresh() + } else { + ElMessage.error(res.errmsg || '暂停失败') + } +} const handleCurrentChange = (current) => { currentPage.value = current onRefresh() diff --git a/web/src/management/pages/list/components/StateModule.vue b/web/src/management/pages/list/components/StateModule.vue index ecbae312..5e7ecd03 100644 --- a/web/src/management/pages/list/components/StateModule.vue +++ b/web/src/management/pages/list/components/StateModule.vue @@ -1,23 +1,23 @@ -