代码拉取完成,页面将自动刷新
package com.yupi.bi.controller;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.bi.annotation.AuthCheck;
import com.yupi.bi.bizmq.BiMessageProducer;
import com.yupi.bi.common.BaseResponse;
import com.yupi.bi.common.DeleteRequest;
import com.yupi.bi.common.ErrorCode;
import com.yupi.bi.common.ResultUtils;
import com.yupi.bi.constant.CommonConstant;
import com.yupi.bi.constant.UserConstant;
import com.yupi.bi.exception.BusinessException;
import com.yupi.bi.exception.ThrowUtils;
import com.yupi.bi.manager.AiManager;
import com.yupi.bi.manager.RedisLimiterManager;
import com.yupi.bi.model.dto.chart.*;
import com.yupi.bi.model.entity.Chart;
import com.yupi.bi.model.entity.User;
import com.yupi.bi.model.enums.ChartStatusEnum;
import com.yupi.bi.model.vo.BiResponse;
import com.yupi.bi.service.ChartService;
import com.yupi.bi.service.UserService;
import com.yupi.bi.utils.ExcelUtills;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 图表接口
* @author yupi
*/
@RestController
@RequestMapping("/chart")
@Slf4j
public class ChartController {
@Resource
private ChartService chartService;
@Resource
private UserService userService;
@Resource
private AiManager aiManager;
@Resource
private RedisLimiterManager redisLimiterManager;
@Resource
private ThreadPoolExecutor threadPoolExecutor;
@Resource
private BiMessageProducer biMessageProducer;
/**
* 创建
*
* @param chartAddRequest
* @param request
* @return
*/
@PostMapping("/add")
public BaseResponse<Long> addChart(@RequestBody ChartAddRequest chartAddRequest, HttpServletRequest request) {
if (chartAddRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Chart chart = new Chart();
BeanUtils.copyProperties(chartAddRequest, chart);
User loginUser = userService.getLoginUser(request);
chart.setUserId(loginUser.getId());
boolean result = chartService.save(chart);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
long newChartId = chart.getId();
return ResultUtils.success(newChartId);
}
/**
* 删除
*
* @param deleteRequest
* @param request
* @return
*/
@PostMapping("/delete")
public BaseResponse<Boolean> deleteChart(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
if (deleteRequest == null || deleteRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User user = userService.getLoginUser(request);
long id = deleteRequest.getId();
// 判断是否存在
Chart oldChart = chartService.getById(id);
ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可删除
if (!oldChart.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
boolean b = chartService.removeById(id);
return ResultUtils.success(b);
}
/**
* 更新(仅管理员)
*
* @param chartUpdateRequest
* @return
*/
@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> updateChart(@RequestBody ChartUpdateRequest chartUpdateRequest) {
if (chartUpdateRequest == null || chartUpdateRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Chart chart = new Chart();
BeanUtils.copyProperties(chartUpdateRequest, chart);
long id = chartUpdateRequest.getId();
// 判断是否存在
Chart oldChart = chartService.getById(id);
ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR);
boolean result = chartService.updateById(chart);
return ResultUtils.success(result);
}
/**
* 根据 id 获取
*
* @param id
* @return
*/
@GetMapping("/get")
public BaseResponse<Chart> getChartById(long id, HttpServletRequest request) {
if (id <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Chart chart = chartService.getById(id);
if (chart == null) {
throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
}
return ResultUtils.success(chart);
}
/**
* 分页获取列表(封装类)
*
* @param chartQueryRequest
* @param request
* @return
*/
@PostMapping("/list/page")
public BaseResponse<Page<Chart>> listChartByPage(@RequestBody ChartQueryRequest chartQueryRequest,
HttpServletRequest request) {
long current = chartQueryRequest.getCurrent();
long size = chartQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
Page<Chart> chartPage = chartService.page(new Page<>(current, size),
chartService.getQueryWrapper(chartQueryRequest));
return ResultUtils.success(chartPage);
}
/**
* 分页获取当前用户创建的资源列表
*
* @param chartQueryRequest
* @param request
* @return
*/
@PostMapping("/my/list/page")
public BaseResponse<Page<Chart>> listMyChartByPage(@RequestBody ChartQueryRequest chartQueryRequest,
HttpServletRequest request) {
if (chartQueryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User loginUser = userService.getLoginUser(request);
chartQueryRequest.setUserId(loginUser.getId());
long current = chartQueryRequest.getCurrent();
long size = chartQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
Page<Chart> chartPage = chartService.page(new Page<>(current, size),
chartService.getQueryWrapper(chartQueryRequest));
return ResultUtils.success(chartPage);
}
/**
* 编辑(用户)
*
* @param chartEditRequest
* @param request
* @return
*/
@PostMapping("/edit")
public BaseResponse<Boolean> editChart(@RequestBody ChartEditRequest chartEditRequest, HttpServletRequest request) {
if (chartEditRequest == null || chartEditRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Chart chart = new Chart();
BeanUtils.copyProperties(chartEditRequest, chart);
User loginUser = userService.getLoginUser(request);
long id = chartEditRequest.getId();
// 判断是否存在
Chart oldChart = chartService.getById(id);
ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可编辑
if (!oldChart.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
boolean result = chartService.updateById(chart);
return ResultUtils.success(result);
}
/**
* 智能分析(同步)
*
* @param multipartFile
* @param genChartByAiRequest
* @param request
* @return
*/
@PostMapping("/gen")
public BaseResponse<BiResponse> genChartByAi(@RequestPart("file") MultipartFile multipartFile,
GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) {
String goal = genChartByAiRequest.getGoal();
String name = genChartByAiRequest.getName();
String chartType = genChartByAiRequest.getChartType();
// 校验
ThrowUtils.throwIf(StringUtils.isAnyBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空");
ThrowUtils.throwIf(StringUtils.isAnyBlank(name), ErrorCode.PARAMS_ERROR, "名称为空");
ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长");
ThrowUtils.throwIf(StringUtils.isAnyBlank(chartType), ErrorCode.PARAMS_ERROR, "类型为空");
ThrowUtils.throwIf(ObjectUtils.isEmpty(multipartFile), ErrorCode.PARAMS_ERROR, "文件为空");
// 校验文件大小
long size = multipartFile.getSize();
final long TEN_MB = 10 * 1024 * 1024L;
ThrowUtils.throwIf(size > TEN_MB, ErrorCode.PARAMS_ERROR, "文件超过 10M");
// 校验文件后缀名
String originalFilename = multipartFile.getOriginalFilename();
String suffix = FileUtil.getSuffix(originalFilename);
final List<String> validFileSuffix = Collections.singletonList("xlsx");
ThrowUtils.throwIf(!validFileSuffix.contains(suffix), ErrorCode.PARAMS_ERROR, "文件后缀非法");
User loginUser = userService.getLoginUser(request);
// 用户输入
//分析需求:
//分析网站用户的增长情况
//原始数据:
//目期,用户数
//1号,10
//2号,20
//3号,30
StringBuilder userInput = new StringBuilder();
userInput.append("分析需求:").append("\n");
// 拼接分析目标
String userGoal = goal;
userGoal += ",请使用" + chartType;
userInput.append(userGoal).append("\n");
userInput.append("原始数据:").append("\n");
// userInput.append("图表类型:").append(chartType).append("\n");
// 把上传的数据转为 csv
String csvData = ExcelUtills.excelToCsv(multipartFile);
userInput.append("数据:").append(csvData);
String result = aiManager.doChart(CommonConstant.BI_MODEL_ID, userInput.toString());
System.out.println("result===>" + result);
String[] split = result.split("【【【【【");
if (split.length < 2) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "AI 生成错误");
}
String genChart = split[1].trim();
String genResult = split[2].trim();
// 插入数据库
Chart chart = new Chart();
chart.setGoal(goal);
chart.setName(name);
chart.setChartData(csvData);
chart.setChartType(chartType);
chart.setGenChart(genChart);
chart.setGenResult(genResult);
chart.setStatus(ChartStatusEnum.SUCCESS.getValue());
chart.setUserId(loginUser.getId());
boolean saveResult = chartService.save(chart);
ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败!");
BiResponse biResponse = new BiResponse();
biResponse.setGenChart(genChart);
biResponse.setGenResult(genResult);
biResponse.setChartId(chart.getId());
return ResultUtils.success(biResponse);
}
/**
* 智能分析(异步)
*
* @param multipartFile
* @param genChartByAiRequest
* @param request
* @return
*/
@PostMapping("/gen/async")
public BaseResponse<BiResponse> genChartByAiAsync(@RequestPart("file") MultipartFile multipartFile,
GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) {
String goal = genChartByAiRequest.getGoal();
String name = genChartByAiRequest.getName();
String chartType = genChartByAiRequest.getChartType();
// 校验
ThrowUtils.throwIf(StringUtils.isAnyBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空");
ThrowUtils.throwIf(StringUtils.isAnyBlank(name), ErrorCode.PARAMS_ERROR, "名称为空");
ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长");
ThrowUtils.throwIf(StringUtils.isAnyBlank(chartType), ErrorCode.PARAMS_ERROR, "类型为空");
ThrowUtils.throwIf(ObjectUtils.isEmpty(multipartFile), ErrorCode.PARAMS_ERROR, "文件为空");
// 校验文件大小
long size = multipartFile.getSize();
final long TEN_MB = 10 * 1024 * 1024L;
ThrowUtils.throwIf(size > TEN_MB, ErrorCode.PARAMS_ERROR, "文件超过 10M");
// 校验文件后缀名
String originalFilename = multipartFile.getOriginalFilename();
String suffix = FileUtil.getSuffix(originalFilename);
final List<String> validFileSuffix = Collections.singletonList("xlsx");
ThrowUtils.throwIf(!validFileSuffix.contains(suffix), ErrorCode.PARAMS_ERROR, "文件后缀非法");
User loginUser = userService.getLoginUser(request);
// 限流判断
redisLimiterManager.doRateLimit("genChartByAi_" + loginUser.getId());
// 用户输入
//分析需求:
//分析网站用户的增长情况
//原始数据:
//目期,用户数
//1号,10
//2号,20
//3号,30
StringBuilder userInput = new StringBuilder();
userInput.append("分析需求:").append("\n");
// 拼接分析目标
String userGoal = goal;
userGoal += ",请使用" + chartType;
userInput.append(userGoal).append("\n");
userInput.append("原始数据:").append("\n");
// userInput.append("图表类型:").append(chartType).append("\n");
// 把上传的数据转为 csv
String csvData = ExcelUtills.excelToCsv(multipartFile);
userInput.append("数据:").append(csvData);
// 插入数据库
Chart chart = new Chart();
chart.setGoal(goal);
chart.setName(name);
chart.setChartData(csvData);
chart.setChartType(chartType);
chart.setStatus(ChartStatusEnum.WAIT.getValue());
chart.setUserId(loginUser.getId());
boolean saveResult = chartService.save(chart);
ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败!");
// todo 建议处理任务队列满了之后,抛异常情况
CompletableFuture.runAsync(() -> {
// 先修改图表任务状态为“执行中”。等执行成功后,修改为“已完成”、保存执行结果;执行失败后,状态修改为“失败”,记录任务失败信息
Chart updateChart = new Chart();
updateChart.setId(chart.getId());
updateChart.setStatus(ChartStatusEnum.RUNNING.getValue());
boolean b = chartService.updateById(updateChart);
if (!b) {
chartService.handleChartUpdateError(chart.getId(), "更新图表执行中状态失败");
return;
}
// 调用 AI
String result = aiManager.doChart(CommonConstant.BI_MODEL_ID, userInput.toString());
System.out.println("result===>" + result);
String[] split = result.split("【【【【【");
if (split.length < 2) {
chartService.handleChartUpdateError(chart.getId(), "AI 生成错误");
return;
}
String genChart = split[1].trim();
String genResult = split[2].trim();
Chart updateChartResult = new Chart();
updateChartResult.setId(chart.getId());
updateChartResult.setGenChart(genChart);
updateChartResult.setGenResult(genResult);
updateChartResult.setStatus(ChartStatusEnum.SUCCESS.getValue());
boolean updateResult = chartService.updateById(updateChartResult);
if (!updateResult) {
chartService.handleChartUpdateError(chart.getId(), "更新图表成功状态失败");
}
}, threadPoolExecutor);
BiResponse biResponse = new BiResponse();
biResponse.setChartId(chart.getId());
return ResultUtils.success(biResponse);
}
/**
* 智能分析(异步消息队列)
*
* @param multipartFile
* @param genChartByAiRequest
* @param request
* @return
*/
@PostMapping("/gen/async/mq")
public BaseResponse<BiResponse> genChartByAiAsyncMq(@RequestPart("file") MultipartFile multipartFile,
GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) {
String goal = genChartByAiRequest.getGoal();
String name = genChartByAiRequest.getName();
String chartType = genChartByAiRequest.getChartType();
// 校验
ThrowUtils.throwIf(StringUtils.isAnyBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空");
ThrowUtils.throwIf(StringUtils.isAnyBlank(name), ErrorCode.PARAMS_ERROR, "名称为空");
ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长");
ThrowUtils.throwIf(StringUtils.isAnyBlank(chartType), ErrorCode.PARAMS_ERROR, "类型为空");
ThrowUtils.throwIf(ObjectUtils.isEmpty(multipartFile), ErrorCode.PARAMS_ERROR, "文件为空");
// 校验文件大小
long size = multipartFile.getSize();
final long TEN_MB = 10 * 1024 * 1024L;
ThrowUtils.throwIf(size > TEN_MB, ErrorCode.PARAMS_ERROR, "文件超过 10M");
// 校验文件后缀名
String originalFilename = multipartFile.getOriginalFilename();
String suffix = FileUtil.getSuffix(originalFilename);
final List<String> validFileSuffix = Collections.singletonList("xlsx");
ThrowUtils.throwIf(!validFileSuffix.contains(suffix), ErrorCode.PARAMS_ERROR, "文件后缀非法");
User loginUser = userService.getLoginUser(request);
// 限流判断
redisLimiterManager.doRateLimit("genChartByAi_" + loginUser.getId());
// 用户输入
//分析需求:
//分析网站用户的增长情况
//原始数据:
//目期,用户数
//1号,10
//2号,20
//3号,30
StringBuilder userInput = new StringBuilder();
userInput.append("分析需求:").append("\n");
// 拼接分析目标
String userGoal = goal;
userGoal += ",请使用" + chartType;
userInput.append(userGoal).append("\n");
userInput.append("原始数据:").append("\n");
// userInput.append("图表类型:").append(chartType).append("\n");
// 把上传的数据转为 csv
String csvData = ExcelUtills.excelToCsv(multipartFile);
userInput.append("数据:").append(csvData);
// 插入数据库
Chart chart = new Chart();
chart.setGoal(goal);
chart.setName(name);
chart.setChartData(csvData);
chart.setChartType(chartType);
chart.setStatus(ChartStatusEnum.WAIT.getValue());
chart.setUserId(loginUser.getId());
boolean saveResult = chartService.save(chart);
ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败!");
long newChartId = chart.getId();
// 发消息
biMessageProducer.sendMessage(String.valueOf(newChartId));
BiResponse biResponse = new BiResponse();
biResponse.setChartId(newChartId);
return ResultUtils.success(biResponse);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。