hejianhao
2026-09-01 287fa25ac03c4747472086232150723edb2db82f
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/agent/service/ProvincialAgentAppService.java
@@ -1,6 +1,10 @@
package com.tcm.training.admin.agent.service;
import cn.hutool.json.JSONUtil;
import cn.idev.excel.FastExcel;
import com.fasterxml.jackson.databind.JsonNode;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tcm.training.admin.agent.dto.ProvincialAgentSaveRequest;
@@ -10,146 +14,276 @@
import com.tcm.training.admin.agent.mapper.ProvincialAgentMapper;
import com.tcm.training.admin.agent.vo.ProvincialAgentDetailVO;
import com.tcm.training.admin.agent.vo.ProvincialAgentListItemVO;
import com.tcm.training.admin.app.register.entity.SysRegion;
import com.tcm.training.admin.app.register.mapper.SysRegionMapper;
import com.tcm.training.admin.common.PageResponse;
import com.tcm.training.admin.common.PhoneMasker;
import com.tcm.training.admin.live.entity.Clinic;
import com.tcm.training.admin.live.mapper.ClinicMapper;
import com.tcm.training.admin.utils.VzanHttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.tcm.training.admin.common.enums.EnabledStatusEnum;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.LinkedHashMap;
@Slf4j
@Service
public class ProvincialAgentAppService {
    private final ProvincialAgentMapper agentMapper;
    private final AgentRegionMapper regionMapper;
    private final SysRegionMapper sysRegionMapper;
    private final ClinicMapper clinicMapper;
    private final VzanHttpUtil vzanHttpUtil;
    private volatile Map<String, SysRegion> regionCache;
    public ProvincialAgentAppService(ProvincialAgentMapper agentMapper, AgentRegionMapper regionMapper) {
    public ProvincialAgentAppService(ProvincialAgentMapper agentMapper, AgentRegionMapper regionMapper,
                                     SysRegionMapper sysRegionMapper, ClinicMapper clinicMapper, VzanHttpUtil vzanHttpUtil) {
        this.agentMapper = agentMapper;
        this.regionMapper = regionMapper;
        this.sysRegionMapper = sysRegionMapper;
        this.clinicMapper = clinicMapper;
        this.vzanHttpUtil = vzanHttpUtil;
    }
    public PageResponse<ProvincialAgentListItemVO> page(int page, int pageSize, String agentName, String province) {
        LambdaQueryWrapper<ProvincialAgent> q = new LambdaQueryWrapper<ProvincialAgent>().eq(ProvincialAgent::getDeleted, 0)
                .like(agentName != null && !agentName.trim().isEmpty(), ProvincialAgent::getAgentName, trim(agentName))
                .like(province != null && !province.trim().isEmpty(), ProvincialAgent::getProvince, trim(province))
                .orderByDesc(ProvincialAgent::getCreatedAt).orderByDesc(ProvincialAgent::getId);
        IPage<ProvincialAgent> result = agentMapper.selectPage(new Page<ProvincialAgent>(page, pageSize), q);
    public PageResponse<ProvincialAgentListItemVO> page(int page, int pageSize, String regionCode,
                                                        String clinicName, String contactInfo, Integer status) {
        LambdaQueryWrapper<ProvincialAgent> query = new LambdaQueryWrapper<ProvincialAgent>()
                .eq(ProvincialAgent::getDeleted, 0)
                .like(trim(contactInfo) != null, ProvincialAgent::getContactInfo, trim(contactInfo))
                .eq(status != null, ProvincialAgent::getStatus, status)
                .orderByAsc(ProvincialAgent::getCreatedAt).orderByAsc(ProvincialAgent::getId);
        if (trim(regionCode) != null) {
            List<Long> ids = new ArrayList<Long>();
            for (AgentRegion region : regionMapper.selectList(new LambdaQueryWrapper<AgentRegion>()
                    .eq(AgentRegion::getRegionCode, trim(regionCode))))
                ids.add(region.getAgentId());
            if (ids.isEmpty()) {
                return emptyPage(page, pageSize);
            }
            query.in(ProvincialAgent::getId, ids);
        }
        if (trim(clinicName) != null) {
            List<Long> ids = new ArrayList<Long>();
            for (Clinic clinic : clinicMapper.selectList(new LambdaQueryWrapper<Clinic>()
                    .like(Clinic::getName, trim(clinicName)))) {
                if (clinic.getAgentId() != null && !ids.contains(clinic.getAgentId())) ids.add(clinic.getAgentId());
            }
            if (ids.isEmpty()) {
                return emptyPage(page, pageSize);
            }
            query.in(ProvincialAgent::getId, ids);
        }
        IPage<ProvincialAgent> result = agentMapper.selectPage(new Page<ProvincialAgent>(page, pageSize), query);
        List<ProvincialAgentListItemVO> list = new ArrayList<ProvincialAgentListItemVO>();
        for (ProvincialAgent item : result.getRecords()) list.add(toList(item));
        for (ProvincialAgent item : result.getRecords()) {
            list.add(toList(item));
        }
        return PageResponse.of(list, result.getTotal(), result.getCurrent(), result.getSize());
    }
    private PageResponse<ProvincialAgentListItemVO> emptyPage(int page, int pageSize) {
        return PageResponse.of(new ArrayList<ProvincialAgentListItemVO>(), 0, page, pageSize);
    }
    public ProvincialAgentDetailVO detail(Long id) {
        return toDetail(require(id));
    }
    @Transactional
    @Transactional(rollbackFor = Exception.class)
    public ProvincialAgentDetailVO create(ProvincialAgentSaveRequest request) {
        ProvincialAgent a = new ProvincialAgent();
        fill(a, request);
        a.setDeleted(0);
        agentMapper.insert(a);
        saveRegions(a, request);
        return detail(a.getId());
        boolean firstAgent = agentMapper.selectCount(new LambdaQueryWrapper<ProvincialAgent>()
                .eq(ProvincialAgent::getDeleted, 0)) == 0;
        ProvincialAgent agent = new ProvincialAgent();
        fill(agent, request);
        agent.setDeleted(0);
        agentMapper.insert(agent);
        saveRegions(agent, request);
        if (firstAgent) {
            clinicMapper.update(null, new LambdaUpdateWrapper<Clinic>().set(Clinic::getAgentId, agent.getId()));
        }
        log.info("调用微赞创建代理,入参 agentMobile={}, agentName={}, levelCode={}, parentMobile={}, storeName={}",
                request.getContactInfo(), request.getAgentName(), 2, null, null);
        try {
            JsonNode vzanResponse = vzanHttpUtil.createAgent(
                    request.getContactInfo(), request.getAgentName(), 2, null, null);
            log.info("微赞创建代理成功,出参={}", vzanResponse);
        } catch (RuntimeException ex) {
            log.error("微赞创建代理失败,本地事务将回滚,入参 agentMobile={}, agentName={}, levelCode={}, parentMobile={}, storeName={}",
                    request.getContactInfo(), request.getAgentName(), 1, null, request.getAgentName(), ex);
//            throw ex;
            throw new IllegalStateException("微赞创建代理失败", ex);
        }
        return detail(agent.getId());
    }
    @Transactional
    @Transactional(rollbackFor = Exception.class)
    public ProvincialAgentDetailVO update(Long id, ProvincialAgentSaveRequest request) {
        ProvincialAgent a = require(id);
        fill(a, request);
        agentMapper.updateById(a);
        ProvincialAgent agent = require(id);
        fill(agent, request);
        agentMapper.updateById(agent);
        regionMapper.delete(new LambdaQueryWrapper<AgentRegion>().eq(AgentRegion::getAgentId, id));
        saveRegions(a, request);
        saveRegions(agent, request);
        return detail(id);
    }
    @Transactional
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        require(id);
        agentMapper.deleteById(id);
    }
    private void fill(ProvincialAgent a, ProvincialAgentSaveRequest r) {
        a.setAgentName(trim(r.getAgentName()));
        a.setProvince(trim(r.getProvince()));
        a.setBankName(trim(r.getBankName()));
        a.setAccountNumber(trim(r.getAccountNumber()));
        a.setAccountHolder(trim(r.getAccountHolder()));
        a.setBranchName(trim(r.getBranchName()));
        a.setContactInfo(trim(r.getContactInfo()));
        a.setAddress(trim(r.getAddress()));
    private void fill(ProvincialAgent agent, ProvincialAgentSaveRequest request) {
        agent.setAgentName(trim(request.getAgentName()));
        agent.setProvince("");
        agent.setBankName(trim(request.getBankName()));
        agent.setAccountNumber(trim(request.getAccountNumber()));
        agent.setAccountHolder(trim(request.getAccountHolder()));
        agent.setBranchName(trim(request.getBranchName()));
        agent.setContactInfo(trim(request.getContactInfo()));
        agent.setStatus(request.getStatus() == null ? EnabledStatusEnum.ENABLED.getValue() : request.getStatus());
        agent.setAddress(trim(request.getAddress()));
    }
    private void saveRegions(ProvincialAgent a, ProvincialAgentSaveRequest r) {
        if (r.getRegions() == null) return;
        for (ProvincialAgentSaveRequest.RegionItem x : r.getRegions()) {
            if (x == null || trim(x.getRegionCode()) == null) continue;
            AgentRegion ar = new AgentRegion();
            ar.setAgentId(a.getId());
            ar.setAgentName(a.getAgentName());
            ar.setRegionCode(trim(x.getRegionCode()));
            ar.setRegionName(trim(x.getRegionName()));
            ar.setRegionLevel(x.getRegionLevel());
            regionMapper.insert(ar);
    private void saveRegions(ProvincialAgent agent, ProvincialAgentSaveRequest request) {
        if (request.getRegions() == null) return;
        List<AgentRegion> regions = new ArrayList<AgentRegion>();
        for (ProvincialAgentSaveRequest.RegionItem item : request.getRegions()) {
            if (item == null || trim(item.getRegionCode()) == null) continue;
            RegionInfo info = resolveRegion(item.getRegionCode());
            AgentRegion region = new AgentRegion();
            region.setAgentId(agent.getId());
            region.setRegionCode(trim(item.getRegionCode()));
            region.setRegionName(info.name);
            region.setRegionLevel(info.path.size());
            regions.add(region);
        }
        if (!regions.isEmpty()) {
            regionMapper.insertBatch(regions);
        }
    }
    private ProvincialAgent require(Long id) {
        ProvincialAgent a = agentMapper.selectOne(new LambdaQueryWrapper<ProvincialAgent>().eq(ProvincialAgent::getId, id).eq(ProvincialAgent::getDeleted, 0).last("limit 1"));
        if (a == null) throw new IllegalArgumentException("省代理不存在");
        return a;
        ProvincialAgent agent = agentMapper.selectOne(new LambdaQueryWrapper<ProvincialAgent>()
                .eq(ProvincialAgent::getId, id).eq(ProvincialAgent::getDeleted, 0).last("limit 1"));
        if (agent == null) throw new IllegalArgumentException("省代理不存在");
        return agent;
    }
    private ProvincialAgentListItemVO toList(ProvincialAgent a) {
        ProvincialAgentListItemVO v = new ProvincialAgentListItemVO();
        v.setId(a.getId());
        v.setAgentName(a.getAgentName());
        v.setProvince(a.getProvince());
        v.setContactInfo(a.getContactInfo());
        v.setAddress(a.getAddress());
        List<AgentRegion> rs = regions(a.getId());
        v.setRegionCount(rs.size());
    private ProvincialAgentListItemVO toList(ProvincialAgent agent) {
        ProvincialAgentListItemVO vo = new ProvincialAgentListItemVO();
        vo.setId(agent.getId());
        vo.setAgentName(agent.getAgentName());
        vo.setContactInfo(PhoneMasker.mask(agent.getContactInfo()));
        vo.setAddress(agent.getAddress());
        vo.setCreatedAt(agent.getCreatedAt());
        vo.setStatus(agent.getStatus());
        vo.setClinicCount(clinicMapper.selectCount(new LambdaQueryWrapper<Clinic>().eq(Clinic::getAgentId, agent.getId())));
        List<AgentRegion> regions = regions(agent.getId());
        vo.setRegionCount(regions.size());
        List<String> names = new ArrayList<String>();
        for (AgentRegion r : rs) names.add(r.getRegionName() == null ? r.getRegionCode() : r.getRegionName());
        v.setRegionNames(names);
        v.setCreatedAt(a.getCreatedAt());
        return v;
        for (AgentRegion region : regions) {
            names.add(resolveRegion(region.getRegionCode()).name);
        }
        vo.setRegionNames(names);
        return vo;
    }
    private ProvincialAgentDetailVO toDetail(ProvincialAgent a) {
        ProvincialAgentDetailVO v = new ProvincialAgentDetailVO();
        ProvincialAgentListItemVO base = toList(a);
        v.setId(base.getId());
        v.setAgentName(base.getAgentName());
        v.setProvince(base.getProvince());
        v.setContactInfo(base.getContactInfo());
        v.setAddress(base.getAddress());
        v.setRegionCount(base.getRegionCount());
        v.setRegionNames(base.getRegionNames());
        v.setCreatedAt(base.getCreatedAt());
        v.setBankName(a.getBankName());
        v.setAccountNumber(a.getAccountNumber());
        v.setAccountHolder(a.getAccountHolder());
        v.setBranchName(a.getBranchName());
        v.setUpdatedAt(a.getUpdatedAt());
        List<ProvincialAgentDetailVO.RegionVO> out = new ArrayList<ProvincialAgentDetailVO.RegionVO>();
        for (AgentRegion r : regions(a.getId())) {
            ProvincialAgentDetailVO.RegionVO x = new ProvincialAgentDetailVO.RegionVO();
            x.setRegionCode(r.getRegionCode());
            x.setRegionName(r.getRegionName());
            x.setRegionLevel(r.getRegionLevel());
            out.add(x);
    private ProvincialAgentDetailVO toDetail(ProvincialAgent agent) {
        ProvincialAgentDetailVO vo = new ProvincialAgentDetailVO();
        ProvincialAgentListItemVO base = toList(agent);
        vo.setId(base.getId());
        vo.setAgentName(base.getAgentName());
        vo.setContactInfo(base.getContactInfo());
        vo.setAddress(base.getAddress());
        vo.setRegionCount(base.getRegionCount());
        vo.setRegionNames(base.getRegionNames());
        vo.setCreatedAt(base.getCreatedAt());
        vo.setStatus(base.getStatus());
        vo.setClinicCount(base.getClinicCount());
        vo.setBankName(agent.getBankName());
        vo.setAccountNumber(agent.getAccountNumber());
        vo.setAccountHolder(agent.getAccountHolder());
        vo.setBranchName(agent.getBranchName());
        vo.setUpdatedAt(agent.getUpdatedAt());
        List<ProvincialAgentDetailVO.RegionVO> values = new ArrayList<ProvincialAgentDetailVO.RegionVO>();
        for (AgentRegion region : regions(agent.getId())) {
            RegionInfo info = resolveRegion(region.getRegionCode());
            ProvincialAgentDetailVO.RegionVO value = new ProvincialAgentDetailVO.RegionVO();
            value.setRegionCode(region.getRegionCode());
            value.setRegionName(info.name);
            value.setRegionLevel(info.path.size());
            value.setRegionPath(info.path);
            values.add(value);
        }
        v.setRegions(out);
        return v;
        vo.setRegions(values);
        return vo;
    }
    private List<AgentRegion> regions(Long id) {
        return regionMapper.selectList(new LambdaQueryWrapper<AgentRegion>().eq(AgentRegion::getAgentId, id).orderByAsc(AgentRegion::getId));
        return regionMapper.selectList(new LambdaQueryWrapper<AgentRegion>()
                .eq(AgentRegion::getAgentId, id).orderByAsc(AgentRegion::getId));
    }
    private String trim(String s) {
        if (s == null) return null;
        String x = s.trim();
        return x.isEmpty() ? null : x;
    private RegionInfo resolveRegion(String code) {
        List<String> path = new ArrayList<String>();
        List<String> names = new ArrayList<String>();
        SysRegion current = getRegionCache().get(code);
        while (current != null) {
            path.add(0, current.getCode());
            names.add(0, current.getName());
            current = current.getParentId() == null || current.getParentId() == 0 ? null : getRegionById(current.getParentId());
        }
        if (path.isEmpty()) {
            path.add(code);
            names.add(code);
        }
        return new RegionInfo(path, String.join("", names));
    }
    private Map<String, SysRegion> getRegionCache() {
        Map<String, SysRegion> cache = regionCache;
        if (cache == null) {
            synchronized (this) {
                cache = regionCache;
                if (cache == null) {
                    cache = new LinkedHashMap<String, SysRegion>();
                    for (SysRegion region : sysRegionMapper.selectAllOrdered()) cache.put(region.getCode(), region);
                    regionCache = cache;
                }
            }
        }
        return cache;
    }
    private SysRegion getRegionById(Long id) {
        for (SysRegion region : getRegionCache().values()) if (id.equals(region.getId())) {
            return region;
        }
        return null;
    }
    private String trim(String value) {
        if (value == null) return null;
        String trimmed = value.trim();
        return trimmed.isEmpty() ? null : trimmed;
    }
    private static class RegionInfo {
        private final List<String> path;
        private final String name;
        private RegionInfo(List<String> path, String name) {
            this.path = path;
            this.name = name;
        }
    }
}