Merge branch 'refs/heads/master-jdk17' into master-jdk17-excel

# Conflicts:
#	yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java
This commit is contained in:
xingyu4j 2025-06-15 18:54:13 +08:00
commit f38485ffd5
88 changed files with 5752 additions and 2044 deletions

View File

@ -40,9 +40,6 @@
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<!-- 看看咋放到 bom 里 -->
<lombok.version>1.18.36</lombok.version>
<spring.boot.version>3.4.5</spring.boot.version>
<mapstruct.version>1.6.3</mapstruct.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@ -80,12 +77,10 @@
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring.boot.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,14 @@
Author: dhb52 (https://gitee.com/dhb52)
pip install simple-ddl-parser
or with uv
uv run --with simple-ddl-parser convertor.py postgres > ../postgresql/ruoyi-vue-pro.sql 239ms 5/22 21:03:16 2025
uv run --with simple-ddl-parser convertor.py sqlserver > ../sqlserver/ruoyi-vue-pro.sql
uv run --with simple-ddl-parser convertor.py kingbase > ../kingbase/ruoyi-vue-pro.sql
uv run --with simple-ddl-parser convertor.py opengauss > ../opengauss/ruoyi-vue-pro.sql
uv run --with simple-ddl-parser convertor.py oracle > ../oracle/ruoyi-vue-pro.sql
uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql
"""
import argparse
@ -38,6 +46,7 @@ def load_and_clean(sql_file: str) -> str:
str: 清理后的sql文件内容
"""
REPLACE_PAIR_LIST = (
(")\nVALUES ", ") VALUES "),
(" CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ", " "),
(" KEY `", " INDEX `"),
("UNIQUE INDEX", "UNIQUE KEY"),
@ -45,7 +54,7 @@ def load_and_clean(sql_file: str) -> str:
("b'1'", "'1'"),
)
content = open(sql_file).read()
content = open(sql_file, encoding="utf-8").read()
for replace_pair in REPLACE_PAIR_LIST:
content = content.replace(*replace_pair)
content = re.sub(r"ENGINE.*COMMENT", "COMMENT", content)
@ -110,18 +119,28 @@ class Convertor(ABC):
pass
@abstractmethod
def gen_comment(self, table_sql: str, table_name: str) -> str:
def gen_comment(self, table_ddl: Dict) -> str:
"""生成字段/表注释
Args:
table_sql (str): 原始表SQL
table_name (str): 表名
table_ddl (Dict): 表DDL
Returns:
str: 生成脚本
"""
pass
@abstractmethod
def gen_uk(self, table_ddl: Dict) -> str:
"""生成
Args:
table_ddl (Dict): 表DDL
Returns:
str: 生成脚本
"""
@abstractmethod
def gen_insert(self, table_name: str) -> str:
"""生成 insert 语句块
@ -178,6 +197,16 @@ class Convertor(ABC):
table_name = ddl["table_name"].lower()
yield f"CREATE INDEX idx_{table_name}_{no:02d} ON {table_name} ({columns})"
@staticmethod
def unique_index(ddl: Dict) -> Generator:
if "constraints" in ddl and "uniques" in ddl["constraints"]:
uk_list = ddl["constraints"]["uniques"]
for uk in uk_list:
table_name = ddl["table_name"]
uk_name = uk["constraint_name"]
uk_columns = uk["columns"]
yield table_name, uk_name, uk_columns
@staticmethod
def filed_comments(table_sql: str) -> Generator:
for line in table_sql.split("\n"):
@ -188,7 +217,7 @@ class Convertor(ABC):
yield field, comment_string
def table_comment(self, table_sql: str) -> str:
match = re.search(r"COMMENT \= '([^']+)';", table_sql)
match = re.search(r"COMMENT \='([^']+)';", table_sql)
return match.group(1) if match else None
def print(self):
@ -226,11 +255,21 @@ class Convertor(ABC):
if table_name.lower().startswith("qrtz"):
continue
# 为每个表生成个5个基本部分
# 解析注释
for column in table_ddl["columns"]:
column["comment"] = bytes(column["comment"], "utf-8").decode(
"unicode_escape"
)[1:-1]
table_ddl["comment"] = bytes(table_ddl["comment"], "utf-8").decode(
"unicode_escape"
)[1:-1]
# 为每个表生成个6个基本部分
create = self.gen_create(table_ddl)
pk = self.gen_pk(table_name)
uk = self.gen_uk(table_ddl)
index = self.gen_index(table_ddl)
comment = self.gen_comment(table_sql, table_name)
comment = self.gen_comment(table_ddl)
inserts = self.gen_insert(table_name)
# 组合当前表的DDL脚本
@ -238,6 +277,8 @@ class Convertor(ABC):
{pk}
{uk}
{index}
{comment}
@ -267,17 +308,19 @@ class PostgreSQLConvertor(Convertor):
if type == "varchar":
return f"varchar({size})"
if type == "int":
if type in ("int", "int unsigned"):
return "int4"
if type == "bigint" or type == "bigint unsigned":
if type in ("bigint", "bigint unsigned"):
return "int8"
if type == "datetime":
return "timestamp"
if type == "timestamp":
return f"timestamp({size})"
if type == "bit":
return "bool"
if type in ("tinyint", "smallint"):
return "int2"
if type == "text":
if type in ("text", "longtext"):
return "text"
if type in ("blob", "mediumblob"):
return "bytea"
@ -316,18 +359,22 @@ CREATE TABLE {table_name} (
def gen_index(self, ddl: Dict) -> str:
return "\n".join(f"{script};" for script in self.index(ddl))
def gen_comment(self, table_sql: str, table_name: str) -> str:
def gen_comment(self, table_ddl: Dict) -> str:
"""生成字段及表的注释"""
script = ""
for field, comment_string in self.filed_comments(table_sql):
for column in table_ddl["columns"]:
table_comment = column["comment"]
script += (
f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
f"COMMENT ON COLUMN {table_ddl['table_name']}.{column['name']} IS '{table_comment}';"
+ "\n"
)
table_comment = self.table_comment(table_sql)
table_comment = table_ddl["comment"]
if table_comment:
script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
script += (
f"COMMENT ON TABLE {table_ddl['table_name']} IS '{table_comment}';\n"
)
return script
@ -335,6 +382,15 @@ CREATE TABLE {table_name} (
"""生成主键定义"""
return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
def gen_uk(self, table_ddl: Dict) -> str:
script = ""
uk_list = list(Convertor.unique_index(table_ddl))
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
uk_name = f"uk_{table_name}_{idx:02d}"
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)});\n"
return script
def gen_insert(self, table_name: str) -> str:
"""生成 insert 语句,以及根据最后的 insert id+1 生成 Sequence"""
@ -393,17 +449,19 @@ class OracleConvertor(Convertor):
if type == "varchar":
return f"varchar2({size if size < 4000 else 4000})"
if type == "int":
if type in ("int", "int unsigned"):
return "number"
if type == "bigint" or type == "bigint unsigned":
return "number"
if type == "datetime":
return "date"
if type == "timestamp":
return f"timestamp({size})"
if type == "bit":
return "number(1,0)"
if type in ("tinyint", "smallint"):
return "smallint"
if type == "text":
if type in ("text", "longtext"):
return "clob"
if type in ("blob", "mediumblob"):
return "blob"
@ -423,6 +481,8 @@ class OracleConvertor(Convertor):
type = col["type"].lower()
full_type = self.translate_type(type, col["size"])
nullable = "NULL" if col["nullable"] else "NOT NULL"
# Oracle的 INSERT '' 不能通过NOT NULL校验因此对文字类型字段覆写为 NULL
nullable = "NULL" if type in ("varchar", "text", "longtext") else nullable
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
# Oracle 中 size 不能作为字段名
field_name = '"size"' if name == "size" else name
@ -447,16 +507,20 @@ CREATE TABLE {table_name} (
def gen_index(self, ddl: Dict) -> str:
return "\n".join(f"{script};" for script in self.index(ddl))
def gen_comment(self, table_sql: str, table_name: str) -> str:
def gen_comment(self, table_ddl: Dict) -> str:
script = ""
for field, comment_string in self.filed_comments(table_sql):
for column in table_ddl["columns"]:
table_comment = column["comment"]
script += (
f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
f"COMMENT ON COLUMN {table_ddl['table_name']}.{column['name']} IS '{table_comment}';"
+ "\n"
)
table_comment = self.table_comment(table_sql)
table_comment = table_ddl["comment"]
if table_comment:
script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
script += (
f"COMMENT ON TABLE {table_ddl['table_name']} IS '{table_comment}';\n"
)
return script
@ -464,6 +528,15 @@ CREATE TABLE {table_name} (
"""生成主键定义"""
return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
def gen_uk(self, table_ddl: Dict) -> str:
script = ""
uk_list = list(Convertor.unique_index(table_ddl))
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
uk_name = f"uk_{table_name}_{idx:02d}"
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)});\n"
return script
def gen_index(self, ddl: Dict) -> str:
return "\n".join(f"{script};" for script in self.index(ddl))
@ -521,17 +594,17 @@ class SQLServerConvertor(Convertor):
if type == "varchar":
return f"nvarchar({size if size < 4000 else 4000})"
if type == "int":
if type in ("int", "int unsigned"):
return "int"
if type == "bigint" or type == "bigint unsigned":
if type in ("bigint", "bigint unsigned"):
return "bigint"
if type == "datetime":
if type in ("datetime", "timestamp"):
return "datetime2"
if type == "bit":
return "varchar(1)"
if type in ("tinyint", "smallint"):
return "tinyint"
if type == "text":
if type in ("text", "longtext"):
return "nvarchar(max)"
if type in ("blob", "mediumblob"):
return "varbinary(max)"
@ -571,14 +644,18 @@ GO"""
return script
def gen_comment(self, table_sql: str, table_name: str) -> str:
def gen_comment(self, table_ddl: Dict) -> str:
"""生成字段及表的注释"""
script = ""
table_name = table_ddl["table_name"]
for column in table_ddl["columns"]:
column_comment = column["comment"]
field = column["name"]
for field, comment_string in self.filed_comments(table_sql):
script += f"""EXEC sp_addextendedproperty
'MS_Description', N'{comment_string}',
'MS_Description', N'{column_comment}',
'SCHEMA', N'dbo',
'TABLE', N'{table_name}',
'COLUMN', N'{field}'
@ -586,7 +663,7 @@ GO
"""
table_comment = self.table_comment(table_sql)
table_comment = table_ddl["comment"]
if table_comment:
script += f"""EXEC sp_addextendedproperty
'MS_Description', N'{table_comment}',
@ -601,6 +678,15 @@ GO
"""生成主键定义"""
return ""
def gen_uk(self, table_ddl: Dict) -> str:
script = ""
uk_list = list(Convertor.unique_index(table_ddl))
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
uk_name = f"uk_{table_name}_{idx:02d}"
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)})\nGO"
return script
def gen_index(self, ddl: Dict) -> str:
"""生成 index"""
return "\n".join(f"{script}\nGO" for script in self.index(ddl))
@ -674,22 +760,22 @@ class DM8Convertor(Convertor):
if type == "varchar":
return f"varchar({size})"
if type == "int":
if type in ("int", "int unsigned"):
return "int"
if type == "bigint" or type == "bigint unsigned":
if type in ("bigint", "bigint unsigned"):
return "bigint"
if type == "datetime":
return "datetime"
if type == "timestamp":
return f"timestamp({size})"
if type == "bit":
return "bit"
if type in ("tinyint", "smallint"):
return "smallint"
if type == "text":
if type in ("text", "longtext"):
return "text"
if type == "blob":
if type in ("blob", "mediumblob"):
return "blob"
if type == "mediumblob":
return "varchar(10240)"
if type == "decimal":
return (
f"decimal({','.join(str(s) for s in size)})" if len(size) else "decimal"
@ -724,19 +810,20 @@ CREATE TABLE {table_name} (
return script
def gen_index(self, ddl: Dict) -> str:
return "\n".join(f"{script};" for script in self.index(ddl))
def gen_comment(self, table_sql: str, table_name: str) -> str:
def gen_comment(self, table_ddl: Dict) -> str:
script = ""
for field, comment_string in self.filed_comments(table_sql):
for column in table_ddl["columns"]:
table_comment = column["comment"]
script += (
f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
f"COMMENT ON COLUMN {table_ddl['table_name']}.{column['name']} IS '{table_comment}';"
+ "\n"
)
table_comment = self.table_comment(table_sql)
table_comment = table_ddl["comment"]
if table_comment:
script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
script += (
f"COMMENT ON TABLE {table_ddl['table_name']} IS '{table_comment}';\n"
)
return script
@ -744,6 +831,15 @@ CREATE TABLE {table_name} (
"""生成主键定义"""
return ""
def gen_uk(self, table_ddl: Dict) -> str:
script = ""
uk_list = list(Convertor.unique_index(table_ddl))
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
uk_name = f"uk_{table_name}_{idx:02d}"
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)});\n"
return script
def gen_index(self, ddl: Dict) -> str:
return "\n".join(f"{script};" for script in self.index(ddl))
@ -784,6 +880,8 @@ class KingbaseConvertor(PostgreSQLConvertor):
type = col["type"].lower()
full_type = self.translate_type(type, col["size"])
nullable = "NULL" if col["nullable"] else "NOT NULL"
if full_type == "text":
nullable = "NULL"
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
return f"{name} {full_type} {nullable} {default}"

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.date;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
@ -19,7 +20,7 @@ import static cn.hutool.core.date.DatePattern.UTC_MS_WITH_XXX_OFFSET_PATTERN;
import static cn.hutool.core.date.DatePattern.createFormatter;
/**
* 时间工具类用于 {@link java.time.LocalDateTime}
* 时间工具类用于 {@link LocalDateTime}
*
* @author 芋道源码
*/
@ -312,4 +313,16 @@ public class LocalDateTimeUtils {
}
}
/**
* 将给定的 {@link LocalDateTime} 转换为自 Unix 纪元时间1970-01-01T00:00:00Z以来的秒数
*
* @param sourceDateTime 需要转换的本地日期时间不能为空
* @return 1970-01-01T00:00:00Z 起的秒数epoch second
* @throws NullPointerException 如果 {@code sourceDateTime} {@code null}
* @throws DateTimeException 如果转换过程中发生时间超出范围或其他时间处理异常
*/
public static Long toEpochSecond(LocalDateTime sourceDateTime) {
return TemporalAccessorUtil.toInstant(sourceDateTime).getEpochSecond();
}
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.excel.core.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.poi.excel.ExcelUtil;
@ -10,6 +11,12 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.write.handler.SheetWriteHandler;
import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
@ -20,6 +27,7 @@ import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@ -56,7 +64,20 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
public SelectSheetWriteHandler(Class<?> head) {
// 解析下拉数据
int colIndex = 0;
boolean ignoreUnannotated = head.isAnnotationPresent(ExcelIgnoreUnannotated.class);
for (Field field : head.getDeclaredFields()) {
// 关联 https://github.com/YunaiV/ruoyi-vue-pro/pull/853
// 1.1 忽略 static final transient 的字段
if (isStaticFinalOrTransient(field) ) {
continue;
}
// 1.2 忽略的字段跳过
if ((ignoreUnannotated && !field.isAnnotationPresent(ExcelProperty.class))
|| field.isAnnotationPresent(ExcelIgnore.class)) {
continue;
}
// 2. 核心处理有 ExcelColumnSelect 注解的字段
if (field.isAnnotationPresent(ExcelColumnSelect.class)) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty != null && excelProperty.index() != -1) {
@ -68,6 +89,19 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
}
}
/**
* 判断字段是否是静态的最终的 transient
* 原因EasyExcel 默认是忽略 static final transient 的字段所以需要判断
*
* @param field 字段
* @return 是否是静态的最终的transient
*/
private boolean isStaticFinalOrTransient(Field field) {
return (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|| Modifier.isTransient(field.getModifiers());
}
/**
* 获得下拉数据并添加到 {@link #selectMap}
*

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.framework.mybatis.core.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.SortingField;
@ -103,4 +105,18 @@ public class MyBatisUtils {
.replace("#{value}", StrUtil.toString(value));
}
/**
* 将驼峰命名转换为下划线命名
*
* 使用场景
* 1. <a href="https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1357/files">fix:修复"商品统计聚合函数的别名与排序字段不符"导致的 SQL 异常</a>
*
* @param func 字段名函数(驼峰命名)
* @return 字段名(下划线命名)
*/
public static <T> String toUnderlineCase(Func1<T, ?> func) {
String fieldName = LambdaUtil.getFieldName(func);
return StrUtil.toUnderlineCase(fieldName);
}
}

View File

@ -270,7 +270,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
.setCandidateUserIds(getTaskCandidateUserList(bpmnModel, node.getId(),
loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables)));
if (CollUtil.isNotEmpty(nextActivityNodes)) {
if (CollUtil.isEmpty(nextActivityNodes)) {
return nextActivityNodes;
}

View File

@ -147,7 +147,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
}
@Override
@LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
@LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}}",
success = CRM_BUSINESS_FOLLOW_UP_SUCCESS)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
public void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {

View File

@ -162,7 +162,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
}
@Override
@LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
@LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}}",
success = CRM_CUSTOMER_FOLLOW_UP_SUCCESS)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
public void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {

View File

@ -122,6 +122,15 @@ public class CodegenController {
return success(true);
}
@Operation(summary = "批量删除数据库的表和字段定义")
@DeleteMapping("/delete-list")
@Parameter(name = "tableIds", description = "表编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:codegen:delete')")
public CommonResult<Boolean> deleteCodegenList(@RequestParam("tableIds") List<Long> tableIds) {
codegenService.deleteCodegenList(tableIds);
return success(true);
}
@Operation(summary = "预览生成代码")
@GetMapping("/preview")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")

View File

@ -62,6 +62,15 @@ public class ConfigController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除参数配置")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:config:delete')")
public CommonResult<Boolean> deleteConfigList(@RequestParam("ids") List<Long> ids) {
configService.deleteConfigList(ids);
return success(true);
}
@GetMapping(value = "/get")
@Operation(summary = "获得参数配置")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -52,6 +52,15 @@ public class DataSourceConfigController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除数据源配置")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')")
public CommonResult<Boolean> deleteDataSourceConfigList(@RequestParam("ids") List<Long> ids) {
dataSourceConfigService.deleteDataSourceConfigList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得数据源配置")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -10,7 +10,7 @@ import java.time.LocalDateTime;
public class DataSourceConfigRespVO {
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer id;
private Long id;
@Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
private String name;

View File

@ -17,6 +17,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 文件配置")
@ -60,6 +62,15 @@ public class FileConfigController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除文件配置")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:file-config:delete')")
public CommonResult<Boolean> deleteFileConfigList(@RequestParam("ids") List<Long> ids) {
fileConfigService.deleteFileConfigList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得文件配置")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -26,6 +26,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
@ -75,6 +77,15 @@ public class FileController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除文件")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
public CommonResult<Boolean> deleteFileList(@RequestParam("ids") List<Long> ids) throws Exception {
fileService.deleteFileList(ids);
return success(true);
}
@GetMapping("/{configId}/get/**")
@PermitAll
@TenantIgnore

View File

@ -81,6 +81,16 @@ public class JobController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除定时任务")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
public CommonResult<Boolean> deleteJobList(@RequestParam("ids") List<Long> ids)
throws SchedulerException {
jobService.deleteJobList(ids);
return success(true);
}
@PutMapping("/trigger")
@Operation(summary = "触发定时任务")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
@ -17,8 +18,12 @@ public interface CodegenColumnMapper extends BaseMapperX<CodegenColumnDO> {
}
default void deleteListByTableId(Long tableId) {
delete(CodegenColumnDO::getTableId, tableId);
}
default void deleteListByTableId(Collection<Long> tableIds) {
delete(new LambdaQueryWrapperX<CodegenColumnDO>()
.eq(CodegenColumnDO::getTableId, tableId));
.in(CodegenColumnDO::getTableId, tableIds));
}
}

View File

@ -48,6 +48,13 @@ public interface CodegenService {
*/
void deleteCodegen(Long tableId);
/**
* 批量删除数据库的表和字段定义
*
* @param tableIds 数据编号列表
*/
void deleteCodegenList(List<Long> tableIds);
/**
* 获得表定义列表
*

View File

@ -222,6 +222,15 @@ public class CodegenServiceImpl implements CodegenService {
codegenColumnMapper.deleteListByTableId(tableId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteCodegenList(List<Long> tableIds) {
// 批量删除 table 表定义
codegenTableMapper.deleteByIds(tableIds);
// 批量删除 column 字段定义
codegenColumnMapper.deleteListByTableId(tableIds);
}
@Override
public List<CodegenTableDO> getCodegenTableList(Long dataSourceConfigId) {
return codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId);

View File

@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
import jakarta.validation.Valid;
import java.util.List;
/**
* 参数配置 Service 接口
*
@ -35,6 +37,13 @@ public interface ConfigService {
*/
void deleteConfig(Long id);
/**
* 批量删除参数配置
*
* @param ids 配置编号列表
*/
void deleteConfigList(List<Long> ids);
/**
* 获得参数配置
*

View File

@ -13,6 +13,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
@ -63,6 +65,20 @@ public class ConfigServiceImpl implements ConfigService {
configMapper.deleteById(id);
}
@Override
public void deleteConfigList(List<Long> ids) {
// 校验是否有内置配置
List<ConfigDO> configs = configMapper.selectByIds(ids);
configs.forEach(config -> {
if (ConfigTypeEnum.SYSTEM.getType().equals(config.getType())) {
throw exception(CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE);
}
});
// 批量删除
configMapper.deleteByIds(ids);
}
@Override
public ConfigDO getConfig(Long id) {
return configMapper.selectById(id);

View File

@ -35,6 +35,13 @@ public interface DataSourceConfigService {
*/
void deleteDataSourceConfig(Long id);
/**
* 批量删除数据源配置
*
* @param ids 编号列表
*/
void deleteDataSourceConfigList(List<Long> ids);
/**
* 获得数据源配置
*

View File

@ -63,6 +63,11 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
dataSourceConfigMapper.deleteById(id);
}
@Override
public void deleteDataSourceConfigList(List<Long> ids) {
dataSourceConfigMapper.deleteByIds(ids);
}
private void validateDataSourceConfigExists(Long id) {
if (dataSourceConfigMapper.selectById(id) == null) {
throw exception(DATA_SOURCE_CONFIG_NOT_EXISTS);

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient;
import jakarta.validation.Valid;
import java.util.List;
/**
* 文件配置 Service 接口
*
@ -43,6 +45,13 @@ public interface FileConfigService {
*/
void deleteFileConfig(Long id);
/**
* 批量删除文件配置
*
* @param ids 编号列表
*/
void deleteFileConfigList(List<Long> ids);
/**
* 获得文件配置
*

View File

@ -25,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -134,6 +135,23 @@ public class FileConfigServiceImpl implements FileConfigService {
clearCache(id, null);
}
@Override
public void deleteFileConfigList(List<Long> ids) {
// 校验是否有主配置
List<FileConfigDO> configs = fileConfigMapper.selectByIds(ids);
for (FileConfigDO config : configs) {
if (Boolean.TRUE.equals(config.getMaster())) {
throw exception(FILE_CONFIG_DELETE_FAIL_MASTER);
}
}
// 批量删除
fileConfigMapper.deleteByIds(ids);
// 清空缓存
ids.forEach(id -> clearCache(id, null));
}
/**
* 清空指定文件配置
*

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresigned
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
/**
* 文件 Service 接口
*
@ -59,6 +61,13 @@ public interface FileService {
*/
void deleteFile(Long id) throws Exception;
/**
* 批量删除文件
*
* @param ids 编号列表
*/
void deleteFileList(List<Long> ids) throws Exception;
/**
* 获得文件内容
*

View File

@ -20,6 +20,8 @@ import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import java.util.List;
import static cn.hutool.core.date.DatePattern.PURE_DATE_PATTERN;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;
@ -156,6 +158,23 @@ public class FileServiceImpl implements FileService {
fileMapper.deleteById(id);
}
@Override
@SneakyThrows
public void deleteFileList(List<Long> ids) {
// 删除文件
List<FileDO> files = fileMapper.selectByIds(ids);
for (FileDO file : files) {
// 获取客户端
FileClient client = fileConfigService.getFileClient(file.getConfigId());
Assert.notNull(client, "客户端({}) 不能为空", file.getPath());
// 删除文件
client.delete(file.getPath());
}
// 删除记录
fileMapper.deleteByIds(ids);
}
private FileDO validateFileExists(Long id) {
FileDO fileDO = fileMapper.selectById(id);
if (fileDO == null) {

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO;
import jakarta.validation.Valid;
import org.quartz.SchedulerException;
import java.util.List;
/**
* 定时任务 Service 接口
*
@ -58,6 +60,13 @@ public interface JobService {
*/
void deleteJob(Long id) throws SchedulerException;
/**
* 批量删除定时任务
*
* @param ids 编号列表
*/
void deleteJobList(List<Long> ids) throws SchedulerException;
/**
* 获得定时任务
*

View File

@ -169,6 +169,19 @@ public class JobServiceImpl implements JobService {
schedulerManager.deleteJob(job.getHandlerName());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteJobList(List<Long> ids) throws SchedulerException {
// 批量删除
List<JobDO> jobs = jobMapper.selectByIds(ids);
jobMapper.deleteByIds(ids);
// 删除 Job Quartz
for (JobDO job : jobs) {
schedulerManager.deleteJob(job.getHandlerName());
}
}
private JobDO validateJobExists(Long id) {
JobDO job = jobMapper.selectById(id);
if (job == null) {

View File

@ -175,8 +175,6 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
@Transactional(rollbackFor = Exception.class)
#end
public void delete${simpleClassName}ListByIds(List<${primaryColumn.javaType}> ids) {
// 校验存在
validate${simpleClassName}Exists(ids);
// 删除
${classNameVar}Mapper.deleteByIds(ids);
## 特殊:主子表专属逻辑
@ -193,12 +191,6 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
#end
}
private void validate${simpleClassName}Exists(List<${primaryColumn.javaType}> ids) {
List<${table.className}DO> list = ${classNameVar}Mapper.selectByIds(ids);
if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
}
}
#end
private void validate${simpleClassName}Exists(${primaryColumn.javaType} id) {

View File

@ -122,10 +122,8 @@ public interface CombinationActivityConvert {
return convert(reqDTO).setVirtualGroup(false)
.setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()) // 创建后默认状态为进行中
.setUserSize(activity.getUserSize()).setUserCount(1) // 默认就是 1 插入后会接着更新一次所有的拼团记录
// 用户信息
.setNickname(user.getNickname()).setAvatar(user.getAvatar())
// 商品信息
.setSpuName(spu.getName()).setPicUrl(sku.getPicUrl());
.setNickname(user.getNickname()).setAvatar(user.getAvatar()) // 用户信息
.setSpuName(spu.getName()).setPicUrl(ObjectUtil.defaultIfBlank(sku.getPicUrl(), spu.getPicUrl())); // 商品信息
}
default List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list,

View File

@ -50,8 +50,6 @@ import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.bef
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.promotion.enums.MessageTemplateConstants.COMBINATION_SUCCESS;
// TODO 芋艿等拼团记录做完完整 review
/**
* 拼团记录 Service 实现类
*
@ -219,9 +217,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
// 3. 拼团成功发送订阅消息
if (updateSuccess && isFull) {
records.forEach(item -> {
getSelf().sendCombinationResultMessage(item);
});
records.forEach(item -> getSelf().sendCombinationResultMessage(item));
}
}

View File

@ -15,6 +15,8 @@ import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils.toUnderlineCase;
/**
* 商品统计 Mapper
*
@ -49,16 +51,16 @@ public interface ProductStatisticsMapper extends BaseMapperX<ProductStatisticsDO
private static MPJLambdaWrapperX<ProductStatisticsDO> buildWrapper(ProductStatisticsReqVO reqVO) {
return new MPJLambdaWrapperX<ProductStatisticsDO>()
.betweenIfPresent(ProductStatisticsDO::getTime, reqVO.getTimes())
.selectSum(ProductStatisticsDO::getBrowseCount)
.selectSum(ProductStatisticsDO::getBrowseUserCount)
.selectSum(ProductStatisticsDO::getFavoriteCount)
.selectSum(ProductStatisticsDO::getCartCount)
.selectSum(ProductStatisticsDO::getOrderCount)
.selectSum(ProductStatisticsDO::getOrderPayCount)
.selectSum(ProductStatisticsDO::getOrderPayPrice)
.selectSum(ProductStatisticsDO::getAfterSaleCount)
.selectSum(ProductStatisticsDO::getAfterSaleRefundPrice)
.selectAvg(ProductStatisticsDO::getBrowseConvertPercent);
.selectSum(ProductStatisticsDO::getBrowseCount, toUnderlineCase(ProductStatisticsDO::getBrowseCount))
.selectSum(ProductStatisticsDO::getBrowseUserCount, toUnderlineCase(ProductStatisticsDO::getBrowseUserCount))
.selectSum(ProductStatisticsDO::getFavoriteCount, toUnderlineCase(ProductStatisticsDO::getFavoriteCount))
.selectSum(ProductStatisticsDO::getCartCount, toUnderlineCase(ProductStatisticsDO::getCartCount))
.selectSum(ProductStatisticsDO::getOrderCount, toUnderlineCase(ProductStatisticsDO::getOrderCount))
.selectSum(ProductStatisticsDO::getOrderPayCount, toUnderlineCase(ProductStatisticsDO::getOrderPayCount))
.selectSum(ProductStatisticsDO::getOrderPayPrice, toUnderlineCase(ProductStatisticsDO::getOrderPayPrice))
.selectSum(ProductStatisticsDO::getAfterSaleCount, toUnderlineCase(ProductStatisticsDO::getAfterSaleCount))
.selectSum(ProductStatisticsDO::getAfterSaleRefundPrice, toUnderlineCase(ProductStatisticsDO::getAfterSaleRefundPrice))
.selectAvg(ProductStatisticsDO::getBrowseConvertPercent, toUnderlineCase(ProductStatisticsDO::getBrowseConvertPercent));
}
/**

View File

@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.pay.service.wallet;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
@ -16,12 +18,14 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargePackageDO;
import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletRechargeMapper;
import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaOrderUploadShippingInfoReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -156,9 +160,8 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
@Async
public void sendWalletRechargerPaidMessage(Long payOrderId, PayWalletRechargeDO walletRecharge) {
// 1. 获得会员钱包信
// 1. 构建并发送模版消
PayWalletDO wallet = payWalletService.getWallet(walletRecharge.getWalletId());
// 2. 构建并发送模版消息
socialClientApi.sendWxaSubscribeMessage(new SocialWxaSubscribeMessageSendReqDTO()
.setUserId(wallet.getUserId()).setUserType(wallet.getUserType())
.setTemplateTitle(WXA_WALLET_RECHARGER_PAID)
@ -167,6 +170,23 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
.addMessage("amount2", fenToYuanStr(walletRecharge.getTotalPrice())) // 充值金额
.addMessage("time3", LocalDateTimeUtil.formatNormal(walletRecharge.getCreateTime())) // 充值时间
.addMessage("phrase4", "充值成功")); // 充值状态
// 2. 调用接口上传虚拟物品发货信息
// 注意只有微信小程序支付的订单才需要同步
PayOrderDO payOrder = payOrderService.getOrder(payOrderId);
if (ObjUtil.notEqual(payOrder.getChannelCode(), PayChannelEnum.WX_LITE.getCode())) {
return;
}
SocialWxaOrderUploadShippingInfoReqDTO reqDTO = new SocialWxaOrderUploadShippingInfoReqDTO()
.setTransactionId(payOrder.getChannelOrderNo())
.setOpenid(payOrder.getChannelUserId())
.setItemDesc(payOrder.getSubject())
.setLogisticsType(SocialWxaOrderUploadShippingInfoReqDTO.LOGISTICS_TYPE_VIRTUAL); // 虚拟物品发货类型
try {
socialClientApi.uploadWxaOrderShippingInfo(UserTypeEnum.MEMBER.getValue(), reqDTO);
} catch (Exception ex) {
log.error("[sendWalletRechargerPaidMessage][订单({}) 上传订单物流信息到微信小程序失败]", payOrder, ex);
}
}
@Override

View File

@ -58,11 +58,20 @@ public class DictDataController {
@Operation(summary = "删除字典数据")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dict:delete')")
public CommonResult<Boolean> deleteDictData(Long id) {
public CommonResult<Boolean> deleteDictData(@RequestParam("id") Long id) {
dictDataService.deleteDictData(id);
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除字典数据")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:dict:delete')")
public CommonResult<Boolean> deleteDictDataList(@RequestParam("ids") List<Long> ids) {
dictDataService.deleteDictDataList(ids);
return success(true);
}
@GetMapping(value = {"/list-all-simple", "simple-list"})
@Operation(summary = "获得全部字典数据列表", description = "一般用于管理后台缓存字典数据在本地")
// 无需添加权限认证因为前端全局都需要
@ -73,7 +82,7 @@ public class DictDataController {
}
@GetMapping("/page")
@Operation(summary = "/获得字典类型的分页列表")
@Operation(summary = "获得字典类型的分页")
@PreAuthorize("@ss.hasPermission('system:dict:query')")
public CommonResult<PageResult<DictDataRespVO>> getDictTypePage(@Valid DictDataPageReqVO pageReqVO) {
PageResult<DictDataDO> pageResult = dictDataService.getDictDataPage(pageReqVO);

View File

@ -62,6 +62,15 @@ public class DictTypeController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除字典类型")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:dict:delete')")
public CommonResult<Boolean> deleteDictTypeList(@RequestParam("ids") List<Long> ids) {
dictTypeService.deleteDictTypeList(ids);
return success(true);
}
@GetMapping("/page")
@Operation(summary = "获得字典类型的分页列表")
@PreAuthorize("@ss.hasPermission('system:dict:query')")

View File

@ -13,11 +13,11 @@ import cn.iocoder.yudao.module.system.service.mail.MailAccountService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -54,6 +54,15 @@ public class MailAccountController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除邮箱账号")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:mail-account:delete')")
public CommonResult<Boolean> deleteMailAccountList(@RequestParam("ids") List<Long> ids) {
mailAccountService.deleteMailAccountList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得邮箱账号")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -10,11 +10,11 @@ import cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -54,6 +54,15 @@ public class MailTemplateController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除邮件模版")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:mail-template:delete')")
public CommonResult<Boolean> deleteMailTemplateList(@RequestParam("ids") List<Long> ids) {
mailTempleService.deleteMailTemplateList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得邮件模版")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -14,12 +14,13 @@ import cn.iocoder.yudao.module.system.service.notice.NoticeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -60,6 +61,15 @@ public class NoticeController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除通知公告")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:notice:delete')")
public CommonResult<Boolean> deleteNoticeList(@RequestParam("ids") List<Long> ids) {
noticeService.deleteNoticeList(ids);
return success(true);
}
@GetMapping("/page")
@Operation(summary = "获取通知公告列表")
@PreAuthorize("@ss.hasPermission('system:notice:query')")

View File

@ -4,19 +4,23 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.*;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSendReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
import cn.iocoder.yudao.module.system.service.notify.NotifySendService;
import cn.iocoder.yudao.module.system.service.notify.NotifyTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -56,6 +60,15 @@ public class NotifyTemplateController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除站内信模版")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:notify-template:delete')")
public CommonResult<Boolean> deleteNotifyTemplateList(@RequestParam("ids") List<Long> ids) {
notifyTemplateService.deleteNotifyTemplateList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得站内信模版")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -11,12 +11,13 @@ import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -53,6 +54,15 @@ public class OAuth2ClientController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除 OAuth2 客户端")
@PreAuthorize("@ss.hasPermission('system:oauth2-client:delete')")
public CommonResult<Boolean> deleteOAuth2ClientList(@RequestParam("ids") List<Long> ids) {
oAuth2ClientService.deleteOAuth2ClientList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得 OAuth2 客户端")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -12,11 +12,12 @@ import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -47,4 +48,14 @@ public class OAuth2TokenController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除访问令牌")
@Parameter(name = "accessTokens", description = "访问令牌数组", required = true)
@PreAuthorize("@ss.hasPermission('system:oauth2-token:delete')")
public CommonResult<Boolean> deleteAccessTokenList(@RequestParam("accessTokens") List<String> accessTokens) {
accessTokens.forEach(accessToken ->
authService.logout(accessToken, LoginLogTypeEnum.LOGOUT_DELETE.getType()));
return success(true);
}
}

View File

@ -12,12 +12,12 @@ import cn.iocoder.yudao.module.system.service.permission.MenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.Comparator;
import java.util.List;
@ -57,6 +57,15 @@ public class MenuController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除菜单")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:menu:delete')")
public CommonResult<Boolean> deleteMenuList(@RequestParam("ids") List<Long> ids) {
menuService.deleteMenuList(ids);
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面")
@PreAuthorize("@ss.hasPermission('system:menu:query')")

View File

@ -7,7 +7,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleRespVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import io.swagger.v3.oas.annotations.Operation;
@ -61,6 +63,15 @@ public class RoleController {
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除角色")
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('system:role:delete')")
public CommonResult<Boolean> deleteRoleList(@RequestParam("ids") List<Long> ids) {
roleService.deleteRoleList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得角色信息")
@PreAuthorize("@ss.hasPermission('system:role:query')")

View File

@ -12,11 +12,11 @@ import cn.iocoder.yudao.module.system.service.sms.SmsChannelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.Comparator;
import java.util.List;
@ -54,6 +54,15 @@ public class SmsChannelController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除短信渠道")
@PreAuthorize("@ss.hasPermission('system:sms-channel:delete')")
public CommonResult<Boolean> deleteSmsChannelList(@RequestParam("ids") List<Long> ids) {
smsChannelService.deleteSmsChannelList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得短信渠道")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -1,24 +1,27 @@
package cn.iocoder.yudao.module.system.controller.admin.sms;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.*;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService;
import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@ -59,6 +62,15 @@ public class SmsTemplateController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除短信模板")
@PreAuthorize("@ss.hasPermission('system:sms-template:delete')")
public CommonResult<Boolean> deleteSmsTemplateList(@RequestParam("ids") List<Long> ids) {
smsTemplateService.deleteSmsTemplateList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得短信模板")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -19,6 +19,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 社交客户端")
@ -56,6 +58,15 @@ public class SocialClientController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除社交客户端")
@PreAuthorize("@ss.hasPermission('system:social-client:delete')")
public CommonResult<Boolean> deleteSocialClientList(@RequestParam("ids") List<Long> ids) {
socialClientService.deleteSocialClientList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得社交客户端")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -95,6 +95,15 @@ public class TenantController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除租户")
@PreAuthorize("@ss.hasPermission('system:tenant:delete')")
public CommonResult<Boolean> deleteTenantList(@RequestParam("ids") List<Long> ids) {
tenantService.deleteTenantList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得租户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -4,18 +4,21 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.*;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageRespVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSimpleRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
import cn.iocoder.yudao.module.system.service.tenant.TenantPackageService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -53,6 +56,15 @@ public class TenantPackageController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除租户套餐")
@PreAuthorize("@ss.hasPermission('system:tenant-package:delete')")
public CommonResult<Boolean> deleteTenantPackageList(@RequestParam("ids") List<Long> ids) {
tenantPackageService.deleteTenantPackageList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得租户套餐")
@Parameter(name = "id", description = "编号", required = true, example = "1024")

View File

@ -71,6 +71,15 @@ public class UserController {
return success(true);
}
@DeleteMapping("/delete-list")
@Parameter(name = "ids", description = "编号列表", required = true)
@Operation(summary = "批量删除用户")
@PreAuthorize("@ss.hasPermission('system:user:delete')")
public CommonResult<Boolean> deleteUserList(@RequestParam("ids") List<Long> ids) {
userService.deleteUserList(ids);
return success(true);
}
@PutMapping("/update-password")
@Operation(summary = "重置用户密码")
@PreAuthorize("@ss.hasPermission('system:user:update-password')")

View File

@ -38,6 +38,13 @@ public interface PostService {
*/
void deletePost(Long id);
/**
* 批量删除岗位信息
*
* @param ids 岗位编号数组
*/
void deletePostList(List<Long> ids);
/**
* 获得岗位列表
*

View File

@ -8,10 +8,10 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqV
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.PostMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -58,10 +58,15 @@ public class PostServiceImpl implements PostService {
public void deletePost(Long id) {
// 校验是否存在
validatePostExists(id);
// 删除部门
// 删除岗位
postMapper.deleteById(id);
}
@Override
public void deletePostList(List<Long> ids) {
postMapper.deleteByIds(ids);
}
private void validatePostForCreateOrUpdate(Long id, String name, String code) {
// 校验自己存在
validatePostExists(id);

View File

@ -38,6 +38,13 @@ public interface DictDataService {
*/
void deleteDictData(Long id);
/**
* 批量删除字典数据
*
* @param ids 字典数据编号列表
*/
void deleteDictDataList(List<Long> ids);
/**
* 获得字典数据列表
*

View File

@ -98,6 +98,11 @@ public class DictDataServiceImpl implements DictDataService {
dictDataMapper.deleteById(id);
}
@Override
public void deleteDictDataList(List<Long> ids) {
dictDataMapper.deleteByIds(ids);
}
@Override
public long getDictDataCountByDictType(String dictType) {
return dictDataMapper.selectCountByDictType(dictType);

View File

@ -36,6 +36,13 @@ public interface DictTypeService {
*/
void deleteDictType(Long id);
/**
* 批量删除字典类型
*
* @param ids 字典类型编号列表
*/
void deleteDictTypeList(List<Long> ids);
/**
* 获得字典类型分页列表
*

View File

@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSave
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
@ -87,6 +87,21 @@ public class DictTypeServiceImpl implements DictTypeService {
dictTypeMapper.updateToDelete(id, LocalDateTime.now());
}
@Override
public void deleteDictTypeList(List<Long> ids) {
// 1. 校验是否有字典数据
List<DictTypeDO> dictTypes = dictTypeMapper.selectByIds(ids);
dictTypes.forEach(dictType -> {
if (dictDataService.getDictDataCountByDictType(dictType.getType()) > 0) {
throw exception(DICT_TYPE_HAS_CHILDREN);
}
});
// 2. 批量删除字典类型
LocalDateTime now = LocalDateTime.now();
ids.forEach(id -> dictTypeMapper.updateToDelete(id, now));
}
@Override
public List<DictTypeDO> getDictTypeList() {
return dictTypeMapper.selectList();

View File

@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import jakarta.validation.Valid;
import java.util.List;
/**
@ -38,6 +38,13 @@ public interface MailAccountService {
*/
void deleteMailAccount(Long id);
/**
* 批量删除邮箱账号
*
* @param ids 编号列表
*/
void deleteMailAccountList(List<Long> ids);
/**
* 获取邮箱账号信息
*

View File

@ -7,13 +7,13 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -69,6 +69,21 @@ public class MailAccountServiceImpl implements MailAccountService {
mailAccountMapper.deleteById(id);
}
@Override
@CacheEvict(value = RedisKeyConstants.MAIL_ACCOUNT,
allEntries = true) // allEntries 清空所有缓存因为 Spring Cache 不支持按照 ids 批量删除
public void deleteMailAccountList(List<Long> ids) {
// 1. 校验是否存在关联模版
for (Long id : ids) {
if (mailTemplateService.getMailTemplateCountByAccountId(id) > 0) {
throw exception(MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS);
}
}
// 2. 批量删除
mailAccountMapper.deleteByIds(ids);
}
private void validateMailAccountExists(Long id) {
if (mailAccountMapper.selectById(id) == null) {
throw exception(MAIL_ACCOUNT_NOT_EXISTS);

View File

@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
@ -39,6 +39,13 @@ public interface MailTemplateService {
*/
void deleteMailTemplate(Long id);
/**
* 批量删除邮件模版
*
* @param ids 编号列表
*/
void deleteMailTemplateList(List<Long> ids);
/**
* 获取邮件模版
*

View File

@ -11,14 +11,14 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@ -97,6 +97,13 @@ public class MailTemplateServiceImpl implements MailTemplateService {
mailTemplateMapper.deleteById(id);
}
@Override
@CacheEvict(cacheNames = RedisKeyConstants.MAIL_TEMPLATE,
allEntries = true) // allEntries 清空所有缓存因为 id 不是直接的缓存 code不好清理
public void deleteMailTemplateList(List<Long> ids) {
mailTemplateMapper.deleteByIds(ids);
}
private void validateMailTemplateExists(Long id) {
if (mailTemplateMapper.selectById(id) == null) {
throw exception(MAIL_TEMPLATE_NOT_EXISTS);
@ -125,14 +132,19 @@ public class MailTemplateServiceImpl implements MailTemplateService {
return StrUtil.format(content, params);
}
@VisibleForTesting
public List<String> parseTemplateContentParams(String content) {
return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
}
@Override
public long getMailTemplateCountByAccountId(Long accountId) {
return mailTemplateMapper.selectCountByAccountId(accountId);
}
/**
* 获得邮件模板中的参数形如 {key}
*
* @param content 内容
* @return 参数列表
*/
private List<String> parseTemplateContentParams(String content) {
return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
}
}

View File

@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO
import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO;
import java.util.List;
/**
* 通知公告 Service 接口
*/
@ -32,6 +34,13 @@ public interface NoticeService {
*/
void deleteNotice(Long id);
/**
* 批量删除通知公告
*
* @param ids 编号列表
*/
void deleteNoticeList(List<Long> ids);
/**
* 获得通知公告分页列表
*

View File

@ -7,9 +7,10 @@ import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO
import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO;
import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND;
@ -49,6 +50,11 @@ public class NoticeServiceImpl implements NoticeService {
noticeMapper.deleteById(id);
}
@Override
public void deleteNoticeList(List<Long> ids) {
noticeMapper.deleteByIds(ids);
}
@Override
public PageResult<NoticeDO> getNoticePage(NoticePageReqVO reqVO) {
return noticeMapper.selectPage(reqVO);

View File

@ -4,8 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
/**
@ -37,6 +38,13 @@ public interface NotifyTemplateService {
*/
void deleteNotifyTemplate(Long id);
/**
* 批量删除站内信模版
*
* @param ids 编号列表
*/
void deleteNotifyTemplateList(List<Long> ids);
/**
* 获得站内信模版
*

View File

@ -10,13 +10,13 @@ import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@ -85,6 +85,13 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
notifyTemplateMapper.deleteById(id);
}
@Override
@CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE,
allEntries = true) // allEntries 清空所有缓存因为 id 不是直接的缓存 code不好清理
public void deleteNotifyTemplateList(List<Long> ids) {
notifyTemplateMapper.deleteByIds(ids);
}
private void validateNotifyTemplateExists(Long id) {
if (notifyTemplateMapper.selectById(id) == null) {
throw exception(NOTIFY_TEMPLATE_NOT_EXISTS);

View File

@ -4,9 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import jakarta.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* OAuth2.0 Client Service 接口
@ -39,6 +40,13 @@ public interface OAuth2ClientService {
*/
void deleteOAuth2Client(Long id);
/**
* 批量删除 OAuth2 客户端
*
* @param ids 编号数组
*/
void deleteOAuth2ClientList(List<Long> ids);
/**
* 获得 OAuth2 客户端
*

View File

@ -14,14 +14,15 @@ import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@ -72,6 +73,13 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
oauth2ClientMapper.deleteById(id);
}
@Override
@CacheEvict(cacheNames = RedisKeyConstants.OAUTH_CLIENT,
allEntries = true) // allEntries 清空所有缓存因为 id 不是直接的缓存 key不好清理
public void deleteOAuth2ClientList(List<Long> ids) {
oauth2ClientMapper.deleteByIds(ids);
}
private void validateOAuth2ClientExists(Long id) {
if (oauth2ClientMapper.selectById(id) == null) {
throw exception(OAUTH2_CLIENT_NOT_EXISTS);

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.system.service.permission;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import java.util.Collection;
@ -36,6 +36,13 @@ public interface MenuService {
*/
void deleteMenu(Long id);
/**
* 批量删除菜单
*
* @param ids 菜单编号数组
*/
void deleteMenuList(List<Long> ids);
/**
* 获得所有菜单列表
*

View File

@ -104,6 +104,24 @@ public class MenuServiceImpl implements MenuService {
permissionService.processMenuDeleted(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST,
allEntries = true) // allEntries 清空所有缓存因为 Spring Cache 不支持按照 ids 批量删除
public void deleteMenuList(List<Long> ids) {
// 校验是否还有子菜单
ids.forEach(id -> {
if (menuMapper.selectCountByParentId(id) > 0) {
throw exception(MENU_EXISTS_CHILDREN);
}
});
// 标记删除
menuMapper.deleteByIds(ids);
// 删除授予给角色的权限
ids.forEach(id -> permissionService.processMenuDeleted(id));
}
@Override
public List<MenuDO> getMenuList() {
return menuMapper.selectList();

View File

@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import jakarta.validation.Valid;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@ -40,6 +40,13 @@ public interface RoleService {
*/
void deleteRole(Long id);
/**
* 批量删除角色
*
* @param ids 角色编号数组
*/
void deleteRoleList(List<Long> ids);
/**
* 设置角色的数据权限
*

View File

@ -122,6 +122,18 @@ public class RoleServiceImpl implements RoleService {
LogRecordContext.putVariable("role", role);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteRoleList(List<Long> ids) {
// 1. 校验是否可以删除
ids.forEach(this::validateRoleForUpdate);
// 2.1 标记删除
roleMapper.deleteByIds(ids);
// 2.2 删除相关数据
ids.forEach(id -> permissionService.processRoleDeleted(id));
}
/**
* 校验角色的唯一字段是否重复
*

View File

@ -1,12 +1,12 @@
package cn.iocoder.yudao.module.system.service.sms;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import jakarta.validation.Valid;
import java.util.List;
/**
@ -39,6 +39,13 @@ public interface SmsChannelService {
*/
void deleteSmsChannel(Long id);
/**
* 批量删除短信渠道
*
* @param ids 编号数组
*/
void deleteSmsChannelList(List<Long> ids);
/**
* 获得短信渠道
*

View File

@ -65,6 +65,19 @@ public class SmsChannelServiceImpl implements SmsChannelService {
smsChannelMapper.deleteById(id);
}
@Override
public void deleteSmsChannelList(List<Long> ids) {
// 1. 校验是否有在使用该账号的模版
ids.forEach(id -> {
if (smsTemplateService.getSmsTemplateCountByChannelId(id) > 0) {
throw exception(SMS_CHANNEL_HAS_CHILDREN);
}
});
// 2. 批量删除
smsChannelMapper.deleteByIds(ids);
}
private SmsChannelDO validateSmsChannelExists(Long id) {
SmsChannelDO channel = smsChannelMapper.selectById(id);
if (channel == null) {

View File

@ -4,8 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
/**
@ -38,6 +39,13 @@ public interface SmsTemplateService {
*/
void deleteSmsTemplate(Long id);
/**
* 批量删除短信模板
*
* @param ids 编号数组
*/
void deleteSmsTemplateList(List<Long> ids);
/**
* 获得短信模板
*

View File

@ -7,22 +7,22 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -100,6 +100,13 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
smsTemplateMapper.deleteById(id);
}
@Override
@CacheEvict(cacheNames = RedisKeyConstants.SMS_TEMPLATE,
allEntries = true) // allEntries 清空所有缓存因为 id 不是直接的缓存 code不好清理
public void deleteSmsTemplateList(List<Long> ids) {
smsTemplateMapper.deleteByIds(ids);
}
private void validateSmsTemplateExists(Long id) {
if (smsTemplateMapper.selectById(id) == null) {
throw exception(SMS_TEMPLATE_NOT_EXISTS);

View File

@ -134,6 +134,13 @@ public interface SocialClientService {
*/
void deleteSocialClient(Long id);
/**
* 批量删除社交客户端
*
* @param ids 编号数组
*/
void deleteSocialClientList(List<Long> ids);
/**
* 获得社交客户端
*

View File

@ -68,6 +68,7 @@ import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.UTC_MS_WITH_XXX_OFFSET_FORMATTER;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.toEpochSecond;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static java.util.Collections.singletonList;
@ -379,7 +380,7 @@ public class SocialClientServiceImpl implements SocialClientService {
WxMaService service = getWxMaService(userType);
WxMaOrderShippingInfoNotifyConfirmRequest request = WxMaOrderShippingInfoNotifyConfirmRequest.builder()
.transactionId(reqDTO.getTransactionId())
.receivedTime(LocalDateTimeUtil.toEpochMilli(reqDTO.getReceivedTime()))
.receivedTime(toEpochSecond(reqDTO.getReceivedTime()))
.build();
try {
WxMaOrderShippingInfoBaseResponse response = service.getWxMaOrderShippingService().notifyConfirmReceive(request);
@ -466,6 +467,11 @@ public class SocialClientServiceImpl implements SocialClientService {
socialClientMapper.deleteById(id);
}
@Override
public void deleteSocialClientList(List<Long> ids) {
socialClientMapper.deleteByIds(ids);
}
private void validateSocialClientExists(Long id) {
if (socialClientMapper.selectById(id) == null) {
throw exception(SOCIAL_CLIENT_NOT_EXISTS);

View File

@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
import jakarta.validation.Valid;
import java.util.List;
/**
@ -37,6 +37,13 @@ public interface TenantPackageService {
*/
void deleteTenantPackage(Long id);
/**
* 批量删除租户套餐
*
* @param ids 编号数组
*/
void deleteTenantPackageList(List<Long> ids);
/**
* 获得租户套餐
*

View File

@ -12,11 +12,11 @@ import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -76,6 +76,19 @@ public class TenantPackageServiceImpl implements TenantPackageService {
tenantPackageMapper.deleteById(id);
}
@Override
public void deleteTenantPackageList(List<Long> ids) {
// 1. 校验是否有租户正在使用该套餐
for (Long id : ids) {
if (tenantService.getTenantCountByPackageId(id) > 0) {
throw exception(TENANT_PACKAGE_USED);
}
}
// 2. 批量删除
tenantPackageMapper.deleteByIds(ids);
}
private TenantPackageDO validateTenantPackageExists(Long id) {
TenantPackageDO tenantPackage = tenantPackageMapper.selectById(id);
if (tenantPackage == null) {

View File

@ -7,8 +7,8 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSa
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Set;
@ -49,6 +49,13 @@ public interface TenantService {
*/
void deleteTenant(Long id);
/**
* 批量删除租户
*
* @param ids 编号数组
*/
void deleteTenantList(List<Long> ids);
/**
* 获得租户
*

View File

@ -31,13 +31,13 @@ import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@ -225,6 +225,15 @@ public class TenantServiceImpl implements TenantService {
tenantMapper.deleteById(id);
}
@Override
public void deleteTenantList(List<Long> ids) {
// 1. 校验存在
ids.forEach(this::validateUpdateTenant);
// 2. 批量删除
tenantMapper.deleteByIds(ids);
}
private TenantDO validateUpdateTenant(Long id) {
TenantDO tenant = tenantMapper.selectById(id);
if (tenant == null) {

View File

@ -95,6 +95,13 @@ public interface AdminUserService {
*/
void deleteUser(Long id);
/**
* 批量删除用户
*
* @param ids 用户编号数组
*/
void deleteUserList(List<Long> ids);
/**
* 通过用户名查询用户
*

View File

@ -248,6 +248,19 @@ public class AdminUserServiceImpl implements AdminUserService {
LogRecordContext.putVariable("user", user);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteUserList(List<Long> ids) {
// 1. 批量删除用户
userMapper.deleteByIds(ids);
// 2. 批量删除用户关联数据
ids.forEach(id -> {
permissionService.processUserDeleted(id);
userPostMapper.deleteByUserId(id);
});
}
@Override
public AdminUserDO getUserByUsername(String username) {
return userMapper.selectByUsername(username);

View File

@ -138,7 +138,6 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>