| | |
| | | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import opennlp.tools.dictionary.serializer.Entry; |
| | | import org.jeecg.modules.demo.copywritingScheme.entity.CopywritingScheme; |
| | | import org.jeecg.modules.demo.copywritingScheme.service.ICopywritingSchemeService; |
| | | import org.jeecg.modules.system.entity.SysUser; |
| | | import org.jeecg.modules.system.service.ISysUserService; |
| | | import org.jetbrains.annotations.NotNull; |
| | |
| | | private ISemanticWordService semanticWordService;; |
| | | @Autowired |
| | | private ISysUserService sysUserService; |
| | | |
| | | |
| | | @Autowired |
| | | private ICopywritingSchemeService copywritingSchemeService; |
| | | /** |
| | | * 分页列表查询 |
| | | * |
| | |
| | | } |
| | | if (StringUtils.isNotBlank(copywriting.getWordLike())){ |
| | | queryWrapper.exists("SELECT 1 FROM semantic_word WHERE semantic_word.id = copywriting.word_id " + |
| | | "AND semantic_word.word LIKE '%" + copywriting.getWordLike() + "%'"); |
| | | "AND semantic_word.word LIKE '%" + copywriting.getWordLike() + "%'"); |
| | | |
| | | } |
| | | if (StringUtils.isNotBlank(copywriting.getContractId())) { |
| | | // 1. 拼接关联 contact 表的 EXISTS 子查询,使用 contact.id 作为外键关联 |
| | | // 2. 使用 MyBatis-Plus 的参数占位符避免 SQL 注入,而不是直接字符串拼接 |
| | | String existsSql = "SELECT 1 FROM semantic_word " + |
| | | "LEFT JOIN contract ON semantic_word.contract_id = contract.id " + // 关联 contact 表(外键关联) |
| | | "WHERE semantic_word.id = copywriting.word_id " + |
| | | "AND contract.id = " + copywriting.getContractId(); // 使用 contact 表的 id 作为条件 |
| | | |
| | | // 给 QueryWrapper 设置参数,避免 SQL 注入 |
| | | queryWrapper.exists(existsSql); |
| | | } |
| | | Page<Copywriting> page = new Page<Copywriting>(pageNo, pageSize); |
| | | IPage<Copywriting> pageList = copywritingService.page(page, queryWrapper); |
| | |
| | | @RequiresPermissions("copywriting:copywriting:aiCreateCopyWriting") |
| | | @RequestMapping(value = "/aiCreateCopyWriting", method = RequestMethod.POST) |
| | | public Result<?> aiCreateCopyWriting( |
| | | @RequestParam("jianli") String jianli, |
| | | @RequestParam(name = "file", required = false) String jianli, |
| | | @RequestParam(name = "url", required = false) String jianli2, |
| | | @RequestParam String wenanyaoqiu, |
| | | @RequestParam String louchu, |
| | | @RequestParam String youshang, |
| | | @RequestParam String wenti, |
| | | @RequestParam String user) { |
| | | return getResult(jianli, wenanyaoqiu, louchu, youshang, wenti, user); |
| | | @RequestParam String user, |
| | | @RequestParam String csId) { |
| | | if (csId == null){ |
| | | csId = "2020795745607319553"; |
| | | } |
| | | CopywritingScheme copywritingScheme = new CopywritingScheme(); |
| | | copywritingScheme.setId(csId); |
| | | return getResult(jianli, jianli2, wenanyaoqiu, louchu, youshang, wenti, user, copywritingScheme); |
| | | } |
| | | |
| | | public Result<?> getResult(String jianli, String wenanyaoqiu, String louchu, String youshang, String wenti, String user) { |
| | | if (jianli == null || jianli.equals("")) { |
| | | return Result.error("请选择文件"); |
| | | public Result<?> getResult(String jianli, String jianli2, String wenanyaoqiu, String louchu, String youshang, String wenti, String user, CopywritingScheme cs) { |
| | | QueryWrapper<CopywritingScheme> copywritingSchemeQueryWrapper = new QueryWrapper<>(); |
| | | |
| | | if (cs.getId() == null){ |
| | | cs.setId("2020795745607319553"); |
| | | } |
| | | copywritingSchemeQueryWrapper.eq("id", cs.getId()); |
| | | List<CopywritingScheme> list = copywritingSchemeService.list(copywritingSchemeQueryWrapper); |
| | | if(list.size()==0) { |
| | | return Result.error("方案不存在"); |
| | | } else { |
| | | cs = list.get(0); |
| | | } |
| | | // 配置信息 |
| | | String serverFileRoot = uploadPath; |
| | | String workflowUrl = "http://14.103.174.44/v1/workflows/run"; |
| | | String fileUploadUrl = "http://14.103.174.44/v1/files/upload"; // 文件上传接口(假设) |
| | | String authToken = "app-J1Tqytg0ZetcrVTF2fVHHY8B"; |
| | | String workflowUrl = cs.getWorkflowUrl(); |
| | | String fileUploadUrl = cs.getFileUploadUrl(); // 文件上传接口(假设) |
| | | String authToken = cs.getAuthToken(); |
| | | String userId = user; |
| | | String appId = "cf85fe4d-b76b-4c4c-801a-1336c880d473"; |
| | | String appId = cs.getAppId(); |
| | | |
| | | try { |
| | | // 步骤1:上传简历文件,获取 upload_file_id 列表 |
| | | List<String> jianliFileList = Arrays.asList(jianli.split(",")); |
| | | List<String> jianliFileIds = new ArrayList<>(); |
| | | for (String fileName : jianliFileList) { |
| | | // 修正:只过滤路径遍历字符,保留合法的 / |
| | | String safeFileName = File.separator + fileName.trim() |
| | | // 过滤 ../ 和 ./ 序列(防止访问上级目录) |
| | | .replaceAll("\\.\\./", "") |
| | | .replaceAll("\\./", ""); |
| | | Map<String, Object> inputs = new HashMap<>(); |
| | | if (jianli != null) { |
| | | // 步骤2:构建 inputs 参数(按接口要求格式) |
| | | List<String> jianliFileList = Arrays.asList(jianli.split(",")); |
| | | if (jianliFileList != null && !jianliFileList.isEmpty()) { |
| | | // 步骤1:上传简历文件,获取 upload_file_id 列表 |
| | | List<String> jianliFileIds = new ArrayList<>(); |
| | | for (String fileName : jianliFileList) { |
| | | // 修正:只过滤路径遍历字符,保留合法的 / |
| | | String safeFileName = File.separator + fileName.trim() |
| | | // 过滤 ../ 和 ./ 序列(防止访问上级目录) |
| | | .replaceAll("\\.\\./", "") |
| | | .replaceAll("\\./", ""); |
| | | |
| | | // 进一步安全校验:确保拼接后的文件路径在服务器根目录下(核心安全措施) |
| | | File file = new File(serverFileRoot + safeFileName); |
| | | String canonicalPath = file.getCanonicalPath(); // 获取标准化路径(自动解析 ../ 等) |
| | | String canonicalRootPath = new File(serverFileRoot).getCanonicalPath(); |
| | | File file = new File(serverFileRoot + safeFileName); |
| | | String canonicalPath = file.getCanonicalPath(); // 获取标准化路径(自动解析 ../ 等) |
| | | String canonicalRootPath = new File(serverFileRoot).getCanonicalPath(); |
| | | |
| | | // 校验:如果文件路径不在服务器根目录下,视为非法请求 |
| | | if (!canonicalPath.startsWith(canonicalRootPath)) { |
| | | throw new RuntimeException("非法文件访问:" + fileName); |
| | | } |
| | | if (!canonicalPath.startsWith(canonicalRootPath)) { |
| | | throw new RuntimeException("非法文件访问:" + fileName); |
| | | } |
| | | |
| | | // 再判断文件是否存在 |
| | | if (!file.exists() || !file.isFile()) { |
| | | return Result.error("服务器不存在文件:" + safeFileName + ",路径:" + file.getAbsolutePath()); |
| | | if (!file.exists() || !file.isFile()) { |
| | | return Result.error("服务器不存在文件:" + safeFileName + ",路径:" + file.getAbsolutePath()); |
| | | } |
| | | // 调用文件上传接口,获取 upload_file_id |
| | | String fileId = uploadFileToServer(file, fileUploadUrl, authToken); |
| | | jianliFileIds.add(fileId); |
| | | } |
| | | |
| | | |
| | | // 处理简历文件(jianli 是 variable_name,对应接口的 {variable_name}) |
| | | if (!jianliFileIds.isEmpty()) { |
| | | // 若支持多个文件,可能需要数组形式;单个文件则直接放对象 |
| | | List<Map<String, String>> jianliFiles = new ArrayList<>(); |
| | | for (String fileId : jianliFileIds) { |
| | | Map<String, String> fileInfo = new HashMap<>(); |
| | | fileInfo.put("transfer_method", "local_file"); // 固定值,接口要求 |
| | | fileInfo.put("upload_file_id", fileId); // 上传文件返回的ID |
| | | fileInfo.put("type", "document"); // 文件类型,如 document/image 等(按接口要求) |
| | | jianliFiles.add(fileInfo); |
| | | } |
| | | inputs.put("jianli", jianliFiles); // jianli 对应 {variable_name} |
| | | } else { |
| | | inputs.put("jianli", new ArrayList<>()); // 空文件列表 |
| | | } |
| | | } |
| | | // 调用文件上传接口,获取 upload_file_id |
| | | String fileId = uploadFileToServer(file, fileUploadUrl, authToken); |
| | | jianliFileIds.add(fileId); |
| | | } |
| | | |
| | | // 步骤2:构建 inputs 参数(按接口要求格式) |
| | | Map<String, Object> inputs = new HashMap<>(); |
| | | |
| | | // 处理简历文件(jianli 是 variable_name,对应接口的 {variable_name}) |
| | | if (!jianliFileIds.isEmpty()) { |
| | | // 若支持多个文件,可能需要数组形式;单个文件则直接放对象 |
| | | List<Map<String, String>> jianliFiles = new ArrayList<>(); |
| | | for (String fileId : jianliFileIds) { |
| | | Map<String, String> fileInfo = new HashMap<>(); |
| | | fileInfo.put("transfer_method", "local_file"); // 固定值,接口要求 |
| | | fileInfo.put("upload_file_id", fileId); // 上传文件返回的ID |
| | | fileInfo.put("type", "document"); // 文件类型,如 document/image 等(按接口要求) |
| | | jianliFiles.add(fileInfo); |
| | | } |
| | | inputs.put("jianli", jianliFiles); // jianli 对应 {variable_name} |
| | | } else { |
| | | inputs.put("jianli", new ArrayList<>()); // 空文件列表 |
| | | if (jianli2 != null) { |
| | | inputs.put("jianli2", jianli2); |
| | | } |
| | | |
| | | // 添加其他文本参数 |
| | | inputs.put("wenanyaoqiu", wenanyaoqiu); |
| | | inputs.put("benchmarkUrl", wenanyaoqiu); |
| | | inputs.put("louchu", louchu); |
| | | inputs.put("youshang", youshang); |
| | | inputs.put("wenti", wenti); |
| | |
| | | // 连接超时:建立TCP连接的超时时间,单位毫秒(建议设5秒) |
| | | factory.setConnectTimeout(5000); |
| | | // 读取超时:等待服务端响应数据的超时时间,单位毫秒(根据接口耗时调整,这里设30秒) |
| | | factory.setReadTimeout(100000); |
| | | factory.setReadTimeout(200000); |
| | | // 步骤4:调用工作流接口 |
| | | RestTemplate restTemplate = new RestTemplate(factory); |
| | | HttpHeaders headers = new HttpHeaders(); |