1. 新增在线协同文档功能 v 1

(cherry picked from commit 1ed31a4f49)
This commit is contained in:
chenbowen
2025-09-01 10:01:35 +08:00
committed by chenbowen
parent 2cd864f63f
commit 3ff84e6f5f
43 changed files with 2734 additions and 3 deletions

View File

@@ -32,6 +32,12 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.config;
import cn.iocoder.yudao.module.infra.websocket.DocWebSocketHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import jakarta.annotation.Resource;
/**
* WebSocket 配置
*
* @author 芋道源码
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Resource
private DocWebSocketHandler docWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册文档协作WebSocket处理器
registry.addHandler(docWebSocketHandler, "/doc-collaboration")
.setAllowedOrigins("*") // 允许跨域,生产环境应该限制域名
.withSockJS(); // 启用SockJS支持
}
}

View File

@@ -0,0 +1,99 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - OnlyOffice 编辑器配置 Response VO")
@Data
public class DocEditorConfigRespVO {
@Schema(description = "文档类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "text")
private String documentType;
@Schema(description = "文档配置", requiredMode = Schema.RequiredMode.REQUIRED)
private DocumentConfig document;
@Schema(description = "编辑器配置", requiredMode = Schema.RequiredMode.REQUIRED)
private EditorConfig editorConfig;
@Schema(description = "文档高度", requiredMode = Schema.RequiredMode.REQUIRED, example = "100%")
private String height;
@Schema(description = "令牌", requiredMode = Schema.RequiredMode.REQUIRED)
private String token;
@Schema(description = "OnlyOffice服务器地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://localhost:8085")
private String documentServerUrl;
@Schema(description = "文档配置")
@Data
public static class DocumentConfig {
@Schema(description = "文件类型", example = "docx")
private String fileType;
@Schema(description = "文档key", example = "doc123")
private String key;
@Schema(description = "文档标题", example = "技术文档")
private String title;
@Schema(description = "文档地址")
private String url;
@Schema(description = "权限配置")
private Permissions permissions;
}
@Schema(description = "权限配置")
@Data
public static class Permissions {
@Schema(description = "是否可编辑", example = "true")
private Boolean edit;
@Schema(description = "是否可下载", example = "true")
private Boolean download;
@Schema(description = "是否可打印", example = "true")
private Boolean print;
}
@Schema(description = "编辑器配置")
@Data
public static class EditorConfig {
@Schema(description = "回调地址")
private String callbackUrl;
@Schema(description = "语言", example = "zh-CN")
private String lang;
@Schema(description = "模式", example = "edit")
private String mode;
@Schema(description = "用户配置")
private User user;
@Schema(description = "协作配置")
private CoEditing coEditing;
}
@Schema(description = "用户配置")
@Data
public static class User {
@Schema(description = "用户ID", example = "1")
private String id;
@Schema(description = "用户名", example = "admin")
private String name;
}
@Schema(description = "协作配置")
@Data
public static class CoEditing {
@Schema(description = "协作模式", example = "fast")
private String mode;
@Schema(description = "是否允许更改", example = "true")
private Boolean change;
}
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
@Schema(description = "管理后台 - 在线文档创建 Request VO")
@Data
public class DocFileCreateReqVO {
@Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术文档")
@NotEmpty(message = "文档标题不能为空")
private String title;
@Schema(description = "文件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "docx")
@NotEmpty(message = "文件类型不能为空")
private String fileType;
@Schema(description = "空间类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "空间类型不能为空")
private Integer spaceType;
@Schema(description = "文档描述", example = "这是一个技术文档")
private String description;
@Schema(description = "文件编号", example = "1")
private Long fileId;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 在线文档分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DocFilePageReqVO extends PageParam {
@Schema(description = "文档标题", example = "技术文档")
private String title;
@Schema(description = "文件类型", example = "docx")
private String fileType;
@Schema(description = "空间类型", example = "1")
private Integer spaceType;
@Schema(description = "状态", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 文档权限 Request VO")
@Data
public class DocFilePermissionReqVO {
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "文档编号不能为空")
private Long docFileId;
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "角色编号不能为空")
private Long roleId;
@Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "权限类型不能为空")
private Integer permissionType;
@Schema(description = "过期时间", example = "2024-12-31 23:59:59")
private LocalDateTime expireTime;
}

View File

@@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 文档权限 Response VO")
@Data
public class DocFilePermissionRespVO {
@Schema(description = "权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long docFileId;
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long roleId;
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "管理员")
private String roleName;
@Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer permissionType;
@Schema(description = "过期时间", example = "2024-12-31 23:59:59")
private LocalDateTime expireTime;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 在线文档 Response VO")
@Data
public class DocFileRespVO {
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术文档")
private String title;
@Schema(description = "文件编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long fileId;
@Schema(description = "文件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "docx")
private String fileType;
@Schema(description = "空间类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer spaceType;
@Schema(description = "文档描述", example = "这是一个技术文档")
private String description;
@Schema(description = "最新版本编号", example = "3072")
private Long latestVersionId;
@Schema(description = "所有者用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long ownerUserId;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
// 以下字段从 fileService 动态获取
@Schema(description = "文件名称", example = "document.docx")
private String fileName;
@Schema(description = "文件大小", example = "1024")
private Long fileSize;
@Schema(description = "文件访问地址", example = "http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac073b8")
private String fileUrl;
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
@Schema(description = "管理后台 - 在线文档更新 Request VO")
@Data
public class DocFileUpdateReqVO {
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "文档编号不能为空")
private Long id;
@Schema(description = "文档标题", example = "技术文档")
private String title;
@Schema(description = "文档描述", example = "这是一个技术文档")
private String description;
}

Some files were not shown because too many files have changed in this diff Show More