Commit 0d821d705d7d8aa403722259b5d19cb5d58f31c9

Authored by puhui999
1 parent b41d469d

crm-客户管理:完善客户、公海客户分页查询

yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmCustomerSceneEnum.java renamed to yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneEnum.java
... ... @@ -8,18 +8,18 @@ import lombok.Getter;
8 8 import java.util.Arrays;
9 9  
10 10 /**
11   - * CRM 客户等级
  11 + * CRM 列表检索场景
12 12 *
13   - * @author Wanwan
  13 + * @author HUIHUI
14 14 */
15 15 @Getter
16 16 @AllArgsConstructor
17   -public enum CrmCustomerSceneEnum implements IntArrayValuable {
  17 +public enum CrmSceneEnum implements IntArrayValuable {
18 18  
19   - OWNER(1, "我负责的客户"),
20   - FOLLOW(2, "我关注的客户");
  19 + OWNER(1, "我负责的"),
  20 + FOLLOW(2, "我关注的");
21 21  
22   - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerSceneEnum::getType).toArray();
  22 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmSceneEnum::getType).toArray();
23 23  
24 24 /**
25 25 * 场景类型
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.customer;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
4 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
... ... @@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
9 10 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
10 11 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
11 12 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
12   -import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
13 13 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
14 14 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
15 15 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
... ... @@ -51,8 +51,6 @@ public class CrmCustomerController {
51 51 private DeptApi deptApi;
52 52 @Resource
53 53 private AdminUserApi adminUserApi;
54   - @Resource
55   - private CrmPermissionService permissionService;
56 54  
57 55 @PostMapping("/create")
58 56 @Operation(summary = "创建客户")
... ... @@ -119,20 +117,14 @@ public class CrmCustomerController {
119 117 return success(true);
120 118 }
121 119  
122   - // TODO @puhui999:可以在 CrmCustomerPageReqVO 里面加个 pool 参数,为 true 时,代表来自公海客户的分页
123 120 @GetMapping("/page")
124 121 @Operation(summary = "获得客户分页")
125 122 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
126 123 public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
127   - //PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO, getLoginUserId());
128   - //if (CollUtil.isEmpty(pageResult.getList())) {
129   - // return success(PageResult.empty(pageResult.getTotal()));
130   - //}
131   - // 拼接数据
132   - return convertPage(customerService.getCustomerPage(pageVO, getLoginUserId()));
133   - }
134   -
135   - private CommonResult<PageResult<CrmCustomerRespVO>> convertPage(PageResult<CrmCustomerDO> pageResult) {
  124 + PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO, getLoginUserId());
  125 + if (CollUtil.isEmpty(pageResult.getList())) {
  126 + return success(PageResult.empty(pageResult.getTotal()));
  127 + }
136 128 // 1.1 获取负责人详情
137 129 Set<Long> userIds = convertSet(pageResult.getList(), CrmCustomerDO::getOwnerUserId);
138 130 userIds.addAll(convertSet(pageResult.getList(), item -> Long.parseLong(item.getCreator()))); // 加入创建者
... ... @@ -172,19 +164,19 @@ public class CrmCustomerController {
172 164 return success(true);
173 165 }
174 166  
175   - @PutMapping("/receive")
176   - @Operation(summary = "领取公海客户")
177   - // TODO @xiaqing:1)receiveCustomer 方法名字;2)cIds 改成 ids,要加下 @RequestParam,还有 swagger 注解;3)参数非空,使用 validator 校验;4)返回 true 即可;
178   - @PreAuthorize("@ss.hasPermission('crm:customer:receive')")
179   - public CommonResult<String> receiveByIds(List<Long> cIds) {
180   - // 判断是否为空
181   - if (CollectionUtils.isEmpty(cIds))
182   - return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), GlobalErrorCodeConstants.BAD_REQUEST.getMsg());
183   - // 领取公海任务
184   - // TODO @xiaqing:userid,通过 controller 传递给 service,不要在 service 里面获取,无状态
185   - customerService.receive(cIds);
186   - return success("领取成功");
187   - }
  167 + //@PutMapping("/receive")
  168 + //@Operation(summary = "领取公海客户")
  169 + //// TODO @xiaqing:1)receiveCustomer 方法名字;2)cIds 改成 ids,要加下 @RequestParam,还有 swagger 注解;3)参数非空,使用 validator 校验;4)返回 true 即可;
  170 + //@PreAuthorize("@ss.hasPermission('crm:customer:receive')")
  171 + //public CommonResult<String> receiveByIds(List<Long> cIds) {
  172 + // // 判断是否为空
  173 + // if (CollectionUtils.isEmpty(cIds))
  174 + // return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), GlobalErrorCodeConstants.BAD_REQUEST.getMsg());
  175 + // // 领取公海任务
  176 + // // TODO @xiaqing:userid,通过 controller 传递给 service,不要在 service 里面获取,无状态
  177 + // customerService.receive(cIds);
  178 + // return success("领取成功");
  179 + //}
188 180  
189 181 // TODO @xiaqing:1)distributeCustomer 方法名;2)cIds 同上;3)参数校验,同上;4)ownerId 改成 ownerUserId,和别的模块统一;5)返回 true 即可;
190 182 @PutMapping("/distributeByIds")
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4   -import cn.iocoder.yudao.module.crm.enums.common.CrmCustomerSceneEnum;
  4 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneEnum;
5 5 import io.swagger.v3.oas.annotations.media.Schema;
6 6 import lombok.Data;
7 7 import lombok.EqualsAndHashCode;
8 8 import lombok.ToString;
9 9  
  10 +import javax.validation.constraints.NotNull;
  11 +
10 12 @Schema(description = "管理后台 - CRM 客户分页 Request VO")
11 13 @Data
12 14 @EqualsAndHashCode(callSuper = true)
... ... @@ -31,9 +33,13 @@ public class CrmCustomerPageReqVO extends PageParam {
31 33 /**
32 34 * 场景类型
33 35 *
34   - * 关联 {@link CrmCustomerSceneEnum}
  36 + * 关联 {@link CrmSceneEnum}
35 37 */
36 38 @Schema(description = "场景类型", example = "1")
37 39 private Integer sceneType;
38 40  
  41 + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
  42 + @NotNull(message = "是否为公海数据不能为空")
  43 + private Boolean pool;
  44 +
39 45 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
... ... @@ -7,13 +7,12 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
7 7 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
8 8 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
9 9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  10 +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
  11 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneEnum;
10 12 import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
11   -import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils;
12 13 import com.baomidou.mybatisplus.core.metadata.IPage;
13 14 import org.apache.ibatis.annotations.Mapper;
14 15  
15   -import java.util.Collection;
16   -
17 16 /**
18 17 * 客户 Mapper
19 18 *
... ... @@ -22,9 +21,30 @@ import java.util.Collection;
22 21 @Mapper
23 22 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
24 23  
25   - default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Collection<Long> ids) {
26   - return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmCustomerDO>()
27   - .inIfPresent(CrmCustomerDO::getId, ids)
  24 + default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO) {
  25 + LambdaQueryWrapperX<CrmCustomerDO> queryWrapperX = new LambdaQueryWrapperX<>();
  26 + if (pageReqVO.getPool()) { // 情况一:公海
  27 + queryWrapperX.isNull(CrmCustomerDO::getOwnerUserId);
  28 + } else {// 情况一:不是公海
  29 + queryWrapperX.isNotNull(CrmCustomerDO::getOwnerUserId);
  30 + }
  31 + return selectPage(pageReqVO, queryWrapperX
  32 + .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName())
  33 + .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile())
  34 + .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId())
  35 + .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel())
  36 + .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()));
  37 + }
  38 +
  39 + default PageResult<CrmCustomerDO> selectPage1(CrmCustomerPageReqVO pageReqVO, Long userId) {
  40 + LambdaQueryWrapperX<CrmCustomerDO> queryWrapperX = new LambdaQueryWrapperX<>();
  41 + //queryWrapperX.sql
  42 + if (pageReqVO.getPool()) { // 情况一:公海
  43 + queryWrapperX.isNull(CrmCustomerDO::getOwnerUserId);
  44 + } else {// 情况一:不是公海
  45 + queryWrapperX.isNotNull(CrmCustomerDO::getOwnerUserId);
  46 + }
  47 + return selectPage(pageReqVO, queryWrapperX
28 48 .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName())
29 49 .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile())
30 50 .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId())
... ... @@ -33,11 +53,50 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
33 53 }
34 54  
35 55 default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
36   - // MyBatis Plus 查询
37 56 IPage<CrmCustomerDO> mpPage = MyBatisUtils.buildPage(pageReqVO);
38 57 MPJLambdaWrapperX<CrmCustomerDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
39 58 // 构建数据权限连表条件
40   - CrmPermissionUtils.builderLeftJoinQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CUSTOMER.getType(), userId);
  59 + //CrmPermissionUtils.builderRightJoinQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CUSTOMER.getType(), userId);
  60 + mpjLambdaWrapperX
  61 + //.rightJoin("(SELECT t1.biz_id FROM crm_permission t1 WHERE (t1.biz_type = 1 AND t1.user_id = 1)) t2 on t.id = t2.biz_id");
  62 + .rightJoin(CrmPermissionDO.class, CrmPermissionDO::getBizId, CrmCustomerDO::getId)
  63 + .eq(CrmPermissionDO::getBizType, CrmBizTypeEnum.CRM_CUSTOMER.getType())
  64 + .eq(CrmPermissionDO::getUserId, userId);
  65 + /** TODO @芋艿:
  66 + -- 常规连表-查询正常
  67 + | ==> Preparing:
  68 + SELECT t.id, t.name, t.follow_up_status, t.lock_status, t.deal_status,
  69 + t.industry_id, t.level, t.source, t.mobile, t.telephone, t.website,
  70 + t.qq, t.wechat, t.email, t.description, t.remark, t.owner_user_id,
  71 + t.area_id, t.detail_address, t.contact_last_time, t.contact_next_time,
  72 + t.create_time, t.update_time, t.creator, t.updater, t.deleted
  73 + FROM crm_customer t RIGHT JOIN crm_permission t1 ON (t1.biz_id = t.id) AND t.tenant_id = 1
  74 + WHERE t.deleted = 0 AND t1.deleted = 0
  75 + AND (t1.biz_type = ? AND t1.user_id = ?
  76 + AND t.owner_user_id IS NOT NULL AND t.level = ?) AND t1.tenant_id = 1 LIMIT ?
  77 + | ==> Parameters: 2(Integer), 1(Long), 3(Integer), 10(Long)
  78 +
  79 + -- 连接子查询-报错,但是复制到 navicat 是可以正常执行的
  80 + -- 区别点:常规连表会自动拼接租户 AND t.tenant_id = 1
  81 + SELECT
  82 + t.id,t.name,t.follow_up_status,t.lock_status,t.deal_status,t.industry_id,t.level,
  83 + t.source,t.mobile,t.telephone,t.website,t.qq,t.wechat,t.email,t.description,t.remark,
  84 + t.owner_user_id,t.area_id,t.detail_address,t.contact_last_time,t.contact_next_time,
  85 + t.create_time,t.update_time,t.creator,t.updater,t.deleted
  86 + FROM crm_customer t
  87 + RIGHT JOIN (SELECT t1.biz_id FROM crm_permission t1 WHERE (t1.biz_type = 2 AND t1.user_id = 1)) t2 on t.id = t2.biz_id
  88 + WHERE t.deleted=0
  89 + AND (t.owner_user_id IS NOT NULL)
  90 + */
  91 + if (pageReqVO.getPool()) { // 情况一:公海
  92 + mpjLambdaWrapperX.isNull(CrmCustomerDO::getOwnerUserId);
  93 + } else {// 情况一:不是公海
  94 + mpjLambdaWrapperX.isNotNull(CrmCustomerDO::getOwnerUserId);
  95 + }
  96 + // TODO 场景数据过滤
  97 + if (CrmSceneEnum.isOwner(pageReqVO.getSceneType())) { // 场景一:我负责的数据
  98 + mpjLambdaWrapperX.eq(CrmCustomerDO::getOwnerUserId, userId);
  99 + }
41 100 mpPage = selectJoinPage(mpPage, CrmCustomerDO.class, mpjLambdaWrapperX
42 101 .selectAll(CrmCustomerDO.class)
43 102 .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName())
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
... ... @@ -39,6 +39,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
39 39 private CrmPermissionService crmPermissionService;
40 40  
41 41 @Override
  42 + @Transactional(rollbackFor = Exception.class)
42 43 public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) {
43 44 // 插入
44 45 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO);
... ... @@ -89,32 +90,19 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
89 90  
90 91 @Override
91 92 public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
92   - //// 1.1 TODO 如果是超级管理员
93   - //boolean admin = false;
94   - //if (admin && ObjUtil.notEqual(userId, CrmPermissionDO.POOL_USER_ID)) {
95   - // return customerMapper.selectPage(pageReqVO, Collections.emptyList());
96   - //}
97   - //// 1.2 获取当前用户能看的分页数据
98   - //// TODO @puhui999:如果业务的数据量比较大,in 太多可能有性能问题噢;看看是不是搞成 join 连表了;可以微信讨论下;
99   - //List<CrmPermissionDO> permissions = crmPermissionService.getPermissionListByBizTypeAndUserId(
100   - // CrmBizTypeEnum.CRM_CUSTOMER.getType(), userId);
101   - //// 1.3 TODO 场景数据过滤
102   - //if (CrmCustomerSceneEnum.isOwner(pageReqVO.getSceneType())) { // 场景一:我负责的数据
103   - // permissions = CollectionUtils.filterList(permissions, item -> CrmPermissionLevelEnum.isOwner(item.getLevel()));
104   - //}
105   - //Set<Long> ids = convertSet(permissions, CrmPermissionDO::getBizId);
106   - //if (CollUtil.isEmpty(ids)) { // 没得说明没有什么给他看的
107   - // return PageResult.empty();
108   - //}
109   - //
110   - //// 2. 获取客户分页数据
111   - //return customerMapper.selectPage(pageReqVO, ids);
  93 + // 1.1. TODO 如果是超级管理员
  94 + boolean admin = false;
  95 + if (admin) {
  96 + return customerMapper.selectPage(pageReqVO);
  97 + }
  98 + // 1.2. 获取当前用户能看的分页数据
112 99 return customerMapper.selectPage(pageReqVO, userId);
113 100 }
114 101  
115 102 @Override
116 103 public List<CrmCustomerDO> getCustomerList(CrmCustomerExportReqVO exportReqVO) {
117 104 //return customerMapper.selectList(exportReqVO);
  105 + // TODO puhui999: 等数据权限完善后再实现
118 106 return Collections.emptyList();
119 107 }
120 108  
... ... @@ -161,13 +149,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
161 149  
162 150 @Override
163 151 @Transactional(rollbackFor = Exception.class)
164   - public void receive(List <Long> ids) {
165   - transferCustomerOwner(ids,SecurityFrameworkUtils.getLoginUserId());
  152 + public void receive(List<Long> ids) {
  153 + transferCustomerOwner(ids, SecurityFrameworkUtils.getLoginUserId());
166 154 }
167 155  
168 156 @Override
169   - public void distributeByIds(List <Long> cIds, Long ownerId) {
170   - transferCustomerOwner(cIds,ownerId);
  157 + public void distributeByIds(List<Long> cIds, Long ownerId) {
  158 + transferCustomerOwner(cIds, ownerId);
171 159 }
172 160  
173 161 @Override
... ... @@ -191,6 +179,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
191 179 }
192 180  
193 181 @Override
  182 + @Transactional(rollbackFor = Exception.class)
194 183 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
195 184 public void putPool(Long id) {
196 185 // 1. 校验存在
... ... @@ -214,7 +203,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
214 203 CrmPermissionLevelEnum.OWNER.getLevel());
215 204 }
216 205  
217   - private void transferCustomerOwner(List <Long> cIds, Long ownerId){
  206 + private void transferCustomerOwner(List<Long> cIds, Long ownerId) {
218 207 // 先一次性校验完成客户是否可用
219 208 // TODO @xiaqing:批量一次性加载客户列表,然后去逐个校验;
220 209 for (Long cId : cIds) {
... ... @@ -228,8 +217,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
228 217 validCustomerDeal(cId);
229 218 }
230 219 // TODO @xiaqing:每个客户更新的时候,where 条件,加上 owner_user_id is null,防止并发问题;
231   - List<CrmCustomerDO> updateDos = new ArrayList <>();
232   - for (Long cId : cIds){
  220 + List<CrmCustomerDO> updateDos = new ArrayList<>();
  221 + for (Long cId : cIds) {
233 222 CrmCustomerDO customerDO = new CrmCustomerDO();
234 223 customerDO.setId(cId);
235 224 customerDO.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId());
... ... @@ -239,19 +228,19 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
239 228 }
240 229  
241 230 private void validCustomerOwnerExist(Long id) {
242   - if (customerMapper.selectById(id).getOwnerUserId()!=null) {
  231 + if (customerMapper.selectById(id).getOwnerUserId() != null) {
243 232 throw exception(CUSTOMER_OWNER_EXISTS);
244 233 }
245 234 }
246 235  
247 236 private void validCustomerIsLocked(Long id) {
248   - if (customerMapper.selectById(id).getLockStatus() ==true) {
  237 + if (customerMapper.selectById(id).getLockStatus() == true) {
249 238 throw exception(CUSTOMER_LOCKED);
250 239 }
251 240 }
252 241  
253 242 private void validCustomerDeal(Long id) {
254   - if (customerMapper.selectById(id).getDealStatus() ==true) {
  243 + if (customerMapper.selectById(id).getDealStatus() == true) {
255 244 throw exception(CUSTOMER_ALREADY_DEAL);
256 245 }
257 246 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java
... ... @@ -17,13 +17,10 @@ public class CrmPermissionUtils {
17 17 * @param bizTyp 模块类型
18 18 * @param userId 用户
19 19 */
20   - public static void builderLeftJoinQuery(MPJLambdaWrapper<?> mpjLambdaWrapper, Integer bizTyp, Long userId) {
  20 + public static void builderRightJoinQuery(MPJLambdaWrapper<?> mpjLambdaWrapper, Integer bizTyp, Long userId) {
  21 + String querySql = "(SELECT t1.biz_id FROM crm_permission t1 WHERE (t1.biz_type = {} AND t1.user_id = {})) t2 on t.id = t2.biz_id";
21 22 // 默认主表别名是 t
22   - mpjLambdaWrapper.leftJoin(StrUtil.format("(" +
23   - "select p.biz_id from crm_permission p" +
24   - " where p.biz_type = {} and p.user_id = {}" +
25   - ") t2" +
26   - " on t.id = t2.biz_id", bizTyp, userId));
  23 + mpjLambdaWrapper.rightJoin(StrUtil.format(querySql, bizTyp, userId));
27 24 }
28 25  
29 26 }
... ...