mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-11-14 23:10:41 +00:00
feat: enhance coding harness, model security and system features
This commit is contained in:
@@ -110,6 +110,12 @@
|
||||
<artifactId>ruoyi-common-social</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -81,7 +81,8 @@ public class SysUserOnlineController extends BaseController {
|
||||
* @param tokenId token值
|
||||
*/
|
||||
@SaCheckPermission("monitor:online:forceLogout")
|
||||
@Log(title = "在线用户", businessType = BusinessType.FORCE)
|
||||
@Log(title = "在线用户", businessType = BusinessType.FORCE,
|
||||
isSaveRequestData = false, isSaveResponseData = false)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping("/{tokenId}")
|
||||
public R<Void> forceLogout(@PathVariable String tokenId) {
|
||||
@@ -115,7 +116,8 @@ public class SysUserOnlineController extends BaseController {
|
||||
*
|
||||
* @param tokenId token值
|
||||
*/
|
||||
@Log(title = "在线设备", businessType = BusinessType.FORCE)
|
||||
@Log(title = "在线设备", businessType = BusinessType.FORCE,
|
||||
isSaveRequestData = false, isSaveResponseData = false)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping("/myself/{tokenId}")
|
||||
public R<Void> remove(@PathVariable("tokenId") String tokenId) {
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
package org.ruoyi.system.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.ruoyi.common.log.annotation.Log;
|
||||
import org.ruoyi.common.log.enums.BusinessType;
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.common.web.core.BaseController;
|
||||
import org.ruoyi.system.domain.bo.CmsContentBo;
|
||||
import org.ruoyi.system.domain.vo.CmsContentVo;
|
||||
import org.ruoyi.system.service.ICmsContentService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 内容管理 信息操作处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/cms/content")
|
||||
public class CmsContentController extends BaseController {
|
||||
|
||||
private final ICmsContentService cmsContentService;
|
||||
|
||||
/**
|
||||
* 获取内容管理列表
|
||||
*/
|
||||
@SaCheckPermission("cms:content:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CmsContentVo> list(CmsContentBo bo, PageQuery pageQuery) {
|
||||
return cmsContentService.selectPageCmsContentList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据内容编号获取详细信息
|
||||
*/
|
||||
@SaCheckPermission("cms:content:query")
|
||||
@GetMapping(value = "/{contentId}")
|
||||
public R<CmsContentVo> getInfo(@PathVariable Long contentId) {
|
||||
return R.ok(cmsContentService.selectCmsContentById(contentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增内容
|
||||
*/
|
||||
@SaCheckPermission("cms:content:add")
|
||||
@Log(title = "内容管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody CmsContentBo bo) {
|
||||
return toAjax(cmsContentService.insertCmsContent(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改内容
|
||||
*/
|
||||
@SaCheckPermission("cms:content:edit")
|
||||
@Log(title = "内容管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated @RequestBody CmsContentBo bo) {
|
||||
return toAjax(cmsContentService.updateCmsContent(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除内容
|
||||
*/
|
||||
@SaCheckPermission("cms:content:remove")
|
||||
@Log(title = "内容管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{contentIds}")
|
||||
public R<Void> remove(@PathVariable Long[] contentIds) {
|
||||
return toAjax(cmsContentService.deleteCmsContentByIds(contentIds));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.ruoyi.system.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.core.validate.AddGroup;
|
||||
import org.ruoyi.common.core.validate.EditGroup;
|
||||
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.ruoyi.common.log.annotation.Log;
|
||||
import org.ruoyi.common.log.enums.BusinessType;
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.common.web.core.BaseController;
|
||||
import org.ruoyi.system.domain.bo.SysUrlBo;
|
||||
import org.ruoyi.system.domain.vo.SysUrlShortcutVo;
|
||||
import org.ruoyi.system.domain.vo.SysUrlVo;
|
||||
import org.ruoyi.system.service.ISysUrlService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* URL 管理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/system/url")
|
||||
public class SysUrlController extends BaseController {
|
||||
|
||||
private final ISysUrlService urlService;
|
||||
|
||||
/**
|
||||
* 分页查询 URL 列表(支持名称、状态筛选)
|
||||
*/
|
||||
@SaCheckPermission("system:url:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<SysUrlVo> list(SysUrlBo bo, PageQuery pageQuery) {
|
||||
return urlService.selectPageUrlList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Copilot 新会话快捷入口(当前租户已启用链接)
|
||||
* 允许 coding:harness:use 或 system:url:list 权限
|
||||
*/
|
||||
@SaCheckPermission(value = {"system:url:list", "coding:harness:use"}, mode = SaMode.OR)
|
||||
@GetMapping("/shortcuts")
|
||||
public R<List<SysUrlShortcutVo>> shortcuts() {
|
||||
return R.ok(urlService.selectShortcutList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 ID 获取 URL 详细信息
|
||||
*
|
||||
* @param urlId 链接ID
|
||||
*/
|
||||
@SaCheckPermission("system:url:query")
|
||||
@GetMapping(value = "/{urlId}")
|
||||
public R<SysUrlVo> getInfo(@NotNull(message = "链接ID不能为空") @PathVariable Long urlId) {
|
||||
return R.ok(urlService.selectUrlById(urlId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增 URL
|
||||
*/
|
||||
@SaCheckPermission("system:url:add")
|
||||
@Log(title = "URL管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysUrlBo bo) {
|
||||
return toAjax(urlService.insertUrl(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改 URL
|
||||
*/
|
||||
@SaCheckPermission("system:url:edit")
|
||||
@Log(title = "URL管理", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysUrlBo bo) {
|
||||
return toAjax(urlService.updateUrl(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 URL(支持批量)
|
||||
*
|
||||
* @param urlIds 链接ID串
|
||||
*/
|
||||
@SaCheckPermission("system:url:remove")
|
||||
@Log(title = "URL管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{urlIds}")
|
||||
public R<Void> remove(@PathVariable Long[] urlIds) {
|
||||
return toAjax(urlService.deleteUrlByIds(urlIds));
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package org.ruoyi.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import org.ruoyi.common.tenant.core.TenantEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 内容管理表 cms_content
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("cms_content")
|
||||
public class CmsContent extends TenantEntity {
|
||||
|
||||
/**
|
||||
* 内容ID
|
||||
*/
|
||||
@TableId(value = "content_id")
|
||||
private Long contentId;
|
||||
|
||||
/**
|
||||
* 内容标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 摘要
|
||||
*/
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
* 正文内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 封面图片
|
||||
*/
|
||||
private String coverImage;
|
||||
|
||||
/**
|
||||
* 状态(0草稿 1已发布 2下架)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 发布时间
|
||||
*/
|
||||
private Date publishTime;
|
||||
|
||||
/**
|
||||
* 排序顺序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private String delFlag;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.ruoyi.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import org.ruoyi.common.tenant.core.TenantEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* URL 管理表 sys_url
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_url")
|
||||
public class SysUrl extends TenantEntity {
|
||||
|
||||
/**
|
||||
* 链接ID
|
||||
*/
|
||||
@TableId(value = "url_id")
|
||||
private Long urlId;
|
||||
|
||||
/**
|
||||
* 链接名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* HTTP(S) 地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 链接说明
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package org.ruoyi.system.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.common.core.xss.Xss;
|
||||
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
|
||||
import org.ruoyi.system.domain.CmsContent;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 内容管理业务对象 cms_content
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = CmsContent.class, reverseConvertGenerate = false)
|
||||
public class CmsContentBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 内容ID
|
||||
*/
|
||||
private Long contentId;
|
||||
|
||||
/**
|
||||
* 内容标题
|
||||
*/
|
||||
@Xss(message = "内容标题不能包含脚本字符")
|
||||
@NotBlank(message = "内容标题不能为空")
|
||||
@Size(min = 0, max = 200, message = "内容标题不能超过{max}个字符")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 摘要
|
||||
*/
|
||||
@Size(min = 0, max = 500, message = "摘要不能超过{max}个字符")
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
* 正文内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 封面图片
|
||||
*/
|
||||
@Size(min = 0, max = 255, message = "封面图片路径不能超过{max}个字符")
|
||||
private String coverImage;
|
||||
|
||||
/**
|
||||
* 状态(0草稿 1已发布 2下架)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 发布时间
|
||||
*/
|
||||
private Date publishTime;
|
||||
|
||||
/**
|
||||
* 排序顺序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Size(min = 0, max = 500, message = "备注不能超过{max}个字符")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建人名称
|
||||
*/
|
||||
private String createByName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.ruoyi.system.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.common.core.validate.AddGroup;
|
||||
import org.ruoyi.common.core.validate.EditGroup;
|
||||
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
|
||||
import org.ruoyi.system.domain.SysUrl;
|
||||
|
||||
/**
|
||||
* URL 管理业务对象 sys_url
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = SysUrl.class, reverseConvertGenerate = false)
|
||||
public class SysUrlBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 链接ID
|
||||
*/
|
||||
@NotNull(message = "链接ID不能为空", groups = {EditGroup.class})
|
||||
private Long urlId;
|
||||
|
||||
/**
|
||||
* 链接名称
|
||||
*/
|
||||
@NotBlank(message = "链接名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(max = 100, message = "链接名称不能超过{max}个字符", groups = {AddGroup.class, EditGroup.class})
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* HTTP(S) 地址
|
||||
*/
|
||||
@NotBlank(message = "链接地址不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(max = 500, message = "链接地址不能超过{max}个字符", groups = {AddGroup.class, EditGroup.class})
|
||||
@Pattern(regexp = "^https?://.*", message = "链接地址必须以 http:// 或 https:// 开头", groups = {AddGroup.class, EditGroup.class})
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 链接说明
|
||||
*/
|
||||
@Size(max = 500, message = "链接说明不能超过{max}个字符", groups = {AddGroup.class, EditGroup.class})
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
@NotBlank(message = "状态不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Pattern(regexp = "^[01]$", message = "状态只能为 0(正常)或 1(停用)", groups = {AddGroup.class, EditGroup.class})
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package org.ruoyi.system.domain.vo;
|
||||
|
||||
import org.ruoyi.common.translation.annotation.Translation;
|
||||
import org.ruoyi.common.translation.constant.TransConstant;
|
||||
import org.ruoyi.system.domain.CmsContent;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 内容管理视图对象 cms_content
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CmsContent.class)
|
||||
public class CmsContentVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 内容ID
|
||||
*/
|
||||
private Long contentId;
|
||||
|
||||
/**
|
||||
* 内容标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 摘要
|
||||
*/
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
* 正文内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 封面图片
|
||||
*/
|
||||
private String coverImage;
|
||||
|
||||
/**
|
||||
* 状态(0草稿 1已发布 2下架)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 发布时间
|
||||
*/
|
||||
private Date publishTime;
|
||||
|
||||
/**
|
||||
* 排序顺序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建人名称
|
||||
*/
|
||||
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
|
||||
private String createByName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.ruoyi.system.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* URL 快捷入口视图对象(供 Copilot 新会话展示)
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class SysUrlShortcutVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 链接ID
|
||||
*/
|
||||
private Long urlId;
|
||||
|
||||
/**
|
||||
* 链接名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* HTTP(S) 地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 链接说明
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.ruoyi.system.domain.vo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.ruoyi.system.domain.SysUrl;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* URL 管理视图对象 sys_url
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = SysUrl.class)
|
||||
public class SysUrlVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 链接ID
|
||||
*/
|
||||
private Long urlId;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 链接名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* HTTP(S) 地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 链接说明
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class UserActionListener implements SaTokenListener {
|
||||
SpringUtils.context().publishEvent(logininforEvent);
|
||||
// 更新登录信息
|
||||
loginService.recordLoginInfo((Long) loginParameter.getExtra(LoginHelper.USER_KEY), ip);
|
||||
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
|
||||
log.info("{}", authenticationEventSummary("login", loginId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +85,7 @@ public class UserActionListener implements SaTokenListener {
|
||||
TenantHelper.dynamic(tenantId, () -> {
|
||||
RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
|
||||
});
|
||||
log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue);
|
||||
log.info("{}", authenticationEventSummary("logout", loginId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +97,7 @@ public class UserActionListener implements SaTokenListener {
|
||||
TenantHelper.dynamic(tenantId, () -> {
|
||||
RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
|
||||
});
|
||||
log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue);
|
||||
log.info("{}", authenticationEventSummary("kickout", loginId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +109,7 @@ public class UserActionListener implements SaTokenListener {
|
||||
TenantHelper.dynamic(tenantId, () -> {
|
||||
RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
|
||||
});
|
||||
log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue);
|
||||
log.info("{}", authenticationEventSummary("replaced", loginId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,4 +160,9 @@ public class UserActionListener implements SaTokenListener {
|
||||
@Override
|
||||
public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
|
||||
}
|
||||
|
||||
/** The logging boundary cannot accept a token, making accidental formatting impossible. */
|
||||
static String authenticationEventSummary(String event, Object loginId) {
|
||||
return "authentication event=" + event + ", userId=" + loginId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.ruoyi.system.mapper;
|
||||
|
||||
import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.ruoyi.system.domain.CmsContent;
|
||||
import org.ruoyi.system.domain.vo.CmsContentVo;
|
||||
|
||||
/**
|
||||
* 内容管理表 数据层
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface CmsContentMapper extends BaseMapperPlus<CmsContent, CmsContentVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.ruoyi.system.mapper;
|
||||
|
||||
import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.ruoyi.system.domain.SysUrl;
|
||||
import org.ruoyi.system.domain.vo.SysUrlVo;
|
||||
|
||||
/**
|
||||
* URL 管理表 数据层
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface SysUrlMapper extends BaseMapperPlus<SysUrl, SysUrlVo> {
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.system.domain.bo.CmsContentBo;
|
||||
import org.ruoyi.system.domain.vo.CmsContentVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 内容管理 服务层
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ICmsContentService {
|
||||
|
||||
/**
|
||||
* 分页查询内容管理列表
|
||||
*/
|
||||
TableDataInfo<CmsContentVo> selectPageCmsContentList(CmsContentBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询内容信息
|
||||
*/
|
||||
CmsContentVo selectCmsContentById(Long contentId);
|
||||
|
||||
/**
|
||||
* 查询内容列表
|
||||
*/
|
||||
List<CmsContentVo> selectCmsContentList(CmsContentBo bo);
|
||||
|
||||
/**
|
||||
* 新增内容
|
||||
*/
|
||||
int insertCmsContent(CmsContentBo bo);
|
||||
|
||||
/**
|
||||
* 修改内容
|
||||
*/
|
||||
int updateCmsContent(CmsContentBo bo);
|
||||
|
||||
/**
|
||||
* 删除内容信息
|
||||
*/
|
||||
int deleteCmsContentById(Long contentId);
|
||||
|
||||
/**
|
||||
* 批量删除内容信息
|
||||
*/
|
||||
int deleteCmsContentByIds(Long[] contentIds);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.system.domain.bo.SysUrlBo;
|
||||
import org.ruoyi.system.domain.vo.SysUrlShortcutVo;
|
||||
import org.ruoyi.system.domain.vo.SysUrlVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* URL 管理 服务层
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ISysUrlService {
|
||||
|
||||
/**
|
||||
* 分页查询 URL 列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return URL 分页列表
|
||||
*/
|
||||
TableDataInfo<SysUrlVo> selectPageUrlList(SysUrlBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 根据 ID 查询 URL 详情
|
||||
*
|
||||
* @param urlId 链接ID
|
||||
* @return URL 信息
|
||||
*/
|
||||
SysUrlVo selectUrlById(Long urlId);
|
||||
|
||||
/**
|
||||
* 新增 URL
|
||||
*
|
||||
* @param bo URL 信息
|
||||
* @return 结果
|
||||
*/
|
||||
int insertUrl(SysUrlBo bo);
|
||||
|
||||
/**
|
||||
* 修改 URL
|
||||
*
|
||||
* @param bo URL 信息
|
||||
* @return 结果
|
||||
*/
|
||||
int updateUrl(SysUrlBo bo);
|
||||
|
||||
/**
|
||||
* 批量删除 URL
|
||||
*
|
||||
* @param urlIds 需要删除的链接ID
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteUrlByIds(Long[] urlIds);
|
||||
|
||||
/**
|
||||
* 查询当前租户已启用的快捷入口列表(按排序升序)
|
||||
*
|
||||
* @return 快捷入口列表
|
||||
*/
|
||||
List<SysUrlShortcutVo> selectShortcutList();
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package org.ruoyi.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.core.utils.MapstructUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.system.domain.CmsContent;
|
||||
import org.ruoyi.system.domain.bo.CmsContentBo;
|
||||
import org.ruoyi.system.domain.vo.CmsContentVo;
|
||||
import org.ruoyi.system.mapper.CmsContentMapper;
|
||||
import org.ruoyi.system.service.ICmsContentService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 内容管理 服务层实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CmsContentServiceImpl implements ICmsContentService {
|
||||
|
||||
private final CmsContentMapper baseMapper;
|
||||
|
||||
@Override
|
||||
public TableDataInfo<CmsContentVo> selectPageCmsContentList(CmsContentBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<CmsContent> lqw = buildQueryWrapper(bo);
|
||||
Page<CmsContentVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CmsContentVo selectCmsContentById(Long contentId) {
|
||||
return baseMapper.selectVoById(contentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CmsContentVo> selectCmsContentList(CmsContentBo bo) {
|
||||
LambdaQueryWrapper<CmsContent> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<CmsContent> buildQueryWrapper(CmsContentBo bo) {
|
||||
LambdaQueryWrapper<CmsContent> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getTitle()), CmsContent::getTitle, bo.getTitle());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), CmsContent::getStatus, bo.getStatus());
|
||||
lqw.eq(bo.getPublishTime() != null, CmsContent::getPublishTime, bo.getPublishTime());
|
||||
lqw.orderByAsc(CmsContent::getSortOrder);
|
||||
lqw.orderByDesc(CmsContent::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertCmsContent(CmsContentBo bo) {
|
||||
CmsContent content = MapstructUtils.convert(bo, CmsContent.class);
|
||||
return baseMapper.insert(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCmsContent(CmsContentBo bo) {
|
||||
CmsContent content = MapstructUtils.convert(bo, CmsContent.class);
|
||||
return baseMapper.updateById(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteCmsContentById(Long contentId) {
|
||||
return baseMapper.deleteById(contentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteCmsContentByIds(Long[] contentIds) {
|
||||
return baseMapper.deleteByIds(Arrays.asList(contentIds));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package org.ruoyi.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.core.exception.ServiceException;
|
||||
import org.ruoyi.common.core.utils.MapstructUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.system.domain.SysUrl;
|
||||
import org.ruoyi.system.domain.bo.SysUrlBo;
|
||||
import org.ruoyi.system.domain.vo.SysUrlShortcutVo;
|
||||
import org.ruoyi.system.domain.vo.SysUrlVo;
|
||||
import org.ruoyi.system.mapper.SysUrlMapper;
|
||||
import org.ruoyi.system.service.ISysUrlService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* URL 管理 服务层实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SysUrlServiceImpl implements ISysUrlService {
|
||||
|
||||
/**
|
||||
* 状态:正常
|
||||
*/
|
||||
private static final String STATUS_NORMAL = "0";
|
||||
|
||||
private final SysUrlMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 分页查询 URL 列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return URL 分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<SysUrlVo> selectPageUrlList(SysUrlBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysUrl> lqw = buildQueryWrapper(bo);
|
||||
Page<SysUrlVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 ID 查询 URL 详情
|
||||
*
|
||||
* @param urlId 链接ID
|
||||
* @return URL 信息
|
||||
*/
|
||||
@Override
|
||||
public SysUrlVo selectUrlById(Long urlId) {
|
||||
SysUrlVo vo = baseMapper.selectVoById(urlId);
|
||||
if (vo == null) {
|
||||
throw new ServiceException("链接不存在或已被删除");
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增 URL
|
||||
*
|
||||
* @param bo URL 信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertUrl(SysUrlBo bo) {
|
||||
validateUrl(bo.getUrl());
|
||||
SysUrl url = MapstructUtils.convert(bo, SysUrl.class);
|
||||
if (url.getSortOrder() == null) {
|
||||
url.setSortOrder(0);
|
||||
}
|
||||
if (StringUtils.isBlank(url.getStatus())) {
|
||||
url.setStatus(STATUS_NORMAL);
|
||||
}
|
||||
return baseMapper.insert(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改 URL
|
||||
*
|
||||
* @param bo URL 信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateUrl(SysUrlBo bo) {
|
||||
validateUrl(bo.getUrl());
|
||||
if (bo.getUrlId() == null || baseMapper.selectById(bo.getUrlId()) == null) {
|
||||
throw new ServiceException("链接不存在或已被删除");
|
||||
}
|
||||
SysUrl url = MapstructUtils.convert(bo, SysUrl.class);
|
||||
return baseMapper.updateById(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除 URL
|
||||
*
|
||||
* @param urlIds 需要删除的链接ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteUrlByIds(Long[] urlIds) {
|
||||
return baseMapper.deleteByIds(Arrays.asList(urlIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前租户已启用的快捷入口列表(按排序升序)
|
||||
*
|
||||
* @return 快捷入口列表
|
||||
*/
|
||||
@Override
|
||||
public List<SysUrlShortcutVo> selectShortcutList() {
|
||||
LambdaQueryWrapper<SysUrl> lqw = Wrappers.<SysUrl>lambdaQuery()
|
||||
.eq(SysUrl::getStatus, STATUS_NORMAL)
|
||||
.orderByAsc(SysUrl::getSortOrder)
|
||||
.orderByAsc(SysUrl::getUrlId);
|
||||
return baseMapper.selectVoList(lqw).stream()
|
||||
.map(this::toShortcut)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<SysUrl> buildQueryWrapper(SysUrlBo bo) {
|
||||
LambdaQueryWrapper<SysUrl> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getName()), SysUrl::getName, bo.getName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysUrl::getStatus, bo.getStatus());
|
||||
lqw.orderByAsc(SysUrl::getSortOrder);
|
||||
lqw.orderByAsc(SysUrl::getUrlId);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
private SysUrlShortcutVo toShortcut(SysUrlVo vo) {
|
||||
SysUrlShortcutVo shortcut = new SysUrlShortcutVo();
|
||||
shortcut.setUrlId(vo.getUrlId());
|
||||
shortcut.setName(vo.getName());
|
||||
shortcut.setUrl(vo.getUrl());
|
||||
shortcut.setDescription(vo.getDescription());
|
||||
shortcut.setSortOrder(vo.getSortOrder());
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 URL 地址是否合法:仅允许 http/https 协议,且 host 必须存在且有效
|
||||
*
|
||||
* @param url 待校验的 URL
|
||||
*/
|
||||
private void validateUrl(String url) {
|
||||
if (StringUtils.isBlank(url)) {
|
||||
throw new ServiceException("链接地址不能为空");
|
||||
}
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(url.trim());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new ServiceException("链接地址格式不正确");
|
||||
}
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme == null || (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme))) {
|
||||
throw new ServiceException("链接地址必须以 http:// 或 https:// 开头");
|
||||
}
|
||||
String host = uri.getHost();
|
||||
if (StringUtils.isBlank(host)) {
|
||||
throw new ServiceException("链接地址的主机名无效");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.ruoyi.system.mapper.CmsContentMapper">
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user