diff --git a/pom.xml b/pom.xml
index 3f0e4094..0816680b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -276,6 +276,12 @@
gson
2.10.1
+
+
+ com.itextpdf
+ itextpdf
+ 5.5.13.2
+
diff --git a/src/main/java/com/ai/da/common/constant/CommonConstant.java b/src/main/java/com/ai/da/common/constant/CommonConstant.java
index 09496110..15372e9b 100644
--- a/src/main/java/com/ai/da/common/constant/CommonConstant.java
+++ b/src/main/java/com/ai/da/common/constant/CommonConstant.java
@@ -1,5 +1,8 @@
package com.ai.da.common.constant;
+import java.util.Arrays;
+import java.util.List;
+
public class CommonConstant {
// 单位 秒 10分钟过期
// public static final Long TASK_EXPIRE_TIME = 24 * 60 * 60L;
@@ -31,6 +34,29 @@ public class CommonConstant {
public static final String PYTHON_PORT_9997 = "9997";
+ public static final List AGES_EN = Arrays.asList("Below 20", "20-30", "30-40", "40+");
+ public static final List AGES_CN = Arrays.asList("20岁以下", "20-30岁", "30-40岁", "40+岁");
+ public static final List IF_HELPFUL_EN = Arrays.asList("Easy to learn and use", "Easy to get trend information",
+ "Lots of creative design proposals","The AIGC functions for moodboard is helpful","The AIGC functions for design sketches is helpful",
+ "Easy to select the right color","The Chatbot function is helpful","The print position function is helpful",
+ "The drawing function is helpful","The export function is useful","Easy to edit the design","Others");
+
+ public static final List IF_HELPFUL_CN = Arrays.asList("易于学习和使用", "容易获取趋势信息",
+ "提供大量创意设计方案","AIGC功能对灵感板有帮助","AIGC功能对设计草图有帮助",
+ "容易选择合适的颜色","聊天机器人功能有帮助","打印位置功能有帮助",
+ "绘图功能有帮助","导出功能有用","设计编辑简单","其他");
+
+ public static final List IF_IMPROVE_EN = Arrays.asList("Proposed designs are boring, need more interesting designs",
+ "Difficult to make changes on design","Only 2D output, no 3D results","Difficult to apply keywords for AIGC generation",
+ "Clothing is not in the right proportion","Not compatible with pattern making solutions","Improved user interface for better navigation",
+ "Lack of responsive customer support","Insufficient tutorial or guidance for new users","Limited personalization options for designs","Others");
+
+ public static final List IF_IMPROVE_CN = Arrays.asList("提供的设计很无聊,需要更多有趣的设计",
+ "设计修改困难","只有2D输出,没有3D结果","难以选择合适的关键词应用于AIGC生成",
+ "服装比例不正确","与打版解决方案不兼容","改进用户界面以便更好导航",
+ "客户支持响应不及时","对新用户的教程或指导不足","设计个性化选项有限","其他");
+
+ public static final List IS_SUBSCRIBE = Arrays.asList("yes", "no");
}
diff --git a/src/main/java/com/ai/da/common/utils/S3Util.java b/src/main/java/com/ai/da/common/utils/S3Util.java
index 705aca7b..7e084f6f 100644
--- a/src/main/java/com/ai/da/common/utils/S3Util.java
+++ b/src/main/java/com/ai/da/common/utils/S3Util.java
@@ -255,6 +255,22 @@ public class S3Util {
}
}
+ public String getPreSignedUrl(String path, int expiry, boolean resetCache) {
+ if (resetCache || LocalCacheUtils.getPresignedUrlCache(path) == null) {
+ if (!path.contains("/")) {
+ throw new BusinessException("The path is error!");
+ }
+ int index = path.indexOf("/");
+ String bucketName = path.substring(0, index);
+ String fileName = path.substring(index + 1);
+ String presignedUrl = getPreSignatureUrl(bucketName, fileName, expiry);
+ LocalCacheUtils.setPresignedUrlCache(path, presignedUrl);
+ return presignedUrl;
+ } else {
+ return LocalCacheUtils.getPresignedUrlCache(path);
+ }
+ }
+
/**
* @param keyName key名称: test/2022/06/123.pdf
* @param signatureDurationTime 有效期 单位:秒
diff --git a/src/main/java/com/ai/da/controller/ConvenientInquiryController.java b/src/main/java/com/ai/da/controller/ConvenientInquiryController.java
index 4b4526bd..93c00239 100644
--- a/src/main/java/com/ai/da/controller/ConvenientInquiryController.java
+++ b/src/main/java/com/ai/da/controller/ConvenientInquiryController.java
@@ -7,6 +7,9 @@ import com.ai.da.mapper.primary.DesignMapper;
import com.ai.da.mapper.primary.TrialOrderMapper;
import com.ai.da.mapper.primary.entity.TrialOrder;
import com.ai.da.model.dto.UserDesignStatisticDTO;
+import com.ai.da.model.vo.QuestionnaireFeedbackVO;
+import com.ai.da.model.vo.QuestionnaireVO;
+import com.ai.da.service.ConvenientInquiryService;
import io.netty.util.internal.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -30,6 +33,10 @@ public class ConvenientInquiryController {
@Resource
private DesignMapper designMapper;
+ @Resource
+ private ConvenientInquiryService convenientInquiryService;
+
+
@ApiOperation("获取当前所有试用用户")
@GetMapping("/getTrial")
public Response> getTrial(){
@@ -60,4 +67,18 @@ public class ConvenientInquiryController {
}
}
+
+ //调查问卷
+ @ApiOperation("获取调查问卷统计详情")
+ @GetMapping("/getQuestionnaireStatistic")
+ public Response getQuestionnaire(){
+ return Response.success(convenientInquiryService.getQuestionnaireInfo());
+ }
+
+ @ApiOperation("获取所有调查问卷")
+ @GetMapping("/getAllQuestionnaire")
+ public Response> getAllQuestionnaire(){
+ return Response.success(convenientInquiryService.getAllQuestionnaire());
+ }
+
}
diff --git a/src/main/java/com/ai/da/model/vo/QuestionnaireFeedbackVO.java b/src/main/java/com/ai/da/model/vo/QuestionnaireFeedbackVO.java
new file mode 100644
index 00000000..baae7b41
--- /dev/null
+++ b/src/main/java/com/ai/da/model/vo/QuestionnaireFeedbackVO.java
@@ -0,0 +1,45 @@
+package com.ai.da.model.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class QuestionnaireFeedbackVO {
+ private Info age;
+ private Info question1;
+ private Info question2;
+ private Info question3;
+ private List otherDesignTools;
+
+ public QuestionnaireFeedbackVO() {
+ }
+
+ public QuestionnaireFeedbackVO(Info age, Info question1, Info question2, Info question3, List otherDesignTools) {
+ this.age = age;
+ this.question1 = question1;
+ this.question2 = question2;
+ this.question3 = question3;
+ this.otherDesignTools = otherDesignTools;
+ }
+
+ public static class Info{
+ public List name;
+ public List values;
+ public List otherReason;
+
+ public Info() {
+ }
+
+ public Info(List name, List values) {
+ this.name = name;
+ this.values = values;
+ }
+
+ public Info(List name, List values, List otherReason) {
+ this.name = name;
+ this.values = values;
+ this.otherReason = otherReason;
+ }
+ }
+}
diff --git a/src/main/java/com/ai/da/service/ConvenientInquiryService.java b/src/main/java/com/ai/da/service/ConvenientInquiryService.java
new file mode 100644
index 00000000..30bffc86
--- /dev/null
+++ b/src/main/java/com/ai/da/service/ConvenientInquiryService.java
@@ -0,0 +1,15 @@
+package com.ai.da.service;
+
+import com.ai.da.mapper.primary.entity.Questionnaire;
+import com.ai.da.model.vo.QuestionnaireFeedbackVO;
+import com.ai.da.model.vo.QuestionnaireVO;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface ConvenientInquiryService extends IService {
+
+ QuestionnaireFeedbackVO getQuestionnaireInfo();
+
+ List getAllQuestionnaire();
+}
diff --git a/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java b/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java
new file mode 100644
index 00000000..efd00abb
--- /dev/null
+++ b/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java
@@ -0,0 +1,217 @@
+package com.ai.da.service.impl;
+
+import com.ai.da.common.constant.CommonConstant;
+import com.ai.da.common.context.UserContext;
+import com.ai.da.mapper.primary.QuestionnaireMapper;
+import com.ai.da.mapper.primary.entity.Account;
+import com.ai.da.mapper.primary.entity.Questionnaire;
+import com.ai.da.model.vo.QuestionnaireFeedbackVO;
+import com.ai.da.model.vo.QuestionnaireVO;
+import com.ai.da.service.AccountService;
+import com.ai.da.service.ConvenientInquiryService;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.pdf.BaseFont;
+import io.netty.util.internal.StringUtil;
+import org.springframework.stereotype.Service;
+
+import com.itextpdf.text.Document;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.pdf.PdfWriter;
+
+import javax.annotation.Resource;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Service
+public class ConvenientInquiryServiceImpl extends ServiceImpl implements ConvenientInquiryService {
+
+ @Resource
+ private AccountService accountService;
+
+
+ public QuestionnaireFeedbackVO getQuestionnaireInfo() {
+ String title = "AiDA_3.0 Feedback Survey--06/2024";
+ List questionnaires = queryByTitle(title);
+ List ageValue = new ArrayList<>(Collections.nCopies(4, 0));
+ List question1Value = new ArrayList<>(Collections.nCopies(12, 0));
+ List question2Value = new ArrayList<>(Collections.nCopies(11, 0));
+ List question3Value = new ArrayList<>(Collections.nCopies(2, 0));
+ List question4Value = new ArrayList<>();
+ ArrayList othersReason1 = new ArrayList<>();
+ ArrayList othersReason2 = new ArrayList<>();
+ ArrayList othersReason3 = new ArrayList<>();
+
+ for (Questionnaire questionnaire : questionnaires) {
+ QuestionnaireVO questionnaireVO = JSON.parseObject(questionnaire.getQuestionnaireInfo(), QuestionnaireVO.class);
+ // 统计年龄区间
+ String age = questionnaireVO.getAge();
+ if (age.contains("20-30")) {
+ Integer num = ageValue.get(1);
+ ageValue.set(1, ++num);
+ } else if (age.contains("30-40")) {
+ Integer num = ageValue.get(2);
+ ageValue.set(2, ++num);
+ } else if (age.contains("40+")) {
+ Integer num = ageValue.get(3);
+ ageValue.set(3, ++num);
+ } else {
+ Integer num = ageValue.get(0);
+ ageValue.set(0, ++num);
+ }
+
+ // How has AiDA been helpful to you? 统计
+ List helpful = questionnaireVO.getHelpful();
+ helpful.forEach(item -> {
+ if (item.matches("\\d+")) {
+ Integer num = question1Value.get(Integer.parseInt(item) - 1);
+ question1Value.set(Integer.parseInt(item) - 1, ++num);
+ } else {
+ Integer num = question1Value.get(11);
+ question1Value.set(11, ++num);
+ othersReason1.add(item);
+ }
+ });
+
+ // What do you think AiDA should improve? 统计
+ List improve = questionnaireVO.getImprove();
+ improve.forEach(item -> {
+ if (item.matches("\\d+")) {
+ Integer num = question2Value.get(Integer.parseInt(item) - 1);
+ question2Value.set(Integer.parseInt(item) - 1, ++num);
+ } else {
+ Integer num = question2Value.get(10);
+ question2Value.set(10, ++num);
+ othersReason2.add(item);
+ }
+ });
+
+ // Will you subscribe to AiDA 3.0?
+ String isSubscribe = questionnaireVO.getIsSubscribe();
+ if (isSubscribe.equals("yes")) {
+ Integer num = question3Value.get(0);
+ question3Value.set(0, ++num);
+ } else {
+ Integer num = question3Value.get(1);
+ question3Value.set(1, ++num);
+ othersReason3.add(String.join(",", questionnaireVO.getReasonForNotSubscribe()));
+ }
+ if (!StringUtil.isNullOrEmpty(questionnaireVO.getDesignTools())) {
+ question4Value.add(questionnaireVO.getDesignTools());
+ }
+ }
+
+ String language = UserContext.getUserHolder().getLanguage();
+ List ageName;
+ List question1Name;
+ List question2Name;
+ if (language.equals("English")) {
+ ageName = CommonConstant.AGES_EN;
+ question1Name = CommonConstant.IF_HELPFUL_EN;
+ question2Name = CommonConstant.IF_IMPROVE_EN;
+ } else {
+ ageName = CommonConstant.AGES_CN;
+ question1Name = CommonConstant.IF_HELPFUL_CN;
+ question2Name = CommonConstant.IF_IMPROVE_CN;
+ }
+ return new QuestionnaireFeedbackVO(
+ new QuestionnaireFeedbackVO.Info(ageName, ageValue),
+ new QuestionnaireFeedbackVO.Info(question1Name, question1Value, othersReason1),
+ new QuestionnaireFeedbackVO.Info(question2Name, question2Value, othersReason2),
+ new QuestionnaireFeedbackVO.Info(CommonConstant.IS_SUBSCRIBE, question3Value, othersReason3),
+ question4Value
+ );
+ }
+
+ private List queryByTitle(String title) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("title", title);
+ return baseMapper.selectList(queryWrapper);
+ }
+
+ public List getAllQuestionnaire() {
+ String title = "AiDA_3.0 Feedback Survey--06/2024";
+ List questionnaires = queryByTitle(title);
+ ArrayList questionnaireVOS = new ArrayList<>();
+
+ questionnaires.forEach(item -> {
+ QuestionnaireVO questionnaireVO = JSON.parseObject(item.getQuestionnaireInfo(), QuestionnaireVO.class);
+ questionnaireVOS.add(questionnaireVO);
+ }
+ );
+
+ return questionnaireVOS;
+ }
+
+
+ // 输出为pdf 需要自己组装pdf内容
+ // 解决iText不显示中文问题
+ public static void main(String[] args) {
+ try {
+ // 创建文档
+ Document document = new Document();
+ PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
+ document.open();
+
+ // 加载字体文件
+ InputStream inputStream = ConvenientInquiryServiceImpl.class.getResourceAsStream("/font/msyhl.ttc");
+ byte[] fontBytes = toByteArray(inputStream);
+ inputStream.close();
+
+ // 创建BaseFont和Font对象
+ BaseFont baseFont = BaseFont.createFont("msyhl.ttc,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, fontBytes, null);
+ Font yaHeiFont = new Font(baseFont, 12, Font.NORMAL);
+
+ // 添加带有中文字体的段落
+ document.add(new Paragraph("你好,世界!", yaHeiFont));
+
+ document.close();
+ } catch (DocumentException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // 将InputStream转换为字节数组
+ public static byte[] toByteArray(InputStream input) throws IOException {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ }
+ return output.toByteArray();
+ }
+
+ /**
+ * 近期新增用户
+ * @param startTime 开始时间
+ * @param endTime 结束时间
+ * @param userType 用户类型 visitor\trial\official
+ * @return
+ */
+ public List recentNewUser(String startTime, String endTime, String userType){
+ if (StringUtil.isNullOrEmpty(startTime) && StringUtil.isNullOrEmpty(endTime) && StringUtil.isNullOrEmpty(userType)){
+ return null;
+ }
+
+ int type = userType.equals("visitor") ? 0 : userType.equals("trial") ? 1 : 2;
+ return accountService.getByDateAndUserType(startTime, endTime, type);
+ }
+
+ // 近期活跃用户
+ public List recentActiveUser(String startTime, String endTime){
+ return null;
+ }
+
+
+
+}
diff --git a/src/main/resources/font/msyhl.ttc b/src/main/resources/font/msyhl.ttc
new file mode 100644
index 00000000..c1850925
Binary files /dev/null and b/src/main/resources/font/msyhl.ttc differ