更新数字基座
build / build-push (push) Successful in 1m3s

This commit is contained in:
chenxing
2026-08-24 09:29:31 +08:00
parent 4ed43dbc05
commit a7539a4cf0
48 changed files with 2983 additions and 3 deletions
@@ -0,0 +1,92 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.entity.MenuBar;
import com.yunhai.userhome.entity.UserCurrentRole;
import com.yunhai.userhome.service.IMenuBarService;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/**
* 菜单栏控制器(对齐旧 UserHome contorller.api.MenuBarController)。
*/
@RestController
@RequestMapping(Config.API_PATH)
public class MenuBarController {
@Autowired
private IMenuBarService menuBarService;
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@GetMapping("getMenuBarSchList")
public List<MenuBar> getMenuBarSchList(BoaUser authUserWithDept) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
return menuBarService.getMenuBarList(userCurrentRole.getSchId());
}
@GetMapping("getMenuBarList")
public List<Map> getMenuBarList(BoaUser authUserWithDept) {
List<Map> result = new ArrayList<>();
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
Integer roleId = userCurrentRole.getRoleId();
if (roleId == 7 || roleId == 2) roleId = 2;
Boolean isSuperAdmin = authUserWithDept.getType() == 1;
List<MenuBar> list = menuBarService.findMenuBarById(authUserWithDept.getId());
for (MenuBar model : list) {
Map map = new HashMap();
if (!isSuperAdmin && !model.getRoleIds().contains(roleId)) continue;
map.put("id", model.getId());
map.put("name", model.getName());
map.put("url", model.getUrl());
map.put("icon", model.getIcon());
map.put("isNative", model.getIsNative());
map.put("isHeader", model.getIsHeader());
map.put("isBottom", model.getIsBottom());
map.put("orderNum", model.getOrderNum());
map.put("openType", model.getLinkOpenType());
result.add(map);
}
return result;
}
@PostMapping(value = "saveMenuBar", produces = "application/json")
public void saveMenuBar(BoaUser authUserWithDept, @RequestBody MenuBar menuBar) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
menuBar.setCId(authUserWithDept.getId());
menuBar.setSchId(userCurrentRole.getSchId());
if (menuBar.getId() == null) menuBar.setCDate(new Date());
menuBarService.saveMenuBar(menuBar);
}
@PostMapping(value = "toggleMenuBarShow", produces = "application/json")
public void toggleMenuBarShow(BoaUser authUserWithDept, Integer id) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
menuBarService.toggleMenuBarShow(id, userCurrentRole.getSchId());
}
@PostMapping(value = "saveMenuBarOrderNum", produces = "application/json")
public void saveMenuBarOrderNum(BoaUser authUserWithDept, @RequestBody Map<String, Integer> params) {
Integer id = params.get("id"),
orderNum = params.get("orderNum");
menuBarService.saveMenuBarOrderNum(id, orderNum);
}
@PostMapping(value = "deleteMenuBar", produces = "application/json")
public void deleteMenuBar(BoaUser authUserWithDept, Integer id) {
menuBarService.deleteMenuBar(id);
}
}
@@ -0,0 +1,111 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.utils.model.BoaApp;
import com.yunhai.platform.utils.model.BoaAppType;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.entity.UserMessage;
import com.yunhai.userhome.service.AppRemoteService;
import com.yunhai.userhome.service.IUserMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* 消息中心接口(CAS 登录态,路径 {@code /{platform}/}),对齐旧 UserHome MessageController 契约。
* <p>响应字段与旧版 {@code getMessageByUserId} 完全一致:{id,msg,date,name,avatar,appPath,msgType}。</p>
*/
@RestController
@RequestMapping(value = Config.API_PATH)
public class MessageController {
@Autowired
private IUserMessageService userMessageService;
@Autowired
private AppRemoteService appRemoteService;
/** schId=0 时推断:主学校 → 主归属组(bureau)→ 0(对齐旧版 school.id→bureau.id→0)。 */
private Integer resolveSchId(BoaUser user) {
if (user.getSchool() != null) {
return user.getSchool().getId();
}
if (user.getBureau() != null) {
return user.getBureau().getId();
}
return 0;
}
private List<BoaApp> flattenApps(BoaUser user) {
List<BoaAppType> types = appRemoteService.getUserApps(user);
if (types == null) {
return new ArrayList<>();
}
List<BoaApp> apps = new ArrayList<>();
for (BoaAppType t : types) {
if (t.getApps() != null) {
apps.addAll(t.getApps());
}
}
return apps;
}
// 获取个人最近消息(对齐旧 getMessageByUserId,响应 List<Map>,字段逐字核对)
@GetMapping("getMessageByUserId")
public List<Map<String, Object>> getMessageByUserId(BoaUser authUserWithDept, Integer page, Integer count) {
Integer userId = authUserWithDept.getId();
Integer schId = resolveSchId(authUserWithDept);
List<UserMessage> msgList = userMessageService.findUserMessageByUserId(userId);
Collections.reverse(msgList);
List<BoaApp> appList = flattenApps(authUserWithDept);
List<Map<String, Object>> list = new ArrayList<>();
for (UserMessage msg : msgList) {
Optional<BoaApp> boaApp = appList.stream().filter(x -> x.getId() != null && x.getId().equals(msg.getAppId())).findFirst();
if (!boaApp.isPresent()) {
continue;
}
BoaApp model = boaApp.get();
Map<String, Object> map = new HashMap<>();
map.put("id", msg.getId());
map.put("msg", msg.getContent());
map.put("date", msg.getCDate());
map.put("name", model.getName());
map.put("avatar", model.getIcon());
map.put("appPath", model.getWebAddr());
map.put("msgType", model.getType());
list.add(map);
}
return list;
}
// 已读消息(对齐旧 readMessage,POST,参数 id,返回 void)
@PostMapping("readMessage")
public void readMessage(BoaUser authUserWithDept, Integer id) {
userMessageService.updateUserRead(id, authUserWithDept.getId());
}
// 全部已读消息(对齐旧 readMessageAll,POST 无参,返回 void)
@PostMapping("readMessageAll")
public void readMessageAll(BoaUser authUserWithDept) {
userMessageService.updateReadAll(authUserWithDept.getId());
}
// 是否有新消息(对齐旧 findUserMessageUnRead,GET,返回 Boolean)
@GetMapping("findUserMessageUnRead")
public Boolean findUserMessageUnRead(BoaUser authUserWithDept) {
return userMessageService.findUserMessageUnRead(authUserWithDept.getId());
}
}
@@ -0,0 +1,58 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.utils.OtherUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView;
import java.util.Map;
/**
* 承载旧后端 UserController 中挂在扁平路径 {@code /{platform}/} 下的端点。
*
* <p>新后端 UserController 已改为 {@code /{platform}/user/} 前缀,
* 但以下两个端点的前端调用路径是扁平的(不含 /user/ 段),故单独抽出:
* <ul>
* <li>{@code POST /api/updateUserPassword} — 前端 BaseApi.updatePassword</li>
* <li>{@code GET /api/RedirectTo/{hexUrl}} — 前端 bschSsoRedirect.replaceOriginUrl</li>
* </ul>
*/
@RestController
@RequestMapping(value = Config.API_PATH)
public class MiscController {
/**
* 修改用户密码(对齐旧 UserController.updateUserPassword)。
* 前端调用:BaseApi.updatePassword → POST /api/updateUserPassword
*/
@PostMapping("updateUserPassword")
public void updateUserPassword(BoaUser authUserWithDept, @RequestBody Map<String, String> params) {
String password = params.get("password");
String oldPassword = params.get("oldPassword");
if (password == null || password.trim().isEmpty() || oldPassword == null || oldPassword.trim().isEmpty()) {
throw new BizException(ErrorCode.PARAM_ERROR, "密码参数不能为空");
}
if (password.equals(oldPassword)) {
throw new BizException(ErrorCode.CUSTOM, "新密码不得与旧密码相同!");
}
try {
YschBaseOpenApi.updateUserPassword(authUserWithDept.getId(), oldPassword, password);
} catch (Exception e) {
throw new BizException(ErrorCode.CUSTOM, e.getMessage());
}
}
/**
* 十六进制 URL 重定向(对齐旧 UserController.RedirectTo)。
* 前端调用:bschSsoRedirect.replaceOriginUrl → GET /api/RedirectTo/{hexUrl}
*/
@GetMapping("RedirectTo/{id}")
public RedirectView redirectTo(@PathVariable(name = "id") String id) {
String url = OtherUtil.hexToString(id);
return new RedirectView(url, true);
}
}
@@ -0,0 +1,84 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.entity.SchSettings;
import com.yunhai.userhome.service.ISchSettingsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.Optional;
/**
* 学校设置接口(CAS 登录态,路径 {@code /{platform}/}),对齐旧 UserHome SchSettingsController。
* <p>getSchSettings 实际跨仓调用 schConfig(见 SchSettingsServiceImpl);
* saveSchTheme/saveSchLogo(P1)本期写入本地 sch_settings 表(跨仓回写可后续对接)。</p>
*/
@RestController
@RequestMapping(value = Config.API_PATH)
public class SchSettingsController {
@Autowired
private ISchSettingsService schSettingsService;
private Integer resolveSchId(BoaUser user) {
if (user.getSchool() != null) {
return user.getSchool().getId();
}
if (user.getBureau() != null) {
return user.getBureau().getId();
}
return 0;
}
@PostMapping("saveSchTheme")
public void saveSchTheme(BoaUser authUserWithDept, String themeName, @RequestParam(name = "schId", defaultValue = "0") Integer schId) {
if (schId == null || schId == 0) {
schId = resolveSchId(authUserWithDept);
}
SchSettings schSettings = new SchSettings();
Optional<SchSettings> model = schSettingsService.findBySchId(schId);
if (model.isPresent()) {
schSettings = model.get();
}
schSettings.setCDate(new Date());
schSettings.setSchId(schId);
schSettings.setCId(authUserWithDept.getId());
schSettings.setThemeName(themeName);
schSettingsService.save(schSettings);
}
@PostMapping("saveSchLogo")
public void saveSchLogo(BoaUser authUserWithDept, String logoUrl, @RequestParam(name = "schId", defaultValue = "0") Integer schId) {
if (schId == null || schId == 0) {
schId = resolveSchId(authUserWithDept);
}
SchSettings schSettings = newSchSettingsOrLoad(schId, authUserWithDept);
schSettings.setLogoUrl(logoUrl);
schSettingsService.save(schSettings);
}
/** getSchSettings:schId=0 时按 主学校→主归属组→0 推断(对齐旧 SchSettingsController)。 */
@GetMapping("getSchSettings")
public Optional<SchSettings> getSchSettings(BoaUser authUserWithDept,
@RequestParam(name = "schId", defaultValue = "0") Integer schId) {
if (schId == null || schId == 0) {
schId = resolveSchId(authUserWithDept);
}
return schSettingsService.findBySchId(schId);
}
private SchSettings newSchSettingsOrLoad(Integer schId, BoaUser user) {
Optional<SchSettings> model = schSettingsService.findBySchId(schId);
SchSettings schSettings = model.orElseGet(SchSettings::new);
schSettings.setCDate(new Date());
schSettings.setSchId(schId);
schSettings.setCId(user.getId());
return schSettings;
}
}
@@ -0,0 +1,33 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.utils.MapCacheUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
/**
* WebSocket 鉴权地址端点(CAS 登录态,路径 {@code /{platform}/})。
* <p>对齐旧 UserHome SocketController.getMsgAddress:生成 uuid → 缓存(uuid→userId, 20s) →
* 返回 {@code {WEBSOCKET_URL}/{uuid}},供前端握手阶段鉴权。WS 推送服务端本期可后置,
* 前端改轮询 {@code getMessageByUserId} 兜底刷新。</p>
*/
@RestController
@RequestMapping(value = Config.API_PATH)
public class SocketController {
@Value("${WEBSOCKET_URL:ws://localhost:8091/ws}")
private String websocketUrl;
@GetMapping("getMsgAddress")
public String getMsgAddress(BoaUser authUserWithDept) {
Integer uid = authUserWithDept.getId();
UUID uuid = UUID.randomUUID();
MapCacheUtil.getInstance().add(uuid.toString(), uid.toString(), 20 * 1000L);
return this.websocketUrl + "/" + uuid.toString();
}
}
@@ -0,0 +1,88 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.entity.StatsBar;
import com.yunhai.userhome.entity.UserCurrentRole;
import com.yunhai.userhome.service.IStatsBarService;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/**
* 统计栏目控制器(对齐旧 UserHome contorller.api.StatsBarController)。
*/
@RestController
@RequestMapping(Config.API_PATH)
public class StatsBarController {
@Autowired
private IStatsBarService statsBarService;
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@GetMapping("getStatsBarSchList")
public List<StatsBar> getStatsBarSchList(BoaUser authUserWithDept) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
return statsBarService.getStatsBarList(userCurrentRole.getSchId());
}
@GetMapping("getStatsBarList")
public List<Map> getStatsBarList(BoaUser authUserWithDept) {
List<Map> result = new ArrayList<>();
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
Integer roleId = userCurrentRole.getRoleId();
if (roleId == 7 || roleId == 2) roleId = 2;
Boolean isSuperAdmin = authUserWithDept.getType() == 1;
List<StatsBar> list = statsBarService.findStatsBarById(authUserWithDept.getId());
for (StatsBar model : list) {
Map map = new HashMap();
if (!isSuperAdmin && !model.getRoleIds().contains(roleId)) continue;
map.put("id", model.getId());
map.put("name", model.getName());
map.put("url", model.getUrl());
map.put("icon", model.getIcon());
map.put("openType", model.getLinkOpenType());
result.add(map);
}
return result;
}
@PostMapping(value = "saveStatsBar", produces = "application/json")
public void saveStatsBar(BoaUser authUserWithDept, @RequestBody StatsBar statsBar) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
statsBar.setCId(authUserWithDept.getId());
statsBar.setSchId(userCurrentRole.getSchId());
if (statsBar.getId() == null) statsBar.setCDate(new Date());
statsBarService.saveStatsBar(statsBar);
}
@PostMapping(value = "toggleStatsBarShow", produces = "application/json")
public void toggleStatsBarShow(BoaUser authUserWithDept, Integer id) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
statsBarService.toggleStatsBarShow(id, userCurrentRole.getSchId());
}
@PostMapping(value = "saveStatsBarOrderNum", produces = "application/json")
public void saveStatsBarOrderNum(BoaUser authUserWithDept, @RequestBody Map<String, Integer> params) {
Integer id = params.get("id"),
orderNum = params.get("orderNum");
statsBarService.saveStatsBarOrderNum(id, orderNum);
}
@PostMapping(value = "deleteStatsBar", produces = "application/json")
public void deleteStatsBar(BoaUser authUserWithDept, Integer id) {
statsBarService.deleteStatsBar(id);
}
}
@@ -0,0 +1,89 @@
package com.yunhai.userhome.controller.api;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.entity.TeacherCopilot;
import com.yunhai.userhome.entity.UserCurrentRole;
import com.yunhai.userhome.service.ITeacherCopilotService;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/**
* 教师助手控制器(对齐旧 UserHome contorller.api.TeacherCopilotController)。
*/
@RestController
@RequestMapping(Config.API_PATH)
public class TeacherCopilotController {
@Autowired
private ITeacherCopilotService teacherCopilotService;
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@GetMapping("TeacherCopilot/getSchList")
public List<TeacherCopilot> getList(BoaUser authUserWithDept) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
return teacherCopilotService.getList(userCurrentRole.getSchId());
}
@GetMapping("TeacherCopilot/getUserList")
public List<TeacherCopilot.Dto> getUserList(BoaUser authUserWithDept) {
List<TeacherCopilot.Dto> result = new ArrayList<>();
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
Integer roleId = userCurrentRole.getRoleId();
if (roleId == 7 || roleId == 2) roleId = 2;
Boolean isSuperAdmin = authUserWithDept.getType() == 1;
List<TeacherCopilot> list = teacherCopilotService.findById(authUserWithDept.getId());
for (TeacherCopilot model : list) {
TeacherCopilot.Dto dto = new TeacherCopilot.Dto();
if (!isSuperAdmin && !model.getRoleIds().contains(roleId)) continue;
dto.setId(model.getId());
dto.setName(model.getName());
dto.setUrl(model.getUrl());
dto.setIcon(model.getIcon());
dto.setOpenType(model.getLinkOpenType());
dto.setType(model.getType());
result.add(dto);
}
return result;
}
@PostMapping(value = "TeacherCopilot/save", produces = "application/json")
public void save(BoaUser authUserWithDept, @RequestBody TeacherCopilot teacherCopilot) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
teacherCopilot.setCId(authUserWithDept.getId());
teacherCopilot.setSchId(userCurrentRole.getSchId());
if (teacherCopilot.getId() == null) teacherCopilot.setCDate(new Date());
teacherCopilotService.save(teacherCopilot);
}
@PostMapping(value = "TeacherCopilot/toggleShow", produces = "application/json")
public void toggleShow(BoaUser authUserWithDept, Integer id) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new com.yunhai.platform.apistd.BizException(com.yunhai.platform.utils.exception.ErrorCode.INTERNAL_SERVER_ERROR));
teacherCopilotService.toggleShow(id, userCurrentRole.getSchId());
}
@PostMapping(value = "TeacherCopilot/saveOrderNum", produces = "application/json")
public void saveOrderNum(BoaUser authUserWithDept, @RequestBody Map<String, Integer> params) {
Integer id = params.get("id"),
orderNum = params.get("orderNum");
teacherCopilotService.saveOrderNum(id, orderNum);
}
@PostMapping(value = "TeacherCopilot/delete", produces = "application/json")
public void delete(BoaUser authUserWithDept, Integer id) {
teacherCopilotService.delete(id);
}
}
@@ -0,0 +1,428 @@
package com.yunhai.userhome.controller.api;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
import com.yunhai.platform.utils.enums.ClientEnum;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.platform.utils.model.BoaApp;
import com.yunhai.platform.utils.model.BoaAppType;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userhome.config.Config;
import com.yunhai.userhome.entity.*;
import com.yunhai.userhome.enums.DesktopAppType;
import com.yunhai.userhome.enums.LightAppGroup;
import com.yunhai.userhome.enums.LinkOpenType;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import com.yunhai.userhome.service.IUserSettingsService;
import com.yunhai.userhome.service.UsedAppService;
import com.yunhai.userhome.utils.EnumUtil;
import com.yunhai.userhome.utils.FileUtil;
import com.yunhai.userhome.utils.OtherUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
/**
* 用户设置控制器(对齐旧 UserHome contorller.api.UserSettingsController)。
*
* <p>待确认接口(已写入待确认清单):
* <ul>
* <li>getUserSettings 中 bschBaseOpenApi.getPcGrzxPage —— 新框架 YschBaseOpenApi 是否有此方法待确认</li>
* <li>GetSchSettingsWallpaper 依赖 SCH_CONF_URL —— 需确认环境地址</li>
* </ul>
*/
@RestController
@RequestMapping(Config.API_PATH)
public class UserSettingsController {
@Value("${FILE_PATH:./upload/}")
private String FILE_PATH;
@Value("${FILE_WEB_PATH:}")
private String FILE_WEB_PATH;
@Value("${SCH_CONF_URL:}")
private String SCH_CONF_URL;
@Autowired
private IUserSettingsService userSettingsService;
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@Autowired
private UsedAppService usedAppService;
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
// ==================== 壁纸 ====================
@PostMapping(value = "wallpaperUpload", produces = "application/json")
public void wallpaperUpload(BoaUser authUserWithDept, @RequestParam("file") MultipartFile file) {
String uploadUrl = this.upload(file, "wallpaper");
UserCurrentRole currentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
Integer type = authUserWithDept.getType() == 1 ? 0 : OtherUtil.isAdminById(currentRole.getRoleId()) ? 1 : 2;
Wallpaper wallpaper = new Wallpaper();
wallpaper.setSchId(currentRole.getSchId());
wallpaper.setWallpaperUrl(uploadUrl);
wallpaper.setUserId(authUserWithDept.getId());
wallpaper.setType(type);
userSettingsService.saveWallpaper(wallpaper);
}
@PostMapping(value = "iconUpload", produces = "application/json")
public String iconUpload(BoaUser authUserWithDept, @RequestParam("file") MultipartFile file) {
return this.upload(file, "icon");
}
@PostMapping(value = "deleteWallById", produces = "application/json")
public void deleteWallById(BoaUser authUserWithDept, Integer id) {
userSettingsService.deleteWallById(id);
}
@PostMapping(value = "checkWallpaper", produces = "application/json")
public void checkWallpaper(BoaUser authUserWithDept, @RequestBody Map res) {
String wallpaperUrl = res.get("wallpaperUrl").toString();
userSettingsService.checkWallpaper(authUserWithDept.getId(), wallpaperUrl);
}
@GetMapping(value = "getUserWallpaperList")
public List<Map> getUserWallpaperList(BoaUser authUserWithDept, Integer schId) {
List<Map> result = new ArrayList<>();
List<Wallpaper> list = userSettingsService.findWallList(authUserWithDept.getId());
list = list.stream().sorted(Comparator.comparing(Wallpaper::getId).reversed()).collect(Collectors.toList());
list.forEach(model -> {
Map map = new HashMap();
map.put("id", model.getId());
map.put("url", FILE_WEB_PATH + model.getWallpaperUrl().replace("/upload", ""));
map.put("type", model.getType());
map.put("isEdit", model.getIsEdit());
result.add(map);
});
if (authUserWithDept.getType() != 1 && !list.stream().anyMatch(x -> x.getType() == 1)) {
List<String> schList = getSchSettingsWallpaper(schId);
for (String schWall : schList) {
Map map = new HashMap();
map.put("id", null);
map.put("type", 1);
map.put("url", schWall);
map.put("isEdit", false);
result.add(map);
}
}
return result;
}
// ==================== 用户设置 ====================
@GetMapping(value = "getUserSettings")
public UserSettings getUserSettings(BoaUser authUserWithDept) {
UserCurrentRole currentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
Integer schId = currentRole.getSchId();
UserSettings model = new UserSettings();
Optional<UserSettings> optional = userSettingsService.findUserSettings(authUserWithDept.getId());
// TODO 待确认:bschBaseOpenApi.getPcGrzxPage —— 新框架 YschBaseOpenApi 是否有此方法待确认
// List<BoaApp> appPageList = bschBaseOpenApi.getPcGrzxPage(authUserWithDept.getId(), schId);
List<BoaApp> appPageList = Collections.emptyList();
if (optional.isPresent()) model = optional.get();
if (model.getWallpaperUrl() == null || model.getWallpaperUrl().isEmpty()) {
List<String> schList = getSchSettingsWallpaper(schId);
if (schList.size() > 0) model.setWallpaperUrl(schList.get(0));
}
List<Map> mapList = appPageList.stream().map(boaApp -> {
Map map = new HashMap<>();
map.put("id", boaApp.getId());
map.put("appId", boaApp.getId());
map.put("name", boaApp.getName());
map.put("url", boaApp.getWebAddr());
return map;
}).collect(Collectors.toList());
model.setWidgetAppList(mapList);
return model;
}
@GetMapping(value = "getUserDesktopAppList")
public List<Map> getUserDesktopAppList(BoaUser authUserWithDept) {
UserCurrentRole currentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
Optional<UserSettings> optional = userSettingsService.findUserSettings(authUserWithDept.getId());
Integer schId = currentRole.getSchId(), userId = currentRole.getUserId();
UserSettings model = new UserSettings();
List<UserSettingsDesktopApp> desktopAppList = new ArrayList<>();
List<Map> result = new ArrayList<>();
if (optional.isPresent()) model = optional.get();
// 初始化设置为常用应用
if (model.getDesktopApps().isEmpty()) desktopAppList = getUserUsedByUserId(authUserWithDept.getId());
else desktopAppList = model.getDesktopApps();
List<BoaApp> bschAllList = new ArrayList<>();
List<LightApp> lightAllList = new ArrayList<>();
List<Integer> bschAppIds = desktopAppList.stream()
.filter(x -> x.getAppType() == DesktopAppType.Bsch)
.map(UserSettingsDesktopApp::getAppId)
.collect(Collectors.toList());
List<Integer> lightAppIds = desktopAppList.stream()
.filter(x -> x.getAppType() == DesktopAppType.Light)
.map(UserSettingsDesktopApp::getAppId)
.collect(Collectors.toList());
if (bschAppIds.size() > 0) {
List<BoaAppType> appTypeList = YschBaseOpenApi.getUserApp(authUserWithDept.getId(), ClientEnum.PC_BROWSER);
for (BoaAppType mode : appTypeList) bschAllList.addAll(mode.getApps());
}
if (lightAppIds.size() > 0) {
lightAllList = userSettingsService.findLightAppList(schId, userId);
}
desktopAppList = desktopAppList.stream()
.sorted(Comparator.comparing(UserSettingsDesktopApp::getOrderNum, Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
for (UserSettingsDesktopApp desktopApp : desktopAppList) {
Map map = new HashMap();
map.put("id", desktopApp.getId());
map.put("appId", desktopApp.getAppId());
if (desktopApp.getAppType() == DesktopAppType.Bsch) {
Optional<BoaApp> optionalBoaApp = bschAllList.stream()
.filter(boa -> desktopApp.getAppId().equals(boa.getId())).findFirst();
if (!optionalBoaApp.isPresent()) continue;
map.put("name", optionalBoaApp.get().getName());
map.put("icon", optionalBoaApp.get().getIcon());
map.put("url", optionalBoaApp.get().getWebAddr());
map.put("type", DesktopAppType.Bsch.getKey());
map.put("linkType", LinkOpenType.Open.getKey());
map.put("layout", null);
} else if (desktopApp.getAppType() == DesktopAppType.Light) {
Optional<LightApp> optionalLightApp = lightAllList.stream()
.filter(app -> desktopApp.getAppId().equals(app.getId())).findFirst();
if (!optionalLightApp.isPresent()) continue;
map.put("name", optionalLightApp.get().getName());
map.put("icon", optionalLightApp.get().getIcon());
map.put("url", optionalLightApp.get().getUrl());
map.put("type", DesktopAppType.Light.getKey());
map.put("linkType", optionalLightApp.get().getLinkOpenType());
map.put("layout", optionalLightApp.get().getLayout());
}
result.add(map);
}
return result;
}
@PostMapping(value = "saveUserWidget", produces = "application/json")
public void saveUserWidget(BoaUser authUserWithDept, @RequestBody UserSettings userSettings) {
userSettings.setUserId(authUserWithDept.getId());
userSettingsService.saveUserWidget(userSettings);
}
@PostMapping(value = "toggleWidgetShow", produces = "application/json")
public void toggleWidgetShow(BoaUser authUserWithDept, @RequestBody Map<String, Integer> params) {
Integer id = params.get("id");
userSettingsService.toggleWidgetShow(id, authUserWithDept.getId());
}
@PostMapping(value = "saveUserAppIds", produces = "application/json")
public void saveUserAppIds(BoaUser authUserWithDept, @RequestBody Map<String, String> params) {
Integer id = null;
if (params.get("id") != null) id = Integer.parseInt(params.get("id"));
String appIds = params.get("appIds");
userSettingsService.saveUserAppIds(id, authUserWithDept.getId(), appIds);
}
// ==================== 轻应用 ====================
@GetMapping(value = "getLightAppGroup")
public Object getLightAppGroup(BoaUser authUserWithDept) {
return EnumUtil.toMapList(LightAppGroup.class);
}
@GetMapping(value = "getLightAppList", produces = "application/json")
public List<LightApp> getLightAppList(BoaUser authUserWithDept) {
UserCurrentRole currentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
Integer schId, userId = null;
if (authUserWithDept.getType() == 1) {
schId = 0;
} else if (currentRole.getRoleId() == 7 || currentRole.getRoleId() == 2) {
schId = currentRole.getSchId();
} else {
schId = currentRole.getSchId();
userId = currentRole.getUserId();
}
return userSettingsService.findLightAppList(schId, userId);
}
@PostMapping(value = "saveLightApp", produces = "application/json")
public void saveLightApp(BoaUser authUserWithDept, @RequestBody LightApp lightApp) {
UserCurrentRole currentRole = userCurrentRoleService.findById(authUserWithDept.getId())
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
Integer schId, userId = null;
if (authUserWithDept.getType() == 1) {
schId = 0;
} else if (currentRole.getRoleId() == 7 || currentRole.getRoleId() == 2) {
schId = currentRole.getSchId();
} else {
schId = currentRole.getSchId();
userId = currentRole.getUserId();
}
lightApp.setUserId(userId);
lightApp.setSchId(schId);
lightApp.setCId(authUserWithDept.getId());
lightApp.setCDate(new Date());
userSettingsService.saveLightApp(lightApp);
}
@PostMapping(value = "deleteLightAppById", produces = "application/json")
public void deleteLightAppById(BoaUser authUserWithDept, Integer id) {
userSettingsService.deleteLightAppById(id);
}
// ==================== 桌面应用 ====================
@PostMapping(value = "saveUserDesktopAppById", produces = "application/json")
public void saveUserDesktopAppById(BoaUser authUserWithDept, @RequestBody Map<String, Integer> params) {
Integer id = params.get("id");
Integer type = params.get("type");
DesktopAppType desktopAppType = DesktopAppType.valueOf(type);
Optional<UserSettings> optional = userSettingsService.findUserSettings(authUserWithDept.getId());
if (!optional.isPresent() || optional.get().getDesktopApps().isEmpty()) {
initUserSettingsDesktopApp(authUserWithDept.getId());
optional = userSettingsService.findUserSettings(authUserWithDept.getId());
}
UserSettings userSettings = optional.get();
if (userSettings.getDesktopApps().stream().anyMatch(x -> x.getAppId().equals(id)))
throw new BizException(ErrorCode.CUSTOM, "该应用已存在于桌面,请勿重复添加!");
UserSettingsDesktopApp desktopApp = new UserSettingsDesktopApp();
desktopApp.setAppType(desktopAppType);
desktopApp.setAppId(id);
desktopApp.setUserSettingsId(userSettings.getId());
userSettingsService.saveDesktopApp(desktopApp);
}
@PostMapping(value = "deleteDesktopAppById", produces = "application/json")
public void deleteDesktopAppById(BoaUser authUserWithDept, @RequestBody Map<String, Integer> params) {
Integer id = params.get("id");
Integer appId = params.get("appId");
if (id != null) {
userSettingsService.deleteDesktopAppById(id);
} else {
Integer userId = authUserWithDept.getId();
Optional<UserSettings> optional = userSettingsService.findUserSettings(userId);
List<UserSettingsDesktopApp> desktopList = getUserUsedByUserId(userId);
desktopList = desktopList.stream().filter(x -> !x.getAppId().equals(appId)).collect(Collectors.toList());
UserSettings model;
if (!optional.isPresent()) model = userSettingsService.initUserSettings(userId);
else model = optional.get();
desktopList.forEach(x -> x.setUserSettingsId(model.getId()));
userSettingsService.saveDesktopAppList(desktopList);
}
}
@PostMapping(value = "sortUserDesktopApp", produces = "application/json")
public void sortUserDesktopApp(BoaUser authUserWithDept, @RequestBody Map<String, String> params) {
String idsStr = params.get("ids");
List<Integer> ids = Arrays.stream(idsStr.split(",")).map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
Optional<UserSettings> optional = userSettingsService.findUserSettings(authUserWithDept.getId());
List<UserSettingsDesktopApp> desktopApps = new ArrayList<>();
if (!optional.isPresent() || optional.get().getDesktopApps().isEmpty()) {
desktopApps = initUserSettingsDesktopApp(authUserWithDept.getId());
desktopApps.forEach(x -> {
Integer i = ids.indexOf(x.getAppId());
x.setOrderNum(i);
});
} else {
desktopApps = optional.get().getDesktopApps();
desktopApps.forEach(x -> {
Integer i = ids.indexOf(x.getId());
x.setOrderNum(i);
});
}
userSettingsService.saveDesktopAppList(desktopApps);
}
// ==================== 私有方法 ====================
private String upload(@RequestParam("file") MultipartFile file, String pathName) {
File fl = new File(FILE_PATH + "/" + pathName + "/");
if (!fl.exists()) fl.mkdirs();
String fileName = FileUtil.uploadImg(file, FILE_PATH + "/" + pathName + "/");
return "/upload/" + pathName + "/" + fileName;
}
/**
* 获取学校设置的壁纸集合(对齐旧 UserHome GetSchSettingsWallpaper,fastjson → Jackson)。
*/
private List<String> getSchSettingsWallpaper(Integer schId) {
if (SCH_CONF_URL == null || SCH_CONF_URL.isEmpty()) return Collections.emptyList();
String apiPath = SCH_CONF_URL + "/oapi/getSchSetting?schId=" + schId;
List<String> result = new ArrayList<>();
try {
String resultStr = restTemplate.getForObject(apiPath, String.class);
if (resultStr == null || resultStr.isEmpty()) return result;
JsonNode root = objectMapper.readTree(resultStr);
JsonNode dataNode = root.get("data");
if (root.has("code") && "0".equals(root.get("code").asText()) && dataNode != null && !dataNode.isNull()) {
JsonNode appBgUrlNode = dataNode.get("appBackgroundUrl");
if (appBgUrlNode == null) appBgUrlNode = dataNode.get("appBgUrl");
String appBgUrlStr = appBgUrlNode != null ? appBgUrlNode.asText("") : "";
if (appBgUrlStr.isEmpty()) return result;
String[] imgUrls = appBgUrlStr.split(",");
for (String imgUrl : imgUrls) {
if (!imgUrl.contains(SCH_CONF_URL))
result.add(SCH_CONF_URL + imgUrl);
else
result.add(imgUrl);
}
}
} catch (Exception e) {
// 跨仓调用失败时返回空列表
}
return result;
}
/**
* 将某个人常用应用转化为桌面应用
*/
private List<UserSettingsDesktopApp> initUserSettingsDesktopApp(Integer userId) {
Optional<UserSettings> optional = userSettingsService.findUserSettings(userId);
List<UserSettingsDesktopApp> desktopList = getUserUsedByUserId(userId);
UserSettings model;
if (!optional.isPresent()) model = userSettingsService.initUserSettings(userId);
else model = optional.get();
desktopList.forEach(x -> x.setUserSettingsId(model.getId()));
return userSettingsService.saveDesktopAppList(desktopList);
}
/**
* 获取常用应用转化为桌面应用类型
*/
private List<UserSettingsDesktopApp> getUserUsedByUserId(Integer userId) {
UserCurrentRole currentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
Optional<UsedApp> optionalUsedApp = usedAppService.findById(currentRole.getSchId(), currentRole.getUserId(), currentRole.getRoleId());
List<UserSettingsDesktopApp> desktopAppList = new ArrayList<>();
if (optionalUsedApp.isPresent() && optionalUsedApp.get().getAppIds() != null && !optionalUsedApp.get().getAppIds().isEmpty()) {
List<String> appIds = Arrays.asList(optionalUsedApp.get().getAppIds().split(","));
List<Integer> bschAppIds = appIds.stream().mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
Integer i = 0;
for (Integer appId : bschAppIds) {
UserSettingsDesktopApp desktopApp = new UserSettingsDesktopApp();
desktopApp.setAppId(appId);
desktopApp.setAppType(DesktopAppType.Bsch);
desktopApp.setOrderNum(i);
desktopAppList.add(desktopApp);
i++;
}
}
return desktopAppList;
}
}
@@ -0,0 +1,63 @@
package com.yunhai.userhome.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* 轻应用数据实体(对齐旧 UserHome model.LightApp)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "light_app")
public class LightApp {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = UsedApp.Update.class)
private Integer id;
private String name;
private Integer groupId;
private String icon;
private String url;
@Column(name = "desc_txt")
private String desc;
@JsonIgnore
private Boolean isPublic = false;
@Transient
private Boolean isEdit = false;
private Integer linkOpenType;
private String layout;
@Column(name = "sch_id")
private Integer schId;
private Integer userId;
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_date")
private Date cDate;
}
@@ -0,0 +1,78 @@
package com.yunhai.userhome.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 菜单栏实体类(对齐旧 UserHome model.MenuBar)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "menu_bar")
public class MenuBar {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = Update.class)
private Integer id;
private String name;
private String url;
private String icon;
private Integer linkOpenType;
private Boolean isNative = false;
private Boolean isHeader = false;
private Boolean isBottom = false;
private Integer orderNum;
private Integer schId;
@ElementCollection
@CollectionTable(name = "menu_bar_role")
@Column(name = "role_ids")
private List<Integer> roleIds = new ArrayList<>();
@JsonIgnore
@ElementCollection
@CollectionTable(name = "menu_bar_hide_sch")
@Column(name = "sch_ids")
private List<Integer> hideSchIds = new ArrayList<>();
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_date")
private Date cDate;
@Transient
private Boolean isShow = true;
@Transient
private Boolean isEdit = false;
public @interface Update {}
}
@@ -0,0 +1,57 @@
package com.yunhai.userhome.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 学校设置(sch_settings 表,字段名/表名对齐旧 UserHome model.SchSettings)。
* <p>注意:旧版 {@code SchSettingsService.getSchSettings} 并不查本地表,而是跨仓调用
* {@code SCH_CONF_URL/oapi/getSchSetting},返回结构经 fastjson 映射为此实体。本工程保持同一行为。</p>
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "sch_settings")
public class SchSettings {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "theme_name")
private String themeName;
@Column(name = "logo_url")
private String logoUrl;
@Column(name = "home_img_url")
private String homeImgUrl;
@Column(name = "app_background_url")
private String appBgUrl;
@Column(name = "sch_id")
private Integer schId;
// 是否开启桌面
private Boolean isEnableDesktop = false;
// 是否默认跳转桌面
private Boolean isLinkDesktop = false;
// 操作人id
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_date")
private java.util.Date cDate;
}
@@ -0,0 +1,72 @@
package com.yunhai.userhome.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 统计栏目实体(对齐旧 UserHome model.StatsBar)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "stats_bar")
public class StatsBar {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = MenuBar.Update.class)
private Integer id;
private String name;
private String url;
private String icon;
private Integer linkOpenType;
private Integer orderNum;
private Integer schId;
@ElementCollection
@CollectionTable(name = "stats_bar_role")
@Column(name = "role_ids")
private List<Integer> roleIds = new ArrayList<>();
@JsonIgnore
@ElementCollection
@CollectionTable(name = "stats_bar_show_sch")
@Column(name = "sch_ids")
private List<Integer> showSchIds = new ArrayList<>();
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_date")
private Date cDate;
@Transient
private Boolean isShow = true;
@Transient
private Boolean isEdit = false;
public @interface Update {}
}
@@ -0,0 +1,85 @@
package com.yunhai.userhome.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 教师助手实体(对齐旧 UserHome model.TeacherCopilot)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "teacher_copilot")
public class TeacherCopilot {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = MenuBar.Update.class)
private Integer id;
private String name;
private String url;
private String icon;
private Integer linkOpenType;
private Integer orderNum;
/** 数据类别 1课前 2课堂 3课后 */
private Integer type;
private Integer schId;
@ElementCollection
@CollectionTable(name = "teacher_copilot_role")
@Column(name = "role_ids")
private List<Integer> roleIds = new ArrayList<>();
@JsonIgnore
@ElementCollection
@CollectionTable(name = "teacher_copilot_show_sch")
@Column(name = "sch_ids")
private List<Integer> showSchIds = new ArrayList<>();
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_date")
private Date cDate;
@Transient
private Boolean isShow = true;
@Transient
private Boolean isEdit = false;
public @interface Update {}
@Data
public static class Dto {
private Integer id;
private String name;
private String url;
private String icon;
private Integer openType;
private Integer type;
}
}
@@ -61,4 +61,7 @@ public class UsedApp extends BaseEntity {
/** 操作时间。 */
@Column(name = "c_date")
private Date cDate;
/** 验证分组:更新操作时 id 必须非空(对齐旧 UserHome UsedApp.Update)。 */
public @interface Update {}
}
@@ -0,0 +1,56 @@
package com.yunhai.userhome.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
/**
* 用户消息表(user_message,字段名/表名对齐旧 UserHome model.UserMessage)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "user_message")
public class UserMessage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "app_id")
private Integer appId;
@Column(name = "c_date")
private Date cDate;
@Column(name = "imgs")
private String imgs;
private String urls;
@Column(name = "btn_texts")
private String btnTexts;
private String content;
@Column(name = "user_id")
private Integer userId;
@Column(name = "sch_id")
private Integer schId;
/** 消息类型(0文字/1图文/2审批,对齐旧 MsgType)。 */
private Integer type;
@Column(name = "is_read")
private Boolean isRead = false;
}
@@ -0,0 +1,75 @@
package com.yunhai.userhome.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 用户个性化配置(对齐旧 UserHome model.UserSettings)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "user_settings", indexes = {@Index(columnList = "user_id,sch_id,role_id", name = "index_setting_user_sch_role")})
public class UserSettings {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = Update.class)
private Integer id;
@Column(name = "widget_app_ids")
private String widgetAppIds;
@Column(name = "is_widget_show")
private Boolean isWidgetShow = true;
@Column(name = "width")
private Integer width;
@Column(name = "height")
private Integer height;
@Column(name = "x_axis")
private Integer xAxis;
@Column(name = "y_axis")
private Integer yAxis;
@Column(name = "wallpaper_url")
private String wallpaperUrl;
@Column(name = "sch_id")
private Integer schId;
@Column(name = "user_id")
private Integer userId;
@Column(name = "role_id")
private Integer roleId;
@JsonIgnore
@OneToMany(mappedBy = "userSettings", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserSettingsDesktopApp> desktopApps = new ArrayList<>();
@Transient
private List<Map> widgetAppList;
public @interface Update {}
}
@@ -0,0 +1,48 @@
package com.yunhai.userhome.entity;
import com.yunhai.userhome.enums.DesktopAppType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
/**
* 用户设置桌面应用(对齐旧 UserHome model.UserSettingsDesktopApp)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "user_settings_desktop_app")
public class UserSettingsDesktopApp {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = UserSettings.Update.class)
private Integer id;
private Integer appId;
@Enumerated(EnumType.ORDINAL)
private DesktopAppType appType;
private Integer orderNum;
@Column(name = "user_settings_id")
private Integer userSettingsId;
@ManyToOne(cascade = {javax.persistence.CascadeType.PERSIST}, optional = false)
@JoinColumn(name = "user_settings_id", insertable = false, updatable = false)
private UserSettings userSettings;
}
@@ -0,0 +1,46 @@
package com.yunhai.userhome.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
/**
* 壁纸实体(对齐旧 UserHome model.Wallpaper)。
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "wallpaper")
public class Wallpaper {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = Update.class)
private Integer id;
/** 0:随机壁纸 | 1:个人上传壁纸 */
private Integer type;
@Column(name = "sch_id")
private Integer schId;
private Integer userId;
@Column(name = "wallpaper_url")
private String wallpaperUrl;
@Transient
private Boolean isEdit = false;
public @interface Update {}
}
@@ -0,0 +1,31 @@
package com.yunhai.userhome.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* 桌面应用类型(对齐旧 UserHome enums.DesktopAppType)。
*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum DesktopAppType {
Bsch(1, "应用中心应用"),
Light(2, "轻应用"),
;
private Integer key;
private String value;
public static DesktopAppType valueOf(Integer value) {
switch (value) {
case 1:
return Bsch;
case 2:
return Light;
default:
return null;
}
}
}
@@ -0,0 +1,25 @@
package com.yunhai.userhome.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* 轻应用分组类型(对齐旧 UserHome enums.LightAppGroup)。
*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum LightAppGroup {
AI(1, "AI助手"),
VR(2, "虚拟现实"),
Program(3, "编程体验"),
Tools(4, "在线工具"),
Resource(5, "资源推荐"),
Others(6, "其他"),
;
private Integer key;
private String value;
}
@@ -0,0 +1,22 @@
package com.yunhai.userhome.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* 链接打开方式(对齐旧 UserHome enums.LinkOpenType)。
*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum LinkOpenType {
Open(1, "新窗口"),
Href(2, "当前页"),
IFrame(3, "嵌入页面"),
;
private Integer key;
private String value;
}
@@ -0,0 +1,43 @@
package com.yunhai.userhome.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* 统计日期类型(对齐旧 UserHome enums.StatsDateType)。
*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum StatsDateType {
Day(1, "今日"),
Week(2, "本周"),
Mont(3, "本月"),
Academic(4, "本学期"),
Total(5, "累计"),
Custom(6, "自定义"),
;
private Integer key;
private String value;
public static StatsDateType valueOf(Integer value) {
switch (value) {
case 1:
return Day;
case 2:
return Week;
case 3:
return Mont;
case 4:
return Academic;
case 5:
return Total;
case 6:
return Custom;
default:
return null;
}
}
}
@@ -0,0 +1,8 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.LightApp;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface LightAppRepository extends JpaRepository<LightApp, Integer>, JpaSpecificationExecutor<LightApp> {
}
@@ -0,0 +1,14 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.MenuBar;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface MenuBarRepository extends JpaRepository<MenuBar, Integer>, JpaSpecificationExecutor<MenuBar> {
List<MenuBar> findBySchId(Integer schId);
List<MenuBar> findBySchIdIn(List<Integer> schIds);
}
@@ -0,0 +1,19 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.SchSettings;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface SchSettingsRepository extends JpaRepository<SchSettings, Integer>, JpaSpecificationExecutor<SchSettings> {
Optional<SchSettings> findFirstBySchId(Integer schId);
@Query(nativeQuery = true, value = "SELECT * FROM `sch_settings` where sch_id in ?1 ")
List<SchSettings> getSchSettingList(List<Integer> schIds);
}
@@ -0,0 +1,14 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.StatsBar;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface StatsBarRepository extends JpaRepository<StatsBar, Integer>, JpaSpecificationExecutor<StatsBar> {
List<StatsBar> findBySchId(Integer schId);
List<StatsBar> findBySchIdIn(List<Integer> schIds);
}
@@ -0,0 +1,14 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.TeacherCopilot;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface TeacherCopilotRepository extends JpaRepository<TeacherCopilot, Integer>, JpaSpecificationExecutor<TeacherCopilot> {
List<TeacherCopilot> findBySchId(Integer schId);
List<TeacherCopilot> findBySchIdIn(List<Integer> schIds);
}
@@ -0,0 +1,34 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.UserMessage;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface UserMessageRepository extends JpaRepository<UserMessage, Integer>, JpaSpecificationExecutor<UserMessage> {
List<UserMessage> findUserMessageByUserIdAndAppId(Integer userId, Integer appId);
/** 按用户分组取「每应用最新一条消息」(对齐旧 getUserMessageAppList 原生 SQL)。 */
@Query(nativeQuery = true, value = "select * from (SELECT * FROM `user_message` where user_id=?1 group by app_id,c_date desc) as Base group by app_id order by c_date desc")
List<UserMessage> getUserMessageAppList(Integer userId, Integer schId);
@Transactional
@Modifying
@Query(nativeQuery = true, value = "update user_message set is_read =1 where user_id=?1 and app_id=?2 and is_read = 0")
void updateRead(Integer userId, Integer appId);
@Transactional
@Modifying
@Query(nativeQuery = true, value = "update user_message set is_read =1 where user_id=?1 and is_read = 0")
void updateReadAll(Integer userId);
@Transactional
@Modifying
@Query(nativeQuery = true, value = "update user_message set is_read =1 where id=:msgId ")
void updateReadById(Integer msgId);
}
@@ -0,0 +1,8 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.UserSettingsDesktopApp;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface UserSettingsDesktopAppRepository extends JpaRepository<UserSettingsDesktopApp, Integer>, JpaSpecificationExecutor<UserSettingsDesktopApp> {
}
@@ -0,0 +1,12 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.UserSettings;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.Optional;
public interface UserSettingsRepository extends JpaRepository<UserSettings, Integer>, JpaSpecificationExecutor<UserSettings> {
Optional<UserSettings> findByUserIdAndSchIdAndRoleId(Integer userId, Integer schId, Integer roleId);
}
@@ -0,0 +1,14 @@
package com.yunhai.userhome.repository;
import com.yunhai.userhome.entity.Wallpaper;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface WallpaperRepository extends JpaRepository<Wallpaper, Integer>, JpaSpecificationExecutor<Wallpaper> {
List<Wallpaper> findByUserIdAndType(Integer userId, Integer type);
List<Wallpaper> findBySchIdAndType(Integer schId, Integer type);
}
@@ -0,0 +1,20 @@
package com.yunhai.userhome.service;
import com.yunhai.userhome.entity.MenuBar;
import java.util.List;
public interface IMenuBarService {
List<MenuBar> getMenuBarList(Integer schId);
List<MenuBar> findMenuBarById(Integer userId);
void saveMenuBar(MenuBar menuBar);
void toggleMenuBarShow(Integer id, Integer schId);
void saveMenuBarOrderNum(Integer id, Integer orderNum);
void deleteMenuBar(Integer id);
}
@@ -0,0 +1,16 @@
package com.yunhai.userhome.service;
import com.yunhai.userhome.entity.SchSettings;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public interface ISchSettingsService {
void save(SchSettings schSettings);
Optional<SchSettings> findBySchId(Integer schId);
List<SchSettings> findBySchIds(List<Integer> schIds);
}
@@ -0,0 +1,20 @@
package com.yunhai.userhome.service;
import com.yunhai.userhome.entity.StatsBar;
import java.util.List;
public interface IStatsBarService {
List<StatsBar> getStatsBarList(Integer schId);
List<StatsBar> findStatsBarById(Integer userId);
void saveStatsBar(StatsBar statsBar);
void toggleStatsBarShow(Integer id, Integer schId);
void saveStatsBarOrderNum(Integer id, Integer orderNum);
void deleteStatsBar(Integer id);
}
@@ -0,0 +1,20 @@
package com.yunhai.userhome.service;
import com.yunhai.userhome.entity.TeacherCopilot;
import java.util.List;
public interface ITeacherCopilotService {
List<TeacherCopilot> getList(Integer schId);
List<TeacherCopilot> findById(Integer userId);
void save(TeacherCopilot teacherCopilot);
void toggleShow(Integer id, Integer schId);
void saveOrderNum(Integer id, Integer orderNum);
void delete(Integer id);
}
@@ -0,0 +1,32 @@
package com.yunhai.userhome.service;
import com.yunhai.userhome.entity.UserMessage;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
public interface IUserMessageService {
List<UserMessage> getUserMessageAppIds(Integer userId, Integer schId);
Page<UserMessage> findUserMessageByAppId(UserMessage userMessage, Pageable pageable);
Page<UserMessage> findUserMessageByUserId(Integer userId, Pageable pageable);
List<UserMessage> findUserMessageByUserId(Integer userId);
Boolean findUserMessageUnRead(Integer userId);
void updateRead(Integer userId, Integer appId);
void updateUserRead(Integer id, Integer userId);
void updateReadAll(Integer userId);
Page<UserMessage> findUserMessageById(Integer userId, Integer page, Integer count);
void readMsgById(Integer msgId);
void readMsgAll(Integer userId);
}
@@ -0,0 +1,44 @@
package com.yunhai.userhome.service;
import com.yunhai.userhome.entity.LightApp;
import com.yunhai.userhome.entity.UserSettings;
import com.yunhai.userhome.entity.UserSettingsDesktopApp;
import com.yunhai.userhome.entity.Wallpaper;
import java.util.List;
import java.util.Optional;
public interface IUserSettingsService {
List<Wallpaper> findWallList(Integer userId);
void deleteWallById(Integer id);
void saveWallpaper(Wallpaper wallpaper);
void checkWallpaper(Integer userId, String wallpaperUrl);
Optional<UserSettings> findUserSettings(Integer userId);
void saveUserSettings(UserSettings userSettings);
void saveUserWidget(UserSettings userSettings);
void saveUserAppIds(Integer id, Integer userId, String appIds);
void toggleWidgetShow(Integer id, Integer userId);
List<LightApp> findLightAppList(Integer schId, Integer userId);
void saveLightApp(LightApp lightApp);
void deleteLightAppById(Integer id);
void deleteDesktopAppById(Integer id);
void saveDesktopApp(UserSettingsDesktopApp model);
List<UserSettingsDesktopApp> saveDesktopAppList(List<UserSettingsDesktopApp> list);
UserSettings initUserSettings(Integer userId);
}
@@ -0,0 +1,98 @@
package com.yunhai.userhome.service.impl;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.userhome.entity.MenuBar;
import com.yunhai.userhome.entity.UserCurrentRole;
import com.yunhai.userhome.repository.MenuBarRepository;
import com.yunhai.userhome.service.IMenuBarService;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 菜单栏服务(对齐旧 UserHome service.impl.MenuBarService)。
*/
@Service
public class MenuBarServiceImpl implements IMenuBarService {
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@Autowired
private MenuBarRepository menuBarRepository;
@Override
public List<MenuBar> getMenuBarList(Integer schId) {
List<MenuBar> list;
if (schId == 0)
list = menuBarRepository.findBySchId(0);
else
list = menuBarRepository.findBySchIdIn(Arrays.asList(0, schId));
list.forEach(x -> {
Boolean isHide = x.getHideSchIds().contains(schId);
x.setIsShow(!isHide);
x.setIsEdit(x.getSchId().equals(schId));
});
list = list.stream().sorted(Comparator.comparing(MenuBar::getOrderNum, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
return list;
}
@Override
public List<MenuBar> findMenuBarById(Integer userId) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
List<MenuBar> list = getMenuBarList(userCurrentRole.getSchId());
List<MenuBar> result = list.stream().filter(MenuBar::getIsShow).collect(Collectors.toList());
result = result.stream().sorted(Comparator.comparing(MenuBar::getOrderNum, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
return result;
}
@Override
public void saveMenuBar(MenuBar menuBar) {
if (menuBar.getId() != null) {
Optional<MenuBar> optional = menuBarRepository.findById(menuBar.getId());
if (optional.isPresent()) {
menuBar.setHideSchIds(optional.get().getHideSchIds());
}
}
menuBarRepository.save(menuBar);
}
@Override
public void saveMenuBarOrderNum(Integer id, Integer orderNum) {
Optional<MenuBar> optionalMenuBar = menuBarRepository.findById(id);
if (!optionalMenuBar.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
MenuBar menuBar = optionalMenuBar.get();
menuBar.setOrderNum(orderNum);
menuBarRepository.save(menuBar);
}
@Override
public void toggleMenuBarShow(Integer id, Integer schId) {
Optional<MenuBar> optionalMenuBar = menuBarRepository.findById(id);
if (!optionalMenuBar.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
MenuBar menuBar = optionalMenuBar.get();
Integer index = menuBar.getHideSchIds().indexOf(schId);
List<Integer> schIds = menuBar.getHideSchIds();
if (index.equals(-1))
schIds.add(schId);
else
schIds.remove(Integer.valueOf(schId));
menuBar.setHideSchIds(schIds);
menuBarRepository.save(menuBar);
}
@Override
public void deleteMenuBar(Integer id) {
Optional<MenuBar> optionalMenuBar = menuBarRepository.findById(id);
if (!optionalMenuBar.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
menuBarRepository.delete(optionalMenuBar.get());
}
}
@@ -0,0 +1,81 @@
package com.yunhai.userhome.service.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunhai.userhome.entity.SchSettings;
import com.yunhai.userhome.repository.SchSettingsRepository;
import com.yunhai.userhome.service.ISchSettingsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Optional;
/**
* 学校设置服务:行为对齐旧 UserHome SchSettingsService。
* <p>关键:{@code findBySchId} 不查本地表,而是跨仓调用 {@code SCH_CONF_URL/oapi/getSchSetting},
* 旧版如此(schConfig 服务为 homeImgUrl/isEnableDesktop/isLinkDesktop 等字段的权威来源),
* 因此本地 sch_settings 表变更类能力(saveSchTheme/saveSchLogo)本期仅保留 P1 占位写入本地表。</p>
*/
@Service
public class SchSettingsServiceImpl implements ISchSettingsService {
@Autowired
private SchSettingsRepository schSettingsRepository;
@Value("${SCH_CONF_URL:}")
private String schConfUrl;
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void save(SchSettings schSettings) {
schSettingsRepository.save(schSettings);
}
@Override
public Optional<SchSettings> findBySchId(Integer schId) {
SchSettings model = new SchSettings();
try {
if (schConfUrl == null || schConfUrl.isEmpty()) {
return Optional.of(localFallbackBySchId(schId));
}
String apiPath = schConfUrl + "/oapi/getSchSetting?schId=" + schId;
String resultStr = restTemplate.getForObject(apiPath, String.class);
if (resultStr == null || resultStr.isEmpty()) {
return Optional.of(localFallbackBySchId(schId));
}
JsonNode root = objectMapper.readTree(resultStr);
JsonNode dataNode = root.get("data");
if (root.has("code") && "0".equals(root.get("code").asText()) && dataNode != null && !dataNode.isNull()) {
model = objectMapper.convertValue(dataNode, SchSettings.class);
} else {
return Optional.of(localFallbackBySchId(schId));
}
} catch (Exception e) {
return Optional.of(localFallbackBySchId(schId));
}
return Optional.of(model);
}
/** 跨仓不通时先查本地表,再兜底默认主题(对齐旧版异常分支)。 */
private SchSettings localFallbackBySchId(Integer schId) {
Optional<SchSettings> local = schSettingsRepository.findFirstBySchId(schId);
if (local.isPresent()) {
return local.get();
}
SchSettings def = new SchSettings();
def.setSchId(schId);
def.setThemeName("default-theme");
def.setAppBgUrl("");
def.setLogoUrl("");
return def;
}
@Override
public java.util.List<SchSettings> findBySchIds(java.util.List<Integer> schId) {
return schSettingsRepository.getSchSettingList(schId);
}
}
@@ -0,0 +1,97 @@
package com.yunhai.userhome.service.impl;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.userhome.entity.StatsBar;
import com.yunhai.userhome.entity.UserCurrentRole;
import com.yunhai.userhome.repository.StatsBarRepository;
import com.yunhai.userhome.service.IStatsBarService;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 统计栏目服务(对齐旧 UserHome service.impl.StatsBarService)。
*/
@Service
public class StatsBarServiceImpl implements IStatsBarService {
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@Autowired
private StatsBarRepository statsBarRepository;
@Override
public List<StatsBar> getStatsBarList(Integer schId) {
List<StatsBar> list;
if (schId == 0)
list = statsBarRepository.findBySchId(0);
else
list = statsBarRepository.findBySchIdIn(Arrays.asList(0, schId));
list.forEach(x -> {
x.setIsShow(x.getShowSchIds().contains(schId));
x.setIsEdit(x.getSchId().equals(schId));
});
list = list.stream().sorted(Comparator.comparing(StatsBar::getOrderNum, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
return list;
}
@Override
public List<StatsBar> findStatsBarById(Integer userId) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
List<StatsBar> list = getStatsBarList(userCurrentRole.getSchId());
List<StatsBar> result = list.stream().filter(StatsBar::getIsShow).collect(Collectors.toList());
result = result.stream().sorted(Comparator.comparing(StatsBar::getOrderNum, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
return result;
}
@Override
public void saveStatsBar(StatsBar statsBar) {
if (statsBar.getId() != null) {
Optional<StatsBar> optional = statsBarRepository.findById(statsBar.getId());
if (optional.isPresent()) {
statsBar.setShowSchIds(optional.get().getShowSchIds());
}
}
statsBarRepository.save(statsBar);
}
@Override
public void saveStatsBarOrderNum(Integer id, Integer orderNum) {
Optional<StatsBar> optionalStatsBar = statsBarRepository.findById(id);
if (!optionalStatsBar.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
StatsBar statsBar = optionalStatsBar.get();
statsBar.setOrderNum(orderNum);
statsBarRepository.save(statsBar);
}
@Override
public void toggleStatsBarShow(Integer id, Integer schId) {
Optional<StatsBar> optionalStatsBar = statsBarRepository.findById(id);
if (!optionalStatsBar.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
StatsBar statsBar = optionalStatsBar.get();
Integer index = statsBar.getShowSchIds().indexOf(schId);
List<Integer> schIds = statsBar.getShowSchIds();
if (index.equals(-1))
schIds.add(schId);
else
schIds.remove(Integer.valueOf(schId));
statsBar.setShowSchIds(schIds);
statsBarRepository.save(statsBar);
}
@Override
public void deleteStatsBar(Integer id) {
Optional<StatsBar> optionalStatsBar = statsBarRepository.findById(id);
if (!optionalStatsBar.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
statsBarRepository.delete(optionalStatsBar.get());
}
}
@@ -0,0 +1,97 @@
package com.yunhai.userhome.service.impl;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.userhome.entity.TeacherCopilot;
import com.yunhai.userhome.entity.UserCurrentRole;
import com.yunhai.userhome.repository.TeacherCopilotRepository;
import com.yunhai.userhome.service.ITeacherCopilotService;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 教师助手服务(对齐旧 UserHome service.impl.TeacherCopilotService)。
*/
@Service
public class TeacherCopilotServiceImpl implements ITeacherCopilotService {
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@Autowired
private TeacherCopilotRepository teacherCopilotRepository;
@Override
public List<TeacherCopilot> getList(Integer schId) {
List<TeacherCopilot> list;
if (schId == 0)
list = teacherCopilotRepository.findBySchId(0);
else
list = teacherCopilotRepository.findBySchIdIn(Arrays.asList(0, schId));
list.forEach(x -> {
x.setIsShow(x.getShowSchIds().contains(schId));
x.setIsEdit(x.getSchId().equals(schId));
});
list = list.stream().sorted(Comparator.comparing(TeacherCopilot::getOrderNum, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
return list;
}
@Override
public List<TeacherCopilot> findById(Integer userId) {
UserCurrentRole userCurrentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
List<TeacherCopilot> list = getList(userCurrentRole.getSchId());
List<TeacherCopilot> result = list.stream().filter(TeacherCopilot::getIsShow).collect(Collectors.toList());
result = result.stream().sorted(Comparator.comparing(TeacherCopilot::getOrderNum, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
return result;
}
@Override
public void save(TeacherCopilot teacherCopilot) {
if (teacherCopilot.getId() != null) {
Optional<TeacherCopilot> optional = teacherCopilotRepository.findById(teacherCopilot.getId());
if (optional.isPresent()) {
teacherCopilot.setShowSchIds(optional.get().getShowSchIds());
}
}
teacherCopilotRepository.save(teacherCopilot);
}
@Override
public void saveOrderNum(Integer id, Integer orderNum) {
Optional<TeacherCopilot> optional = teacherCopilotRepository.findById(id);
if (!optional.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
TeacherCopilot teacherCopilot = optional.get();
teacherCopilot.setOrderNum(orderNum);
teacherCopilotRepository.save(teacherCopilot);
}
@Override
public void toggleShow(Integer id, Integer schId) {
Optional<TeacherCopilot> optional = teacherCopilotRepository.findById(id);
if (!optional.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
TeacherCopilot teacherCopilot = optional.get();
Integer index = teacherCopilot.getShowSchIds().indexOf(schId);
List<Integer> schIds = teacherCopilot.getShowSchIds();
if (index.equals(-1))
schIds.add(schId);
else
schIds.remove(Integer.valueOf(schId));
teacherCopilot.setShowSchIds(schIds);
teacherCopilotRepository.save(teacherCopilot);
}
@Override
public void delete(Integer id) {
Optional<TeacherCopilot> optional = teacherCopilotRepository.findById(id);
if (!optional.isPresent())
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
teacherCopilotRepository.delete(optional.get());
}
}
@@ -0,0 +1,118 @@
package com.yunhai.userhome.service.impl;
import com.yunhai.userhome.entity.UserMessage;
import com.yunhai.userhome.repository.UserMessageRepository;
import com.yunhai.userhome.service.IUserMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* 用户消息服务:行为对齐旧 UserHome UserMessageService(本地 user_message 表)。
* WS 推送态由前端轮询兜底,本服务不消费 Redis 缓存(旧工程依赖 Redis,新工程未引入)。
*/
@Service
public class UserMessageServiceImpl implements IUserMessageService {
@Autowired
private UserMessageRepository userMessageRepository;
@Override
public List<UserMessage> getUserMessageAppIds(Integer userId, Integer schId) {
return userMessageRepository.getUserMessageAppList(userId, schId);
}
@Override
public Page<UserMessage> findUserMessageByAppId(UserMessage userMessage, Pageable pageable) {
return userMessageRepository.findAll(select(userMessage), pageable);
}
@Override
public Page<UserMessage> findUserMessageByUserId(Integer userId, Pageable pageable) {
return userMessageRepository.findAll(select(userId, null), pageable);
}
@Override
public List<UserMessage> findUserMessageByUserId(Integer userId) {
// 旧版优先读 Redis 缓存,缓存缺失再查库;新工程无 Redis,直接查库(行为等价:返回该用户全部消息)
return userMessageRepository.findAll(select(userId, null), PageRequest.of(0, Integer.MAX_VALUE, Sort.by(Sort.Direction.DESC, "cDate"))).getContent();
}
@Override
public Boolean findUserMessageUnRead(Integer userId) {
return userMessageRepository.count(select(userId, false)) > 0;
}
@Override
public void updateRead(Integer userId, Integer appId) {
userMessageRepository.updateRead(userId, appId);
}
@Override
public void updateUserRead(Integer id, Integer userId) {
// 单条已读:前端按 id 移除本地列表后再调;服务端标记该条已读
userMessageRepository.updateReadById(id);
}
@Override
public void updateReadAll(Integer userId) {
userMessageRepository.updateReadAll(userId);
}
@Override
public Page<UserMessage> findUserMessageById(Integer userId, Integer page, Integer count) {
Sort sort = Sort.by(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(page - 1, count, sort);
return userMessageRepository.findAll(select(userId, null), pageable);
}
@Override
public void readMsgById(Integer msgId) {
userMessageRepository.updateReadById(msgId);
}
@Override
public void readMsgAll(Integer userId) {
userMessageRepository.updateReadAll(userId);
}
private Specification<UserMessage> select(UserMessage userMessage) {
return (Root<UserMessage> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (userMessage != null) {
if (userMessage.getUserId() != null) {
predicates.add(cb.equal(root.get("userId"), userMessage.getUserId()));
}
if (userMessage.getAppId() != null) {
predicates.add(cb.equal(root.get("appId"), userMessage.getAppId()));
}
}
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
};
}
private Specification<UserMessage> select(Integer userId, Boolean isRead) {
return (Root<UserMessage> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (userId != null) {
predicates.add(cb.equal(root.get("userId"), userId));
}
if (isRead != null) {
predicates.add(cb.equal(root.get("isRead"), isRead));
}
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
};
}
}
@@ -0,0 +1,203 @@
package com.yunhai.userhome.service.impl;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.userhome.entity.*;
import com.yunhai.userhome.repository.LightAppRepository;
import com.yunhai.userhome.repository.UserSettingsDesktopAppRepository;
import com.yunhai.userhome.repository.UserSettingsRepository;
import com.yunhai.userhome.repository.WallpaperRepository;
import com.yunhai.userhome.service.IUserCurrentRoleService;
import com.yunhai.userhome.service.IUserSettingsService;
import com.yunhai.userhome.utils.OtherUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 用户设置服务(对齐旧 UserHome service.impl.UserSettingsService)。
*/
@Service
public class UserSettingsServiceImpl implements IUserSettingsService {
@Autowired
private WallpaperRepository wallpaperRepository;
@Autowired
private UserSettingsRepository userSettingsRepository;
@Autowired
private IUserCurrentRoleService userCurrentRoleService;
@Autowired
private LightAppRepository lightAppRepository;
@Autowired
private UserSettingsDesktopAppRepository userSettingsDesktopAppRepository;
@Override
public List<Wallpaper> findWallList(Integer userId) {
UserCurrentRole currentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
List<Wallpaper> resultList = new ArrayList<>();
List<Wallpaper> baseList = wallpaperRepository.findBySchIdAndType(0, 0);
List<Wallpaper> schList = wallpaperRepository.findBySchIdAndType(currentRole.getSchId(), 1);
List<Wallpaper> userList = wallpaperRepository.findByUserIdAndType(userId, 2);
if (currentRole.getSchId() == 0) baseList.forEach(x -> x.setIsEdit(true));
if (OtherUtil.isAdminById(currentRole.getRoleId())) schList.forEach(x -> x.setIsEdit(true));
userList.forEach(x -> x.setIsEdit(true));
resultList.addAll(baseList);
resultList.addAll(schList);
resultList.addAll(userList);
return resultList;
}
@Override
public void deleteWallById(Integer id) {
if (!wallpaperRepository.existsById(id))
throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR);
wallpaperRepository.deleteById(id);
}
@Override
public void saveWallpaper(Wallpaper wallpaper) {
wallpaperRepository.save(wallpaper);
}
@Override
public void checkWallpaper(Integer userId, String wallpaperUrl) {
UserSettings model = getUserSettings(null, userId);
model.setWallpaperUrl(wallpaperUrl);
userSettingsRepository.save(model);
}
@Override
public Optional<UserSettings> findUserSettings(Integer userId) {
UserCurrentRole currentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
return userSettingsRepository.findByUserIdAndSchIdAndRoleId(currentRole.getUserId(), currentRole.getSchId(), currentRole.getRoleId());
}
@Override
public void saveUserSettings(UserSettings userSettings) {
userSettingsRepository.save(userSettings);
}
@Override
public void saveUserWidget(UserSettings userSettings) {
UserSettings model = getUserSettings(userSettings.getId(), userSettings.getUserId());
model.setXAxis(userSettings.getXAxis());
model.setYAxis(userSettings.getYAxis());
model.setWidth(userSettings.getWidth());
model.setHeight(userSettings.getHeight());
model.setIsWidgetShow(true);
userSettingsRepository.save(model);
}
@Override
public void saveUserAppIds(Integer id, Integer userId, String appIds) {
UserSettings model = getUserSettings(id, userId);
model.setWidgetAppIds(appIds);
userSettingsRepository.save(model);
}
@Override
public void toggleWidgetShow(Integer id, Integer userId) {
UserSettings model = getUserSettings(id, userId);
if (model.getIsWidgetShow() == null) model.setIsWidgetShow(true);
model.setIsWidgetShow(!model.getIsWidgetShow());
userSettingsRepository.save(model);
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public List<LightApp> findLightAppList(Integer schId, Integer userId) {
Specification specification = (Specification) (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
Predicate basePre = criteriaBuilder.and(
criteriaBuilder.equal(root.get("schId"), 0),
criteriaBuilder.equal(root.get("isPublic"), true));
Predicate schPre = criteriaBuilder.and(
criteriaBuilder.equal(root.get("schId"), schId),
criteriaBuilder.equal(root.get("isPublic"), true));
Predicate userPre = criteriaBuilder.and(
criteriaBuilder.equal(root.get("schId"), schId),
criteriaBuilder.equal(root.get("userId"), userId));
if (schId == 0)
predicates.add(basePre);
else if (userId == null)
predicates.add(criteriaBuilder.or(basePre, schPre));
else
predicates.add(criteriaBuilder.or(basePre, schPre, userPre));
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
};
Sort sort = Sort.by(Sort.Direction.DESC, "id");
List<LightApp> result = lightAppRepository.findAll(specification, sort);
if (schId == 0) result.forEach(x -> x.setIsEdit(true));
else if (userId == null)
result.stream().filter(x -> x.getSchId() != null && x.getSchId().equals(schId) && x.getUserId() == null)
.forEach(x -> x.setIsEdit(true));
else
result.stream().filter(x -> x.getSchId() != null && x.getUserId() != null && x.getSchId().equals(schId) && x.getUserId().equals(userId))
.forEach(x -> x.setIsEdit(true));
return result;
}
@Override
public void saveLightApp(LightApp lightApp) {
if (lightApp.getSchId() == 0) lightApp.setUserId(null);
if (lightApp.getUserId() == null) lightApp.setIsPublic(true);
lightAppRepository.save(lightApp);
}
@Override
public void deleteLightAppById(Integer id) {
lightAppRepository.deleteById(id);
}
@Override
public void deleteDesktopAppById(Integer id) {
userSettingsDesktopAppRepository.deleteById(id);
}
@Override
public void saveDesktopApp(UserSettingsDesktopApp model) {
userSettingsDesktopAppRepository.save(model);
}
@Override
public List<UserSettingsDesktopApp> saveDesktopAppList(List<UserSettingsDesktopApp> list) {
return userSettingsDesktopAppRepository.saveAll(list);
}
@Override
public UserSettings initUserSettings(Integer userId) {
UserCurrentRole currentRole = userCurrentRoleService.findById(userId)
.orElseThrow(() -> new BizException(ErrorCode.INTERNAL_SERVER_ERROR));
UserSettings model = new UserSettings();
model.setSchId(currentRole.getSchId());
model.setRoleId(currentRole.getRoleId());
model.setUserId(currentRole.getUserId());
return userSettingsRepository.save(model);
}
private UserSettings getUserSettings(Integer id, Integer userId) {
Optional<UserSettings> optional;
if (id != null)
optional = userSettingsRepository.findById(id);
else
optional = findUserSettings(userId);
if (optional.isPresent()) return optional.get();
else {
return initUserSettings(userId);
}
}
}
@@ -0,0 +1,108 @@
package com.yunhai.userhome.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 枚举工具类(对齐旧 UserHome utils.EnumUtil,commons-lang → hutool)。
*/
public final class EnumUtil {
/**
* 枚举转 List&lt;Map&gt; 格式(每个枚举项 → {key, value, enum})。
*/
@SuppressWarnings("rawtypes")
public static List<Map<String, Object>> toMapList(Class targetEnumClazz) {
Method[] methods = targetEnumClazz.getMethods();
Field[] fields = targetEnumClazz.getDeclaredFields();
List<Field> fieldList = new ArrayList<>();
for (Method method : methods) {
for (Field field : fields) {
String capitalized = Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);
if (method.getName().endsWith(capitalized)) {
fieldList.add(field);
}
}
}
List<Map<String, Object>> resultList = new ArrayList<>();
Enum[] enums = (Enum[]) targetEnumClazz.getEnumConstants();
Object value = null;
try {
for (Enum e : enums) {
Map<String, Object> eMap = new HashMap<>();
for (Field field : fieldList) {
field.setAccessible(true);
value = field.get(e);
eMap.put(field.getName(), value);
}
eMap.put("enum", e);
resultList.add(eMap);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return resultList;
}
@SuppressWarnings("rawtypes")
public static String getValue(Class targetEnumClazz, String key) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("key").toString().equals(key)) {
return map.get("value").toString();
}
}
return "";
}
@SuppressWarnings("rawtypes")
public static String getKey(Class targetEnumClazz, String value) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("value").toString().equals(value)) {
return map.get("key").toString();
}
}
return "";
}
@SuppressWarnings("rawtypes")
public static boolean isExistKey(Class targetEnumClazz, String key) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
return list.stream().filter(x -> x.get("key").equals(key)).count() > 0;
}
@SuppressWarnings("rawtypes")
public static boolean isExistValue(Class targetEnumClazz, String value) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
return list.stream().filter(x -> x.get("value").equals(value)).count() > 0;
}
@SuppressWarnings("rawtypes")
public static Object getEnumByKey(Class targetEnumClazz, String key) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("key").toString().equals(key)) {
return map.get("enum");
}
}
return null;
}
@SuppressWarnings("rawtypes")
public static List<Map<String, Object>> toMapList(Class targetEnumClazz, String keyName, String valueName) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
List result = new ArrayList();
for (Map map : list) {
Map newMap = new HashMap();
newMap.put(keyName, map.get("key"));
newMap.put(valueName, map.get("value"));
result.add(newMap);
}
return result;
}
}
@@ -0,0 +1,70 @@
package com.yunhai.userhome.utils;
import cn.hutool.core.util.IdUtil;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
/**
* File工具类(对齐旧 UserHome utils.FileUtil,仅保留 uploadImg 方法——本期迁移实际使用的唯一方法)。
*/
public class FileUtil {
/**
* 上传图片(byte[] 版),返回生成的文件名。
*/
public static String uploadImg(byte[] imgData, String pathName) {
String imgName = null;
String path = null;
File floorFile = null;
try {
for (int i = 0; i < 100; i++) {
imgName = UUID.randomUUID().toString().substring(0, 8) + ".png";
path = pathName + imgName;
floorFile = new File(path);
if (floorFile.exists()) continue;
else break;
}
FileOutputStream fos = new FileOutputStream(floorFile);
fos.write(imgData);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
return imgName;
}
/**
* 上传图片(MultipartFile 版),保留原始扩展名,返回生成的文件名。
*/
public static String uploadImg(MultipartFile file, String pathName) {
String imgName = null;
String path = null;
File floorFile = null;
try {
byte[] imgData = file.getBytes();
String fileName = file.getOriginalFilename();
int index = fileName.lastIndexOf(".");
String ext = "";
if (index > 0) {
ext = fileName.substring(index);
}
for (int i = 0; i < 100; i++) {
imgName = UUID.randomUUID().toString().substring(0, 8) + ext;
path = pathName + imgName;
floorFile = new File(path);
if (floorFile.exists()) continue;
else break;
}
FileOutputStream fos = new FileOutputStream(floorFile);
fos.write(imgData);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
return imgName;
}
}
@@ -0,0 +1,89 @@
package com.yunhai.userhome.utils;
import org.springframework.stereotype.Component;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* 轻量内存缓存(替换旧工程 bsch MapCacheUtil)。
* 用于 getMsgAddress 的 uuid→userId 鉴权握手缓存,20s 有效。
* 单例 + 守护线程周期清扫过期项,线程安全(ConcurrentHashMap)。
*/
@Component
public class MapCacheUtil {
private static final int CLEAN_UP_PERIOD_IN_SEC = 5;
private final ConcurrentHashMap<String, CacheObject> cache = new ConcurrentHashMap<>();
private static MapCacheUtil instance;
public static synchronized MapCacheUtil getInstance() {
if (instance == null) {
instance = new MapCacheUtil();
}
return instance;
}
private MapCacheUtil() {
Thread cleanerThread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(CLEAN_UP_PERIOD_IN_SEC * 1000L);
cache.entrySet().removeIf(entry ->
Optional.ofNullable(entry.getValue()).map(CacheObject::isExpired).orElse(false));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
cleanerThread.setDaemon(true);
cleanerThread.start();
}
public void add(String key, Object value, long periodInMillis) {
if (key == null) {
return;
}
if (value == null) {
cache.remove(key);
} else {
long expiryTime = System.currentTimeMillis() + periodInMillis;
cache.put(key, new CacheObject(value, expiryTime));
}
}
public void remove(String key) {
cache.remove(key);
}
public Object get(String key) {
return Optional.ofNullable(cache.get(key))
.filter(c -> !c.isExpired())
.map(CacheObject::getValue)
.orElse(null);
}
public void clear() {
cache.clear();
}
private static class CacheObject {
private final Object value;
private final long expiryTime;
private CacheObject(Object value, long expiryTime) {
this.value = value;
this.expiryTime = expiryTime;
}
boolean isExpired() {
return System.currentTimeMillis() > expiryTime;
}
public Object getValue() {
return value;
}
}
}
@@ -0,0 +1,29 @@
package com.yunhai.userhome.utils;
import java.util.Arrays;
/**
* 杂项公用方法集合(对齐旧 UserHome utils.OtherUtil,fastjson 相关方法移除——新框架用 Jackson)。
*/
public class OtherUtil {
/**
* 十六进制转字符串
*/
public final static String hexToString(String hex) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hex.length(); i += 2) {
String hexSubstring = hex.substring(i, i + 2);
int decimalValue = Integer.parseInt(hexSubstring, 16);
sb.append((char) decimalValue);
}
return sb.toString();
}
/**
* 判断是否为校领导
*/
public final static Boolean isAdminById(Integer roleId) {
return Arrays.asList(2, 5, 7).contains(roleId);
}
}
+17 -3
View File
@@ -38,10 +38,16 @@ spring:
# ===== 基础平台 yh 配置(遵循 yh-* spring-boot-starter 约定,具体 key 以对应 starter 版本为准)=====
yh:
auth:
enabled: true
sso:
# CAS 单点登录(浏览器 SSO 重定向 / ticket 校验)
cas:
server-url-prefix: https://sso.yunhaixingtong.com/cas
service: http://localhost:8070
server-url-prefix: https://sso.yunhaixingtong.com/cas/
# 本地 context-path=/、端口 8070;prod 由 Nacos 的 yh.sso.client-host-url 覆盖
client-host-url: http://localhost:8070
allow-headers: all
allow-origins: all
url-pattern: /api/*
mobi-api-pattern: /mobiapi/*
app-auth:
# 应用间签名鉴权(UserHome 作为调用方访问 UserBase 跨仓接口时使用)
enabled: true
@@ -60,3 +66,11 @@ yh:
logging:
level:
com.yunhai.userhome: debug
# ===== 文件上传与学校配置 =====
# 文件存储根目录(UserSettingsController 壁纸/图标上传使用)
FILE_PATH: ./upload/
# 文件 Web 访问前缀(prod 由 Nacos 覆盖)
FILE_WEB_PATH: http://localhost:8070/upload/
# 学校配置接口基址(SchSettingsController 使用,prod 由 Nacos 覆盖)
SCH_CONF_URL: ""