Skip to content

service 服务层

service 服务层在系统或者插件下 service 文件夹下,service 的作用是实现相关业务的功能逻辑,同时为接口提供相关的数据结构

目录结构

分层架构设计

text
service/
├── admin/       # 管理后台API相关业务逻辑
├── api/         # 前端用户API相关业务逻辑  
├── basic/       # 基础业务逻辑
├── core/        # 与接口无关的核心业务逻辑
└── site/        # 站点相关业务逻辑

各层职责划分

admin 层

  • 职责:实现管理后台接口(adminapi)的业务逻辑

  • 特点:面向管理员用户,提供系统配置、数据管理、权限控制等功能

  • 示例功能:用户管理、角色权限配置、数据统计、内容审核等

api 层

  • 职责:实现前端用户接口(api)的业务逻辑

  • 特点:面向普通用户,提供业务操作、数据查询、交互功能等

  • 示例功能:用户注册登录、商品浏览、订单创建、支付操作等

basic 层

  • 职责:实现基础业务逻辑,为其他业务层提供通用基础服务

  • 特点:提供基础数据处理和通用业务功能,被多个业务层复用

  • 示例功能:数据格式转换、基础校验、通用查询等

core 层

  • 职责:实现与接口无关的核心业务逻辑,为 admin 和 api 层提供底层支持

  • 特点:业务逻辑的底层实现,与具体接口类型无关,提供通用的业务功能

  • 示例功能:订单状态流转、支付处理、消息发送、数据验证等

site 层

  • 职责:实现站点相关的业务逻辑

  • 特点:专注于站点管理和操作相关的业务功能

  • 示例功能:站点创建、站点配置、站点状态管理等

接口定义规范

Service 接口是业务逻辑的契约,定义了业务功能的对外接口。接口设计应遵循清晰、一致、可扩展的原则,确保业务功能的正确表达和系统的可维护性。

接口命名规范

接口名称

  • 采用 I{业务主题}Service 的命名格式

  • I 开头表示接口类型

  • Service 结尾表示服务层组件

  • 业务主题应与功能模块名称一致

示例:

java
ISiteShopService      // 站点店铺服务接口
ISiteService          // 站点服务接口
IUserService          // 用户服务接口
IOrderService         // 订单服务接口

方法命名规范

  • 分页查询page(PageParam pageParam, {SearchParam} searchParam)

  • 列表查询list({SearchParam} searchParam)

  • 详情查询info(Integer id)

  • 添加操作add({AddParam} addParam)

  • 编辑操作edit(Integer id, {EditParam} editParam)

  • 删除操作del(Integer id)

  • 业务操作:根据具体业务功能命名,如 shopQrcode(Integer id)

参数规范

  • 分页参数:使用统一的 PageParam 对象

  • 查询参数:命名格式为 {业务主题}SearchParam

  • 添加参数:命名格式为 {业务主题}AddParam

  • 编辑参数:命名格式为 {业务主题}EditParam

  • 选择参数:命名格式为 {业务主题}SelectParam

返回值规范

  • 分页结果:使用统一的 PageResult<T> 对象

  • 列表结果:使用 List<T> 对象

  • 详情结果:使用 {业务主题}InfoVo 对象

  • 简单结果:使用基本数据类型或包装类

实现类规范

Service 实现类是接口的具体实现,负责实现业务逻辑。实现类应遵循清晰、可维护、高性能的原则

命名规范

  • 实现类名称:{业务主题}ServiceImpl

  • 包路径:与接口路径一致,在 impl 子目录下

依赖注入

  • 使用 @Resource 注解进行依赖注入

  • 注入的依赖包括:

    • Mapper 接口:用于数据库操作

    • 其他 Service 接口:用于调用其他业务逻辑

    • 工具类:用于通用功能处理

方法实现

  • 实现接口中定义的所有方法

  • 方法实现应遵循单一职责原则

  • 使用合适的设计模式处理复杂业务逻辑

  • 对输入参数进行验证

  • 处理异常并向上抛出

事务管理

  • 使用 @Transactional 注解管理事务

  • 事务应尽量小,避免长时间占用数据库连接

  • 合理设置事务的传播行为和隔离级别

数据结构

Service 层使用多种数据结构来处理数据,包括实体类、参数类和视图类

实体类

  • 位于 entity 目录下

  • 映射数据库表结构

  • 使用 @Data 注解简化代码

参数类

  • 位于 param 子目录下

  • 用于接收和验证输入参数

  • 命名格式为 {业务主题}{ParamType}Param

  • 使用 @Data 注解简化代码

视图类(VO)

  • 位于 vo 子目录下

  • 用于封装输出数据

  • 命名格式为 {业务主题}{VoType}Vo

  • 使用 @Data 注解简化代码

示例:站点店铺服务

接口定义

java
package com.niu.core.service.api.shop;

import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.api.shop.param.SiteShopAccountParam;
import com.niu.core.service.api.shop.param.SiteShopParam;
import com.niu.core.service.api.shop.param.SiteShopSearchParam;
import com.niu.core.service.api.shop.param.SiteShopSelectParam;
import com.niu.core.service.api.shop.vo.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 店铺扩展服务接口
 */
public interface ISiteShopService {

    /**
     * 店铺扩展列表
     * @param pageParam 分页参数
     * @param searchParam 搜索参数
     * @return PageResult<SiteShopListVo>
     */
    PageResult<SiteShopListVo> page(PageParam pageParam, SiteShopSearchParam searchParam);

    List<SiteShopListVo> list(SiteShopSearchParam searchParam);

    /**
     * 店铺扩展详情
     * @param id 主键ID
     * @return SiteShopInfoVo
     */
    SiteShopInfoVo info(Integer id);

    /**
     * 店铺二维码
     * @param id 主键ID
     * @return String 二维码图片路径
     */
    String shopQrcode(Integer id);

    /**
     * 获取店铺下拉列表
     * @param pageParam 分页参数
     * @param siteShopSelectParam 选择参数
     * @return SiteShopSelectPage
     */
    SiteShopSelectPage getSelectPage(PageParam pageParam, SiteShopSelectParam siteShopSelectParam);

    /**
     * 更新关注店铺
     * @param siteId 站点ID
     * @param isFollow 是否关注(0:取消关注,1:关注)
     */
    void editFollowNumber(Integer siteId, Integer isFollow);

    /**
     * 选择店铺列表
     * @return WebShopListVo
     */
    WebShopListVo selectShopList();
}

实现类

java
package com.niu.core.service.api.shop.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJQueryWrapper;
import com.niu.core.service.api.shop.vo.*;
import com.niu.core.service.core.app.helper.EventAndSubscribeOfPublisher;
import com.niu.core.event.shop.MallShopGoodsListEventDefiner;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.exception.CommonException;
import com.niu.core.common.utils.QrcodeUtils;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.mapper.QueryMapperUtils;
import com.niu.core.entity.shop.SiteShop;
import com.niu.core.entity.shop.SiteShopMember;
import com.niu.core.entity.site.Site;
import com.niu.core.enums.site.SiteStatusEnum;
import com.niu.core.mapper.shop.SiteShopMapper;
import com.niu.core.mapper.shop.SiteShopMemberMapper;
import com.niu.core.mapper.site.SiteMapper;
import com.niu.core.service.admin.web.IWebConfigService;
import com.niu.core.service.admin.web.vo.WebConfigVo;
import com.niu.core.service.api.shop.ISiteShopService;
import com.niu.core.service.api.shop.param.SiteShopSearchParam;
import com.niu.core.service.api.shop.param.SiteShopSelectParam;
import com.niu.core.service.core.sys.ICoreConfigService;
import com.niu.core.service.core.sys.ICoreSysConfigService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 店铺扩展实现
 */
@Service
public class SiteShopServiceImpl implements ISiteShopService {
    
    @Resource
    SiteMapper siteMapper;

    @Resource
    SiteShopMapper siteShopMapper;

    @Resource
    SiteShopMemberMapper siteShopMemberMapper;

    @Resource
    ICoreConfigService coreConfigService;

    @Resource
    IWebConfigService webConfigService;

    @Resource
    ICoreSysConfigService coreSysConfigService;

    @Override
    public PageResult<SiteShopListVo> page(PageParam pageParam, SiteShopSearchParam searchParam) {
        Integer page  = pageParam.getPage();
        Integer limit = pageParam.getLimit();

        MPJQueryWrapper<Site> queryWrapper = new MPJQueryWrapper<>();
        queryWrapper.select("ns.site_id, ns.site_name, ns.group_id, ns.keywords, ns.app_type, ns.logo, ns.`desc`, ns.status, ns.latitude, ns.longitude, ns.province_id, ns.city_id, ns.district_id, ns.address, ns.full_address, ns.phone, ns.business_hours, ns.create_time, ns.expire_time, ns.front_end_name, ns.front_end_logo, ns.front_end_icon, ns.icon, ns.member_no, ns.app, ns.addons, ns.initalled_addon, ns.site_domain, ns.isinit, nsg.group_name, nss.id, nssc.category_name, nss.is_recommend, nss.is_self, nss.contact_mobile, nss.category_id, nss.commission_rate, nss.shop_deposit, nss.money, nss.money_get, nss.money_cash_outing, nss.bank_type, nss.bank_account_name, nss.bank_account_no, nss.bank_name, nss.bank_address, nss.follow_number, nss.alipay_name, nss.alipay_account_no, nss.alipay_payment_code, nss.wechat_name, nss.wechat_account_no, nss.wechat_payment_code, nss.business_license")
                .setAlias("ns")
                .leftJoin("?_site_shop nss ON ns.site_id = nss.site_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_group nsg ON ns.group_id = nsg.group_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_shop_category nssc ON nss.category_id = nssc.category_id".replace("?_", GlobalConfig.tablePrefix));

        if (ObjectUtil.isNotEmpty(searchParam.getCreateTime())) {
            QueryMapperUtils.buildByTime(queryWrapper, "ns.create_time", searchParam.getCreateTime());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getGroupId())) {
            queryWrapper.eq("nss.group_id", searchParam.getGroupId());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getCategoryId())) {
            queryWrapper.eq("nss.category_id", searchParam.getCategoryId());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getStatus())) {
            queryWrapper.eq("ns.status", searchParam.getStatus());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getIsSelf())) {
            queryWrapper.eq("nss.is_self", searchParam.getIsSelf());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getKeyword())) {
            queryWrapper.and(i -> i.or(j -> j.like("ns.site_name", searchParam.getKeyword()))
                    .or(j-> j.like("ns.keywords", searchParam.getKeyword()))
            );
        }
        queryWrapper.orderByDesc("ns.create_time");
        IPage<SiteShopListVo> iPage = siteMapper.selectJoinPage(new Page<>(page, limit), SiteShopListVo.class, queryWrapper);
        for (SiteShopListVo item : iPage.getRecords()) {
            SiteShopListVo.SiteShop shop = new SiteShopListVo.SiteShop();
            BeanUtils.copyProperties(item, shop);
            item.setShop(shop);
        }
        return PageResult.build(iPage);
    }

    @Override
    public List<SiteShopListVo> list(SiteShopSearchParam searchParam) {
        MPJQueryWrapper<Site> queryWrapper = new MPJQueryWrapper<>();
        queryWrapper.select("ns.site_id, ns.site_name, ns.group_id, ns.keywords, ns.app_type, ns.logo, ns.`desc`, ns.status, ns.latitude, ns.longitude, ns.province_id, ns.city_id, ns.district_id, ns.address, ns.full_address, ns.phone, ns.business_hours, ns.create_time, ns.expire_time, ns.front_end_name, ns.front_end_logo, ns.front_end_icon, ns.icon, ns.member_no, ns.app, ns.addons, ns.initalled_addon, ns.site_domain, ns.isinit, nsg.group_name, nss.id, nssc.category_name, nss.is_recommend, nss.is_self, nss.contact_mobile, nss.category_id, nss.commission_rate, nss.shop_deposit, nss.money, nss.money_get, nss.money_cash_outing, nss.bank_type, nss.bank_account_name, nss.bank_account_no, nss.bank_name, nss.bank_address, nss.follow_number, nss.alipay_name, nss.alipay_account_no, nss.alipay_payment_code, nss.wechat_name, nss.wechat_account_no, nss.wechat_payment_code, nss.business_license")
                .setAlias("ns")
                .leftJoin("?_site_shop nss ON ns.site_id = nss.site_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_group nsg ON ns.group_id = nsg.group_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_shop_category nssc ON nss.category_id = nssc.category_id".replace("?_", GlobalConfig.tablePrefix));

        if (ObjectUtil.isNotEmpty(searchParam.getCreateTime())) {
            QueryMapperUtils.buildByTime(queryWrapper, "ns.create_time", searchParam.getCreateTime());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getGroupId())) {
            queryWrapper.eq("ns.group_id", searchParam.getGroupId());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getCategoryId())) {
            queryWrapper.eq("nss.category_id", searchParam.getCategoryId());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getStatus())) {
            queryWrapper.eq("ns.status", searchParam.getStatus());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getIsSelf())) {
            queryWrapper.eq("ns.is_self", searchParam.getIsSelf());
        }
        if (ObjectUtil.isNotEmpty(searchParam.getKeyword())) {
            queryWrapper.and(i -> i.or(j -> j.like("ns.site_name", searchParam.getKeyword()))
                    .or(j-> j.like("ns.keywords", searchParam.getKeyword()))
            );
        }
        queryWrapper.orderByDesc("ns.create_time");
        List<SiteShopListVo> list = siteMapper.selectJoinList(SiteShopListVo.class, queryWrapper);
        for (SiteShopListVo item : list) {
            SiteShopListVo.SiteShop shop = new SiteShopListVo.SiteShop();
            BeanUtils.copyProperties(item, shop);
            item.setShop(shop);
        }
        return list;
    }

    @Override
    public SiteShopSelectPage getSelectPage(PageParam pageParam, SiteShopSelectParam siteShopSelectParam) {
        Integer page  = pageParam.getPage();
        Integer limit = pageParam.getLimit();
        List<Integer> siteIds = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getVerifySiteIds())) {
            QueryWrapper<Site> siteQueryWrapper = new QueryWrapper<>();
            siteQueryWrapper.in("site_id", siteShopSelectParam.getVerifySiteIds());
            siteQueryWrapper.eq("status", SiteStatusEnum.ON.getCode());
            List<Site> siteList = siteMapper.selectList(siteQueryWrapper);
            siteIds = siteList.stream().map(Site::getSiteId).collect(Collectors.toList());
        }
        MPJQueryWrapper<Site> queryWrapper = new MPJQueryWrapper<>();
        queryWrapper.select("ns.site_id, ns.site_name, ns.group_id, ns.keywords, ns.app_type, ns.logo, ns.`desc`, ns.status, ns.latitude, ns.longitude, ns.province_id, ns.city_id, ns.district_id, ns.address, ns.full_address, ns.phone, ns.business_hours, ns.create_time, ns.expire_time, ns.front_end_name, ns.front_end_logo, ns.front_end_icon, ns.icon, ns.member_no, ns.app, ns.addons, ns.initalled_addon, ns.site_domain, ns.isinit, nsg.group_name, nss.id, nssc.category_name, nss.is_recommend, nss.is_self, nss.contact_mobile, nss.category_id, nss.commission_rate, nss.shop_deposit, nss.money, nss.money_get, nss.money_cash_outing, nss.bank_type, nss.bank_account_name, nss.bank_account_no, nss.bank_name, nss.bank_address, nss.follow_number, nss.alipay_name, nss.alipay_account_no, nss.alipay_payment_code, nss.wechat_name, nss.wechat_account_no, nss.wechat_payment_code, nss.business_license")
                .setAlias("ns")
                .leftJoin("?_site_shop nss ON ns.site_id = nss.site_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_group nsg ON ns.group_id = nsg.group_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_shop_category nssc ON nss.category_id = nssc.category_id".replace("?_", GlobalConfig.tablePrefix));
        queryWrapper.ne("ns.app_type", "admin");
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getCreateTime())) {
            QueryMapperUtils.buildByTime(queryWrapper, "ns.create_time", siteShopSelectParam.getCreateTime());
        }
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getExpireTime())) {
            QueryMapperUtils.buildByTime(queryWrapper, "ns.expire_time", siteShopSelectParam.getExpireTime());
        }
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getGroupId())) {
            queryWrapper.eq("ns.group_id", siteShopSelectParam.getGroupId());
        }
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getCategoryId())) {
            queryWrapper.eq("ns.category_id", siteShopSelectParam.getCategoryId());
        }
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getStatus())) {
            queryWrapper.eq("ns.status", siteShopSelectParam.getStatus());
        }
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getIsSelf())) {
            queryWrapper.eq("ns.is_self", siteShopSelectParam.getIsSelf());
        }
        if (ObjectUtil.isNotEmpty(siteShopSelectParam.getKeyword())) {
            queryWrapper.and(i -> i.or(j -> j.like("ns.site_name", siteShopSelectParam.getKeyword()))
                    .or(j-> j.like("ns.keywords", siteShopSelectParam.getKeyword()))
            );
        }
        queryWrapper.orderByDesc("ns.create_time");
        IPage<SiteShopListVo> iPage = siteMapper.selectJoinPage(new Page<>(page, limit), SiteShopListVo.class, queryWrapper);
        for (SiteShopListVo item : iPage.getRecords()) {
            SiteShopListVo.SiteShop shop = new SiteShopListVo.SiteShop();
            BeanUtils.copyProperties(item, shop);
            item.setShop(shop);
        }
        PageResult<SiteShopListVo> pageRes = PageResult.build(iPage);
        SiteShopSelectPage vo = new SiteShopSelectPage();
        BeanUtils.copyProperties(pageRes, vo);
        vo.setVerifySiteIds(siteIds);
        return vo;
    }

    @Override
    public void editFollowNumber(Integer siteId, Integer isFollow) {
        SiteShop siteShop = siteShopMapper.selectOne(new QueryWrapper<SiteShop>().eq("site_id", siteId));
        if (siteShop == null) {
            throw new CommonException("店铺扩展不存在");
        }
        if (isFollow.equals(1)) {
            siteShopMapper.update(null, new UpdateWrapper<SiteShop>().set("follow_number", siteShop.getFollowNumber() + 1).eq("site_id", siteId));
        } else {
            siteShopMapper.update(null, new UpdateWrapper<SiteShop>().set("follow_number", siteShop.getFollowNumber() - 1).eq("site_id", siteId));
        }
        //关注列表
        SiteShopMember siteShopMember = siteShopMemberMapper.selectOne(
                new LambdaQueryWrapper<SiteShopMember>()
                        .eq(SiteShopMember::getSiteId, siteId)
                        .eq(SiteShopMember::getMemberId, RequestUtils.memberId())
        );
        if (siteShopMember == null) {
            siteShopMember = new SiteShopMember();
            siteShopMember.setSiteId(siteId);
            siteShopMember.setMemberId(RequestUtils.memberId());
        }
        siteShopMember.setIsFollow(Objects.equals(isFollow, 1) ? 1 : 0);
        siteShopMemberMapper.insertOrUpdate(siteShopMember);
    }

    @Override
    public SiteShopInfoVo info(Integer id) {
        MPJQueryWrapper<Site> queryWrapper = new MPJQueryWrapper<>();
        queryWrapper.select("ns.site_id, ns.site_name, ns.group_id, ns.keywords, ns.app_type, ns.logo, ns.`desc`, ns.status, ns.latitude, ns.longitude, ns.province_id, ns.city_id, ns.district_id, ns.address, ns.full_address, ns.phone, ns.business_hours, ns.create_time, ns.expire_time, ns.front_end_name, ns.front_end_logo, ns.front_end_icon, ns.icon, ns.member_no, ns.app, ns.addons, ns.initalled_addon, ns.site_domain, ns.isinit, nsg.group_name, nss.id, nssc.category_name, nss.is_recommend, nss.is_self, nss.contact_mobile, nss.category_id, nss.commission_rate, nss.shop_deposit, nss.money, nss.money_get, nss.money_cash_outing, nss.bank_type, nss.bank_account_name, nss.bank_account_no, nss.bank_name, nss.bank_address, nss.follow_number, nss.alipay_name, nss.alipay_account_no, nss.alipay_payment_code, nss.wechat_name, nss.wechat_account_no, nss.wechat_payment_code, nss.business_license")
                .setAlias("ns")
                .leftJoin("?_site_shop nss ON ns.site_id = nss.site_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_group nsg ON ns.group_id = nsg.group_id".replace("?_", GlobalConfig.tablePrefix))
                .leftJoin("?_site_shop_category nssc ON nss.category_id = nssc.category_id".replace("?_", GlobalConfig.tablePrefix));

        queryWrapper.eq("ns.site_id", id);
        SiteShopInfoVo model = siteMapper.selectJoinOne(SiteShopInfoVo.class, queryWrapper);
        Assert.notNull(model, "店铺扩展不存在");
        SiteShopInfoVo.SiteShop shop = new SiteShopInfoVo.SiteShop();
        BeanUtils.copyProperties(model, shop);
        model.setShop(shop);
        //会员基础信息
        SiteShopInfoVo.MemberInfo memberInfo = new SiteShopInfoVo.MemberInfo();
        memberInfo.setIsFollow(0);
        if (ObjectUtil.isNotEmpty(RequestUtils.memberId())) {
            SiteShopMember member = siteShopMemberMapper.selectOne(new QueryWrapper<SiteShopMember>().eq("member_id", RequestUtils.memberId()).eq("site_id", id).last("limit 1"));
            if (ObjectUtil.isNotEmpty(member)) {
                memberInfo.setIsFollow(member.getIsFollow());
            }
        }
        model.setMemberInfo(memberInfo);
        return model;
    }

    @Override
    public String shopQrcode(Integer id) {
        Map<String, Object> urlParam = new HashMap<>();
        urlParam.put("key", "site_id");
        urlParam.put("value", id);
        // 生成二维码
        String url = QrcodeUtils.qrcodeToFile(
                id, "weapp",
                coreSysConfigService.getSceneDomain().getWapUrl(),
                "addon/mall/pages/index",
                urlParam,
                "upload/qrcode/" + id + "/shop"
        );
        return url;
    }

    @Override
    public WebShopListVo selectShopList() {
        WebShopListVo vo = new WebShopListVo();

        WebConfigVo webConfigVo = webConfigService.getWebConfig();
        List<WebShopListVo.SiteWithShopInfo> list = new ArrayList<>();
        if(webConfigVo.getIsShowShop() != 0){
            List<Integer> siteIds = new ArrayList<>();
            try {
                if (ObjectUtil.isNotEmpty(webConfigVo.getSite_ids()) && !webConfigVo.getSite_ids().equals("[]")) {
                    JSONArray jsonArray = JSONUtil.parseArray(webConfigVo.getSite_ids());
                    siteIds = jsonArray.toList(Integer.class);
                }
            } catch (Exception e) {
            }
            if (!siteIds.isEmpty()) {
                MPJQueryWrapper<Site> queryWrapper = new MPJQueryWrapper<>();
                queryWrapper.select("ns.site_id,ns.site_name,ns.front_end_name,ns.front_end_logo,ns.icon")
                    .setAlias("ns")
                    .leftJoin("?_site_shop nss ON ns.site_id = nss.site_id".replace("?_", GlobalConfig.tablePrefix))
                    .ne("ns.app_type", "admin")
                    .eq("ns.status", SiteStatusEnum.ON.getCode())
                    .eq("nss.business_status", SiteStatusEnum.ON.getCode())
                    .gt("nss.mall_up_num", 0)
                    .in("ns.site_id", siteIds)
                    .orderByDesc("nss.mall_up_num", "nss.follow_number");
                List<Site> siteList = siteMapper.selectJoinList(Site.class, queryWrapper);

                for (Site site : siteList) {
                    WebShopListVo.SiteWithShopInfo siteWithShopInfo = new WebShopListVo.SiteWithShopInfo();
                    BeanUtils.copyProperties(site, siteWithShopInfo);

                    WebShopListVo.SiteWithShopInfo.ShopInfo shopInfo = new WebShopListVo.SiteWithShopInfo.ShopInfo();
                    shopInfo.setIsSelf(1);
                    siteWithShopInfo.setShop(shopInfo);
                    MallShopGoodsListEventDefiner.MallShopGoodsListEvent event = new MallShopGoodsListEventDefiner.MallShopGoodsListEvent();
                    event.setSiteId(site.getSiteId());
                    event.setNum(2);
                    List<MallShopGoodsListEventDefiner.MallShopGoodsListEventResult> results = EventAndSubscribeOfPublisher.publishAndCallback(event);

                    List<MallGoodsListVo> goodsList = new ArrayList<>();
                    if (results != null && !results.isEmpty()) {
                        MallShopGoodsListEventDefiner.MallShopGoodsListEventResult result = results.get(0);
                        if (result != null && result.getGoodsList() != null) {
                            goodsList = result.getGoodsList();
                        }
                    }
                    siteWithShopInfo.setGoodsList(goodsList);
                    list.add(siteWithShopInfo);
                }
            }
        }
        
        vo.setList(list);
        vo.setWebConfigVo(webConfigVo);
        return vo;
    }
}

基于 MIT 协议发布