lmx 2 дней назад
Родитель
Сommit
228af093d4

+ 18 - 0
fs-admin-saas/src/main/java/com/fs/company/controller/CompanySmsTempController.java

@@ -7,8 +7,10 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.utils.SecurityUtils;
 import com.fs.company.domain.CompanySmsTemp;
 import com.fs.company.service.ICompanySmsTempService;
+import com.fs.company.service.tenant.ITenantMasterSmsApiQueryService;
 import com.fs.company.vo.CompanySmsTempListVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -29,6 +31,22 @@ public class CompanySmsTempController extends BaseController
     @Autowired
     private ICompanySmsTempService companySmsTempService;
 
+    @Autowired
+    private ITenantMasterSmsApiQueryService tenantMasterSmsApiQueryService;
+
+    /**
+     * 查询当前租户已绑定的短信接口(主库 company_sms_api_tenant,供模板绑定下拉)
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:list')")
+    @GetMapping("/smsApiOptions")
+    public AjaxResult smsApiOptions() {
+        Long tenantId = SecurityUtils.getTenantId();
+        if (tenantId == null) {
+            return AjaxResult.error("无法获取当前租户信息");
+        }
+        return AjaxResult.success(tenantMasterSmsApiQueryService.selectBoundSmsApisByTenantId(tenantId));
+    }
+
     /**
      * 查询短信模板列表
      */

+ 105 - 3
fs-admin/src/main/java/com/fs/web/controller/system/CompanySmsApiTenantController.java

@@ -2,13 +2,19 @@ package com.fs.web.controller.system;
 
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.utils.StringUtils;
 import com.fs.proxy.domain.CompanySmsApiTenant;
+import com.fs.proxy.domain.SmsApiTenantBatchAddResult;
 import com.fs.proxy.service.ICompanySmsApiTenantService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 短信接口-租户绑定Controller (adminUI)
@@ -20,12 +26,13 @@ public class CompanySmsApiTenantController extends BaseController {
     @Autowired
     private ICompanySmsApiTenantService smsApiTenantService;
 
-    /** 查询绑定列表 */
+    /** 分页查询绑定列表 */
     @PreAuthorize("@ss.hasPermi('platform:smsApiTenant:list')")
     @GetMapping("/list")
-    public AjaxResult list(CompanySmsApiTenant query) {
+    public TableDataInfo list(CompanySmsApiTenant query) {
+        startPage();
         List<CompanySmsApiTenant> list = smsApiTenantService.selectSmsApiTenantList(query);
-        return AjaxResult.success(list);
+        return getDataTable(list);
     }
 
     /** 获取绑定详情 */
@@ -49,6 +56,38 @@ public class CompanySmsApiTenantController extends BaseController {
         return toAjax(smsApiTenantService.insertSmsApiTenant(tenant));
     }
 
+    /** 批量新增绑定 */
+    @PreAuthorize("@ss.hasPermi('platform:smsApiTenant:add')")
+    @PostMapping("/batch")
+    public AjaxResult batchAdd(@RequestBody Map<String, Object> body) {
+        List<Long> apiIds = parseIdList(body.get("apiIds"));
+        List<Long> tenantIds = parseIdList(body.get("tenantIds"));
+        if (apiIds.isEmpty()) {
+            apiIds = parseIdList(body.get("apiId"));
+        }
+        if (tenantIds.isEmpty()) {
+            tenantIds = parseIdList(body.get("tenantId"));
+        }
+        CompanySmsApiTenant template = new CompanySmsApiTenant();
+        if (body.get("price") != null && StringUtils.isNotEmpty(body.get("price").toString())) {
+            template.setPrice(new BigDecimal(body.get("price").toString()));
+        }
+        if (body.get("priority") != null && StringUtils.isNotEmpty(body.get("priority").toString())) {
+            template.setPriority(Integer.valueOf(body.get("priority").toString()));
+        }
+        if (body.get("allowManual") != null && StringUtils.isNotEmpty(body.get("allowManual").toString())) {
+            template.setAllowManual(Integer.valueOf(body.get("allowManual").toString()));
+        }
+        if (body.get("status") != null && StringUtils.isNotEmpty(body.get("status").toString())) {
+            template.setStatus(Integer.valueOf(body.get("status").toString()));
+        } else {
+            template.setStatus(1);
+        }
+        SmsApiTenantBatchAddResult result = smsApiTenantService.batchInsertSmsApiTenant(apiIds, tenantIds, template);
+        String msg = String.format("成功 %d 条,失败 %d 条", result.getSuccessCount(), result.getFailCount());
+        return AjaxResult.success(msg, result);
+    }
+
     /** 修改绑定(调价/启停) */
     @PreAuthorize("@ss.hasPermi('platform:smsApiTenant:edit')")
     @PutMapping
@@ -56,10 +95,73 @@ public class CompanySmsApiTenantController extends BaseController {
         return toAjax(smsApiTenantService.updateSmsApiTenant(tenant));
     }
 
+    /** 批量更新租户定价/绑定配置 */
+    @PreAuthorize("@ss.hasPermi('platform:smsApiTenant:edit')")
+    @PutMapping("/batchPricing")
+    public AjaxResult batchPricing(@RequestBody Map<String, Object> body) {
+        List<Long> ids = parseIdList(body.get("ids"));
+        if (ids.isEmpty()) {
+            return AjaxResult.error("请选择要更新的记录");
+        }
+        CompanySmsApiTenant pricing = parsePricingFields(body);
+        if (pricing.getPrice() == null && pricing.getPriority() == null && pricing.getAllowManual() == null) {
+            return AjaxResult.error("请至少填写一项要批量更新的配置");
+        }
+        return toAjax(smsApiTenantService.batchUpdatePricing(ids, pricing));
+    }
+
+    /** 批量更新状态 */
+    @PreAuthorize("@ss.hasPermi('platform:smsApiTenant:edit')")
+    @PutMapping("/batchStatus")
+    public AjaxResult batchStatus(@RequestBody Map<String, Object> body) {
+        List<Long> ids = parseIdList(body.get("ids"));
+        if (ids.isEmpty()) {
+            return AjaxResult.error("请选择要更新的记录");
+        }
+        if (body.get("status") == null) {
+            return AjaxResult.error("请指定状态");
+        }
+        Integer status = Integer.valueOf(body.get("status").toString());
+        if (status != 0 && status != 1) {
+            return AjaxResult.error("状态值无效");
+        }
+        return toAjax(smsApiTenantService.batchUpdateStatus(ids, status));
+    }
+
     /** 解除绑定 */
     @PreAuthorize("@ss.hasPermi('platform:smsApiTenant:remove')")
     @DeleteMapping("/{id}")
     public AjaxResult remove(@PathVariable Long id) {
         return toAjax(smsApiTenantService.deleteSmsApiTenantById(id));
     }
+
+    private CompanySmsApiTenant parsePricingFields(Map<String, Object> body) {
+        CompanySmsApiTenant pricing = new CompanySmsApiTenant();
+        if (body.get("price") != null && StringUtils.isNotEmpty(body.get("price").toString())) {
+            pricing.setPrice(new BigDecimal(body.get("price").toString()));
+        }
+        if (body.get("priority") != null && StringUtils.isNotEmpty(body.get("priority").toString())) {
+            pricing.setPriority(Integer.valueOf(body.get("priority").toString()));
+        }
+        if (body.get("allowManual") != null && StringUtils.isNotEmpty(body.get("allowManual").toString())) {
+            pricing.setAllowManual(Integer.valueOf(body.get("allowManual").toString()));
+        }
+        return pricing;
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Long> parseIdList(Object raw) {
+        List<Long> ids = new ArrayList<>();
+        if (raw == null) {
+            return ids;
+        }
+        if (raw instanceof List) {
+            for (Object item : (List<?>) raw) {
+                if (item != null) {
+                    ids.add(Long.valueOf(item.toString()));
+                }
+            }
+        }
+        return ids;
+    }
 }

+ 12 - 0
fs-service/src/main/java/com/fs/company/domain/CompanySmsTemp.java

@@ -48,6 +48,17 @@ public class CompanySmsTemp extends BaseEntity
 
     private Integer isAudit;
 
+    /** 绑定的短信接口IDs(逗号分隔,存主库 api_id) */
+    private String smsApiIds;
+
+    public String getSmsApiIds() {
+        return smsApiIds;
+    }
+
+    public void setSmsApiIds(String smsApiIds) {
+        this.smsApiIds = smsApiIds;
+    }
+
     public Integer getIsAudit() {
         return isAudit;
     }
@@ -142,6 +153,7 @@ public class CompanySmsTemp extends BaseEntity
             .append("updateTime", getUpdateTime())
             .append("status", getStatus())
             .append("cateId", getCateId())
+            .append("smsApiIds", getSmsApiIds())
             .toString();
     }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanySmsTempServiceImpl.java

@@ -1,7 +1,9 @@
 package com.fs.company.service.impl;
 
 import java.util.List;
+import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.company.param.CompanySmsTempListQueryParam;
 import com.fs.company.vo.CompanySmsTempListQueryVO;
 import com.fs.company.vo.CompanySmsTempListVO;
@@ -56,6 +58,9 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
     @Override
     public int insertCompanySmsTemp(CompanySmsTemp companySmsTemp)
     {
+        if (StringUtils.isEmpty(companySmsTemp.getSmsApiIds())) {
+            throw new ServiceException("请选择绑定的短信接口");
+        }
         companySmsTemp.setCreateTime(DateUtils.getNowDate());
         return companySmsTempMapper.insertCompanySmsTemp(companySmsTemp);
     }

+ 16 - 0
fs-service/src/main/java/com/fs/company/service/tenant/ITenantMasterSmsApiQueryService.java

@@ -0,0 +1,16 @@
+package com.fs.company.service.tenant;
+
+import com.fs.proxy.domain.CompanySmsApiTenant;
+
+import java.util.List;
+
+/**
+ * 主库 company_sms_api_tenant 查询(租户总后台短信模板绑定下拉等)
+ */
+public interface ITenantMasterSmsApiQueryService {
+
+    /**
+     * 查询当前租户已绑定的短信接口(主库)
+     */
+    List<CompanySmsApiTenant> selectBoundSmsApisByTenantId(Long tenantId);
+}

+ 35 - 0
fs-service/src/main/java/com/fs/company/service/tenant/impl/TenantMasterSmsApiQueryServiceImpl.java

@@ -0,0 +1,35 @@
+package com.fs.company.service.tenant.impl;
+
+import com.fs.common.enums.DataSourceType;
+import com.fs.company.service.tenant.ITenantMasterSmsApiQueryService;
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.proxy.domain.CompanySmsApiTenant;
+import com.fs.proxy.mapper.CompanySmsApiTenantMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+@Service
+public class TenantMasterSmsApiQueryServiceImpl implements ITenantMasterSmsApiQueryService {
+
+    @Autowired
+    private CompanySmsApiTenantMapper companySmsApiTenantMapper;
+
+    @Override
+    public List<CompanySmsApiTenant> selectBoundSmsApisByTenantId(Long tenantId) {
+        if (tenantId == null) {
+            return Collections.emptyList();
+        }
+        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+        try {
+            CompanySmsApiTenant query = new CompanySmsApiTenant();
+            query.setTenantId(tenantId);
+            query.setStatus(1);
+            return companySmsApiTenantMapper.selectSmsApiTenantList(query);
+        } finally {
+            DynamicDataSourceContextHolder.clearDataSourceType();
+        }
+    }
+}

+ 28 - 0
fs-service/src/main/java/com/fs/proxy/domain/SmsApiTenantBatchAddResult.java

@@ -0,0 +1,28 @@
+package com.fs.proxy.domain;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 短信接口-租户批量绑定结果
+ */
+@Data
+public class SmsApiTenantBatchAddResult {
+
+    private int successCount;
+
+    private int failCount;
+
+    private List<String> failMessages = new ArrayList<>();
+
+    public void addSuccess() {
+        successCount++;
+    }
+
+    public void addFail(String message) {
+        failCount++;
+        failMessages.add(message);
+    }
+}

+ 7 - 0
fs-service/src/main/java/com/fs/proxy/mapper/CompanySmsApiTenantMapper.java

@@ -20,10 +20,17 @@ public interface CompanySmsApiTenantMapper {
 
     List<CompanySmsApiTenant> selectByCompanyId(@Param("tenantId") Long tenantId);
 
+    /** 按接口+租户查询绑定(唯一键 uk_api_company) */
+    CompanySmsApiTenant selectByApiIdAndTenantId(@Param("apiId") Long apiId, @Param("tenantId") Long tenantId);
+
     int insertSmsApiTenant(CompanySmsApiTenant tenant);
 
     int updateSmsApiTenant(CompanySmsApiTenant tenant);
 
+    int batchUpdatePricing(@Param("ids") List<Long> ids, @Param("data") CompanySmsApiTenant data);
+
+    int batchUpdateStatus(@Param("ids") List<Long> ids, @Param("status") Integer status);
+
     int deleteSmsApiTenantById(Long id);
 
     /** 批量删除某接口的所有租户绑定 */

+ 7 - 0
fs-service/src/main/java/com/fs/proxy/service/ICompanySmsApiTenantService.java

@@ -1,6 +1,7 @@
 package com.fs.proxy.service;
 
 import com.fs.proxy.domain.CompanySmsApiTenant;
+import com.fs.proxy.domain.SmsApiTenantBatchAddResult;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -21,7 +22,13 @@ public interface ICompanySmsApiTenantService {
 
     int insertSmsApiTenant(CompanySmsApiTenant tenant);
 
+    SmsApiTenantBatchAddResult batchInsertSmsApiTenant(List<Long> apiIds, List<Long> tenantIds, CompanySmsApiTenant template);
+
     int updateSmsApiTenant(CompanySmsApiTenant tenant);
 
+    int batchUpdatePricing(List<Long> ids, CompanySmsApiTenant data);
+
+    int batchUpdateStatus(List<Long> ids, Integer status);
+
     int deleteSmsApiTenantById(Long id);
 }

+ 63 - 0
fs-service/src/main/java/com/fs/proxy/service/impl/CompanySmsApiTenantServiceImpl.java

@@ -1,6 +1,9 @@
 package com.fs.proxy.service.impl;
 
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.StringUtils;
 import com.fs.proxy.domain.CompanySmsApiTenant;
+import com.fs.proxy.domain.SmsApiTenantBatchAddResult;
 import com.fs.proxy.mapper.CompanySmsApiTenantMapper;
 import com.fs.proxy.service.ICompanySmsApiTenantService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,14 +45,74 @@ public class CompanySmsApiTenantServiceImpl implements ICompanySmsApiTenantServi
 
     @Override
     public int insertSmsApiTenant(CompanySmsApiTenant tenant) {
+        if (tenant.getApiId() == null || tenant.getTenantId() == null) {
+            throw new ServiceException("请选择短信接口和租户");
+        }
+        CompanySmsApiTenant existing = smsApiTenantMapper.selectByApiIdAndTenantId(
+                tenant.getApiId(), tenant.getTenantId());
+        if (existing != null) {
+            throw new ServiceException(buildDuplicateMessage(existing, tenant.getApiId(), tenant.getTenantId()));
+        }
         return smsApiTenantMapper.insertSmsApiTenant(tenant);
     }
 
+    @Override
+    public SmsApiTenantBatchAddResult batchInsertSmsApiTenant(List<Long> apiIds, List<Long> tenantIds,
+                                                              CompanySmsApiTenant template) {
+        if (apiIds == null || apiIds.isEmpty() || tenantIds == null || tenantIds.isEmpty()) {
+            throw new ServiceException("请选择至少一个短信接口和一个租户");
+        }
+        SmsApiTenantBatchAddResult result = new SmsApiTenantBatchAddResult();
+        for (Long apiId : apiIds) {
+            for (Long tenantId : tenantIds) {
+                CompanySmsApiTenant existing = smsApiTenantMapper.selectByApiIdAndTenantId(apiId, tenantId);
+                if (existing != null) {
+                    result.addFail(buildDuplicateMessage(existing, apiId, tenantId));
+                    continue;
+                }
+                CompanySmsApiTenant tenant = new CompanySmsApiTenant();
+                tenant.setApiId(apiId);
+                tenant.setTenantId(tenantId);
+                tenant.setPrice(template.getPrice());
+                tenant.setPriority(template.getPriority());
+                tenant.setAllowManual(template.getAllowManual());
+                tenant.setStatus(template.getStatus() != null ? template.getStatus() : 1);
+                smsApiTenantMapper.insertSmsApiTenant(tenant);
+                result.addSuccess();
+            }
+        }
+        return result;
+    }
+
+    private String buildDuplicateMessage(CompanySmsApiTenant existing, Long apiId, Long tenantId) {
+        String tenantName = existing != null && StringUtils.isNotEmpty(existing.getTenantName())
+                ? existing.getTenantName() : String.valueOf(tenantId);
+        String apiName = existing != null && StringUtils.isNotEmpty(existing.getApiName())
+                ? existing.getApiName() : String.valueOf(apiId);
+        return "租户「" + tenantName + "」已绑定短信接口「" + apiName + "」";
+    }
+
     @Override
     public int updateSmsApiTenant(CompanySmsApiTenant tenant) {
         return smsApiTenantMapper.updateSmsApiTenant(tenant);
     }
 
+    @Override
+    public int batchUpdatePricing(List<Long> ids, CompanySmsApiTenant data) {
+        if (ids == null || ids.isEmpty()) {
+            return 0;
+        }
+        return smsApiTenantMapper.batchUpdatePricing(ids, data);
+    }
+
+    @Override
+    public int batchUpdateStatus(List<Long> ids, Integer status) {
+        if (ids == null || ids.isEmpty()) {
+            return 0;
+        }
+        return smsApiTenantMapper.batchUpdateStatus(ids, status);
+    }
+
     @Override
     public int deleteSmsApiTenantById(Long id) {
         return smsApiTenantMapper.deleteSmsApiTenantById(id);

+ 5 - 1
fs-service/src/main/resources/mapper/company/CompanySmsTempMapper.xml

@@ -16,10 +16,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="status"    column="status"    />
         <result property="cateId"    column="cate_id"    />
         <result property="isAudit"    column="is_audit"    />
+        <result property="smsApiIds"    column="sms_api_ids"    />
     </resultMap>
 
     <sql id="selectCompanySmsTempVo">
-        select temp_id, company_id, title, content, temp_code, temp_type, create_time, update_time, status, cate_id,is_audit from company_sms_temp
+        select temp_id, company_id, title, content, temp_code, temp_type, create_time, update_time, status, cate_id, is_audit, sms_api_ids from company_sms_temp
     </sql>
 
     <select id="selectCompanySmsTempList" resultMap="CompanySmsTempResult">
@@ -54,6 +55,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="status != null">status,</if>
             <if test="cateId != null">cate_id,</if>
             <if test="isAudit != null">is_audit,</if>
+            <if test="smsApiIds != null">sms_api_ids,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyId != null">#{companyId},</if>
@@ -66,6 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="status != null">#{status},</if>
             <if test="cateId != null">#{cateId},</if>
             <if test="isAudit != null">#{isAudit},</if>
+            <if test="smsApiIds != null">#{smsApiIds},</if>
          </trim>
     </insert>
 
@@ -82,6 +85,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="status != null">status = #{status},</if>
             <if test="cateId != null">cate_id = #{cateId},</if>
             <if test="isAudit != null">is_audit = #{isAudit},</if>
+            <if test="smsApiIds != null">sms_api_ids = #{smsApiIds},</if>
         </trim>
         where temp_id = #{tempId}
     </update>

+ 29 - 0
fs-service/src/main/resources/mapper/proxy/CompanySmsApiTenantMapper.xml

@@ -62,6 +62,12 @@
         ORDER BY a.sms_type ASC
     </select>
 
+    <select id="selectByApiIdAndTenantId" resultMap="CompanySmsApiTenantResult">
+        <include refid="selectSmsApiTenantVo"/>
+        WHERE t.api_id = #{apiId} AND t.tenant_id = #{tenantId}
+        LIMIT 1
+    </select>
+
     <insert id="insertSmsApiTenant" useGeneratedKeys="true" keyProperty="id">
         INSERT INTO company_sms_api_tenant (api_id, tenant_id, price, priority, allow_manual, status, create_time)
         VALUES (#{apiId}, #{tenantId}, #{price}, #{priority}, #{allowManual}, #{status}, NOW())
@@ -79,6 +85,29 @@
         WHERE id = #{id}
     </update>
 
+    <update id="batchUpdatePricing">
+        UPDATE company_sms_api_tenant
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="data.price != null">price = #{data.price},</if>
+            <if test="data.priority != null">priority = #{data.priority},</if>
+            <if test="data.allowManual != null">allow_manual = #{data.allowManual},</if>
+            update_time = NOW(),
+        </trim>
+        WHERE id IN
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+    <update id="batchUpdateStatus">
+        UPDATE company_sms_api_tenant
+        SET status = #{status}, update_time = NOW()
+        WHERE id IN
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
     <delete id="deleteSmsApiTenantById">
         DELETE FROM company_sms_api_tenant WHERE id = #{id}
     </delete>