This commit is contained in:
Leo
2025-11-13 23:38:30 +08:00
parent 8889791a83
commit 2cd3a0a798
9 changed files with 1343 additions and 0 deletions

View File

@@ -0,0 +1,282 @@
package com.ruoyi.jarvis.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 闲鱼商品对象 erp_product
*
* @author ruoyi
* @date 2024-01-01
*/
public class ErpProduct extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 管家商品ID */
@Excel(name = "管家商品ID")
private Long productId;
/** 商品标题 */
@Excel(name = "商品标题")
private String title;
/** 商品图片(主图) */
@Excel(name = "商品图片")
private String mainImage;
/** 商品价格(分) */
@Excel(name = "商品价格")
private Long price;
/** 商品库存 */
@Excel(name = "商品库存")
private Integer stock;
/** 商品状态 1:上架 2:下架 3:已售 */
@Excel(name = "商品状态", readConverterExp = "1=上架,2=下架,3=已售")
private Integer productStatus;
/** 销售状态 */
@Excel(name = "销售状态")
private Integer saleStatus;
/** 闲鱼会员名 */
@Excel(name = "闲鱼会员名")
private String userName;
/** 上架时间 */
@Excel(name = "上架时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Long onlineTime;
/** 下架时间 */
@Excel(name = "下架时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Long offlineTime;
/** 售出时间 */
@Excel(name = "售出时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Long soldTime;
/** 创建时间(闲鱼) */
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Long createTimeXy;
/** 更新时间(闲鱼) */
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Long updateTimeXy;
/** ERP应用ID */
@Excel(name = "ERP应用ID")
private String appid;
/** 商品链接 */
@Excel(name = "商品链接")
private String productUrl;
/** 备注 */
@Excel(name = "备注")
private String remark;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setProductId(Long productId)
{
this.productId = productId;
}
public Long getProductId()
{
return productId;
}
public void setTitle(String title)
{
this.title = title;
}
public String getTitle()
{
return title;
}
public void setMainImage(String mainImage)
{
this.mainImage = mainImage;
}
public String getMainImage()
{
return mainImage;
}
public void setPrice(Long price)
{
this.price = price;
}
public Long getPrice()
{
return price;
}
public void setStock(Integer stock)
{
this.stock = stock;
}
public Integer getStock()
{
return stock;
}
public void setProductStatus(Integer productStatus)
{
this.productStatus = productStatus;
}
public Integer getProductStatus()
{
return productStatus;
}
public void setSaleStatus(Integer saleStatus)
{
this.saleStatus = saleStatus;
}
public Integer getSaleStatus()
{
return saleStatus;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String getUserName()
{
return userName;
}
public void setOnlineTime(Long onlineTime)
{
this.onlineTime = onlineTime;
}
public Long getOnlineTime()
{
return onlineTime;
}
public void setOfflineTime(Long offlineTime)
{
this.offlineTime = offlineTime;
}
public Long getOfflineTime()
{
return offlineTime;
}
public void setSoldTime(Long soldTime)
{
this.soldTime = soldTime;
}
public Long getSoldTime()
{
return soldTime;
}
public void setCreateTimeXy(Long createTimeXy)
{
this.createTimeXy = createTimeXy;
}
public Long getCreateTimeXy()
{
return createTimeXy;
}
public void setUpdateTimeXy(Long updateTimeXy)
{
this.updateTimeXy = updateTimeXy;
}
public Long getUpdateTimeXy()
{
return updateTimeXy;
}
public void setAppid(String appid)
{
this.appid = appid;
}
public String getAppid()
{
return appid;
}
public void setProductUrl(String productUrl)
{
this.productUrl = productUrl;
}
public String getProductUrl()
{
return productUrl;
}
@Override
public void setRemark(String remark)
{
this.remark = remark;
}
@Override
public String getRemark()
{
return remark;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("productId", getProductId())
.append("title", getTitle())
.append("mainImage", getMainImage())
.append("price", getPrice())
.append("stock", getStock())
.append("productStatus", getProductStatus())
.append("saleStatus", getSaleStatus())
.append("userName", getUserName())
.append("onlineTime", getOnlineTime())
.append("offlineTime", getOfflineTime())
.append("soldTime", getSoldTime())
.append("createTimeXy", getCreateTimeXy())
.append("updateTimeXy", getUpdateTimeXy())
.append("appid", getAppid())
.append("productUrl", getProductUrl())
.append("remark", getRemark())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.jarvis.mapper;
import java.util.List;
import com.ruoyi.jarvis.domain.ErpProduct;
/**
* 闲鱼商品Mapper接口
*
* @author ruoyi
* @date 2024-01-01
*/
public interface ErpProductMapper
{
/**
* 查询闲鱼商品
*
* @param id 闲鱼商品主键
* @return 闲鱼商品
*/
public ErpProduct selectErpProductById(Long id);
/**
* 查询闲鱼商品列表
*
* @param erpProduct 闲鱼商品
* @return 闲鱼商品集合
*/
public List<ErpProduct> selectErpProductList(ErpProduct erpProduct);
/**
* 新增闲鱼商品
*
* @param erpProduct 闲鱼商品
* @return 结果
*/
public int insertErpProduct(ErpProduct erpProduct);
/**
* 修改闲鱼商品
*
* @param erpProduct 闲鱼商品
* @return 结果
*/
public int updateErpProduct(ErpProduct erpProduct);
/**
* 删除闲鱼商品
*
* @param id 闲鱼商品主键
* @return 结果
*/
public int deleteErpProductById(Long id);
/**
* 批量删除闲鱼商品
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteErpProductByIds(Long[] ids);
/**
* 根据商品ID和appid查询
*
* @param productId 商品ID
* @param appid ERP应用ID
* @return 闲鱼商品
*/
public ErpProduct selectErpProductByProductIdAndAppid(Long productId, String appid);
/**
* 批量插入或更新闲鱼商品
*
* @param erpProducts 闲鱼商品列表
* @return 结果
*/
public int batchInsertOrUpdateErpProduct(List<ErpProduct> erpProducts);
}

View File

@@ -0,0 +1,73 @@
package com.ruoyi.jarvis.service;
import java.util.List;
import com.ruoyi.jarvis.domain.ErpProduct;
/**
* 闲鱼商品Service接口
*
* @author ruoyi
* @date 2024-01-01
*/
public interface IErpProductService
{
/**
* 查询闲鱼商品
*
* @param id 闲鱼商品主键
* @return 闲鱼商品
*/
public ErpProduct selectErpProductById(Long id);
/**
* 查询闲鱼商品列表
*
* @param erpProduct 闲鱼商品
* @return 闲鱼商品集合
*/
public List<ErpProduct> selectErpProductList(ErpProduct erpProduct);
/**
* 新增闲鱼商品
*
* @param erpProduct 闲鱼商品
* @return 结果
*/
public int insertErpProduct(ErpProduct erpProduct);
/**
* 修改闲鱼商品
*
* @param erpProduct 闲鱼商品
* @return 结果
*/
public int updateErpProduct(ErpProduct erpProduct);
/**
* 批量删除闲鱼商品
*
* @param ids 需要删除的闲鱼商品主键集合
* @return 结果
*/
public int deleteErpProductByIds(Long[] ids);
/**
* 删除闲鱼商品信息
*
* @param id 闲鱼商品主键
* @return 结果
*/
public int deleteErpProductById(Long id);
/**
* 从闲鱼ERP拉取商品列表并保存
*
* @param appid ERP应用ID
* @param pageNo 页码
* @param pageSize 每页大小
* @param productStatus 商品状态
* @return 拉取结果
*/
public int pullAndSaveProductList(String appid, Integer pageNo, Integer pageSize, Integer productStatus);
}

View File

@@ -0,0 +1,281 @@
package com.ruoyi.jarvis.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.jarvis.mapper.ErpProductMapper;
import com.ruoyi.jarvis.domain.ErpProduct;
import com.ruoyi.jarvis.service.IErpProductService;
import com.ruoyi.erp.request.ERPAccount;
import com.ruoyi.erp.request.ProductListQueryRequest;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 闲鱼商品Service业务层处理
*
* @author ruoyi
* @date 2024-01-01
*/
@Service
public class ErpProductServiceImpl implements IErpProductService
{
private static final Logger log = LoggerFactory.getLogger(ErpProductServiceImpl.class);
@Autowired
private ErpProductMapper erpProductMapper;
/**
* 查询闲鱼商品
*
* @param id 闲鱼商品主键
* @return 闲鱼商品
*/
@Override
public ErpProduct selectErpProductById(Long id)
{
return erpProductMapper.selectErpProductById(id);
}
/**
* 查询闲鱼商品列表
*
* @param erpProduct 闲鱼商品
* @return 闲鱼商品
*/
@Override
public List<ErpProduct> selectErpProductList(ErpProduct erpProduct)
{
return erpProductMapper.selectErpProductList(erpProduct);
}
/**
* 新增闲鱼商品
*
* @param erpProduct 闲鱼商品
* @return 结果
*/
@Override
public int insertErpProduct(ErpProduct erpProduct)
{
// 检查是否已存在
ErpProduct existing = erpProductMapper.selectErpProductByProductIdAndAppid(
erpProduct.getProductId(), erpProduct.getAppid());
if (existing != null) {
// 更新已存在的商品
erpProduct.setId(existing.getId());
return erpProductMapper.updateErpProduct(erpProduct);
}
return erpProductMapper.insertErpProduct(erpProduct);
}
/**
* 修改闲鱼商品
*
* @param erpProduct 闲鱼商品
* @return 结果
*/
@Override
public int updateErpProduct(ErpProduct erpProduct)
{
return erpProductMapper.updateErpProduct(erpProduct);
}
/**
* 批量删除闲鱼商品
*
* @param ids 需要删除的闲鱼商品主键
* @return 结果
*/
@Override
public int deleteErpProductByIds(Long[] ids)
{
return erpProductMapper.deleteErpProductByIds(ids);
}
/**
* 删除闲鱼商品信息
*
* @param id 闲鱼商品主键
* @return 结果
*/
@Override
public int deleteErpProductById(Long id)
{
return erpProductMapper.deleteErpProductById(id);
}
/**
* 从闲鱼ERP拉取商品列表并保存
*
* @param appid ERP应用ID
* @param pageNo 页码
* @param pageSize 每页大小
* @param productStatus 商品状态
* @return 拉取并保存的商品数量
*/
@Override
public int pullAndSaveProductList(String appid, Integer pageNo, Integer pageSize, Integer productStatus)
{
try {
// 解析ERP账号
ERPAccount account = resolveAccount(appid);
// 创建查询请求
ProductListQueryRequest request = new ProductListQueryRequest(account);
if (pageNo != null) {
request.setPageNo(pageNo);
}
if (pageSize != null) {
request.setPageSize(pageSize);
}
if (productStatus != null) {
request.setProductStatus(productStatus);
}
// 调用接口获取商品列表
String responseBody = request.getResponseBody();
JSONObject response = JSONObject.parseObject(responseBody);
if (response == null || response.getInteger("code") == null || response.getInteger("code") != 0) {
log.error("拉取商品列表失败: {}", responseBody);
return 0;
}
// 解析商品列表
JSONObject data = response.getJSONObject("data");
if (data == null) {
log.warn("拉取商品列表返回数据为空");
return 0;
}
JSONArray productList = data.getJSONArray("list");
if (productList == null || productList.isEmpty()) {
log.info("拉取商品列表为空");
return 0;
}
// 转换为实体对象并保存
List<ErpProduct> erpProducts = new ArrayList<>();
for (int i = 0; i < productList.size(); i++) {
JSONObject productJson = productList.getJSONObject(i);
ErpProduct erpProduct = parseProductJson(productJson, appid);
if (erpProduct != null) {
erpProducts.add(erpProduct);
}
}
// 批量保存或更新
if (!erpProducts.isEmpty()) {
// 逐个保存(兼容更新)
int savedCount = 0;
for (ErpProduct product : erpProducts) {
ErpProduct existing = erpProductMapper.selectErpProductByProductIdAndAppid(
product.getProductId(), product.getAppid());
if (existing != null) {
product.setId(existing.getId());
erpProductMapper.updateErpProduct(product);
} else {
erpProductMapper.insertErpProduct(product);
}
savedCount++;
}
log.info("成功拉取并保存 {} 个商品", savedCount);
return savedCount;
}
return 0;
} catch (Exception e) {
log.error("拉取商品列表异常", e);
throw new RuntimeException("拉取商品列表失败: " + e.getMessage(), e);
}
}
/**
* 解析商品JSON数据
*/
private ErpProduct parseProductJson(JSONObject productJson, String appid) {
try {
ErpProduct product = new ErpProduct();
// 管家商品ID
Long productId = productJson.getLong("product_id");
if (productId == null) {
log.warn("商品ID为空跳过: {}", productJson);
return null;
}
product.setProductId(productId);
// 商品标题
product.setTitle(productJson.getString("title"));
// 商品图片(取第一张)
JSONArray images = productJson.getJSONArray("images");
if (images != null && !images.isEmpty()) {
product.setMainImage(images.getString(0));
}
// 价格(分)
Long price = productJson.getLong("price");
if (price == null) {
// 尝试从price字段解析
Object priceObj = productJson.get("price");
if (priceObj instanceof Number) {
price = ((Number) priceObj).longValue();
}
}
product.setPrice(price);
// 库存
Integer stock = productJson.getInteger("stock");
product.setStock(stock);
// 商品状态
Integer productStatus = productJson.getInteger("product_status");
product.setProductStatus(productStatus);
// 销售状态
Integer saleStatus = productJson.getInteger("sale_status");
product.setSaleStatus(saleStatus);
// 闲鱼会员名
product.setUserName(productJson.getString("user_name"));
// 时间字段(时间戳,秒)
product.setOnlineTime(productJson.getLong("online_time"));
product.setOfflineTime(productJson.getLong("offline_time"));
product.setSoldTime(productJson.getLong("sold_time"));
product.setCreateTimeXy(productJson.getLong("create_time"));
product.setUpdateTimeXy(productJson.getLong("update_time"));
// ERP应用ID
product.setAppid(appid);
// 商品链接
product.setProductUrl(productJson.getString("product_url"));
return product;
} catch (Exception e) {
log.error("解析商品JSON失败: {}", productJson, e);
return null;
}
}
/**
* 解析ERP账号
*/
private ERPAccount resolveAccount(String appid) {
if (appid != null && !appid.isEmpty()) {
for (ERPAccount account : ERPAccount.values()) {
if (account.getApiKey().equals(appid)) {
return account;
}
}
}
return ERPAccount.ACCOUNT_HUGE; // 默认账号
}
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.jarvis.mapper.ErpProductMapper">
<resultMap type="ErpProduct" id="ErpProductResult">
<result property="id" column="id" />
<result property="productId" column="product_id" />
<result property="title" column="title" />
<result property="mainImage" column="main_image" />
<result property="price" column="price" />
<result property="stock" column="stock" />
<result property="productStatus" column="product_status" />
<result property="saleStatus" column="sale_status" />
<result property="userName" column="user_name" />
<result property="onlineTime" column="online_time" />
<result property="offlineTime" column="offline_time" />
<result property="soldTime" column="sold_time" />
<result property="createTimeXy" column="create_time_xy" />
<result property="updateTimeXy" column="update_time_xy" />
<result property="appid" column="appid" />
<result property="productUrl" column="product_url" />
<result property="remark" column="remark" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectErpProductVo">
select id, product_id, title, main_image, price, stock, product_status, sale_status,
user_name, online_time, offline_time, sold_time, create_time_xy, update_time_xy,
appid, product_url, remark, create_time, update_time
from erp_product
</sql>
<select id="selectErpProductList" parameterType="ErpProduct" resultMap="ErpProductResult">
<include refid="selectErpProductVo"/>
<where>
<if test="productId != null "> and product_id = #{productId}</if>
<if test="title != null and title != ''"> and title like concat('%', #{title}, '%')</if>
<if test="productStatus != null "> and product_status = #{productStatus}</if>
<if test="saleStatus != null "> and sale_status = #{saleStatus}</if>
<if test="userName != null and userName != ''"> and user_name = #{userName}</if>
<if test="appid != null and appid != ''"> and appid = #{appid}</if>
</where>
order by update_time_xy desc, id desc
</select>
<select id="selectErpProductById" parameterType="Long" resultMap="ErpProductResult">
<include refid="selectErpProductVo"/>
where id = #{id}
</select>
<select id="selectErpProductByProductIdAndAppid" resultMap="ErpProductResult">
<include refid="selectErpProductVo"/>
where product_id = #{productId} and appid = #{appid}
</select>
<insert id="insertErpProduct" parameterType="ErpProduct" useGeneratedKeys="true" keyProperty="id">
insert into erp_product
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="productId != null">product_id,</if>
<if test="title != null">title,</if>
<if test="mainImage != null">main_image,</if>
<if test="price != null">price,</if>
<if test="stock != null">stock,</if>
<if test="productStatus != null">product_status,</if>
<if test="saleStatus != null">sale_status,</if>
<if test="userName != null">user_name,</if>
<if test="onlineTime != null">online_time,</if>
<if test="offlineTime != null">offline_time,</if>
<if test="soldTime != null">sold_time,</if>
<if test="createTimeXy != null">create_time_xy,</if>
<if test="updateTimeXy != null">update_time_xy,</if>
<if test="appid != null">appid,</if>
<if test="productUrl != null">product_url,</if>
<if test="remark != null">remark,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="productId != null">#{productId},</if>
<if test="title != null">#{title},</if>
<if test="mainImage != null">#{mainImage},</if>
<if test="price != null">#{price},</if>
<if test="stock != null">#{stock},</if>
<if test="productStatus != null">#{productStatus},</if>
<if test="saleStatus != null">#{saleStatus},</if>
<if test="userName != null">#{userName},</if>
<if test="onlineTime != null">#{onlineTime},</if>
<if test="offlineTime != null">#{offlineTime},</if>
<if test="soldTime != null">#{soldTime},</if>
<if test="createTimeXy != null">#{createTimeXy},</if>
<if test="updateTimeXy != null">#{updateTimeXy},</if>
<if test="appid != null">#{appid},</if>
<if test="productUrl != null">#{productUrl},</if>
<if test="remark != null">#{remark},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateErpProduct" parameterType="ErpProduct">
update erp_product
<trim prefix="SET" suffixOverrides=",">
<if test="productId != null">product_id = #{productId},</if>
<if test="title != null">title = #{title},</if>
<if test="mainImage != null">main_image = #{mainImage},</if>
<if test="price != null">price = #{price},</if>
<if test="stock != null">stock = #{stock},</if>
<if test="productStatus != null">product_status = #{productStatus},</if>
<if test="saleStatus != null">sale_status = #{saleStatus},</if>
<if test="userName != null">user_name = #{userName},</if>
<if test="onlineTime != null">online_time = #{onlineTime},</if>
<if test="offlineTime != null">offline_time = #{offlineTime},</if>
<if test="soldTime != null">sold_time = #{soldTime},</if>
<if test="createTimeXy != null">create_time_xy = #{createTimeXy},</if>
<if test="updateTimeXy != null">update_time_xy = #{updateTimeXy},</if>
<if test="appid != null">appid = #{appid},</if>
<if test="productUrl != null">product_url = #{productUrl},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteErpProductById" parameterType="Long">
delete from erp_product where id = #{id}
</delete>
<delete id="deleteErpProductByIds" parameterType="String">
delete from erp_product where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<insert id="batchInsertOrUpdateErpProduct" parameterType="java.util.List">
insert into erp_product
(product_id, title, main_image, price, stock, product_status, sale_status,
user_name, online_time, offline_time, sold_time, create_time_xy, update_time_xy,
appid, product_url, remark)
values
<foreach collection="list" item="item" separator=",">
(#{item.productId}, #{item.title}, #{item.mainImage}, #{item.price}, #{item.stock},
#{item.productStatus}, #{item.saleStatus}, #{item.userName}, #{item.onlineTime},
#{item.offlineTime}, #{item.soldTime}, #{item.createTimeXy}, #{item.updateTimeXy},
#{item.appid}, #{item.productUrl}, #{item.remark})
</foreach>
ON DUPLICATE KEY UPDATE
title = VALUES(title),
main_image = VALUES(main_image),
price = VALUES(price),
stock = VALUES(stock),
product_status = VALUES(product_status),
sale_status = VALUES(sale_status),
user_name = VALUES(user_name),
online_time = VALUES(online_time),
offline_time = VALUES(offline_time),
sold_time = VALUES(sold_time),
create_time_xy = VALUES(create_time_xy),
update_time_xy = VALUES(update_time_xy),
product_url = VALUES(product_url),
remark = VALUES(remark),
update_time = NOW()
</insert>
</mapper>