diff --git a/src/main/java/com/yunhai/dormnotice/config/DictSeedRunner.java b/src/main/java/com/yunhai/dormnotice/config/DictSeedRunner.java
deleted file mode 100644
index af7c32e..0000000
--- a/src/main/java/com/yunhai/dormnotice/config/DictSeedRunner.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.yunhai.dormnotice.config;
-
-import com.yunhai.dormnotice.entity.SysDict;
-import com.yunhai.dormnotice.repository.SysDictRepository;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-
-/**
- * 字典自举种子:启动时若 sys_dict 缺 dept / noticeType 则补入默认口径(幂等,仅在为空时插)。
- *
解决「发布部门/通知类型下拉为空」——不依赖 DBA 手动跑 dormnotice_init.sql。
- * 生产可用 {@code dormnotice.seed-dict=false} 关闭。
- */
-@Component
-public class DictSeedRunner implements ApplicationRunner {
-
- private static final Logger log = LoggerFactory.getLogger(DictSeedRunner.class);
-
- private static final String[][] DEPTS = {
- {"D001", "校办"}, {"D002", "德育处"}, {"D003", "生活管理科"}, {"D004", "教务处"},
- {"D005", "后勤保障部"}, {"D006", "校医务室"}, {"D007", "武术训练部"}, {"D008", "安全管理办公室"},
- };
- private static final String[][] NOTICE_TYPES = {
- {"T001", "作息调整"}, {"T002", "宿舍调整"}, {"T003", "卫生检查"}, {"T004", "违规通报"},
- {"T005", "停水停电"}, {"T006", "安全排查"}, {"T007", "留宿申请"}, {"T008", "家长探视"},
- {"T009", "夜间查寝"}, {"T010", "物品清退"}, {"T011", "疫情防控"}, {"T012", "假期安排"}, {"T013", "其他"},
- };
-
- @Autowired
- private SysDictRepository sysDictRepository;
-
- @Value("${dormnotice.seed-dict:true}")
- private boolean enabled;
-
- @Override
- @Transactional
- public void run(ApplicationArguments args) {
- if (!enabled) {
- return;
- }
- seed("dept", DEPTS);
- seed("noticeType", NOTICE_TYPES);
- }
-
- private void seed(String type, String[][] items) {
- List existing = sysDictRepository.findByDictTypeOrderBySortOrderAsc(type);
- if (!existing.isEmpty()) {
- log.info("[DictSeed] 字典 {} 已有 {} 条,跳过种子", type, existing.size());
- return;
- }
- int order = 1;
- for (String[] it : items) {
- SysDict d = new SysDict();
- d.setDictType(type);
- d.setDictKey(it[0]);
- d.setDictValue(it[1]);
- d.setSortOrder(order++);
- d.setEnableFlag(1);
- sysDictRepository.save(d);
- }
- log.info("[DictSeed] 字典 {} 已种入 {} 条", type, items.length);
- }
-}
diff --git a/src/main/java/com/yunhai/dormnotice/entity/SysDict.java b/src/main/java/com/yunhai/dormnotice/entity/SysDict.java
index 620d93a..8e523bc 100644
--- a/src/main/java/com/yunhai/dormnotice/entity/SysDict.java
+++ b/src/main/java/com/yunhai/dormnotice/entity/SysDict.java
@@ -9,7 +9,7 @@ import javax.persistence.Entity;
import javax.persistence.Table;
/**
- * 系统字典(发文部门等)。对应原 .NET Common_DeptDic 表。
+ * 系统字典(发文部门 / 通知类型)。按学校隔离(sch_id),对应原 .NET Common_DeptDic 表。
*/
@NoArgsConstructor
@Data
@@ -18,7 +18,7 @@ import javax.persistence.Table;
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class SysDict extends BaseEntity {
- /** 字典类型(如 "dept"=发文部门) */
+ /** 字典类型("dept"=发文部门 / "noticeType"=通知类型) */
@Column(name = "dict_type", length = 50)
private String dictType;
@@ -37,4 +37,8 @@ public class SysDict extends BaseEntity {
/** 是否启用:0 禁用 / 1 启用(原 Enable) */
@Column(name = "enable_flag")
private Integer enableFlag = 1;
+
+ /** 学校ID(多租户隔离;发布/查询按当前学校过滤) */
+ @Column(name = "sch_id")
+ private Integer schId;
}
diff --git a/src/main/java/com/yunhai/dormnotice/repository/SysDictRepository.java b/src/main/java/com/yunhai/dormnotice/repository/SysDictRepository.java
index dceff6b..2437ca2 100644
--- a/src/main/java/com/yunhai/dormnotice/repository/SysDictRepository.java
+++ b/src/main/java/com/yunhai/dormnotice/repository/SysDictRepository.java
@@ -12,4 +12,11 @@ public interface SysDictRepository extends JpaRepository {
/** 按类型+key 取单条字典(发文部门名称解析用) */
Optional findByDictTypeAndDictKey(String dictType, String dictKey);
+
+ /** 学校隔离:按 schId + 类型 查询(schId 传 null 命中 sch_id IS NULL) */
+ List findBySchIdAndDictTypeOrderBySortOrderAsc(Integer schId, String dictType);
+
+ List findBySchIdAndDictTypeAndEnableFlagOrderBySortOrderAsc(Integer schId, String dictType, Integer enableFlag);
+
+ Optional findBySchIdAndDictTypeAndDictKey(Integer schId, String dictType, String dictKey);
}
diff --git a/src/main/java/com/yunhai/dormnotice/service/impl/DictService.java b/src/main/java/com/yunhai/dormnotice/service/impl/DictService.java
index 71c4de9..eb1b5a8 100644
--- a/src/main/java/com/yunhai/dormnotice/service/impl/DictService.java
+++ b/src/main/java/com/yunhai/dormnotice/service/impl/DictService.java
@@ -3,6 +3,7 @@ package com.yunhai.dormnotice.service.impl;
import com.yunhai.dormnotice.entity.SysDict;
import com.yunhai.dormnotice.repository.SysDictRepository;
import com.yunhai.dormnotice.service.IDictService;
+import com.yunhai.dormnotice.utils.UserContext;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.utils.exception.ErrorCode;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,7 +20,8 @@ import java.util.stream.Collectors;
/**
* 系统字典服务(宿舍通知版)。type 维度:dept 发布部门 / noticeType 通知类型。
- * dict_key 存 CodeID(D001/T001…),dict_value 存展示名(Name)。
+ * 按学校隔离(sys_dict.sch_id):读写均限当前 {@link UserContext#getSchId()};
+ * 某校首次访问某类型且为空时,惰性种入默认口径(部门 8 / 类型 13),各校独立可增删改。
*/
@Service
public class DictService implements IDictService {
@@ -27,9 +29,24 @@ public class DictService implements IDictService {
private static final String DEPT = "dept";
private static final String NOTICE_TYPE = "noticeType";
+ /** 默认种子(首次访问按学校惰性写入) */
+ private static final String[][] DEPT_SEED = {
+ {"D001", "校办"}, {"D002", "德育处"}, {"D003", "生活管理科"}, {"D004", "教务处"},
+ {"D005", "后勤保障部"}, {"D006", "校医务室"}, {"D007", "武术训练部"}, {"D008", "安全管理办公室"},
+ };
+ private static final String[][] NOTICE_TYPE_SEED = {
+ {"T001", "作息调整"}, {"T002", "宿舍调整"}, {"T003", "卫生检查"}, {"T004", "违规通报"},
+ {"T005", "停水停电"}, {"T006", "安全排查"}, {"T007", "留宿申请"}, {"T008", "家长探视"},
+ {"T009", "夜间查寝"}, {"T010", "物品清退"}, {"T011", "疫情防控"}, {"T012", "假期安排"}, {"T013", "其他"},
+ };
+
@Autowired
private SysDictRepository sysDictRepository;
+ private Integer currentSchId() {
+ return UserContext.getSchId();
+ }
+
private String normalizeType(String type) {
if (!StringUtils.hasText(type)) {
return NOTICE_TYPE;
@@ -41,12 +58,34 @@ public class DictService implements IDictService {
return DEPT.equals(type) ? "D" : "T";
}
+ /** 首次访问某校某类型且为空时,种入默认口径(幂等,按 schId)。 */
+ @Transactional
+ public void ensureSeeded(Integer schId, String type) {
+ if (!sysDictRepository.findBySchIdAndDictTypeOrderBySortOrderAsc(schId, type).isEmpty()) {
+ return;
+ }
+ String[][] seed = DEPT.equals(type) ? DEPT_SEED : NOTICE_TYPE_SEED;
+ int order = 1;
+ for (String[] it : seed) {
+ SysDict d = new SysDict();
+ d.setDictType(type);
+ d.setDictKey(it[0]);
+ d.setDictValue(it[1]);
+ d.setSortOrder(order++);
+ d.setEnableFlag(1);
+ d.setSchId(schId);
+ sysDictRepository.save(d);
+ }
+ }
+
// ============================ List(下拉) ============================
@Override
public List