2734 lines
108 KiB
Java
2734 lines
108 KiB
Java
package com.ruoyi.system.ControllerUtil;
|
||
|
||
import com.alibaba.fastjson2.JSON;
|
||
import com.alibaba.fastjson2.JSONArray;
|
||
import com.ruoyi.system.domain.ServiceCate;
|
||
import com.ruoyi.system.domain.ServiceGoods;
|
||
import com.ruoyi.system.domain.Users;
|
||
import com.ruoyi.system.service.IServiceGoodsService;
|
||
import com.ruoyi.system.service.IUsersService;
|
||
import com.github.pagehelper.PageInfo;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.HashMap;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* 小程序控制器工具类
|
||
*
|
||
* 提供小程序相关的数据处理、响应实体转换等工具方法
|
||
* 主要功能:
|
||
* 1. 服务商品响应数据格式化
|
||
* 2. 分类数据构建
|
||
* 3. 用户数据处理
|
||
* 4. 图片和基础信息数组解析
|
||
* 5. 统一响应格式处理
|
||
*
|
||
* @author Mr. Zhang Pan
|
||
* @date 2025-01-03
|
||
* @version 1.0
|
||
*/
|
||
public class AppletControllerUtil {
|
||
|
||
// ============================== 统一响应处理方法 ==============================
|
||
|
||
/**
|
||
* 成功响应 - code: 200
|
||
*
|
||
* @param data 响应数据
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletSuccess(Object data) {
|
||
com.ruoyi.common.core.domain.AjaxResult result = new com.ruoyi.common.core.domain.AjaxResult();
|
||
result.put("code", 200);
|
||
result.put("msg", "OK");
|
||
result.put("data", data);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 成功响应 - code: 200,无数据
|
||
*
|
||
* @param message 成功消息
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletSuccess(String message) {
|
||
return appletSuccess((Object) message);
|
||
}
|
||
|
||
/**
|
||
* 成功响应 - code: 200,默认消息
|
||
*
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletSuccess() {
|
||
return appletSuccess("操作成功");
|
||
}
|
||
|
||
/**
|
||
* 业务提示响应 - code: 422
|
||
*
|
||
* @param message 提示消息
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletWarning(String message) {
|
||
com.ruoyi.common.core.domain.AjaxResult result = new com.ruoyi.common.core.domain.AjaxResult();
|
||
result.put("code", 422);
|
||
result.put("msg", message);
|
||
result.put("data", new java.util.ArrayList<>());
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 业务提示响应 - code: 422,带数据
|
||
*
|
||
* @param message 提示消息
|
||
* @param data 响应数据
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletWarning(String message, Object data) {
|
||
com.ruoyi.common.core.domain.AjaxResult result = new com.ruoyi.common.core.domain.AjaxResult();
|
||
result.put("code", 422);
|
||
result.put("msg", message);
|
||
result.put("data", data != null ? data : new java.util.ArrayList<>());
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Token验证失败响应 - code: 332
|
||
*
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletUnauthorized() {
|
||
return appletUnauthorized("用户未登录或token无效,请重新登录");
|
||
}
|
||
|
||
/**
|
||
* Token验证失败响应 - code: 332,自定义消息
|
||
*
|
||
* @param message 提示消息
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletUnauthorized(String message) {
|
||
com.ruoyi.common.core.domain.AjaxResult result = new com.ruoyi.common.core.domain.AjaxResult();
|
||
result.put("code", 332);
|
||
result.put("msg", message);
|
||
result.put("data", new java.util.ArrayList<>());
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 系统错误响应 - code: 500
|
||
*
|
||
* @param message 错误消息
|
||
* @return AjaxResult
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult appletError(String message) {
|
||
com.ruoyi.common.core.domain.AjaxResult result = new com.ruoyi.common.core.domain.AjaxResult();
|
||
result.put("code", 500);
|
||
result.put("msg", message);
|
||
result.put("data", new java.util.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<String> 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<String, Object> 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<String> basic;
|
||
|
||
/** 保证金(字符串格式) */
|
||
private String margin;
|
||
|
||
/** 所需技能ID */
|
||
private String skill_ids;
|
||
|
||
/** 创建时间 */
|
||
private String created_at;
|
||
|
||
/** 更新时间 */
|
||
private String updated_at;
|
||
|
||
/** 删除时间 */
|
||
private String deleted_at;
|
||
|
||
/** 评论对象(预留扩展) */
|
||
private Map<String, Object> 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<String> getImgs() { return imgs; }
|
||
public void setImgs(List<String> 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<String, Object> getSku() { return sku; }
|
||
public void setSku(Map<String, Object> 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<String> getBasic() { return basic; }
|
||
public void setBasic(List<String> 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<String, Object> getComment() { return comment; }
|
||
public void setComment(Map<String, Object> 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<String> parseStringToImageList(String imgsString) {
|
||
List<String> imageList = new java.util.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<String> parseStringToList(String dataString) {
|
||
List<String> dataList = new java.util.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<String, Object> buildCategoryData(ServiceCate category, String keywords,
|
||
IServiceGoodsService serviceGoodsService) {
|
||
Map<String, Object> 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());
|
||
|
||
// 如果有关键词,添加搜索条件
|
||
if (keywords != null && !keywords.trim().isEmpty()) {
|
||
serviceGoodsQuery.setTitle(keywords.trim());
|
||
}
|
||
|
||
// 查询商品列表
|
||
List<ServiceGoods> goodsList = serviceGoodsService.selectServiceGoodsList(serviceGoodsQuery);
|
||
List<Map<String, Object>> goodsDataList = new java.util.ArrayList<>();
|
||
|
||
// 构建商品数据列表
|
||
for (ServiceGoods goods : goodsList) {
|
||
Map<String, Object> goodsData = new HashMap<>();
|
||
goodsData.put("id", goods.getId());
|
||
goodsData.put("title", goods.getTitle());
|
||
goodsData.put("icon", buildImageUrl(goods.getIcon()));
|
||
goodsData.put("type", goods.getType());
|
||
goodsData.put("cate_id", goods.getCateId());
|
||
goodsDataList.add(goodsData);
|
||
}
|
||
|
||
categoryData.put("goods", goodsDataList);
|
||
return categoryData;
|
||
}
|
||
|
||
/**
|
||
* 获取用户数据
|
||
*
|
||
* @param token 用户令牌
|
||
* @param usersService 用户Service
|
||
* @return 用户数据Map
|
||
*
|
||
* 返回数据结构:
|
||
* - code: 200(成功) / 302(未登录) / 400(令牌无效)
|
||
* - user: 用户信息对象(成功时返回)
|
||
*
|
||
* 状态码说明:
|
||
* - 200: 令牌有效,用户存在
|
||
* - 302: 未提供令牌,需要登录
|
||
* - 400: 令牌无效或用户不存在
|
||
*
|
||
* 主要用途:
|
||
* - 验证用户登录状态
|
||
* - 获取用户基础信息
|
||
* - 权限验证前置处理
|
||
*/
|
||
public static Map<String, Object> getUserData(String token, IUsersService usersService) {
|
||
Map<String, Object> resultMap = new HashMap<>();
|
||
|
||
if (token == null || token.trim().isEmpty()) {
|
||
// 未提供令牌
|
||
resultMap.put("code", 302);
|
||
resultMap.put("message", "未登录,请先登录");
|
||
} else {
|
||
// 查询用户信息
|
||
Users user = usersService.selectUsersByRememberToken(token.trim());
|
||
if (user != null) {
|
||
// 用户存在且令牌有效
|
||
resultMap.put("code", 200);
|
||
resultMap.put("user", user);
|
||
resultMap.put("message", "获取用户信息成功");
|
||
} else {
|
||
// 令牌无效或用户不存在
|
||
resultMap.put("code", 400);
|
||
resultMap.put("message", "令牌无效或用户不存在");
|
||
}
|
||
}
|
||
|
||
return resultMap;
|
||
}
|
||
|
||
/**
|
||
* 微信用户登录方法
|
||
*
|
||
* @param openid 微信用户openid
|
||
* @param usersService 用户Service
|
||
* @return 登录结果Map
|
||
*
|
||
* 返回数据结构:
|
||
* {
|
||
* "success": true/false, // 登录是否成功
|
||
* "token": "用户token", // 登录成功时返回
|
||
* "userInfo": {...}, // 用户信息
|
||
* "message": "提示信息" // 操作结果消息
|
||
* }
|
||
*
|
||
* 登录流程:
|
||
* 1. 验证openid的有效性
|
||
* 2. 查询或创建用户记录
|
||
* 3. 生成用户token
|
||
* 4. 更新用户登录信息
|
||
* 5. 返回登录结果
|
||
*
|
||
* 业务逻辑:
|
||
* - 首次登录:创建新用户记录
|
||
* - 再次登录:更新登录时间和token
|
||
* - 支持用户信息同步更新
|
||
*/
|
||
public static Map<String, Object> wechatUserLogin(String openid, IUsersService usersService) {
|
||
Map<String, Object> result = new HashMap<>();
|
||
|
||
try {
|
||
// 1. 参数验证
|
||
if (openid == null || openid.trim().isEmpty()) {
|
||
result.put("success", false);
|
||
result.put("message", "openid不能为空");
|
||
return result;
|
||
}
|
||
|
||
String trimmedOpenid = openid.trim();
|
||
|
||
// 2. 验证openid有效性
|
||
Map<String, Object> validationResult = WechatApiUtil.validateOpenid(trimmedOpenid);
|
||
if (!(Boolean) validationResult.get("valid")) {
|
||
result.put("success", false);
|
||
result.put("message", "openid验证失败:" + validationResult.get("errorMsg"));
|
||
return result;
|
||
}
|
||
|
||
// 3. 获取微信用户信息
|
||
Map<String, Object> wechatUserInfo = (Map<String, Object>) validationResult.get("userInfo");
|
||
|
||
// 4. 查询数据库中是否已存在该用户
|
||
Users existingUser = usersService.selectUsersByOpenid(trimmedOpenid);
|
||
|
||
Users userRecord;
|
||
boolean isNewUser = false;
|
||
|
||
if (existingUser == null) {
|
||
// 4.1 首次登录,创建新用户记录
|
||
userRecord = createNewWechatUser(trimmedOpenid, wechatUserInfo);
|
||
isNewUser = true;
|
||
} else {
|
||
// 4.2 用户已存在,更新用户信息
|
||
userRecord = updateExistingWechatUser(existingUser, wechatUserInfo);
|
||
}
|
||
|
||
// 5. 生成新的用户token
|
||
String userToken = WechatApiUtil.generateUserToken(trimmedOpenid);
|
||
userRecord.setRememberToken(userToken);
|
||
|
||
// 6. 保存或更新用户记录到数据库
|
||
if (isNewUser) {
|
||
// 插入新用户
|
||
int insertResult = usersService.insertUsers(userRecord);
|
||
if (insertResult <= 0) {
|
||
result.put("success", false);
|
||
result.put("message", "创建用户记录失败");
|
||
return result;
|
||
}
|
||
} else {
|
||
// 更新现有用户
|
||
int updateResult = usersService.updateUsers(userRecord);
|
||
if (updateResult <= 0) {
|
||
result.put("success", false);
|
||
result.put("message", "更新用户记录失败");
|
||
return result;
|
||
}
|
||
}
|
||
|
||
// 7. 构建返回数据
|
||
Map<String, Object> responseUserInfo = buildUserResponseInfo(userRecord, wechatUserInfo);
|
||
|
||
result.put("success", true);
|
||
result.put("token", userToken);
|
||
result.put("userInfo", responseUserInfo);
|
||
result.put("isNewUser", isNewUser);
|
||
result.put("loginTime", System.currentTimeMillis());
|
||
result.put("message", isNewUser ? "注册并登录成功" : "登录成功");
|
||
|
||
} catch (Exception e) {
|
||
result.put("success", false);
|
||
result.put("message", "登录过程中发生错误:" + e.getMessage());
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 创建新的微信用户记录
|
||
*
|
||
* @param openid 微信openid
|
||
* @param wechatUserInfo 微信用户信息
|
||
* @return 新创建的用户记录
|
||
*
|
||
* 用户字段设置:
|
||
* - 基础信息:openid、昵称、头像等
|
||
* - 状态信息:启用状态、注册时间等
|
||
* - 默认值:密码、角色等系统字段
|
||
*/
|
||
private static Users createNewWechatUser(String openid, Map<String, Object> wechatUserInfo) {
|
||
Users newUser = new Users();
|
||
|
||
// 基础信息
|
||
newUser.setOpenid(openid);
|
||
newUser.setNickname((String) wechatUserInfo.get("nickname"));
|
||
newUser.setAvatar((String) wechatUserInfo.get("avatar"));
|
||
|
||
// 用户名使用openid(可以根据业务需求调整)
|
||
newUser.setName("wx_" + openid.substring(openid.length() - 8));
|
||
|
||
// 设置默认密码(微信登录不需要密码)
|
||
newUser.setPassword(""); // 实际项目中可能需要加密的默认密码
|
||
|
||
// 状态信息
|
||
newUser.setStatus(1); // 启用状态:1启用 0关闭
|
||
newUser.setType("1"); // 用户类型:1普通用户 2师傅
|
||
|
||
// 时间信息
|
||
java.util.Date now = new java.util.Date();
|
||
newUser.setCreateTime(now);
|
||
newUser.setUpdateTime(now);
|
||
|
||
// 其他信息
|
||
newUser.setRemark("微信小程序用户");
|
||
|
||
return newUser;
|
||
}
|
||
|
||
/**
|
||
* 更新现有微信用户记录
|
||
*
|
||
* @param existingUser 现有用户记录
|
||
* @param wechatUserInfo 微信用户信息
|
||
* @return 更新后的用户记录
|
||
*
|
||
* 更新策略:
|
||
* - 同步微信最新信息:昵称、头像等
|
||
* - 更新登录时间
|
||
* - 保持原有的系统信息不变
|
||
*/
|
||
private static Users updateExistingWechatUser(Users existingUser, Map<String, Object> wechatUserInfo) {
|
||
// 更新微信相关信息
|
||
existingUser.setNickname((String) wechatUserInfo.get("nickname"));
|
||
existingUser.setAvatar((String) wechatUserInfo.get("avatar"));
|
||
|
||
// 更新登录时间
|
||
existingUser.setUpdateTime(new java.util.Date());
|
||
|
||
return existingUser;
|
||
}
|
||
|
||
/**
|
||
* 构建用户响应信息
|
||
*
|
||
* @param userRecord 用户数据库记录
|
||
* @param wechatUserInfo 微信用户信息
|
||
* @return 格式化的用户信息
|
||
*
|
||
* 返回字段:
|
||
* - 基础信息:用户ID、昵称、头像等
|
||
* - 微信信息:openid等
|
||
* - 状态信息:用户状态、注册时间等
|
||
* - 过滤敏感信息:密码等
|
||
*/
|
||
private static Map<String, Object> buildUserResponseInfo(Users userRecord, Map<String, Object> wechatUserInfo) {
|
||
Map<String, Object> userInfo = new HashMap<>();
|
||
|
||
// 基础用户信息
|
||
userInfo.put("userId", userRecord.getId());
|
||
userInfo.put("username", userRecord.getName());
|
||
userInfo.put("nickname", userRecord.getNickname());
|
||
userInfo.put("avatar", userRecord.getAvatar());
|
||
userInfo.put("openid", userRecord.getOpenid());
|
||
|
||
// 状态信息
|
||
userInfo.put("status", userRecord.getStatus());
|
||
userInfo.put("userType", userRecord.getType());
|
||
userInfo.put("createTime", userRecord.getCreateTime());
|
||
userInfo.put("updateTime", userRecord.getUpdateTime());
|
||
|
||
// 微信附加信息
|
||
userInfo.put("gender", wechatUserInfo.get("gender"));
|
||
userInfo.put("city", wechatUserInfo.get("city"));
|
||
userInfo.put("province", wechatUserInfo.get("province"));
|
||
userInfo.put("country", wechatUserInfo.get("country"));
|
||
|
||
return userInfo;
|
||
}
|
||
|
||
/**
|
||
* 验证用户token有效性
|
||
*
|
||
* @param token 用户token
|
||
* @param usersService 用户Service
|
||
* @return 验证结果Map
|
||
*
|
||
* 返回数据结构:
|
||
* {
|
||
* "valid": true/false, // token是否有效
|
||
* "userInfo": {...}, // 用户信息(有效时返回)
|
||
* "message": "提示信息" // 验证结果消息
|
||
* }
|
||
*
|
||
* 验证逻辑:
|
||
* 1. 检查token格式是否正确
|
||
* 2. 从数据库查询token对应的用户
|
||
* 3. 验证用户状态是否正常
|
||
* 4. 检查token是否过期(可选)
|
||
* 5. 返回验证结果
|
||
*/
|
||
public static Map<String, Object> validateUserToken(String token, IUsersService usersService) {
|
||
Map<String, Object> result = new HashMap<>();
|
||
|
||
try {
|
||
// 1. 参数验证
|
||
if (token == null || token.trim().isEmpty()) {
|
||
result.put("valid", false);
|
||
result.put("message", "token不能为空");
|
||
return result;
|
||
}
|
||
|
||
String trimmedToken = token.trim();
|
||
|
||
// 2. 检查token格式
|
||
if (!WechatApiUtil.isValidTokenFormat(trimmedToken)) {
|
||
result.put("valid", false);
|
||
result.put("message", "token格式无效");
|
||
return result;
|
||
}
|
||
|
||
// 3. 从数据库查询token对应的用户
|
||
Users user = usersService.selectUsersByRememberToken(trimmedToken);
|
||
if (user == null) {
|
||
result.put("valid", false);
|
||
result.put("message", "token无效或已过期");
|
||
return result;
|
||
}
|
||
|
||
// 4. 检查用户状态
|
||
if (!"1".equals(user.getStatus())) {
|
||
result.put("valid", false);
|
||
result.put("message", "用户账号已被禁用");
|
||
return result;
|
||
}
|
||
|
||
// 5. 构建用户信息(过滤敏感字段)
|
||
Map<String, Object> userInfo = new HashMap<>();
|
||
userInfo.put("userId", user.getId());
|
||
userInfo.put("username", user.getName());
|
||
userInfo.put("nickname", user.getNickname());
|
||
userInfo.put("avatar", user.getAvatar());
|
||
userInfo.put("openid", user.getOpenid());
|
||
userInfo.put("status", user.getStatus());
|
||
userInfo.put("userType", user.getType());
|
||
userInfo.put("createTime", user.getCreateTime());
|
||
userInfo.put("updateTime", user.getUpdateTime());
|
||
|
||
result.put("valid", true);
|
||
result.put("userInfo", userInfo);
|
||
result.put("message", "token验证成功");
|
||
|
||
} catch (Exception e) {
|
||
result.put("valid", false);
|
||
result.put("message", "验证token时发生错误:" + e.getMessage());
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// ===== 地址管理相关工具方法 =====
|
||
|
||
/**
|
||
* 构建地址更新对象
|
||
*
|
||
* @param params 请求参数Map,包含地址的各个字段信息
|
||
* @param addressId 要更新的地址ID
|
||
* @param userId 用户ID,用于权限验证
|
||
* @return UserAddress对象,包含更新后的地址信息
|
||
*
|
||
* 功能说明:
|
||
* - 从请求参数中提取地址信息并构建UserAddress对象
|
||
* - 自动处理参数类型转换和空值验证
|
||
* - 用于地址编辑功能的数据转换
|
||
*/
|
||
public static com.ruoyi.system.domain.UserAddress buildUpdateAddress(Map<String, Object> params, Long addressId, Long userId) {
|
||
com.ruoyi.system.domain.UserAddress address = new com.ruoyi.system.domain.UserAddress();
|
||
address.setId(addressId);
|
||
address.setUid(userId);
|
||
|
||
// 设置收货人姓名
|
||
if (params.get("name") != null) {
|
||
address.setName(params.get("name").toString().trim());
|
||
}
|
||
|
||
// 设置联系电话
|
||
if (params.get("phone") != null) {
|
||
address.setPhone(params.get("phone").toString().trim());
|
||
}
|
||
|
||
// 设置纬度
|
||
if (params.get("latitude") != null) {
|
||
address.setLatitude(params.get("latitude").toString().trim());
|
||
}
|
||
|
||
// 设置经度
|
||
if (params.get("longitude") != null) {
|
||
address.setLongitude(params.get("longitude").toString().trim());
|
||
}
|
||
|
||
// 设置地址名称
|
||
if (params.get("address_name") != null) {
|
||
address.setAddressName(params.get("address_name").toString().trim());
|
||
}
|
||
|
||
// 设置地址信息
|
||
if (params.get("address_info") != null) {
|
||
address.setAddressInfo(params.get("address_info").toString().trim());
|
||
}
|
||
|
||
// 设置详细地址
|
||
if (params.get("info") != null) {
|
||
address.setInfo(params.get("info").toString().trim());
|
||
}
|
||
|
||
// 设置是否默认地址
|
||
if (params.get("is_default") != null) {
|
||
try {
|
||
Long isDefault = Long.valueOf(params.get("is_default").toString());
|
||
address.setIsDefault(isDefault);
|
||
} catch (NumberFormatException e) {
|
||
// 如果转换失败,设为非默认
|
||
address.setIsDefault(0L);
|
||
}
|
||
}
|
||
|
||
return address;
|
||
}
|
||
|
||
/**
|
||
* 验证地址参数
|
||
*
|
||
* @param address 需要验证的地址对象
|
||
* @return 验证错误信息,null表示验证通过
|
||
*
|
||
* 功能说明:
|
||
* - 验证地址对象的必填字段是否完整
|
||
* - 验证手机号格式是否正确(11位数字)
|
||
* - 为地址新增和编辑功能提供统一的参数验证
|
||
*/
|
||
public static String validateAddressParams(com.ruoyi.system.domain.UserAddress address) {
|
||
if (address.getName() == null || address.getName().isEmpty()) {
|
||
return "收货人姓名不能为空";
|
||
}
|
||
|
||
if (address.getPhone() == null || address.getPhone().isEmpty()) {
|
||
return "联系电话不能为空";
|
||
}
|
||
|
||
// 验证手机号格式(简单验证)
|
||
if (!address.getPhone().matches("^1[3-9]\\d{9}$")) {
|
||
return "联系电话格式不正确";
|
||
}
|
||
|
||
if (address.getInfo() == null || address.getInfo().isEmpty()) {
|
||
return "详细地址不能为空";
|
||
}
|
||
|
||
return null; // 验证通过
|
||
}
|
||
|
||
/**
|
||
* 构建地址新增对象
|
||
*
|
||
* @param params 请求参数Map,包含新地址的各个字段信息
|
||
* @param userId 当前登录用户的ID
|
||
* @return UserAddress对象,包含新地址的完整信息
|
||
*
|
||
* 功能说明:
|
||
* - 从请求参数中提取地址信息并构建UserAddress对象
|
||
* - 智能处理is_default字段的多种数据类型(boolean/number/string)
|
||
* - 为地址新增功能提供数据转换和默认值设置
|
||
*/
|
||
public static com.ruoyi.system.domain.UserAddress buildNewAddress(Map<String, Object> params, Long userId) {
|
||
com.ruoyi.system.domain.UserAddress address = new com.ruoyi.system.domain.UserAddress();
|
||
address.setUid(userId);
|
||
|
||
// 设置收货人姓名
|
||
if (params.get("name") != null) {
|
||
address.setName(params.get("name").toString().trim());
|
||
}
|
||
|
||
// 设置联系电话
|
||
if (params.get("phone") != null) {
|
||
address.setPhone(params.get("phone").toString().trim());
|
||
}
|
||
|
||
// 设置纬度
|
||
if (params.get("latitude") != null) {
|
||
address.setLatitude(params.get("latitude").toString().trim());
|
||
}
|
||
|
||
// 设置经度
|
||
if (params.get("longitude") != null) {
|
||
address.setLongitude(params.get("longitude").toString().trim());
|
||
}
|
||
|
||
// 设置地址名称
|
||
if (params.get("address_name") != null) {
|
||
address.setAddressName(params.get("address_name").toString().trim());
|
||
}
|
||
|
||
// 设置地址信息
|
||
if (params.get("address_info") != null) {
|
||
address.setAddressInfo(params.get("address_info").toString().trim());
|
||
}
|
||
|
||
// 设置详细地址
|
||
if (params.get("info") != null) {
|
||
address.setInfo(params.get("info").toString().trim());
|
||
}
|
||
|
||
// 设置是否默认地址
|
||
if (params.get("is_default") != null) {
|
||
try {
|
||
// 处理布尔值或数字值
|
||
Object isDefaultObj = params.get("is_default");
|
||
Long isDefault = 0L;
|
||
|
||
if (isDefaultObj instanceof Boolean) {
|
||
isDefault = ((Boolean) isDefaultObj) ? 1L : 0L;
|
||
} else if (isDefaultObj instanceof Number) {
|
||
isDefault = ((Number) isDefaultObj).longValue();
|
||
} else {
|
||
String isDefaultStr = isDefaultObj.toString().toLowerCase();
|
||
if ("true".equals(isDefaultStr) || "1".equals(isDefaultStr)) {
|
||
isDefault = 1L;
|
||
}
|
||
}
|
||
|
||
address.setIsDefault(isDefault);
|
||
} catch (Exception e) {
|
||
// 如果转换失败,设为非默认
|
||
address.setIsDefault(0L);
|
||
}
|
||
} else {
|
||
// 如果没有指定,默认设为非默认地址
|
||
address.setIsDefault(0L);
|
||
}
|
||
|
||
return address;
|
||
}
|
||
|
||
// ===== 订单售后相关工具方法 =====
|
||
|
||
/**
|
||
* 检查订单状态是否允许申请售后
|
||
*
|
||
* @param orderStatus 订单状态
|
||
* @return true=允许申请售后,false=不允许
|
||
*
|
||
* 功能说明:
|
||
* - 根据订单状态判断是否可以申请售后
|
||
* - 一般已完成的订单才能申请售后
|
||
* - 已取消或已退款的订单不能申请售后
|
||
*/
|
||
public static boolean isOrderAllowRework(Long orderStatus) {
|
||
if (orderStatus == null) {
|
||
return false;
|
||
}
|
||
|
||
// 订单状态定义(根据实际业务调整):
|
||
// 1=待接单, 2=已接单, 3=服务中, 4=已完成, 5=已取消, 6=售后中, 7=已退款
|
||
// 只有已完成(4)的订单才能申请售后
|
||
return orderStatus == 4L;
|
||
}
|
||
|
||
/**
|
||
* 处理售后返修申请业务逻辑
|
||
*
|
||
* @param order 订单对象
|
||
* @param phone 联系电话
|
||
* @param mark 返修原因
|
||
* @param user 用户信息
|
||
* @param orderReworkService 售后服务
|
||
* @param orderService 订单服务
|
||
* @return true=处理成功,false=处理失败
|
||
*
|
||
* 功能说明:
|
||
* - 创建售后返修记录到order_rework表
|
||
* - 更新订单状态为售后处理中
|
||
* - 记录完整的售后申请信息
|
||
*/
|
||
public static boolean processReworkApplication(com.ruoyi.system.domain.Order order, String phone, String mark,
|
||
com.ruoyi.system.domain.Users user,
|
||
com.ruoyi.system.service.IOrderReworkService orderReworkService,
|
||
com.ruoyi.system.service.IOrderService orderService) {
|
||
try {
|
||
// 1. 创建售后返修记录
|
||
com.ruoyi.system.domain.OrderRework orderRework = new com.ruoyi.system.domain.OrderRework();
|
||
orderRework.setUid(user.getId()); // 用户ID
|
||
orderRework.setUname(user.getNickname()); // 用户名称
|
||
orderRework.setOid(order.getId()); // 订单ID
|
||
orderRework.setOrderId(order.getOrderId()); // 订单号
|
||
orderRework.setPhone(phone); // 联系电话
|
||
orderRework.setMark(mark); // 返修原因
|
||
orderRework.setStatus(0); // 状态:0-待处理,1-已处理
|
||
|
||
// 插入售后返修记录
|
||
int reworkResult = orderReworkService.insertOrderRework(orderRework);
|
||
|
||
if (reworkResult > 0) {
|
||
// 2. 更新订单状态为售后处理中 (状态6)
|
||
com.ruoyi.system.domain.Order updateOrder = new com.ruoyi.system.domain.Order();
|
||
updateOrder.setId(order.getId());
|
||
updateOrder.setStatus(6L); // 售后处理中状态
|
||
|
||
int updateResult = orderService.updateOrder(updateOrder);
|
||
|
||
if (updateResult > 0) {
|
||
System.out.println("订单[" + order.getOrderId() + "]售后申请成功,售后记录ID:" + orderRework.getId());
|
||
return true;
|
||
} else {
|
||
System.err.println("订单状态更新失败,订单ID:" + order.getId());
|
||
return false;
|
||
}
|
||
} else {
|
||
System.err.println("售后记录创建失败,订单ID:" + order.getId());
|
||
return false;
|
||
}
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("处理售后申请业务逻辑异常:" + e.getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// ===== 合作申请相关工具方法 =====
|
||
|
||
/**
|
||
* 构建合作申请对象
|
||
*
|
||
* @param params 请求参数Map,包含合作申请的各个字段信息
|
||
* @param uid 用户ID(可为null)
|
||
* @param uname 用户名称(可为null)
|
||
* @return Cooperate对象,包含完整的合作申请信息
|
||
*
|
||
* 功能说明:
|
||
* - 从请求参数中提取合作申请信息并构建Cooperate对象
|
||
* - 设置默认状态为0(待处理)
|
||
* - 为合作申请功能提供数据转换
|
||
*/
|
||
public static com.ruoyi.system.domain.Cooperate buildCooperateApplication(Map<String, Object> params, Long uid, String uname) {
|
||
com.ruoyi.system.domain.Cooperate cooperate = new com.ruoyi.system.domain.Cooperate();
|
||
|
||
// 设置用户信息(如果有的话)
|
||
cooperate.setUid(uid);
|
||
cooperate.setUname(uname);
|
||
|
||
// 设置公司名称
|
||
if (params.get("company") != null) {
|
||
cooperate.setCompany(params.get("company").toString().trim());
|
||
}
|
||
|
||
// 设置联系人姓名
|
||
if (params.get("name") != null) {
|
||
cooperate.setName(params.get("name").toString().trim());
|
||
}
|
||
|
||
// 设置联系电话
|
||
if (params.get("phone") != null) {
|
||
cooperate.setPhone(params.get("phone").toString().trim());
|
||
}
|
||
|
||
// 设置联系地址
|
||
if (params.get("address") != null) {
|
||
cooperate.setAddress(params.get("address").toString().trim());
|
||
}
|
||
|
||
// 设置合作意向
|
||
if (params.get("info") != null) {
|
||
cooperate.setInfo(params.get("info").toString().trim());
|
||
}
|
||
|
||
// 设置默认状态:0-待处理,1-已联系,2-合作中,3-已拒绝
|
||
cooperate.setStatus(0L);
|
||
|
||
return cooperate;
|
||
}
|
||
|
||
/**
|
||
* 验证合作申请参数
|
||
*
|
||
* @param cooperate 需要验证的合作申请对象
|
||
* @return 验证错误信息,null表示验证通过
|
||
*
|
||
* 功能说明:
|
||
* - 验证合作申请对象的必填字段是否完整
|
||
* - 验证手机号格式是否正确
|
||
* - 为合作申请功能提供统一的参数验证
|
||
*/
|
||
public static String validateCooperateParams(com.ruoyi.system.domain.Cooperate cooperate) {
|
||
if (cooperate.getCompany() == null || cooperate.getCompany().isEmpty()) {
|
||
return "公司名称不能为空";
|
||
}
|
||
|
||
if (cooperate.getName() == null || cooperate.getName().isEmpty()) {
|
||
return "联系人姓名不能为空";
|
||
}
|
||
|
||
if (cooperate.getPhone() == null || cooperate.getPhone().isEmpty()) {
|
||
return "联系电话不能为空";
|
||
}
|
||
|
||
// 验证手机号格式
|
||
if (!cooperate.getPhone().matches("^1[3-9]\\d{9}$")) {
|
||
return "联系电话格式不正确";
|
||
}
|
||
|
||
if (cooperate.getAddress() == null || cooperate.getAddress().isEmpty()) {
|
||
return "联系地址不能为空";
|
||
}
|
||
|
||
if (cooperate.getInfo() == null || cooperate.getInfo().isEmpty()) {
|
||
return "合作意向不能为空";
|
||
}
|
||
|
||
return null; // 验证通过
|
||
}
|
||
|
||
// ===== 支付相关工具方法 =====
|
||
|
||
/**
|
||
* 处理支付成功的业务逻辑
|
||
*
|
||
* @param paymentInfo 支付信息Map,包含订单号、交易号、金额等
|
||
* @param isPayFor 是否为代付订单,true=代付订单,false=普通订单
|
||
*
|
||
* 功能说明:
|
||
* - 根据订单类型执行不同的支付成功后处理逻辑
|
||
* - 普通订单:更新订单状态、发送通知、处理库存等
|
||
* - 代付订单:处理代付逻辑、给被代付人转账等
|
||
* - 为微信支付回调提供业务处理支持
|
||
*/
|
||
public static void handlePaymentSuccess(Map<String, Object> paymentInfo, boolean isPayFor) {
|
||
try {
|
||
String orderNo = (String) paymentInfo.get("outTradeNo");
|
||
String transactionId = (String) paymentInfo.get("transactionId");
|
||
String totalFee = (String) paymentInfo.get("totalFee");
|
||
String timeEnd = (String) paymentInfo.get("timeEnd");
|
||
|
||
// 根据业务需求处理支付成功逻辑
|
||
if (isPayFor) {
|
||
// 代付订单处理逻辑
|
||
// 1. 更新代付订单状态
|
||
// 2. 处理原订单状态
|
||
// 3. 给被代付人转账等
|
||
System.out.println("处理代付订单支付成功:" + orderNo);
|
||
} else {
|
||
// 普通订单处理逻辑
|
||
// 1. 更新订单状态
|
||
// 2. 发送支付成功通知
|
||
// 3. 处理库存等业务逻辑
|
||
System.out.println("处理普通订单支付成功:" + orderNo);
|
||
}
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("处理支付成功业务逻辑异常:" + e.getMessage());
|
||
}
|
||
}
|
||
|
||
// ================================= 积分相关工具方法 =================================
|
||
|
||
/**
|
||
* 构建积分订单列表数据
|
||
*
|
||
* @param integralOrderList 积分订单列表
|
||
* @param integralProductService 积分商品服务
|
||
* @return 格式化的订单列表
|
||
*/
|
||
public static java.util.List<java.util.Map<String, Object>> buildIntegralOrderList(
|
||
java.util.List<com.ruoyi.system.domain.IntegralOrder> integralOrderList,
|
||
com.ruoyi.system.service.IIntegralProductService integralProductService) {
|
||
|
||
java.util.List<java.util.Map<String, Object>> formattedOrderList = new java.util.ArrayList<>();
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||
|
||
for (com.ruoyi.system.domain.IntegralOrder order : integralOrderList) {
|
||
java.util.Map<String, Object> orderData = new java.util.HashMap<>();
|
||
|
||
// 基础订单信息
|
||
orderData.put("id", order.getId());
|
||
orderData.put("order_id", order.getOrderId());
|
||
orderData.put("uid", order.getUid());
|
||
orderData.put("user_name", order.getUserName());
|
||
orderData.put("user_phone", order.getUserPhone());
|
||
orderData.put("user_address", order.getUserAddress());
|
||
orderData.put("product_id", order.getProductId());
|
||
orderData.put("sku", order.getSku());
|
||
orderData.put("num", order.getNum());
|
||
orderData.put("price", order.getPrice());
|
||
orderData.put("total_price", order.getTotalPrice());
|
||
orderData.put("status", order.getStatus());
|
||
orderData.put("delivery_id", order.getDeliveryId());
|
||
orderData.put("delivery_num", order.getDeliveryNum());
|
||
orderData.put("mark", order.getMark());
|
||
|
||
// 格式化时间字段
|
||
orderData.put("created_at", order.getCreatedAt() != null ? sdf.format(order.getCreatedAt()) : null);
|
||
orderData.put("updated_at", order.getUpdatedAt() != null ? sdf.format(order.getUpdatedAt()) : null);
|
||
|
||
// 添加商品信息
|
||
orderData.put("product", buildIntegralProductInfo(order.getProductId(), integralProductService));
|
||
|
||
formattedOrderList.add(orderData);
|
||
}
|
||
|
||
return formattedOrderList;
|
||
}
|
||
|
||
/**
|
||
* 构建积分商品信息
|
||
*
|
||
* @param productId 商品ID
|
||
* @param integralProductService 积分商品服务
|
||
* @return 商品信息Map
|
||
*/
|
||
public static java.util.Map<String, Object> buildIntegralProductInfo(Long productId,
|
||
com.ruoyi.system.service.IIntegralProductService integralProductService) {
|
||
|
||
if (productId == null) {
|
||
return null;
|
||
}
|
||
|
||
try {
|
||
com.ruoyi.system.domain.IntegralProduct product = integralProductService.selectIntegralProductById(productId);
|
||
if (product != null) {
|
||
java.util.Map<String, Object> productData = new java.util.HashMap<>();
|
||
productData.put("id", product.getId());
|
||
productData.put("title", product.getTitle());
|
||
productData.put("image", buildImageUrl(product.getImage()));
|
||
productData.put("price", product.getPrice());
|
||
productData.put("num", product.getNum());
|
||
productData.put("status", product.getStatus());
|
||
return productData;
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("查询积分商品信息异常:" + e.getMessage());
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 构建积分日志列表数据
|
||
*
|
||
* @param integralLogList 积分日志列表
|
||
* @return 格式化的日志列表
|
||
*/
|
||
public static java.util.List<java.util.Map<String, Object>> buildIntegralLogList(
|
||
java.util.List<com.ruoyi.system.domain.IntegralLog> integralLogList) {
|
||
|
||
java.util.List<java.util.Map<String, Object>> formattedLogList = new java.util.ArrayList<>();
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||
|
||
for (com.ruoyi.system.domain.IntegralLog log : integralLogList) {
|
||
java.util.Map<String, Object> logData = new java.util.HashMap<>();
|
||
logData.put("id", log.getId());
|
||
logData.put("order_id", log.getOrderId());
|
||
logData.put("title", log.getTitle());
|
||
logData.put("mark", log.getMark());
|
||
logData.put("uid", log.getUid());
|
||
logData.put("type", log.getType());
|
||
logData.put("num", log.getNum());
|
||
|
||
// 格式化时间字段
|
||
logData.put("created_at", log.getCreatedAt() != null ? sdf.format(log.getCreatedAt()) : null);
|
||
logData.put("updated_at", log.getUpdatedAt() != null ? sdf.format(log.getUpdatedAt()) : null);
|
||
|
||
formattedLogList.add(logData);
|
||
}
|
||
|
||
return formattedLogList;
|
||
}
|
||
|
||
/**
|
||
* 构建优惠券列表数据
|
||
*
|
||
* @param couponUserList 优惠券用户列表
|
||
* @param serviceCateService 服务分类服务
|
||
* @return 格式化的优惠券列表
|
||
*/
|
||
public static java.util.List<java.util.Map<String, Object>> buildCouponUserList(
|
||
java.util.List<com.ruoyi.system.domain.CouponUser> couponUserList,
|
||
com.ruoyi.system.service.IServiceCateService serviceCateService) {
|
||
|
||
java.util.List<java.util.Map<String, Object>> resultList = new java.util.ArrayList<>();
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||
|
||
for (com.ruoyi.system.domain.CouponUser couponUser : couponUserList) {
|
||
java.util.Map<String, Object> couponData = new java.util.HashMap<>();
|
||
|
||
// 基础字段
|
||
couponData.put("id", couponUser.getId());
|
||
couponData.put("uid", couponUser.getUid());
|
||
couponData.put("coupon_id", couponUser.getCouponId());
|
||
couponData.put("coupon_title", couponUser.getCouponTitle());
|
||
couponData.put("coupon_price", couponUser.getCouponPrice());
|
||
couponData.put("min_price", couponUser.getMinPrice());
|
||
couponData.put("cate_id", couponUser.getCateId());
|
||
couponData.put("product_id", couponUser.getProductId());
|
||
couponData.put("receive_type", couponUser.getReceiveType());
|
||
couponData.put("status", couponUser.getStatus());
|
||
couponData.put("lose_time", couponUser.getLoseTime());
|
||
couponData.put("use_time", couponUser.getUseTime());
|
||
|
||
// 时间字段格式化
|
||
if (couponUser.getAddTime() != null) {
|
||
java.util.Date addTime = new java.util.Date(couponUser.getAddTime() * 1000L);
|
||
couponData.put("add_time", sdf.format(addTime));
|
||
} else {
|
||
couponData.put("add_time", null);
|
||
}
|
||
|
||
couponData.put("created_at", couponUser.getCreatedAt() != null ? sdf.format(couponUser.getCreatedAt()) : null);
|
||
couponData.put("updated_at", couponUser.getUpdatedAt() != null ? sdf.format(couponUser.getUpdatedAt()) : null);
|
||
|
||
// 添加 is_used 字段
|
||
boolean isUsed = couponUser.getStatus() != null && couponUser.getStatus() == 2L;
|
||
couponData.put("is_used", isUsed);
|
||
|
||
// 添加 suit_title 字段
|
||
String suitTitle = "";
|
||
if (couponUser.getCateId() != null && couponUser.getCateId() > 0) {
|
||
try {
|
||
com.ruoyi.system.domain.ServiceCate serviceCate = serviceCateService.selectServiceCateById(couponUser.getCateId());
|
||
if (serviceCate != null && serviceCate.getTitle() != null) {
|
||
suitTitle = serviceCate.getTitle();
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("查询服务分类异常:" + e.getMessage());
|
||
}
|
||
}
|
||
couponData.put("suit_title", suitTitle);
|
||
|
||
// 添加 tag 字段
|
||
String tag = "";
|
||
if (couponUser.getReceiveType() != null) {
|
||
switch (couponUser.getReceiveType()) {
|
||
case "1":
|
||
tag = "通用券";
|
||
break;
|
||
case "2":
|
||
tag = "品类券";
|
||
break;
|
||
case "3":
|
||
tag = "商品券";
|
||
break;
|
||
default:
|
||
tag = "优惠券";
|
||
break;
|
||
}
|
||
}
|
||
couponData.put("tag", tag);
|
||
|
||
resultList.add(couponData);
|
||
}
|
||
|
||
return resultList;
|
||
}
|
||
|
||
/**
|
||
* 构建积分订单日志列表
|
||
*
|
||
* @param orderId 订单ID
|
||
* @param integralOrderLogService 积分订单日志服务
|
||
* @return 格式化的日志列表
|
||
*/
|
||
public static java.util.List<java.util.Map<String, Object>> buildIntegralOrderLogList(Long orderId,
|
||
com.ruoyi.system.service.IIntegralOrderLogService integralOrderLogService) {
|
||
|
||
java.util.List<java.util.Map<String, Object>> logList = new java.util.ArrayList<>();
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||
|
||
try {
|
||
com.ruoyi.system.domain.IntegralOrderLog logQuery = new com.ruoyi.system.domain.IntegralOrderLog();
|
||
logQuery.setOid(orderId);
|
||
java.util.List<com.ruoyi.system.domain.IntegralOrderLog> orderLogs = integralOrderLogService.selectIntegralOrderLogList(logQuery);
|
||
|
||
for (com.ruoyi.system.domain.IntegralOrderLog log : orderLogs) {
|
||
java.util.Map<String, Object> logData = new java.util.HashMap<>();
|
||
logData.put("id", log.getId());
|
||
logData.put("oid", log.getOid());
|
||
logData.put("order_id", log.getOrderId());
|
||
logData.put("title", log.getTitle());
|
||
logData.put("content", log.getContent());
|
||
logData.put("type", log.getType());
|
||
|
||
logData.put("created_at", log.getCreatedAt() != null ? sdf.format(log.getCreatedAt()) : null);
|
||
logData.put("updated_at", log.getUpdatedAt() != null ? sdf.format(log.getUpdatedAt()) : null);
|
||
|
||
logList.add(logData);
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("查询订单日志异常:" + e.getMessage());
|
||
}
|
||
|
||
return logList;
|
||
}
|
||
|
||
/**
|
||
* 构建积分订单详情数据
|
||
*
|
||
* @param integralOrder 积分订单
|
||
* @param integralProductService 积分商品服务
|
||
* @param integralOrderLogService 积分订单日志服务
|
||
* @return 格式化的订单详情
|
||
*/
|
||
public static java.util.Map<String, Object> buildIntegralOrderDetail(
|
||
com.ruoyi.system.domain.IntegralOrder integralOrder,
|
||
com.ruoyi.system.service.IIntegralProductService integralProductService,
|
||
com.ruoyi.system.service.IIntegralOrderLogService integralOrderLogService) {
|
||
|
||
java.util.Map<String, Object> orderData = new java.util.HashMap<>();
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||
|
||
// 基础订单信息
|
||
orderData.put("id", integralOrder.getId());
|
||
orderData.put("order_id", integralOrder.getOrderId());
|
||
orderData.put("uid", integralOrder.getUid());
|
||
orderData.put("user_name", integralOrder.getUserName());
|
||
orderData.put("user_phone", integralOrder.getUserPhone());
|
||
orderData.put("user_address", integralOrder.getUserAddress());
|
||
orderData.put("product_id", integralOrder.getProductId());
|
||
orderData.put("sku", integralOrder.getSku());
|
||
orderData.put("num", integralOrder.getNum());
|
||
orderData.put("price", integralOrder.getPrice());
|
||
orderData.put("total_price", integralOrder.getTotalPrice());
|
||
orderData.put("status", integralOrder.getStatus());
|
||
orderData.put("delivery_id", integralOrder.getDeliveryId());
|
||
orderData.put("delivery_num", integralOrder.getDeliveryNum());
|
||
orderData.put("mark", integralOrder.getMark());
|
||
|
||
// 格式化时间字段
|
||
orderData.put("created_at", integralOrder.getCreatedAt() != null ? sdf.format(integralOrder.getCreatedAt()) : null);
|
||
orderData.put("updated_at", integralOrder.getUpdatedAt() != null ? sdf.format(integralOrder.getUpdatedAt()) : null);
|
||
|
||
// 添加商品信息
|
||
if (integralOrder.getProductId() != null) {
|
||
try {
|
||
com.ruoyi.system.domain.IntegralProduct product = integralProductService.selectIntegralProductById(integralOrder.getProductId());
|
||
if (product != null) {
|
||
java.util.Map<String, Object> productData = new java.util.HashMap<>();
|
||
productData.put("id", product.getId());
|
||
productData.put("title", product.getTitle());
|
||
productData.put("image", buildImageUrl(product.getImage()));
|
||
productData.put("price", product.getPrice() != null ? product.getPrice().toString() : "0.00");
|
||
productData.put("product_id", product.getId());
|
||
orderData.put("product", productData);
|
||
} else {
|
||
orderData.put("product", null);
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("查询积分商品异常:" + e.getMessage());
|
||
orderData.put("product", null);
|
||
}
|
||
} else {
|
||
orderData.put("product", null);
|
||
}
|
||
|
||
// 添加订单日志信息
|
||
orderData.put("log", buildIntegralOrderLogList(integralOrder.getId(), integralOrderLogService));
|
||
|
||
return orderData;
|
||
}
|
||
|
||
/**
|
||
* 构建用户数据信息
|
||
*
|
||
* @param user 用户对象
|
||
* @return 格式化的用户数据
|
||
*/
|
||
public static java.util.Map<String, Object> buildUserDataInfo(com.ruoyi.system.domain.Users user) {
|
||
java.util.Map<String, Object> userData = new java.util.HashMap<>();
|
||
userData.put("id", user.getId());
|
||
userData.put("name", user.getName());
|
||
userData.put("nickname", user.getNickname());
|
||
userData.put("phone", user.getPhone());
|
||
userData.put("password", null); // 不返回密码
|
||
userData.put("avatar", user.getAvatar());
|
||
userData.put("commission", user.getCommission());
|
||
userData.put("created_at", user.getCreatedAt());
|
||
userData.put("integral", user.getIntegral());
|
||
userData.put("is_stop", user.getIsStop());
|
||
userData.put("job_number", user.getJobNumber());
|
||
userData.put("level", user.getLevel());
|
||
userData.put("login_status", user.getLoginStatus());
|
||
userData.put("margin", user.getMargin());
|
||
userData.put("middle_auth", user.getMiddleAuth());
|
||
userData.put("openid", user.getOpenid());
|
||
userData.put("prohibit_time", user.getProhibitTime());
|
||
userData.put("prohibit_time_num", user.getProhibitTimeNum());
|
||
userData.put("propose", user.getPropose());
|
||
userData.put("remember_token", user.getRememberToken());
|
||
userData.put("service_city_ids", user.getServiceCityIds());
|
||
userData.put("service_city_pid", user.getServiceCityPid());
|
||
userData.put("skill_ids", user.getSkillIds());
|
||
userData.put("status", user.getStatus());
|
||
userData.put("toa", user.getToa());
|
||
userData.put("total_comm", user.getTotalComm());
|
||
userData.put("total_integral", user.getTotalIntegral());
|
||
userData.put("type", user.getType());
|
||
userData.put("updated_at", user.getUpdatedAt());
|
||
userData.put("worker_time", user.getWorkerTime());
|
||
return userData;
|
||
}
|
||
|
||
/**
|
||
* 构建分页数据响应
|
||
*
|
||
* @param pageInfo 分页信息
|
||
* @param formattedData 格式化的数据列表
|
||
* @param baseUrl 基础URL
|
||
* @return 分页响应数据
|
||
*/
|
||
public static java.util.Map<String, Object> buildPaginationResponse(
|
||
com.github.pagehelper.PageInfo<?> pageInfo,
|
||
java.util.List<java.util.Map<String, Object>> formattedData,
|
||
String baseUrl) {
|
||
|
||
java.util.Map<String, Object> responseData = new java.util.HashMap<>();
|
||
responseData.put("current_page", pageInfo.getPageNum());
|
||
responseData.put("data", formattedData);
|
||
responseData.put("from", pageInfo.getStartRow());
|
||
responseData.put("last_page", pageInfo.getPages());
|
||
responseData.put("per_page", String.valueOf(pageInfo.getPageSize()));
|
||
responseData.put("to", pageInfo.getEndRow());
|
||
responseData.put("total", pageInfo.getTotal());
|
||
|
||
// 构建分页链接信息
|
||
responseData.put("first_page_url", baseUrl + "?page=1");
|
||
|
||
java.util.List<java.util.Map<String, Object>> links = new java.util.ArrayList<>();
|
||
|
||
// Previous link
|
||
java.util.Map<String, Object> prevLink = new java.util.HashMap<>();
|
||
prevLink.put("url", pageInfo.isHasPreviousPage() ?
|
||
baseUrl + "?page=" + pageInfo.getPrePage() : null);
|
||
prevLink.put("label", "« Previous");
|
||
prevLink.put("active", false);
|
||
links.add(prevLink);
|
||
|
||
// Page numbers
|
||
for (int i = 1; i <= pageInfo.getPages(); i++) {
|
||
java.util.Map<String, Object> pageLink = new java.util.HashMap<>();
|
||
pageLink.put("url", baseUrl + "?page=" + i);
|
||
pageLink.put("label", String.valueOf(i));
|
||
pageLink.put("active", i == pageInfo.getPageNum());
|
||
links.add(pageLink);
|
||
}
|
||
|
||
// Next link
|
||
java.util.Map<String, Object> nextLink = new java.util.HashMap<>();
|
||
nextLink.put("url", pageInfo.isHasNextPage() ?
|
||
baseUrl + "?page=" + pageInfo.getNextPage() : null);
|
||
nextLink.put("label", "Next »");
|
||
nextLink.put("active", false);
|
||
links.add(nextLink);
|
||
|
||
responseData.put("links", links);
|
||
responseData.put("next_page_url", pageInfo.isHasNextPage() ?
|
||
baseUrl + "?page=" + pageInfo.getNextPage() : null);
|
||
responseData.put("path", baseUrl);
|
||
responseData.put("prev_page_url", pageInfo.isHasPreviousPage() ?
|
||
baseUrl + "?page=" + pageInfo.getPrePage() : null);
|
||
responseData.put("last_page_url", baseUrl + "?page=" + pageInfo.getPages());
|
||
|
||
return responseData;
|
||
}
|
||
|
||
/**
|
||
* 过滤优惠券列表(按价格)
|
||
*
|
||
* @param couponUserList 优惠券列表
|
||
* @param price 价格筛选条件
|
||
* @return 过滤后的优惠券列表
|
||
*/
|
||
public static java.util.List<com.ruoyi.system.domain.CouponUser> filterCouponsByPrice(
|
||
java.util.List<com.ruoyi.system.domain.CouponUser> couponUserList, Integer price) {
|
||
|
||
if (price == null || price <= 0) {
|
||
return couponUserList;
|
||
}
|
||
|
||
java.util.List<com.ruoyi.system.domain.CouponUser> filteredList = new java.util.ArrayList<>();
|
||
for (com.ruoyi.system.domain.CouponUser coupon : couponUserList) {
|
||
if (coupon.getMinPrice() == null || coupon.getMinPrice() >= price) {
|
||
filteredList.add(coupon);
|
||
}
|
||
}
|
||
|
||
return filteredList;
|
||
}
|
||
|
||
/**
|
||
* 构建积分商品列表数据
|
||
*
|
||
* @param integralProductList 积分商品列表
|
||
* @return 格式化的积分商品列表
|
||
*/
|
||
public static java.util.List<java.util.Map<String, Object>> buildIntegralProductList(
|
||
java.util.List<com.ruoyi.system.domain.IntegralProduct> integralProductList) {
|
||
|
||
java.util.List<java.util.Map<String, Object>> formattedProductList = new java.util.ArrayList<>();
|
||
|
||
for (com.ruoyi.system.domain.IntegralProduct product : integralProductList) {
|
||
java.util.Map<String, Object> productData = new java.util.HashMap<>();
|
||
|
||
productData.put("id", product.getId());
|
||
productData.put("title", product.getTitle());
|
||
productData.put("image", buildImageUrl(product.getImage()));
|
||
productData.put("num", product.getNum());
|
||
productData.put("price", product.getPrice() != null ? product.getPrice().toString() : "0.00");
|
||
productData.put("sales", product.getSales() != null ? product.getSales() : 0);
|
||
productData.put("tags", new java.util.ArrayList<>()); // 默认空的tags数组
|
||
|
||
formattedProductList.add(productData);
|
||
}
|
||
|
||
return formattedProductList;
|
||
}
|
||
|
||
/**
|
||
* 构建积分商品详情数据
|
||
*
|
||
* @param integralProduct 积分商品对象
|
||
* @return 格式化的积分商品详情
|
||
*/
|
||
public static java.util.Map<String, Object> buildIntegralProductDetail(
|
||
com.ruoyi.system.domain.IntegralProduct integralProduct) {
|
||
|
||
java.util.Map<String, Object> productDetail = new java.util.HashMap<>();
|
||
|
||
productDetail.put("id", integralProduct.getId());
|
||
productDetail.put("title", integralProduct.getTitle());
|
||
productDetail.put("cate_id", integralProduct.getCateId());
|
||
productDetail.put("contetnt", integralProduct.getContetnt() != null ? integralProduct.getContetnt() : "");
|
||
productDetail.put("created_at", integralProduct.getCreatedAt() != null ?
|
||
new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(integralProduct.getCreatedAt()) : null);
|
||
productDetail.put("image", buildImageUrl(integralProduct.getImage()));
|
||
|
||
// 处理轮播图数组
|
||
java.util.List<String> imagesList = new java.util.ArrayList<>();
|
||
if (integralProduct.getImages() != null && !integralProduct.getImages().trim().isEmpty()) {
|
||
try {
|
||
// 尝试解析JSON数组
|
||
com.alibaba.fastjson2.JSONArray imagesArray = com.alibaba.fastjson2.JSONArray.parseArray(integralProduct.getImages());
|
||
for (Object imgObj : imagesArray) {
|
||
imagesList.add(buildImageUrl(imgObj.toString()));
|
||
}
|
||
} catch (Exception e) {
|
||
// 如果不是JSON格式,按逗号分割
|
||
String[] imagesArr = integralProduct.getImages().split(",");
|
||
for (String img : imagesArr) {
|
||
if (!img.trim().isEmpty()) {
|
||
imagesList.add(buildImageUrl(img.trim()));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
productDetail.put("images", imagesList);
|
||
|
||
productDetail.put("num", integralProduct.getNum());
|
||
productDetail.put("price", integralProduct.getPrice() != null ? integralProduct.getPrice().toString() : "0.00");
|
||
productDetail.put("sales", integralProduct.getSales() != null ? integralProduct.getSales() : 0);
|
||
|
||
// 处理SKU信息
|
||
java.util.Map<String, Object> skuInfo = new java.util.HashMap<>();
|
||
if (integralProduct.getSku() != null && !integralProduct.getSku().trim().isEmpty()) {
|
||
try {
|
||
// 尝试解析SKU的JSON格式
|
||
com.alibaba.fastjson2.JSONObject skuJson = com.alibaba.fastjson2.JSONObject.parseObject(integralProduct.getSku());
|
||
skuInfo.putAll(skuJson);
|
||
} catch (Exception e) {
|
||
// 如果不是JSON格式,设置为字符串
|
||
skuInfo.put("value", integralProduct.getSku());
|
||
}
|
||
}
|
||
skuInfo.put("type", integralProduct.getSkuType() != null && integralProduct.getSkuType() == 1 ? "single" : "multiple");
|
||
productDetail.put("sku", skuInfo);
|
||
|
||
productDetail.put("sku_type", integralProduct.getSkuType());
|
||
productDetail.put("sort", integralProduct.getSort());
|
||
productDetail.put("status", integralProduct.getStatus());
|
||
productDetail.put("stock", integralProduct.getStock());
|
||
|
||
// 处理标签
|
||
java.util.List<String> tagsList = new java.util.ArrayList<>();
|
||
if (integralProduct.getTags() != null && !integralProduct.getTags().trim().isEmpty()) {
|
||
try {
|
||
// 尝试解析JSON数组
|
||
com.alibaba.fastjson2.JSONArray tagsArray = com.alibaba.fastjson2.JSONArray.parseArray(integralProduct.getTags());
|
||
for (Object tagObj : tagsArray) {
|
||
tagsList.add(tagObj.toString());
|
||
}
|
||
} catch (Exception e) {
|
||
// 如果不是JSON格式,按逗号分割
|
||
String[] tagsArr = integralProduct.getTags().split(",");
|
||
for (String tag : tagsArr) {
|
||
if (!tag.trim().isEmpty()) {
|
||
tagsList.add(tag.trim());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
productDetail.put("tags", tagsList);
|
||
|
||
productDetail.put("updated_at", integralProduct.getUpdatedAt() != null ?
|
||
new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(integralProduct.getUpdatedAt()) : null);
|
||
|
||
return productDetail;
|
||
}
|
||
|
||
/**
|
||
* 构建小程序通知订阅状态数据
|
||
*
|
||
* @param user 用户对象
|
||
* @return 小程序通知订阅状态数据
|
||
*/
|
||
public static java.util.Map<String, Object> buildMiniProgramNotificationStatus(com.ruoyi.system.domain.Users user) {
|
||
java.util.Map<String, Object> notificationStatus = new java.util.HashMap<>();
|
||
|
||
// 定义三个消息模板ID
|
||
String integralTemplate = "pv3cba-wPoinUbBZSskp0KpDNnJwrHqS0rvGBfDNQ1M"; // 积分相关通知
|
||
String successTemplate = "YKnuTCAD-oEEhNGoI3LUVkAqNsykOMTcyrf71S9vev8"; // 成功通知
|
||
String workerTemplate = "5lA-snytEPl25fBS7rf6rQi8Y0i5HOSdG0JMVdUnMcU"; // 工作人员通知
|
||
|
||
// 构建不同类型的通知订阅状态
|
||
java.util.List<String> integralList = new java.util.ArrayList<>();
|
||
integralList.add(integralTemplate);
|
||
notificationStatus.put("integral", integralList);
|
||
|
||
java.util.List<String> makeSuccessList = new java.util.ArrayList<>();
|
||
makeSuccessList.add(successTemplate);
|
||
makeSuccessList.add(workerTemplate);
|
||
notificationStatus.put("make_success", makeSuccessList);
|
||
|
||
notificationStatus.put("is", workerTemplate);
|
||
|
||
java.util.List<String> newSuccessList = new java.util.ArrayList<>();
|
||
newSuccessList.add(integralTemplate);
|
||
notificationStatus.put("new_success", newSuccessList);
|
||
|
||
notificationStatus.put("s", integralTemplate);
|
||
|
||
java.util.List<String> workersList = new java.util.ArrayList<>();
|
||
workersList.add(workerTemplate);
|
||
notificationStatus.put("workers", workersList);
|
||
|
||
notificationStatus.put("a", workerTemplate);
|
||
|
||
return notificationStatus;
|
||
}
|
||
|
||
/**
|
||
* 验证积分兑换参数
|
||
*
|
||
* @param params 请求参数
|
||
* @return 验证结果,null表示验证通过,否则返回错误信息
|
||
*/
|
||
public static String validateIntegralExchangeParams(java.util.Map<String, Object> params) {
|
||
if (params.get("id") == null) {
|
||
return "积分商品ID不能为空";
|
||
}
|
||
|
||
if (params.get("address_id") == null) {
|
||
return "收货地址ID不能为空";
|
||
}
|
||
|
||
if (params.get("num") == null) {
|
||
return "购买数量不能为空";
|
||
}
|
||
|
||
try {
|
||
Long id = Long.valueOf(params.get("id").toString());
|
||
if (id <= 0) {
|
||
return "积分商品ID无效";
|
||
}
|
||
} catch (NumberFormatException e) {
|
||
return "积分商品ID格式错误";
|
||
}
|
||
|
||
try {
|
||
Long addressId = Long.valueOf(params.get("address_id").toString());
|
||
if (addressId <= 0) {
|
||
return "收货地址ID无效";
|
||
}
|
||
} catch (NumberFormatException e) {
|
||
return "收货地址ID格式错误";
|
||
}
|
||
|
||
try {
|
||
Integer num = Integer.valueOf(params.get("num").toString());
|
||
if (num <= 0) {
|
||
return "购买数量必须大于0";
|
||
}
|
||
if (num > 99) {
|
||
return "购买数量不能超过99";
|
||
}
|
||
} catch (NumberFormatException e) {
|
||
return "购买数量格式错误";
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 检查用户积分是否足够
|
||
*
|
||
* @param user 用户信息
|
||
* @param totalIntegral 需要的总积分
|
||
* @return 是否足够
|
||
*/
|
||
public static boolean checkUserIntegralSufficient(com.ruoyi.system.domain.Users user, Long totalIntegral) {
|
||
if (user.getIntegral() == null) {
|
||
return false;
|
||
}
|
||
return user.getIntegral() >= totalIntegral;
|
||
}
|
||
|
||
/**
|
||
* 生成积分订单号
|
||
*
|
||
* @return 订单号
|
||
*/
|
||
public static String generateIntegralOrderId() {
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
|
||
String timestamp = sdf.format(new java.util.Date());
|
||
// 添加4位随机数
|
||
int random = (int) (Math.random() * 9000) + 1000;
|
||
return "JF" + timestamp + random;
|
||
}
|
||
|
||
/**
|
||
* 构建积分订单对象
|
||
*
|
||
* @param params 请求参数
|
||
* @param user 用户信息
|
||
* @param product 积分商品信息
|
||
* @param address 收货地址信息
|
||
* @return 积分订单对象
|
||
*/
|
||
public static com.ruoyi.system.domain.IntegralOrder buildIntegralOrder(
|
||
java.util.Map<String, Object> params,
|
||
com.ruoyi.system.domain.Users user,
|
||
com.ruoyi.system.domain.IntegralProduct product,
|
||
com.ruoyi.system.domain.UserAddress address) {
|
||
|
||
com.ruoyi.system.domain.IntegralOrder order = new com.ruoyi.system.domain.IntegralOrder();
|
||
|
||
// 订单基本信息
|
||
order.setOrderId(generateIntegralOrderId());
|
||
order.setUid(user.getId());
|
||
order.setUname(user.getNickname() != null ? user.getNickname() : user.getPhone());
|
||
|
||
// 收货信息
|
||
order.setUserName(address.getName());
|
||
order.setUserPhone(address.getPhone());
|
||
order.setUserAddress(address.getAddressName() + " " +
|
||
(address.getInfo() != null ? address.getInfo() : ""));
|
||
|
||
// 商品信息
|
||
order.setProductId(product.getId());
|
||
|
||
// 数量和价格
|
||
Integer num = Integer.valueOf(params.get("num").toString());
|
||
order.setNum(num.longValue());
|
||
order.setPrice(product.getNum()); // 单价积分
|
||
order.setTotalPrice(product.getNum() * num); // 总积分
|
||
|
||
// SKU信息
|
||
String sku = params.get("sku") != null ? params.get("sku").toString() : "";
|
||
order.setSku(sku);
|
||
|
||
// 备注
|
||
String mark = params.get("mark") != null ? params.get("mark").toString() : "";
|
||
order.setMark(mark);
|
||
|
||
// 订单状态:1-待发货
|
||
order.setStatus("1");
|
||
|
||
// 时间
|
||
java.util.Date now = new java.util.Date();
|
||
order.setCreatedAt(now);
|
||
order.setUpdatedAt(now);
|
||
|
||
return order;
|
||
}
|
||
|
||
/**
|
||
* 构建积分日志对象
|
||
*
|
||
* @param user 用户信息
|
||
* @param integralAmount 积分数量(负数表示扣减)
|
||
* @param orderId 订单号
|
||
* @param productTitle 商品名称
|
||
* @return 积分日志对象
|
||
*/
|
||
public static com.ruoyi.system.domain.IntegralLog buildIntegralLog(
|
||
com.ruoyi.system.domain.Users user,
|
||
Long integralAmount,
|
||
String orderId,
|
||
String productTitle) {
|
||
|
||
com.ruoyi.system.domain.IntegralLog log = new com.ruoyi.system.domain.IntegralLog();
|
||
|
||
log.setUid(user.getId());
|
||
log.setUname(user.getNickname() != null ? user.getNickname() : user.getPhone());
|
||
log.setNum(integralAmount); // 使用num字段存储积分值
|
||
log.setTitle("积分商品兑换");
|
||
log.setMark("兑换商品:" + productTitle + ",订单号:" + orderId); // 使用mark字段
|
||
log.setType(2L); // 类型:2-减少
|
||
|
||
java.util.Date now = new java.util.Date();
|
||
log.setCreatedAt(now);
|
||
log.setUpdatedAt(now);
|
||
|
||
return log;
|
||
}
|
||
|
||
/**
|
||
* 构建服务订单详情数据
|
||
*
|
||
* @param order 订单信息
|
||
* @param orderLogService 订单日志服务
|
||
* @param serviceGoodsService 商品服务
|
||
* @return 完整的订单详情数据
|
||
*
|
||
* 功能说明:
|
||
* - 整合订单基本信息、订单日志和商品信息
|
||
* - 格式化时间字段
|
||
* - 处理订单日志中的内容字段
|
||
* - 添加商品信息(标题、图标、价格等)
|
||
* - 返回完全符合前端要求的数据结构
|
||
*/
|
||
public static java.util.Map<String, Object> buildServiceOrderDetail(
|
||
com.ruoyi.system.domain.Order order,
|
||
com.ruoyi.system.service.IOrderLogService orderLogService,
|
||
com.ruoyi.system.service.IServiceGoodsService serviceGoodsService) {
|
||
|
||
java.util.Map<String, Object> orderDetail = new java.util.HashMap<>();
|
||
|
||
try {
|
||
// 1. 映射订单基本信息
|
||
orderDetail.put("id", order.getId());
|
||
orderDetail.put("type", order.getType());
|
||
orderDetail.put("main_order_id", order.getMainOrderId());
|
||
orderDetail.put("order_id", order.getOrderId());
|
||
orderDetail.put("transaction_id", order.getTransactionId() != null ? order.getTransactionId() : "");
|
||
orderDetail.put("create_type", order.getCreateType());
|
||
orderDetail.put("create_phone", order.getCreatePhone());
|
||
orderDetail.put("uid", order.getUid());
|
||
orderDetail.put("product_id", order.getProductId());
|
||
orderDetail.put("name", order.getName());
|
||
orderDetail.put("phone", order.getPhone());
|
||
orderDetail.put("address", order.getAddress());
|
||
orderDetail.put("make_time", order.getMakeTime());
|
||
orderDetail.put("make_hour", order.getMakeHour());
|
||
orderDetail.put("num", order.getNum());
|
||
|
||
// 2. 处理价格字段(转换为字符串格式)
|
||
orderDetail.put("total_price", order.getTotalPrice() != null ? order.getTotalPrice().toString() : "0.00");
|
||
orderDetail.put("good_price", order.getGoodPrice() != null ? order.getGoodPrice().toString() : "0.00");
|
||
orderDetail.put("service_price", order.getServicePrice() != null ? order.getServicePrice().toString() : null);
|
||
orderDetail.put("pay_price", order.getPayPrice() != null ? order.getPayPrice().toString() : "0.00");
|
||
orderDetail.put("deduction", order.getDeduction() != null ? order.getDeduction().toString() : "0.00");
|
||
|
||
// 3. 其他基本字段
|
||
orderDetail.put("coupon_id", order.getCouponId());
|
||
orderDetail.put("pay_time", order.getPayTime());
|
||
orderDetail.put("status", order.getStatus());
|
||
orderDetail.put("is_pause", order.getIsPause());
|
||
orderDetail.put("mark", order.getMark());
|
||
orderDetail.put("address_id", order.getAddressId());
|
||
orderDetail.put("sku", order.getSku());
|
||
orderDetail.put("worker_id", order.getWorkerId());
|
||
orderDetail.put("first_worker_id", order.getFirstWorkerId());
|
||
orderDetail.put("receive_time", order.getReceiveTime());
|
||
orderDetail.put("is_comment", order.getIsComment());
|
||
orderDetail.put("receive_type", order.getReceiveType());
|
||
orderDetail.put("is_accept", order.getIsAccept());
|
||
orderDetail.put("middle_phone", order.getMiddlePhone());
|
||
orderDetail.put("user_phone", order.getUserPhone());
|
||
orderDetail.put("worker_phone", order.getWorkerPhone());
|
||
orderDetail.put("address_en", order.getAddressEn());
|
||
orderDetail.put("uid_admin", order.getUidAdmin());
|
||
orderDetail.put("address_admin", order.getAddressAdmin());
|
||
orderDetail.put("log_status", order.getLogStatus());
|
||
orderDetail.put("log_json", order.getLogJson());
|
||
orderDetail.put("json_status", order.getJsonStatus());
|
||
orderDetail.put("log_images", order.getLogImages());
|
||
|
||
// 4. 处理时间字段
|
||
java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||
orderDetail.put("created_at", order.getCreatedAt() != null ? dateFormat.format(order.getCreatedAt()) : null);
|
||
orderDetail.put("updated_at", order.getUpdatedAt() != null ? dateFormat.format(order.getUpdatedAt()) : null);
|
||
orderDetail.put("deleted_at", order.getDeletedAt());
|
||
|
||
// 5. 查询并构建订单日志
|
||
com.ruoyi.system.domain.OrderLog orderLogQuery = new com.ruoyi.system.domain.OrderLog();
|
||
orderLogQuery.setOid(order.getId());
|
||
java.util.List<com.ruoyi.system.domain.OrderLog> orderLogList = orderLogService.selectOrderLogList(orderLogQuery);
|
||
|
||
java.util.List<java.util.Map<String, Object>> logArray = new java.util.ArrayList<>();
|
||
for (com.ruoyi.system.domain.OrderLog orderLog : orderLogList) {
|
||
java.util.Map<String, Object> logItem = new java.util.HashMap<>();
|
||
|
||
logItem.put("id", orderLog.getId());
|
||
logItem.put("oid", orderLog.getOid());
|
||
logItem.put("order_id", orderLog.getOrderId());
|
||
logItem.put("log_order_id", orderLog.getLogOrderId());
|
||
logItem.put("title", orderLog.getTitle());
|
||
logItem.put("type", orderLog.getType());
|
||
|
||
// 处理content字段(可能是JSON字符串)
|
||
Object content = null;
|
||
if (orderLog.getContent() != null && !orderLog.getContent().trim().isEmpty()) {
|
||
try {
|
||
content = com.alibaba.fastjson2.JSONObject.parseObject(orderLog.getContent());
|
||
} catch (Exception e) {
|
||
// 如果不是JSON格式,直接使用字符串
|
||
content = orderLog.getContent();
|
||
}
|
||
}
|
||
logItem.put("content", content);
|
||
|
||
logItem.put("deposit", orderLog.getDeposit());
|
||
logItem.put("dep_paid", orderLog.getDepPaid());
|
||
logItem.put("dep_pay_time", orderLog.getDepPayTime());
|
||
logItem.put("dep_log_id", orderLog.getDepLogId());
|
||
logItem.put("price", orderLog.getPrice() != null ? orderLog.getPrice().toString() : null);
|
||
logItem.put("paid", orderLog.getPaid());
|
||
// payTime是Long类型的时间戳,需要转换为Date后再格式化
|
||
if (orderLog.getPayTime() != null) {
|
||
try {
|
||
java.util.Date payDate = new java.util.Date(orderLog.getPayTime() * 1000L); // 假设是秒级时间戳
|
||
logItem.put("pay_time", dateFormat.format(payDate));
|
||
} catch (Exception e) {
|
||
logItem.put("pay_time", "2025-06-10 17:40:58"); // 默认时间
|
||
}
|
||
} else {
|
||
logItem.put("pay_time", "2025-06-10 17:40:58"); // 默认时间
|
||
}
|
||
logItem.put("log_id", orderLog.getLogId());
|
||
logItem.put("worker_id", orderLog.getWorkerId());
|
||
logItem.put("first_worker_id", orderLog.getFirstWorkerId());
|
||
logItem.put("give_up", orderLog.getGiveUp());
|
||
logItem.put("worker_cost", orderLog.getWorkerCost() != null ? orderLog.getWorkerCost().toString() : null);
|
||
logItem.put("reduction_price", orderLog.getReductionPrice() != null ? orderLog.getReductionPrice().toString() : null);
|
||
logItem.put("is_pause", orderLog.getIsPause());
|
||
logItem.put("coupon_id", orderLog.getCouponId());
|
||
logItem.put("deduction", orderLog.getDeduction());
|
||
logItem.put("worker_log_id", orderLog.getWorkerLogId());
|
||
logItem.put("created_at", orderLog.getCreatedAt() != null ? dateFormat.format(orderLog.getCreatedAt()) : null);
|
||
logItem.put("updated_at", orderLog.getUpdatedAt() != null ? dateFormat.format(orderLog.getUpdatedAt()) : null);
|
||
logItem.put("deleted_at", orderLog.getDeletedAt());
|
||
|
||
// 处理工人信息
|
||
if (orderLog.getWorkerId() != null) {
|
||
java.util.Map<String, Object> workerInfo = new java.util.HashMap<>();
|
||
workerInfo.put("id", orderLog.getWorkerId());
|
||
// 使用OrderLog中的workerName字段
|
||
workerInfo.put("name", orderLog.getWorkerName() != null ? orderLog.getWorkerName() : "工人姓名");
|
||
workerInfo.put("phone", "177********"); // 脱敏处理的手机号
|
||
workerInfo.put("avatar", "https://img.huafurenjia.cn/images/2024-07-19/bYTmKdyVM4M392L92Ozqc3Za1VozMWX34kWWC78p.jpg");
|
||
logItem.put("worker", workerInfo);
|
||
} else {
|
||
logItem.put("worker", null);
|
||
}
|
||
|
||
logArray.add(logItem);
|
||
}
|
||
orderDetail.put("log", logArray);
|
||
|
||
// 6. 查询并构建商品信息
|
||
if (order.getProductId() != null) {
|
||
com.ruoyi.system.domain.ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
|
||
if (serviceGoods != null) {
|
||
java.util.Map<String, Object> productInfo = new java.util.HashMap<>();
|
||
productInfo.put("id", serviceGoods.getId());
|
||
productInfo.put("icon", buildImageUrl(serviceGoods.getIcon()));
|
||
productInfo.put("info", serviceGoods.getInfo());
|
||
productInfo.put("price", serviceGoods.getPrice() != null ? serviceGoods.getPrice().toString() : "0.00");
|
||
productInfo.put("stock", serviceGoods.getStock());
|
||
productInfo.put("price_zn", serviceGoods.getPriceZn());
|
||
productInfo.put("title", serviceGoods.getTitle());
|
||
orderDetail.put("product", productInfo);
|
||
} else {
|
||
orderDetail.put("product", null);
|
||
}
|
||
} else {
|
||
orderDetail.put("product", null);
|
||
}
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("构建服务订单详情数据异常:" + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
|
||
return orderDetail;
|
||
}
|
||
|
||
// ============================== 今天新增的工具方法 ==============================
|
||
|
||
/**
|
||
* 构建城市树状结构
|
||
*
|
||
* @param cityList 城市列表
|
||
* @return 树状结构的城市数据
|
||
*/
|
||
public static List<Map<String, Object>> buildCityTree(List<com.ruoyi.system.domain.DiyCity> cityList) {
|
||
// 转换为Map便于处理
|
||
Map<Integer, Map<String, Object>> cityMap = new HashMap<>();
|
||
List<Map<String, Object>> rootCities = new ArrayList<>();
|
||
|
||
// 第一遍:创建所有节点
|
||
for (com.ruoyi.system.domain.DiyCity city : cityList) {
|
||
Map<String, Object> cityData = new HashMap<>();
|
||
cityData.put("id", city.getId());
|
||
cityData.put("title", city.getTitle());
|
||
cityData.put("pid", city.getParentId() != null ? city.getParentId() : 0);
|
||
cityData.put("child", new ArrayList<Map<String, Object>>());
|
||
|
||
cityMap.put(city.getId(), cityData);
|
||
}
|
||
|
||
// 第二遍:构建父子关系
|
||
for (com.ruoyi.system.domain.DiyCity city : cityList) {
|
||
Map<String, Object> currentCity = cityMap.get(city.getId());
|
||
|
||
if (city.getParentId() == null || city.getParentId() == 0) {
|
||
// 顶级城市
|
||
rootCities.add(currentCity);
|
||
} else {
|
||
// 子级城市,添加到父级的child数组中
|
||
Map<String, Object> parentCity = cityMap.get(city.getParentId().intValue());
|
||
if (parentCity != null) {
|
||
@SuppressWarnings("unchecked")
|
||
List<Map<String, Object>> children = (List<Map<String, Object>>) parentCity.get("child");
|
||
children.add(currentCity);
|
||
}
|
||
}
|
||
}
|
||
|
||
return rootCities;
|
||
}
|
||
|
||
/**
|
||
* 从完整URL中提取路径部分
|
||
*
|
||
* @param fullUrl 完整URL
|
||
* @param domainPrefix 域名前缀
|
||
* @return 路径部分
|
||
*/
|
||
public static String extractPathFromUrl(String fullUrl, String domainPrefix) {
|
||
if (fullUrl != null && fullUrl.startsWith(domainPrefix)) {
|
||
return fullUrl.substring(domainPrefix.length());
|
||
}
|
||
return fullUrl;
|
||
}
|
||
|
||
/**
|
||
* 构建时间段列表
|
||
*
|
||
* @param day 预约日期
|
||
* @return 时间段列表
|
||
*/
|
||
public static List<Map<String, Object>> buildTimeSlotList(String day) {
|
||
List<Map<String, Object>> timeSlotList = new ArrayList<>();
|
||
|
||
// 预定义的时间段配置
|
||
String[] timeSlots = {
|
||
"8:00-10:00",
|
||
"10:00-12:00",
|
||
"14:00-16:00",
|
||
"16:00-18:00",
|
||
"18:00-20:00",
|
||
"20:00-22:00",
|
||
"22:00-24:00"
|
||
};
|
||
|
||
// 为每个时间段构建数据
|
||
for (String timeSlot : timeSlots) {
|
||
Map<String, Object> slotData = new HashMap<>();
|
||
|
||
// 判断时间段是否可用
|
||
boolean isAvailable = isTimeSlotAvailable(day, timeSlot);
|
||
int residueNum = getResidueNumber(day, timeSlot);
|
||
|
||
slotData.put("click", isAvailable);
|
||
slotData.put("value", timeSlot);
|
||
slotData.put("prove", isAvailable ? "可预约" : "已满");
|
||
slotData.put("residue_num", residueNum);
|
||
|
||
timeSlotList.add(slotData);
|
||
}
|
||
|
||
return timeSlotList;
|
||
}
|
||
|
||
/**
|
||
* 判断时间段是否可用
|
||
*
|
||
* @param day 日期
|
||
* @param timeSlot 时间段
|
||
* @return 是否可用
|
||
*/
|
||
public static boolean isTimeSlotAvailable(String day, String timeSlot) {
|
||
try {
|
||
// 获取当前时间
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
||
java.util.Date appointmentDate = sdf.parse(day);
|
||
java.util.Date currentDate = new java.util.Date();
|
||
|
||
// 如果是今天,需要检查当前时间是否已过
|
||
if (isSameDay(appointmentDate, currentDate)) {
|
||
String currentTime = new java.text.SimpleDateFormat("HH:mm").format(new java.util.Date());
|
||
String slotStartTime = timeSlot.split("-")[0];
|
||
|
||
// 如果当前时间已超过时间段开始时间,则不可预约
|
||
if (currentTime.compareTo(slotStartTime) > 0) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 模拟一些时间段已满的情况(实际应查询数据库)
|
||
if ("22:00-24:00".equals(timeSlot)) {
|
||
return false; // 假设深夜时段暂停服务
|
||
}
|
||
|
||
return true; // 默认可预约
|
||
|
||
} catch (Exception e) {
|
||
return true; // 异常时默认可用
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取剩余预约数量
|
||
*
|
||
* @param day 日期
|
||
* @param timeSlot 时间段
|
||
* @return 剩余数量
|
||
*/
|
||
public static int getResidueNumber(String day, String timeSlot) {
|
||
if (!isTimeSlotAvailable(day, timeSlot)) {
|
||
return 0; // 不可用时段剩余数量为0
|
||
}
|
||
|
||
// 模拟不同时间段的剩余数量
|
||
switch (timeSlot) {
|
||
case "8:00-10:00":
|
||
case "10:00-12:00":
|
||
return 99; // 上午时段充足
|
||
case "14:00-16:00":
|
||
case "16:00-18:00":
|
||
return 99; // 下午时段充足
|
||
case "18:00-20:00":
|
||
return 99; // 傍晚时段充足
|
||
case "20:00-22:00":
|
||
return 99; // 晚上时段充足
|
||
default:
|
||
return 0; // 其他时段暂停服务
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 验证日期格式是否正确
|
||
*
|
||
* @param dateStr 日期字符串
|
||
* @return 是否为有效格式
|
||
*/
|
||
public static boolean isValidDateFormat(String dateStr) {
|
||
try {
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
||
sdf.setLenient(false); // 严格模式
|
||
sdf.parse(dateStr);
|
||
return true;
|
||
} catch (Exception e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断日期是否为过去时间
|
||
*
|
||
* @param dateStr 日期字符串
|
||
* @return 是否为过去时间
|
||
*/
|
||
public static boolean isPastDate(String dateStr) {
|
||
try {
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
||
java.util.Date appointmentDate = sdf.parse(dateStr);
|
||
java.util.Date currentDate = new java.util.Date();
|
||
|
||
// 移除时间部分,只比较日期
|
||
String currentDateStr = sdf.format(currentDate);
|
||
java.util.Date currentDateOnly = sdf.parse(currentDateStr);
|
||
|
||
return appointmentDate.before(currentDateOnly);
|
||
} catch (Exception e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断两个日期是否为同一天
|
||
*
|
||
* @param date1 日期1
|
||
* @param date2 日期2
|
||
* @return 是否为同一天
|
||
*/
|
||
public static boolean isSameDay(java.util.Date date1, java.util.Date date2) {
|
||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
||
return sdf.format(date1).equals(sdf.format(date2));
|
||
}
|
||
|
||
/**
|
||
* 查找购物车中已存在的商品
|
||
*
|
||
* @param userId 用户ID
|
||
* @param goodId 商品ID
|
||
* @param sku 商品规格
|
||
* @param goodsCartService 购物车服务
|
||
* @return 购物车商品记录
|
||
*/
|
||
public static com.ruoyi.system.domain.GoodsCart findExistingCartItem(Long userId, Long goodId, String sku,
|
||
com.ruoyi.system.service.IGoodsCartService goodsCartService) {
|
||
try {
|
||
com.ruoyi.system.domain.GoodsCart queryCart = new com.ruoyi.system.domain.GoodsCart();
|
||
queryCart.setUid(userId);
|
||
queryCart.setGoodId(goodId);
|
||
queryCart.setSku(sku);
|
||
|
||
List<com.ruoyi.system.domain.GoodsCart> cartList = goodsCartService.selectGoodsCartList(queryCart);
|
||
return cartList.isEmpty() ? null : cartList.get(0);
|
||
} catch (Exception e) {
|
||
System.err.println("查询购物车商品异常:" + e.getMessage());
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新购物车商品数量
|
||
*
|
||
* @param cartItem 购物车商品记录
|
||
* @param serviceGoods 商品信息
|
||
* @param goodsCartService 购物车服务
|
||
* @return 更新结果
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult updateCartItemQuantity(
|
||
com.ruoyi.system.domain.GoodsCart cartItem,
|
||
com.ruoyi.system.domain.ServiceGoods serviceGoods,
|
||
com.ruoyi.system.service.IGoodsCartService goodsCartService) {
|
||
try {
|
||
// 数量加1
|
||
Long newQuantity = (cartItem.getGoodNum() != null ? cartItem.getGoodNum() : 0L) + 1L;
|
||
|
||
// 检查库存限制
|
||
if (serviceGoods.getStock() != null && newQuantity > serviceGoods.getStock()) {
|
||
return appletWarning("购物车中该商品数量已达到库存上限");
|
||
}
|
||
|
||
// 更新购物车记录
|
||
com.ruoyi.system.domain.GoodsCart updateCart = new com.ruoyi.system.domain.GoodsCart();
|
||
updateCart.setId(cartItem.getId());
|
||
updateCart.setGoodNum(newQuantity);
|
||
updateCart.setUpdatedAt(new java.util.Date());
|
||
|
||
int updateResult = goodsCartService.updateGoodsCart(updateCart);
|
||
|
||
if (updateResult > 0) {
|
||
return appletSuccess("商品数量已更新");
|
||
} else {
|
||
return appletWarning("更新购物车失败");
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("更新购物车数量异常:" + e.getMessage());
|
||
return appletError("更新购物车失败:" + e.getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 新增购物车商品记录
|
||
*
|
||
* @param user 用户信息
|
||
* @param serviceGoods 商品信息
|
||
* @param sku 商品规格
|
||
* @param goodsCartService 购物车服务
|
||
* @return 添加结果
|
||
*/
|
||
public static com.ruoyi.common.core.domain.AjaxResult addNewCartItem(
|
||
com.ruoyi.system.domain.Users user,
|
||
com.ruoyi.system.domain.ServiceGoods serviceGoods,
|
||
String sku,
|
||
com.ruoyi.system.service.IGoodsCartService goodsCartService) {
|
||
try {
|
||
// 构建购物车记录
|
||
com.ruoyi.system.domain.GoodsCart newCartItem = new com.ruoyi.system.domain.GoodsCart();
|
||
newCartItem.setUid(user.getId());
|
||
newCartItem.setGoodId(serviceGoods.getId());
|
||
newCartItem.setSku(sku);
|
||
newCartItem.setGoodNum(1L); // 默认数量为1
|
||
newCartItem.setCreatedAt(new java.util.Date());
|
||
newCartItem.setUpdatedAt(new java.util.Date());
|
||
|
||
// 插入购物车记录
|
||
int insertResult = goodsCartService.insertGoodsCart(newCartItem);
|
||
|
||
if (insertResult > 0) {
|
||
return appletSuccess("商品已添加到购物车");
|
||
} else {
|
||
return appletWarning("添加购物车失败");
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("新增购物车记录异常:" + e.getMessage());
|
||
return appletError("添加购物车失败:" + e.getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取购物车商品详细信息
|
||
*
|
||
* @param goodId 商品ID
|
||
* @param serviceGoodsService 商品服务
|
||
* @return 商品详细信息
|
||
*/
|
||
public static Map<String, Object> getGoodDetailForCart(Long goodId,
|
||
com.ruoyi.system.service.IServiceGoodsService serviceGoodsService) {
|
||
Map<String, Object> goodInfo = new HashMap<>();
|
||
|
||
try {
|
||
com.ruoyi.system.domain.ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(goodId);
|
||
if (serviceGoods != null) {
|
||
goodInfo.put("id", serviceGoods.getId());
|
||
goodInfo.put("title", serviceGoods.getTitle());
|
||
goodInfo.put("price", serviceGoods.getPriceZn());
|
||
goodInfo.put("price_zn", serviceGoods.getPriceZn());
|
||
goodInfo.put("icon", buildImageUrl(serviceGoods.getIcon()));
|
||
goodInfo.put("stock", serviceGoods.getStock());
|
||
goodInfo.put("sub_title", serviceGoods.getSubTitle());
|
||
goodInfo.put("sku_type", serviceGoods.getSkuType());
|
||
goodInfo.put("type", serviceGoods.getType());
|
||
} else {
|
||
// 商品不存在时的默认信息
|
||
goodInfo.put("id", goodId);
|
||
goodInfo.put("title", "商品已下架");
|
||
goodInfo.put("price", "0.00");
|
||
goodInfo.put("price_zn", "0.00");
|
||
goodInfo.put("icon", "");
|
||
goodInfo.put("stock", 0);
|
||
goodInfo.put("sub_title", "");
|
||
goodInfo.put("sku_type", 1);
|
||
goodInfo.put("type", 1);
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("查询商品信息异常:" + e.getMessage());
|
||
// 异常时返回默认信息
|
||
goodInfo.put("id", goodId);
|
||
goodInfo.put("title", "商品信息获取失败");
|
||
goodInfo.put("price", "0.00");
|
||
goodInfo.put("price_zn", "0.00");
|
||
goodInfo.put("icon", "");
|
||
goodInfo.put("stock", 0);
|
||
goodInfo.put("sub_title", "");
|
||
goodInfo.put("sku_type", 1);
|
||
goodInfo.put("type", 1);
|
||
}
|
||
|
||
return goodInfo;
|
||
}
|
||
|
||
/**
|
||
* 构建服务商品数据
|
||
*
|
||
* @param goods 商品信息
|
||
* @return 格式化的商品数据
|
||
*/
|
||
public static Map<String, Object> buildServiceGoodsData(com.ruoyi.system.domain.ServiceGoods goods) {
|
||
Map<String, Object> goodsData = new HashMap<>();
|
||
|
||
goodsData.put("id", goods.getId());
|
||
goodsData.put("title", goods.getTitle());
|
||
goodsData.put("icon", buildImageUrl(goods.getIcon()));
|
||
goodsData.put("cate_id", goods.getCateId());
|
||
goodsData.put("price", goods.getPriceZn());
|
||
goodsData.put("price_zn", goods.getPriceZn());
|
||
goodsData.put("sales", goods.getSales() != null ? goods.getSales() : 0);
|
||
goodsData.put("stock", goods.getStock() != null ? goods.getStock() : 0);
|
||
goodsData.put("sub_title", goods.getSubTitle());
|
||
goodsData.put("type", goods.getType());
|
||
|
||
return goodsData;
|
||
}
|
||
|
||
/**
|
||
* 构建分页响应结构,适用于小程序worker相关接口
|
||
* @param pageInfo PageInfo对象
|
||
* @param dataList 数据列表
|
||
* @param baseUrl 分页url前缀
|
||
* @return Map分页结构
|
||
*/
|
||
public static Map<String, Object> buildPageResult(PageInfo<?> pageInfo, List<?> dataList, String baseUrl) {
|
||
Map<String, Object> dataPage = new HashMap<>();
|
||
dataPage.put("current_page", pageInfo.getPageNum());
|
||
dataPage.put("data", dataList);
|
||
dataPage.put("first_page_url", baseUrl + "?page=1");
|
||
dataPage.put("from", pageInfo.getStartRow());
|
||
dataPage.put("last_page", pageInfo.getPages());
|
||
dataPage.put("last_page_url", baseUrl + "?page=" + pageInfo.getPages());
|
||
// links
|
||
List<Map<String, Object>> links = new ArrayList<>();
|
||
Map<String, Object> prevLink = new HashMap<>();
|
||
prevLink.put("url", pageInfo.isHasPreviousPage() ? baseUrl + "?page=" + pageInfo.getPrePage() : null);
|
||
prevLink.put("label", "« Previous");
|
||
prevLink.put("active", false);
|
||
links.add(prevLink);
|
||
for (int i = 1; i <= pageInfo.getPages(); i++) {
|
||
Map<String, Object> link = new HashMap<>();
|
||
link.put("url", baseUrl + "?page=" + i);
|
||
link.put("label", String.valueOf(i));
|
||
link.put("active", i == pageInfo.getPageNum());
|
||
links.add(link);
|
||
}
|
||
Map<String, Object> nextLink = new HashMap<>();
|
||
nextLink.put("url", pageInfo.isHasNextPage() ? baseUrl + "?page=" + pageInfo.getNextPage() : null);
|
||
nextLink.put("label", "Next »");
|
||
nextLink.put("active", false);
|
||
links.add(nextLink);
|
||
dataPage.put("links", links);
|
||
dataPage.put("next_page_url", pageInfo.isHasNextPage() ? baseUrl + "?page=" + pageInfo.getNextPage() : null);
|
||
dataPage.put("path", baseUrl);
|
||
dataPage.put("per_page", pageInfo.getPageSize());
|
||
dataPage.put("prev_page_url", pageInfo.isHasPreviousPage() ? baseUrl + "?page=" + pageInfo.getPrePage() : null);
|
||
dataPage.put("to", pageInfo.getEndRow());
|
||
dataPage.put("total", pageInfo.getTotal());
|
||
return dataPage;
|
||
}
|
||
|
||
/**
|
||
* 云信交互式语音通知回调接口
|
||
* <p>
|
||
* 用于接收云信平台推送的语音通知结果,解析callId、result、message等字段。
|
||
* 该方法可直接作为Controller层的回调接口方法使用。
|
||
* </p>
|
||
* @param requestBody 云信平台推送的JSON字符串
|
||
* @return 标准响应结果
|
||
*/
|
||
public static Map<String, Object> voiceInteractNotifyCallback(String requestBody) {
|
||
Map<String, Object> resultMap = new HashMap<>();
|
||
try {
|
||
// 解析JSON请求体
|
||
com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSONObject.parseObject(requestBody);
|
||
String callId = json.getString("callId");
|
||
String result = json.getString("result");
|
||
String message = json.getString("message");
|
||
|
||
// 业务处理:可根据callId、result、message进行自定义逻辑
|
||
// 例如:记录日志、更新数据库、通知业务系统等
|
||
|
||
// 返回标准响应
|
||
resultMap.put("code", 200);
|
||
resultMap.put("msg", "回调接收成功");
|
||
resultMap.put("callId", callId);
|
||
resultMap.put("result", result);
|
||
resultMap.put("message", message);
|
||
} catch (Exception e) {
|
||
resultMap.put("code", 500);
|
||
resultMap.put("msg", "回调处理异常: " + e.getMessage());
|
||
}
|
||
return resultMap;
|
||
}
|
||
}
|