package com.ruoyi.system.ControllerUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.AppleDoMain.OrderApple;
import com.ruoyi.system.service.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
/**
* 小程序控制器工具类
*
* 提供小程序相关的数据处理、响应实体转换等工具方法
* 主要功能:
* 1. 服务商品响应数据格式化
* 2. 分类数据构建
* 3. 用户数据处理
* 4. 图片和基础信息数组解析
* 5. 统一响应格式处理
*
* @author Mr. Zhang Pan
* @version 1.0
* @date 2025-01-03
*/
public class AppletControllerUtil {
private static final IUsersService usersService = SpringUtils.getBean(IUsersService.class);
private static final IUserAddressService userAddressService = SpringUtils.getBean(IUserAddressService.class);
// ============================== 统一响应处理方法 ==============================
/**
* 成功响应 - code: 200
*
* @param data 响应数据
* @return AjaxResult
*/
public static AjaxResult appletSuccess(Object data) {
AjaxResult result = new AjaxResult();
result.put("code", 200);
result.put("msg", "OK");
result.put("data", data);
return result;
}
/**
* 成功响应 - code: 200,无数据
*
* @param message 成功消息
* @return AjaxResult
*/
public static AjaxResult appletSuccess(String message) {
return appletSuccess((Object) message);
}
/**
* 成功响应 - code: 200,默认消息
*
* @return AjaxResult
*/
public static AjaxResult appletSuccess() {
return appletSuccess("操作成功");
}
/**
* 业务提示响应 - code: 422
*
* @param message 提示消息
* @return AjaxResult
*/
public static AjaxResult appletWarning(String message) {
AjaxResult result = new AjaxResult();
result.put("code", 422);
result.put("msg", message);
result.put("data", new ArrayList<>());
return result;
}
/**
* 业务提示响应 - code:500
*
* @param message 提示消息
* @return AjaxResult
*/
public static AjaxResult appletkaifaWarning(String message) {
AjaxResult result = new AjaxResult();
result.put("code", 500);
result.put("msg", message);
result.put("data", new ArrayList<>());
return result;
}
/**
* 业务提示响应 - code: 422,带数据
*
* @param message 提示消息
* @param data 响应数据
* @return AjaxResult
*/
public static AjaxResult appletWarning(String message, Object data) {
AjaxResult result = new AjaxResult();
result.put("code", 422);
result.put("msg", message);
result.put("data", data != null ? data : new ArrayList<>());
return result;
}
/**
* Token验证失败响应 - code: 332
*
* @return AjaxResult
*/
public static AjaxResult appletUnauthorized() {
return appletUnauthorized("用户未登录或token无效,请重新登录");
}
/**
* Token验证失败响应 - code: 332,自定义消息
*
* @param message 提示消息
* @return AjaxResult
*/
public static AjaxResult appletUnauthorized(String message) {
AjaxResult result = new AjaxResult();
result.put("code", 332);
result.put("msg", message);
result.put("data", new ArrayList<>());
return result;
}
/**
* 系统错误响应 - code: 500
*
* @param message 错误消息
* @return AjaxResult
*/
public static AjaxResult appletError(String message) {
AjaxResult result = new AjaxResult();
result.put("code", 500);
result.put("msg", message);
result.put("data", new ArrayList<>());
return result;
}
/**
* 判断字符串是否能转换为 JSONArray
*
* @param str 需要判断的字符串
* @return 如果是合法的JSON数组字符串,返回 true;否则返回 false
*/
public static boolean canParseToJSONArray(String str) {
if (str == null || str.trim().isEmpty()) {
return false;
}
try {
Object obj = JSON.parse(str);
return obj instanceof JSONArray;
} catch (Exception e) {
// 解析失败,不是合法的JSON数组
return false;
}
}
/**
* 服务商品详情响应实体类
*
* 用于格式化服务商品数据,统一小程序端的数据结构
* 将数据库实体ServiceGoods转换为前端需要的JSON格式
*
* 主要特性:
* - 自动处理图片URL添加CDN前缀
* - 支持JSON数组和逗号分隔的字符串解析
* - 统一数据类型转换(BigDecimal转String等)
* - 设置合理的默认值避免空值异常
*/
public static class ServiceGoodsResponse {
/**
* 商品ID
*/
private Long id;
/**
* 商品标题
*/
private String title;
/**
* 商品图标(自动添加CDN前缀)
*/
private String icon;
/**
* 商品轮播图数组(自动添加CDN前缀)
*/
private List imgs;
/**
* 商品副标题
*/
private String sub_title;
/**
* 商品简介
*/
private String info;
/**
* 商品价格(字符串格式)
*/
private String price;
/**
* 列表价格显示(字符串格式)
*/
private String price_in;
/**
* 销量
*/
private Integer sales;
/**
* 库存
*/
private Integer stock;
/**
* 状态
*/
private String status;
/**
* 商品详情描述
*/
private String description;
/**
* 规格类型 1:单规格 2:多规格
*/
private Integer sku_type;
/**
* SKU规格对象
*/
private Map sku;
/**
* 纬度
*/
private String latitude;
/**
* 经度
*/
private String longitude;
/**
* 类型 1:服务 2:商品
*/
private Integer type;
/**
* 分类ID
*/
private Long cate_id;
/**
* 服务项目
*/
private String project;
/**
* 排序
*/
private Integer sort;
/**
* 物料费用
*/
private String material;
/**
* 邮费(字符串格式)
*/
private String postage;
/**
* 基检现象数组
*/
private List basic;
/**
* 保证金(字符串格式)
*/
private String margin;
/**
* 所需技能ID
*/
private String skill_ids;
/**
* 创建时间
*/
private String created_at;
/**
* 更新时间
*/
private String updated_at;
/**
* 删除时间
*/
private String deleted_at;
/**
* 评论对象(预留扩展)
*/
private Map comment;
/**
* 构造方法 - 将ServiceGoods实体转换为响应格式
*
* @param goods ServiceGoods实体对象
*
* 主要处理:
* 1. 基础字段映射和类型转换
* 2. 图片URL添加CDN前缀
* 3. 数组字段解析(支持JSON和逗号分隔)
* 4. 空值处理和默认值设置
* 5. 特殊对象构建(SKU、评论等)
*/
public ServiceGoodsResponse(ServiceGoods goods) {
// 基础字段映射
this.id = goods.getId();
this.title = goods.getTitle();
this.icon = buildImageUrl(goods.getIcon());
this.sub_title = goods.getSubTitle();
this.info = goods.getInfo();
// 价格字段处理 - BigDecimal转String避免精度问题
this.price = goods.getPrice() != null ? goods.getPrice().toString() : "0.00";
this.price_in = goods.getPriceZn() != null ? goods.getPriceZn() : "";
// 数值字段处理 - Long转Integer并设置默认值
this.sales = goods.getSales() != null ? goods.getSales().intValue() : 0;
this.stock = goods.getStock() != null ? goods.getStock().intValue() : 0;
this.sort = goods.getSort() != null ? goods.getSort().intValue() : 1;
// 状态和类型字段
this.status = goods.getStatus() != null ? goods.getStatus() : "1";
this.type = goods.getType() != null ? goods.getType().intValue() : 1;
this.sku_type = goods.getSkuType() != null ? goods.getSkuType().intValue() : 1;
// 文本字段
this.description = goods.getDescription();
this.latitude = goods.getLatitude();
this.longitude = goods.getLongitude();
this.cate_id = goods.getCateId();
this.project = goods.getProject();
this.material = goods.getMaterial();
this.skill_ids = goods.getSkillIds();
// 金额字段处理 - BigDecimal转String
this.postage = goods.getPostage() != null ? goods.getPostage().toString() : "";
this.margin = goods.getMargin() != null ? goods.getMargin().toString() : "";
// 时间字段处理
this.created_at = goods.getCreatedAt() != null ? goods.getCreatedAt().toString() : "";
this.updated_at = goods.getUpdatedAt() != null ? goods.getUpdatedAt().toString() : "";
this.deleted_at = goods.getDeletedAt() != null ? goods.getDeletedAt().toString() : null;
// 数组字段解析
this.imgs = parseStringToImageList(goods.getImgs());
this.basic = parseStringToList(goods.getBasic());
// 构建SKU对象 - 默认单规格
this.sku = new HashMap<>();
this.sku.put("type", "single");
// 构建评论对象 - 预留扩展
this.comment = new HashMap<>();
}
// Getter和Setter方法(完整实现)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public List getImgs() {
return imgs;
}
public void setImgs(List imgs) {
this.imgs = imgs;
}
public String getSub_title() {
return sub_title;
}
public void setSub_title(String sub_title) {
this.sub_title = sub_title;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getPrice_in() {
return price_in;
}
public void setPrice_in(String price_in) {
this.price_in = price_in;
}
public Integer getSales() {
return sales;
}
public void setSales(Integer sales) {
this.sales = sales;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getSku_type() {
return sku_type;
}
public void setSku_type(Integer sku_type) {
this.sku_type = sku_type;
}
public Map getSku() {
return sku;
}
public void setSku(Map sku) {
this.sku = sku;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Long getCate_id() {
return cate_id;
}
public void setCate_id(Long cate_id) {
this.cate_id = cate_id;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public Integer getSort() {
return sort;
}
public void setSort(Integer sort) {
this.sort = sort;
}
public String getMaterial() {
return material;
}
public void setMaterial(String material) {
this.material = material;
}
public String getPostage() {
return postage;
}
public void setPostage(String postage) {
this.postage = postage;
}
public List getBasic() {
return basic;
}
public void setBasic(List basic) {
this.basic = basic;
}
public String getMargin() {
return margin;
}
public void setMargin(String margin) {
this.margin = margin;
}
public String getSkill_ids() {
return skill_ids;
}
public void setSkill_ids(String skill_ids) {
this.skill_ids = skill_ids;
}
public String getCreated_at() {
return created_at;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
public String getDeleted_at() {
return deleted_at;
}
public void setDeleted_at(String deleted_at) {
this.deleted_at = deleted_at;
}
public Map getComment() {
return comment;
}
public void setComment(Map comment) {
this.comment = comment;
}
}
/**
* CDN域名常量
* 用于图片URL统一添加CDN前缀
*/
private static final String CDN_BASE_URL = "https://img.huafurenjia.cn/";
/**
* 构建完整的图片URL
*
* @param imagePath 图片路径
* @return 完整的图片URL(包含CDN前缀)
*
* 处理逻辑:
* - 如果图片路径为空,返回空字符串
* - 自动添加CDN域名前缀
* - 确保URL格式正确
*/
public static String buildImageUrl(String imagePath) {
if (imagePath == null || imagePath.trim().isEmpty()) {
return "";
}
return CDN_BASE_URL + imagePath.trim();
}
/**
* 解析字符串为图片URL列表
*
* @param imgsString 图片字符串(支持JSON数组或逗号分隔)
* @return 图片URL列表(已添加CDN前缀)
*
* 支持的格式:
* 1. JSON数组格式:["img1.jpg", "img2.jpg"]
* 2. 逗号分隔格式:img1.jpg,img2.jpg
*
* 处理特性:
* - 自动识别数据格式
* - 过滤空值和空白字符
* - 自动添加CDN前缀
* - 异常容错处理
*/
public static List parseStringToImageList(String imgsString) {
List imageList = new ArrayList<>();
if (imgsString == null || imgsString.trim().isEmpty()) {
return imageList;
}
try {
// 尝试解析JSON数组格式
JSONArray jsonArray = JSONArray.parseArray(imgsString);
for (int i = 0; i < jsonArray.size(); i++) {
String img = jsonArray.getString(i);
if (img != null && !img.trim().isEmpty()) {
imageList.add(buildImageUrl(img.trim()));
}
}
} catch (Exception e) {
// JSON解析失败,按逗号分割处理
String[] imgArray = imgsString.split(",");
for (String img : imgArray) {
String trimmedImg = img.trim();
if (!trimmedImg.isEmpty()) {
imageList.add(buildImageUrl(trimmedImg));
}
}
}
return imageList;
}
/**
* 解析字符串为普通字符串列表
*
* @param dataString 数据字符串(支持JSON数组或逗号分隔)
* @return 字符串列表
*
* 用于解析基检现象、标签等文本数组数据
*
* 支持的格式:
* 1. JSON数组格式:["现象1", "现象2"]
* 2. 逗号分隔格式:现象1,现象2
*
* 处理特性:
* - 自动识别数据格式
* - 过滤空值和空白字符
* - 异常容错处理
*/
public static List parseStringToList(String dataString) {
List dataList = new ArrayList<>();
if (dataString == null || dataString.trim().isEmpty()) {
return dataList;
}
try {
// 尝试解析JSON数组格式
JSONArray jsonArray = JSONArray.parseArray(dataString);
for (int i = 0; i < jsonArray.size(); i++) {
String item = jsonArray.getString(i);
if (item != null && !item.trim().isEmpty()) {
dataList.add(item.trim());
}
}
} catch (Exception e) {
// JSON解析失败,按逗号分割处理
String[] dataArray = dataString.split(",");
for (String item : dataArray) {
String trimmedItem = item.trim();
if (!trimmedItem.isEmpty()) {
dataList.add(trimmedItem);
}
}
}
return dataList;
}
/**
* 构建分类数据
*
* @param category 分类信息
* @param keywords 搜索关键词(可选)
* @param serviceGoodsService 服务商品Service
* @return 格式化的分类数据
*
* 返回数据结构:
* {
* "id": 分类ID,
* "title": 分类标题,
* "icon": 分类图标URL,
* "type": 分类类型,
* "cate_id": 分类ID,
* "goods": [商品列表]
* }
*
* 功能特性:
* - 查询分类下的所有商品
* - 支持关键词搜索过滤
* - 自动添加图片CDN前缀
* - 返回统一的数据格式
*/
public static Map buildCategoryData(ServiceCate category, String keywords,
IServiceGoodsService serviceGoodsService) {
Map categoryData = new HashMap<>();
// 分类基础信息
categoryData.put("id", category.getId());
categoryData.put("title", category.getTitle());
categoryData.put("icon", buildImageUrl(category.getIcon()));
categoryData.put("type", category.getType());
categoryData.put("cate_id", category.getId());
// 查询该分类下的商品
ServiceGoods serviceGoodsQuery = new ServiceGoods();
serviceGoodsQuery.setCateId(category.getId());
serviceGoodsQuery.setStatus("1");
// 如果有关键词,添加搜索条件
if (keywords != null && !keywords.trim().isEmpty()) {
serviceGoodsQuery.setTitle(keywords.trim());
}
// 查询商品列表
List goodsList = serviceGoodsService.selectServiceGoodsList(serviceGoodsQuery);
List