【XIAOJUSURVEY& 北大】实现数据导出的前后端全流程

 导读:本专栏主要分享同学们在XIAOJUSURVEY&北大开源实践课程的学习成果。
专栏背景:【XIAOJUSURVEY&北大】2024滴滴开源XIAOJUSURVEY北大软微开源实践课
文内项目Github:XIAOJUSURVEY

作者:Oseast

背景

本文主要是实现下载中心的源码分析,为了实现数据的导出有以下几个基本功能:

  1. 整合问卷回收内容

  2. 获取已经整合导出的问卷列表

  3. 下载问卷到本地

  4. 后台的文件删除

这四个基本功能就对应了四个api请求,这四个请求实现如下分析。

一、整合问卷回收内容

要定位问卷回收内容可通过前端返回指定的问卷元数据id实现,因此前端向后端发送请求必须要包括surveyId这个参数。这个参数可以在问卷分析页通过动态路由轻松获得,即:surveyId: this.$route.params.id

后端收到这个数据之后,控制器SurveyDownloadController通过mongodb查询问卷的基本题目信息交由生产者进行加工。为了防止问卷内容过多整合时间过长导致前端一直等待返回,这里实现了一个简单的消息队列进行解耦。控制器在把任务发送到消息队列上后直接返回,后续过程由后端自动完成。isMask为是否脱敏保存的标志messageService是实现的简单的消息队列responseSchema是问卷的基本配置。

const { surveyId, isMask } = value;
const responseSchema = await this.responseSchemaService.getResponseSchemaByPageId(surveyId);
const id= await this.surveyDownloadService.createDownload({
  surveyId,
  responseSchema
});
this.messageService.addMessage({
    responseSchema,
    surveyId,
    isMask,
    id,
  });
return {
  code: 200,
  data: { message: '正在生成下载文件,请稍后查看'
  },
};

在消息队列中每加入一条任务就会唤醒一位消费者,这个消费者会将问卷信息发送给surveyDownloadService进行加工:

private processMessages = async (): Promise<void> => {
    if (this.processing >= this.concurrency || this.queue.length === 0) {
      return;
    }

    const messagesToProcess = Math.min(this.queue.length, this.concurrency - this.processing);
    const messages = this.queue.splice(0, messagesToProcess);

    this.processing += messagesToProcess;

    await Promise.all(messages.map(async (message) => {
      console.log(`开始计算: ${message}`);
      await this.handleMessage(message);
      this.emit('messageProcessed', message);
    }));

    this.processing -= messagesToProcess;
    if (this.queue.length > 0) {
      setImmediate(() => this.processMessages());
    }
  };

  async handleMessage(message: QueueItem) {
    const { surveyId, responseSchema, isMask,id } = message;
    await this.surveyDownloadService.getDownloadPath({
        responseSchema,
        surveyId,
        isMask,
        id
      });
  }

surveyDownloadService先通过responseSchema获取题目的基本信息listHead,然后通过数据库收集对应问卷的回收数据,然后把回收表中的回答和题目对应起来并格式化,组成listBody,再把这两个列表保存成文件存放在后端相应位置,同时数据库中创建一个对应的信息表:

async getDownloadPath({
    surveyId,
    responseSchema,
    isMask,
    id,
  }: {
    surveyId: string;
    responseSchema: ResponseSchema;
    isMask: boolean;
    id: object;
  }) {
    const dataList = responseSchema?.code?.dataConf?.dataList || [];
    const Head = getListHeadByDataList(dataList);
    const listHead=this.formatHead(Head);
    const dataListMap = keyBy(dataList, 'field');
    const where = {
      pageId: surveyId,
      'curStatus.status': {
        $ne: 'removed',
      },
    };
    const [surveyResponseList, total] =
      await this.surveyResponseRepository.findAndCount({
        where,
        order: {
          createDate: -1,
        },
      });
    const [surveyMeta] = await this.SurveyDmetaRepository.find({
      where: {
        surveyPath: responseSchema.surveyPath,
      },
    });
    const listBody = sur
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值