1
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
package com.ruoyi.web.controller.jarvis;
|
||||||
|
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.jarvis.service.ISocialMediaService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小红书/抖音内容生成Controller
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2025-01-XX
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/jarvis/social-media")
|
||||||
|
public class SocialMediaController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private ISocialMediaService socialMediaService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取关键词
|
||||||
|
*/
|
||||||
|
@PostMapping("/extract-keywords")
|
||||||
|
public AjaxResult extractKeywords(@RequestBody Map<String, Object> request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
String productName = (String) request.get("productName");
|
||||||
|
if (productName == null || productName.trim().isEmpty()) {
|
||||||
|
return AjaxResult.error("商品名称不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> result = socialMediaService.extractKeywords(productName);
|
||||||
|
return AjaxResult.success(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("提取关键词失败", e);
|
||||||
|
return AjaxResult.error("提取关键词失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成文案
|
||||||
|
*/
|
||||||
|
@PostMapping("/generate-content")
|
||||||
|
public AjaxResult generateContent(@RequestBody Map<String, Object> request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
String productName = (String) request.get("productName");
|
||||||
|
if (productName == null || productName.trim().isEmpty()) {
|
||||||
|
return AjaxResult.error("商品名称不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object originalPriceObj = request.get("originalPrice");
|
||||||
|
Object finalPriceObj = request.get("finalPrice");
|
||||||
|
String keywords = (String) request.get("keywords");
|
||||||
|
String style = (String) request.getOrDefault("style", "both");
|
||||||
|
|
||||||
|
Map<String, Object> result = socialMediaService.generateContent(
|
||||||
|
productName, originalPriceObj, finalPriceObj, keywords, style
|
||||||
|
);
|
||||||
|
return AjaxResult.success(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("生成文案失败", e);
|
||||||
|
return AjaxResult.error("生成文案失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一键生成完整内容(关键词 + 文案 + 图片)
|
||||||
|
*/
|
||||||
|
@Log(title = "小红书/抖音内容生成", businessType = BusinessType.OTHER)
|
||||||
|
@PostMapping("/generate-complete")
|
||||||
|
public AjaxResult generateComplete(@RequestBody Map<String, Object> request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
String productImageUrl = (String) request.get("productImageUrl");
|
||||||
|
String productName = (String) request.get("productName");
|
||||||
|
if (productName == null || productName.trim().isEmpty()) {
|
||||||
|
return AjaxResult.error("商品名称不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object originalPriceObj = request.get("originalPrice");
|
||||||
|
Object finalPriceObj = request.get("finalPrice");
|
||||||
|
String style = (String) request.getOrDefault("style", "both");
|
||||||
|
|
||||||
|
Map<String, Object> result = socialMediaService.generateCompleteContent(
|
||||||
|
productImageUrl, productName, originalPriceObj, finalPriceObj, style
|
||||||
|
);
|
||||||
|
return AjaxResult.success(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("生成完整内容失败", e);
|
||||||
|
return AjaxResult.error("生成完整内容失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.ruoyi.jarvis.service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小红书/抖音内容生成Service接口
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2025-01-XX
|
||||||
|
*/
|
||||||
|
public interface ISocialMediaService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 提取商品标题关键词
|
||||||
|
*
|
||||||
|
* @param productName 商品名称
|
||||||
|
* @return 关键词结果
|
||||||
|
*/
|
||||||
|
Map<String, Object> extractKeywords(String productName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成文案
|
||||||
|
*
|
||||||
|
* @param productName 商品名称
|
||||||
|
* @param originalPrice 原价
|
||||||
|
* @param finalPrice 到手价
|
||||||
|
* @param keywords 关键词
|
||||||
|
* @param style 文案风格
|
||||||
|
* @return 生成的文案
|
||||||
|
*/
|
||||||
|
Map<String, Object> generateContent(String productName, Object originalPrice,
|
||||||
|
Object finalPrice, String keywords, String style);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一键生成完整内容(关键词 + 文案 + 图片)
|
||||||
|
*
|
||||||
|
* @param productImageUrl 商品主图URL
|
||||||
|
* @param productName 商品名称
|
||||||
|
* @param originalPrice 原价
|
||||||
|
* @param finalPrice 到手价
|
||||||
|
* @param style 文案风格
|
||||||
|
* @return 完整内容
|
||||||
|
*/
|
||||||
|
Map<String, Object> generateCompleteContent(String productImageUrl, String productName,
|
||||||
|
Object originalPrice, Object finalPrice, String style);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
package com.ruoyi.jarvis.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.http.HttpUtils;
|
||||||
|
import com.ruoyi.jarvis.service.ISocialMediaService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小红书/抖音内容生成Service业务层处理
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2025-01-XX
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SocialMediaServiceImpl implements ISocialMediaService
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SocialMediaServiceImpl.class);
|
||||||
|
|
||||||
|
// jarvis_java 服务地址
|
||||||
|
private final static String JARVIS_BASE_URL = "http://192.168.8.88:6666";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取商品标题关键词
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> extractKeywords(String productName) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(productName)) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "商品名称不能为空");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用 jarvis_java 的接口
|
||||||
|
String url = JARVIS_BASE_URL + "/jarvis/social-media/extract-keywords";
|
||||||
|
JSONObject requestBody = new JSONObject();
|
||||||
|
requestBody.put("productName", productName);
|
||||||
|
|
||||||
|
log.info("调用jarvis_java提取关键词接口,URL: {}, 参数: {}", url, requestBody.toJSONString());
|
||||||
|
String response = HttpUtils.sendJsonPost(url, requestBody.toJSONString());
|
||||||
|
log.info("jarvis_java响应: {}", response);
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(response)) {
|
||||||
|
throw new Exception("jarvis_java返回空结果");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
Object parsed = JSON.parse(response);
|
||||||
|
if (parsed instanceof JSONObject) {
|
||||||
|
JSONObject jsonResponse = (JSONObject) parsed;
|
||||||
|
if (jsonResponse.getInteger("code") == 200) {
|
||||||
|
Object data = jsonResponse.get("data");
|
||||||
|
if (data instanceof Map) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> dataMap = (Map<String, Object>) data;
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String msg = jsonResponse.getString("msg");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", msg != null ? msg : "提取关键词失败");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "响应格式错误");
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("提取关键词失败", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "提取关键词失败: " + e.getMessage());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成文案
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> generateContent(String productName, Object originalPrice,
|
||||||
|
Object finalPrice, String keywords, String style) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(productName)) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "商品名称不能为空");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用 jarvis_java 的接口
|
||||||
|
String url = JARVIS_BASE_URL + "/jarvis/social-media/generate-content";
|
||||||
|
JSONObject requestBody = new JSONObject();
|
||||||
|
requestBody.put("productName", productName);
|
||||||
|
if (originalPrice != null) {
|
||||||
|
requestBody.put("originalPrice", parseDouble(originalPrice));
|
||||||
|
}
|
||||||
|
if (finalPrice != null) {
|
||||||
|
requestBody.put("finalPrice", parseDouble(finalPrice));
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(keywords)) {
|
||||||
|
requestBody.put("keywords", keywords);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(style)) {
|
||||||
|
requestBody.put("style", style);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("调用jarvis_java生成文案接口,URL: {}, 参数: {}", url, requestBody.toJSONString());
|
||||||
|
String response = HttpUtils.sendJsonPost(url, requestBody.toJSONString());
|
||||||
|
log.info("jarvis_java响应: {}", response);
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(response)) {
|
||||||
|
throw new Exception("jarvis_java返回空结果");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
Object parsed = JSON.parse(response);
|
||||||
|
if (parsed instanceof JSONObject) {
|
||||||
|
JSONObject jsonResponse = (JSONObject) parsed;
|
||||||
|
if (jsonResponse.getInteger("code") == 200) {
|
||||||
|
Object data = jsonResponse.get("data");
|
||||||
|
if (data instanceof Map) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> dataMap = (Map<String, Object>) data;
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String msg = jsonResponse.getString("msg");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", msg != null ? msg : "生成文案失败");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "响应格式错误");
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成文案失败", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "生成文案失败: " + e.getMessage());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一键生成完整内容(关键词 + 文案 + 图片)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> generateCompleteContent(String productImageUrl, String productName,
|
||||||
|
Object originalPrice, Object finalPrice, String style) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(productName)) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "商品名称不能为空");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用 jarvis_java 的接口
|
||||||
|
String url = JARVIS_BASE_URL + "/jarvis/social-media/generate-complete";
|
||||||
|
JSONObject requestBody = new JSONObject();
|
||||||
|
if (StringUtils.isNotEmpty(productImageUrl)) {
|
||||||
|
requestBody.put("productImageUrl", productImageUrl);
|
||||||
|
}
|
||||||
|
requestBody.put("productName", productName);
|
||||||
|
if (originalPrice != null) {
|
||||||
|
requestBody.put("originalPrice", parseDouble(originalPrice));
|
||||||
|
}
|
||||||
|
if (finalPrice != null) {
|
||||||
|
requestBody.put("finalPrice", parseDouble(finalPrice));
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(style)) {
|
||||||
|
requestBody.put("style", style);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("调用jarvis_java生成完整内容接口,URL: {}, 参数: {}", url, requestBody.toJSONString());
|
||||||
|
String response = HttpUtils.sendJsonPost(url, requestBody.toJSONString());
|
||||||
|
log.info("jarvis_java响应: {}", response);
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(response)) {
|
||||||
|
throw new Exception("jarvis_java返回空结果");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
Object parsed = JSON.parse(response);
|
||||||
|
if (parsed instanceof JSONObject) {
|
||||||
|
JSONObject jsonResponse = (JSONObject) parsed;
|
||||||
|
if (jsonResponse.getInteger("code") == 200) {
|
||||||
|
Object data = jsonResponse.get("data");
|
||||||
|
if (data instanceof Map) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> dataMap = (Map<String, Object>) data;
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String msg = jsonResponse.getString("msg");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", msg != null ? msg : "生成完整内容失败");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "响应格式错误");
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成完整内容失败", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", "生成完整内容失败: " + e.getMessage());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析Double值
|
||||||
|
*/
|
||||||
|
private Double parseDouble(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof Double) {
|
||||||
|
return (Double) value;
|
||||||
|
}
|
||||||
|
if (value instanceof Number) {
|
||||||
|
return ((Number) value).doubleValue();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Double.parseDouble(value.toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user