mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-27 01:32:03 +08:00
CRM-合同:新增发起合同审批
This commit is contained in:
parent
a877bb4731
commit
1cab3c009c
@ -27,6 +27,11 @@
|
|||||||
<artifactId>yudao-module-crm-api</artifactId>
|
<artifactId>yudao-module-crm-api</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-module-bpm-api</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 业务组件 -->
|
<!-- 业务组件 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -140,4 +140,12 @@ public class CrmContractController {
|
|||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/approve")
|
||||||
|
@Operation(summary = "发起合同审批流程")
|
||||||
|
@PreAuthorize("@ss.hasPermission('crm:contract:update')")
|
||||||
|
public CommonResult<Boolean> transfer(@RequestParam("id") Long id) {
|
||||||
|
contractService.handleApprove(id, getLoginUserId());
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,13 @@ import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFu
|
|||||||
import com.mzt.logapi.starter.annotation.DiffLogField;
|
import com.mzt.logapi.starter.annotation.DiffLogField;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
@ -35,10 +38,6 @@ public class CrmContractSaveReqVO {
|
|||||||
@DiffLogField(name = "商机", function = CrmBusinessParseFunction.NAME)
|
@DiffLogField(name = "商机", function = CrmBusinessParseFunction.NAME)
|
||||||
private Long businessId;
|
private Long businessId;
|
||||||
|
|
||||||
@Schema(description = "工作流编号", example = "1043")
|
|
||||||
@DiffLogField(name = "工作流编号")
|
|
||||||
private Long processInstanceId;
|
|
||||||
|
|
||||||
@Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@DiffLogField(name = "下单日期")
|
@DiffLogField(name = "下单日期")
|
||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
@ -86,16 +85,30 @@ public class CrmContractSaveReqVO {
|
|||||||
@DiffLogField(name = "公司签约人", function = SysAdminUserParseFunction.NAME)
|
@DiffLogField(name = "公司签约人", function = SysAdminUserParseFunction.NAME)
|
||||||
private Long signUserId;
|
private Long signUserId;
|
||||||
|
|
||||||
@Schema(description = "最后跟进时间")
|
|
||||||
@DiffLogField(name = "最后跟进时间")
|
|
||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
|
||||||
private LocalDateTime contactLastTime;
|
|
||||||
|
|
||||||
@Schema(description = "备注", example = "你猜")
|
@Schema(description = "备注", example = "你猜")
|
||||||
@DiffLogField(name = "备注")
|
@DiffLogField(name = "备注")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
// TODO @dhb52:增加一个 status 字段:具体有哪些值,你来枚举下;主要页面上有个【草稿】【提交审核】的流程,可以看看。然后要对接工作流,这块也可以看看,不确定的地方问我。
|
@Schema(description = "产品列表")
|
||||||
|
private List<CrmContractProductItem> productItems;
|
||||||
|
|
||||||
|
@Schema(description = "商品属性")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class CrmContractProductItem {
|
||||||
|
|
||||||
|
@Schema(description = "产品编号", example = "20529")
|
||||||
|
@NotNull(message = "产品编号不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
|
||||||
|
@NotNull(message = "产品数量不能为空")
|
||||||
|
private Long count;
|
||||||
|
|
||||||
|
@Schema(description = "产品折扣")
|
||||||
|
private Integer discountPercent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,12 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||||
|
import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商机产品关联表 DO
|
* 商机产品关联表 DO
|
||||||
*
|
*
|
||||||
@ -29,14 +28,12 @@ public class CrmBusinessProductDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
@TableId
|
@TableId
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商机编号
|
* 商机编号
|
||||||
*
|
*
|
||||||
* 关联 {@link CrmBusinessDO#getId()}
|
* 关联 {@link CrmBusinessDO#getId()}
|
||||||
*/
|
*/
|
||||||
private Long businessId;
|
private Long businessId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 产品编号
|
* 产品编号
|
||||||
*
|
*
|
||||||
@ -50,29 +47,27 @@ public class CrmBusinessProductDO extends BaseDO {
|
|||||||
private Integer price;
|
private Integer price;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 销售价格
|
* 销售价格, 单位:分
|
||||||
*/
|
*/
|
||||||
private BigDecimal salesPrice;
|
private Integer salesPrice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数量
|
* 数量
|
||||||
*/
|
*/
|
||||||
private BigDecimal count;
|
private Integer count;
|
||||||
|
|
||||||
// TODO @lzxhqs:改成 discountPercent
|
|
||||||
/**
|
/**
|
||||||
* 折扣
|
* 折扣
|
||||||
*/
|
*/
|
||||||
private BigDecimal discountPercent;
|
private Integer discountPercent;
|
||||||
|
|
||||||
// TODO @lzxhqs:改成 totalPrice;总计价格,和现有项目风格一致;
|
|
||||||
/**
|
/**
|
||||||
* 小计(折扣后价格)
|
* 总计价格(折扣后价格)
|
||||||
*/
|
*/
|
||||||
private BigDecimal totalPrice;
|
private Integer totalPrice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单位
|
* 单位
|
||||||
|
*
|
||||||
|
* 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT}
|
||||||
*/
|
*/
|
||||||
private String unit;
|
private Integer unit;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ public class CrmContractDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 工作流编号
|
* 工作流编号
|
||||||
*/
|
*/
|
||||||
private Long processInstanceId;
|
private String processInstanceId;
|
||||||
/**
|
/**
|
||||||
* 下单日期
|
* 下单日期
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.crm.dal.dataobject.product;
|
package cn.iocoder.yudao.module.crm.dal.dataobject.product;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
|
||||||
import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum;
|
import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
@ -38,7 +39,7 @@ public class CrmProductDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 单位
|
* 单位
|
||||||
*
|
*
|
||||||
* 字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_PRODUCT_UNIT}
|
* 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT}
|
||||||
*/
|
*/
|
||||||
private Integer unit;
|
private Integer unit;
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,7 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
|
|||||||
default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) {
|
default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) {
|
||||||
MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
|
MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
|
||||||
// 拼接数据权限的查询条件
|
// 拼接数据权限的查询条件
|
||||||
CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(),
|
CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTRACT.getType(),
|
||||||
CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
||||||
// 拼接自身的查询条件
|
// 拼接自身的查询条件
|
||||||
mpjLambdaWrapperX.selectAll(CrmContractDO.class)
|
mpjLambdaWrapperX.selectAll(CrmContractDO.class)
|
||||||
@ -56,7 +56,7 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
|
|||||||
default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||||
MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
|
MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
|
||||||
// 构建数据权限连表条件
|
// 构建数据权限连表条件
|
||||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
|
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), ids, userId);
|
||||||
// 拼接自身的查询条件
|
// 拼接自身的查询条件
|
||||||
query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId);
|
query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId);
|
||||||
return selectJoinList(CrmContractDO.class, query);
|
return selectJoinList(CrmContractDO.class, query);
|
||||||
|
@ -57,6 +57,14 @@ public interface CrmContractService {
|
|||||||
*/
|
*/
|
||||||
void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO);
|
void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起合同审批流程
|
||||||
|
*
|
||||||
|
* @param id 合同编号
|
||||||
|
* @param userId 用户编号
|
||||||
|
*/
|
||||||
|
void handleApprove(Long id, Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得合同
|
* 获得合同
|
||||||
*
|
*
|
||||||
@ -111,9 +119,11 @@ public interface CrmContractService {
|
|||||||
Long getContractCountByCustomerId(Long customerId);
|
Long getContractCountByCustomerId(Long customerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据商机ID获取关联客户的合同数量 TODO @lzxhqs:1)方法注释,和参数注释之间要有空行;2)中英文之间有空格,更清晰,例如说 商机 ID
|
* 根据商机ID获取关联客户的合同数量
|
||||||
* @param businessId 商机ID
|
*
|
||||||
|
* @param businessId 商机编号
|
||||||
* @return 数量
|
* @return 数量
|
||||||
*/
|
*/
|
||||||
Long selectCountByBusinessId(Long businessId);
|
Long selectCountByBusinessId(Long businessId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.collection.ListUtil;
|
import cn.hutool.core.collection.ListUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
||||||
|
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
|
||||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
|
||||||
@ -13,6 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
|
|||||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||||
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
|
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
|
||||||
|
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService;
|
||||||
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
|
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
|
||||||
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
||||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
||||||
@ -40,28 +43,33 @@ import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
|
|||||||
@Validated
|
@Validated
|
||||||
public class CrmContractServiceImpl implements CrmContractService {
|
public class CrmContractServiceImpl implements CrmContractService {
|
||||||
|
|
||||||
|
public static final String CONTRACT_APPROVE = "contract-approve"; // 合同审批流程标识
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CrmContractMapper contractMapper;
|
private CrmContractMapper contractMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CrmPermissionService crmPermissionService;
|
private CrmPermissionService crmPermissionService;
|
||||||
|
@Resource
|
||||||
|
private CrmBusinessProductService businessProductService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BpmProcessInstanceApi bpmProcessInstanceApi;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}",
|
@LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}",
|
||||||
success = CRM_CONTRACT_CREATE_SUCCESS)
|
success = CRM_CONTRACT_CREATE_SUCCESS)
|
||||||
public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) {
|
public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) {
|
||||||
createReqVO.setId(null);
|
|
||||||
// TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
|
// TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
|
||||||
// 插入合同
|
// 插入合同
|
||||||
CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class);
|
CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null);
|
||||||
contractMapper.insert(contract);
|
contractMapper.insert(contract);
|
||||||
|
|
||||||
// 创建数据权限
|
// 创建数据权限
|
||||||
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
|
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
|
||||||
.setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId())
|
.setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId())
|
||||||
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
||||||
|
|
||||||
// 4. 记录操作日志上下文
|
// 4. 记录操作日志上下文
|
||||||
LogRecordContext.putVariable("contract", contract);
|
LogRecordContext.putVariable("contract", contract);
|
||||||
return contract.getId();
|
return contract.getId();
|
||||||
@ -141,6 +149,16 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||||||
contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class).setId(contractUpdateFollowUpReqBO.getBizId()));
|
contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class).setId(contractUpdateFollowUpReqBO.getBizId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleApprove(Long id, Long userId) {
|
||||||
|
// 创建合同审批流程实例
|
||||||
|
String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
|
||||||
|
.setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id)));
|
||||||
|
|
||||||
|
// 更新合同工作流编号
|
||||||
|
contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId));
|
||||||
|
}
|
||||||
|
|
||||||
//======================= 查询相关 =======================
|
//======================= 查询相关 =======================
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -182,6 +200,5 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||||||
public Long selectCountByBusinessId(Long businessId) {
|
public Long selectCountByBusinessId(Long businessId) {
|
||||||
return contractMapper.selectCountByBusinessId(businessId);
|
return contractMapper.selectCountByBusinessId(businessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
|
// TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user