This commit is contained in:
2025-12-20 19:06:00 +08:00
parent 37224e3f95
commit 6c1aa13498
12 changed files with 755 additions and 5 deletions

View File

@@ -0,0 +1,65 @@
package org.xyzh.api.workcase.dto;
import java.util.List;
import com.alibaba.fastjson2.JSONObject;
import org.xyzh.common.dto.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @description 聊天消息表数据对象DTO
* @filename TbChatMessageDTO.java
* @author cascade
* @copyright xyzh
* @since 2025-12-20
*/
@Data
@Schema(description = "聊天消息表对象")
public class TbChatMessageDTO extends BaseDTO {
private static final long serialVersionUID = 1L;
@Schema(description = "消息ID")
private String messageId;
@Schema(description = "聊天室ID")
private String roomId;
@Schema(description = "发送者ID")
private String senderId;
@Schema(description = "发送者类型guest-来客 agent-客服 ai-AI助手 system-系统消息")
private String senderType;
@Schema(description = "发送者名称")
private String senderName;
@Schema(description = "消息类型text-文本 image-图片 file-文件 voice-语音 video-视频 system-系统消息 meeting-会议通知")
private String messageType;
@Schema(description = "消息内容")
private String content;
@Schema(description = "附件文件ID数组")
private List<String> files;
@Schema(description = "扩展内容(会议链接、引用信息等)")
private JSONObject contentExtra;
@Schema(description = "回复的消息ID")
private String replyToMsgId;
@Schema(description = "是否AI消息")
private Boolean isAiMessage;
@Schema(description = "AI原始消息ID")
private String aiMessageId;
@Schema(description = "状态sending-发送中 sent-已发送 delivered-已送达 read-已读 failed-失败 recalled-已撤回")
private String status;
@Schema(description = "已读人数")
private Integer readCount;
@Schema(description = "发送时间")
private String sendTime;
}

View File

@@ -0,0 +1,66 @@
package org.xyzh.api.workcase.dto;
import org.xyzh.common.dto.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @description 聊天室表数据对象DTO
* @filename TbChatRoomDTO.java
* @author cascade
* @copyright xyzh
* @since 2025-12-20
*/
@Data
@Schema(description = "聊天室表对象")
public class TbChatRoomDTO extends BaseDTO {
private static final long serialVersionUID = 1L;
@Schema(description = "聊天室ID")
private String roomId;
@Schema(description = "关联工单ID")
private String workcaseId;
@Schema(description = "聊天室名称")
private String roomName;
@Schema(description = "聊天室类型workcase-工单客服")
private String roomType;
@Schema(description = "状态active-活跃 closed-已关闭 archived-已归档")
private String status;
@Schema(description = "来客ID创建者")
private String guestId;
@Schema(description = "来客姓名")
private String guestName;
@Schema(description = "AI对话会话ID")
private String aiSessionId;
@Schema(description = "当前负责客服ID")
private String currentAgentId;
@Schema(description = "已加入的客服人数")
private Integer agentCount;
@Schema(description = "消息总数")
private Integer messageCount;
@Schema(description = "未读消息数(客服端)")
private Integer unreadCount;
@Schema(description = "最后消息时间")
private String lastMessageTime;
@Schema(description = "最后一条消息内容")
private String lastMessage;
@Schema(description = "关闭人")
private String closedBy;
@Schema(description = "关闭时间")
private String closedTime;
}

View File

@@ -0,0 +1,54 @@
package org.xyzh.api.workcase.dto;
import org.xyzh.common.dto.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @description 聊天室成员表数据对象DTO
* @filename TbChatRoomMemberDTO.java
* @author cascade
* @copyright xyzh
* @since 2025-12-20
*/
@Data
@Schema(description = "聊天室成员表对象")
public class TbChatRoomMemberDTO extends BaseDTO {
private static final long serialVersionUID = 1L;
@Schema(description = "成员记录ID")
private String memberId;
@Schema(description = "聊天室ID")
private String roomId;
@Schema(description = "用户ID来客ID或员工ID")
private String userId;
@Schema(description = "用户类型guest-来客 agent-客服 ai-AI助手")
private String userType;
@Schema(description = "用户名称")
private String userName;
@Schema(description = "角色owner-创建者 admin-管理员 member-普通成员")
private String role;
@Schema(description = "状态active-活跃 left-已离开 removed-被移除")
private String status;
@Schema(description = "该成员的未读消息数")
private Integer unreadCount;
@Schema(description = "最后阅读时间")
private String lastReadTime;
@Schema(description = "最后阅读的消息ID")
private String lastReadMsgId;
@Schema(description = "加入时间")
private String joinTime;
@Schema(description = "离开时间")
private String leaveTime;
}

View File

@@ -0,0 +1,61 @@
package org.xyzh.api.workcase.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.xyzh.common.vo.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.fastjson2.annotation.JSONField;
import java.util.Date;
/**
* 聊天室成员VO
* 用于前端展示聊天室成员信息
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "聊天室成员VO")
public class ChatMemberVO extends BaseVO {
private static final long serialVersionUID = 1L;
@Schema(description = "成员记录ID")
private String memberId;
@Schema(description = "聊天室ID")
private String roomId;
@Schema(description = "用户ID来客ID或员工ID")
private String userId;
@Schema(description = "用户类型guest-来客 agent-客服 ai-AI助手")
private String userType;
@Schema(description = "用户名称")
private String userName;
@Schema(description = "用户头像")
private String userAvatar;
@Schema(description = "角色owner-创建者 admin-管理员 member-普通成员")
private String role;
@Schema(description = "状态active-活跃 left-已离开 removed-被移除")
private String status;
@Schema(description = "该成员的未读消息数")
private Integer unreadCount;
@Schema(description = "最后阅读时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date lastReadTime;
@Schema(description = "最后阅读的消息ID")
private String lastReadMsgId;
@Schema(description = "加入时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date joinTime;
@Schema(description = "离开时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date leaveTime;
}

View File

@@ -0,0 +1,76 @@
package org.xyzh.api.workcase.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.xyzh.common.vo.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.JSONObject;
import java.util.Date;
import java.util.List;
/**
* 聊天消息VO
* 用于前端展示聊天消息
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "聊天消息VO")
public class ChatMessageVO extends BaseVO {
private static final long serialVersionUID = 1L;
@Schema(description = "消息ID")
private String messageId;
@Schema(description = "聊天室ID")
private String roomId;
@Schema(description = "发送者ID")
private String senderId;
@Schema(description = "发送者类型guest-来客 agent-客服 ai-AI助手 system-系统消息")
private String senderType;
@Schema(description = "发送者名称")
private String senderName;
@Schema(description = "发送者头像")
private String senderAvatar;
@Schema(description = "消息类型text-文本 image-图片 file-文件 voice-语音 video-视频 system-系统消息 meeting-会议通知")
private String messageType;
@Schema(description = "消息内容")
private String content;
@Schema(description = "附件文件ID数组")
private List<String> files;
@Schema(description = "附件数量")
private Integer fileCount;
@Schema(description = "扩展内容(会议链接、引用信息等)")
private JSONObject contentExtra;
@Schema(description = "回复的消息ID")
private String replyToMsgId;
@Schema(description = "回复的消息内容")
private String replyToMsgContent;
@Schema(description = "是否AI消息")
private Boolean isAiMessage;
@Schema(description = "AI原始消息ID")
private String aiMessageId;
@Schema(description = "状态sending-发送中 sent-已发送 delivered-已送达 read-已读 failed-失败 recalled-已撤回")
private String status;
@Schema(description = "已读人数")
private Integer readCount;
@Schema(description = "发送时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date sendTime;
}

View File

@@ -0,0 +1,75 @@
package org.xyzh.api.workcase.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.xyzh.common.vo.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.fastjson2.annotation.JSONField;
import java.util.Date;
/**
* 聊天室VO
* 用于前端展示聊天室信息
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "聊天室VO")
public class ChatRoomVO extends BaseVO {
private static final long serialVersionUID = 1L;
@Schema(description = "聊天室ID")
private String roomId;
@Schema(description = "关联工单ID")
private String workcaseId;
@Schema(description = "聊天室名称")
private String roomName;
@Schema(description = "聊天室类型workcase-工单客服")
private String roomType;
@Schema(description = "状态active-活跃 closed-已关闭 archived-已归档")
private String status;
@Schema(description = "来客ID创建者")
private String guestId;
@Schema(description = "来客姓名")
private String guestName;
@Schema(description = "AI对话会话ID")
private String aiSessionId;
@Schema(description = "当前负责客服ID")
private String currentAgentId;
@Schema(description = "当前负责客服名称")
private String currentAgentName;
@Schema(description = "已加入的客服人数")
private Integer agentCount;
@Schema(description = "消息总数")
private Integer messageCount;
@Schema(description = "未读消息数(客服端)")
private Integer unreadCount;
@Schema(description = "最后消息时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date lastMessageTime;
@Schema(description = "最后一条消息内容")
private String lastMessage;
@Schema(description = "关闭人")
private String closedBy;
@Schema(description = "关闭人姓名")
private String closedByName;
@Schema(description = "关闭时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date closedTime;
}

View File

@@ -0,0 +1,82 @@
package org.xyzh.api.workcase.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.xyzh.common.vo.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.JSONObject;
import java.util.Date;
/**
* 视频会议VO
* 用于前端展示Jitsi Meet会议信息
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "视频会议VO")
public class VideoMeetingVO extends BaseVO {
private static final long serialVersionUID = 1L;
@Schema(description = "会议ID")
private String meetingId;
@Schema(description = "关联聊天室ID")
private String roomId;
@Schema(description = "关联工单ID")
private String workcaseId;
@Schema(description = "会议名称")
private String meetingName;
@Schema(description = "会议密码")
private String meetingPassword;
@Schema(description = "JWT Token用于身份验证")
private String jwtToken;
@Schema(description = "Jitsi房间名")
private String jitsiRoomName;
@Schema(description = "Jitsi服务器地址")
private String jitsiServerUrl;
@Schema(description = "状态scheduled-已安排 ongoing-进行中 ended-已结束 cancelled-已取消")
private String status;
@Schema(description = "创建者ID")
private String creatorId;
@Schema(description = "创建者类型guest-来客 agent-客服")
private String creatorType;
@Schema(description = "创建者名称")
private String creatorName;
@Schema(description = "参与人数")
private Integer participantCount;
@Schema(description = "最大参与人数")
private Integer maxParticipants;
@Schema(description = "实际开始时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
@Schema(description = "实际结束时间", format = "date-time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
@Schema(description = "会议时长(秒)")
private Integer durationSeconds;
@Schema(description = "会议时长格式化1小时30分")
private String durationFormatted;
@Schema(description = "iframe嵌入URL")
private String iframeUrl;
@Schema(description = "Jitsi配置项")
private JSONObject config;
}

View File

@@ -33,6 +33,7 @@ declare module 'shared/components/iframe/IframeView.vue' {
const IframeView: DefineComponent<{}, {}, any> const IframeView: DefineComponent<{}, {}, any>
export default IframeView export default IframeView
} }
declare module 'shared/components/ai/knowledge/DocumentSegment.vue' { declare module 'shared/components/ai/knowledge/DocumentSegment.vue' {
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue'
const DocumentSegment: DefineComponent<{}, {}, any> const DocumentSegment: DefineComponent<{}, {}, any>
@@ -47,7 +48,28 @@ declare module 'shared/components/ai/knowledge/DocumentDetail.vue' {
declare module 'shared/components/chatRoom/ChatRoom.vue' { declare module 'shared/components/chatRoom/ChatRoom.vue' {
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue'
const ChatRoom: DefineComponent<{}, {}, any>
interface ChatMessageVO {
messageId: string
senderId: string
senderName: string
senderAvatar: string
content: string
files: string[]
sendTime: string
}
const ChatRoom: DefineComponent<{
messages: ChatMessageVO[]
currentUserId: string
roomName?: string
meetingUrl?: string
showMeeting?: boolean
fileDownloadUrl?: string
}, {}, {}, {}, {}, {}, {}, {
header?: () => any
'action-area'?: () => any
}>
export default ChatRoom export default ChatRoom
} }
@@ -118,7 +140,18 @@ declare module 'shared/types' {
export type { export type {
TbWorkcaseDTO, TbWorkcaseDTO,
TbWorkcaseProcessDTO, TbWorkcaseProcessDTO,
TbWorkcaseDeviceDTO TbWorkcaseDeviceDTO,
// 聊天室相关
TbChatRoomDTO,
TbChatMessageDTO,
TbChatRoomMemberDTO,
ChatRoomVO,
ChatMessageVO,
ChatMemberVO,
VideoMeetingVO,
SendMessageParam,
CreateMeetingParam,
MarkReadParam
} from '../../../shared/src/types/workcase' } from '../../../shared/src/types/workcase'
// 重新导出 menu // 重新导出 menu

View File

@@ -48,7 +48,28 @@ declare module 'shared/components/ai/knowledge/DocumentDetail.vue' {
declare module 'shared/components/chatRoom/ChatRoom.vue' { declare module 'shared/components/chatRoom/ChatRoom.vue' {
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue'
const ChatRoom: DefineComponent<{}, {}, any>
interface ChatMessageVO {
messageId: string
senderId: string
senderName: string
senderAvatar: string
content: string
files: string[]
sendTime: string
}
const ChatRoom: DefineComponent<{
messages: ChatMessageVO[]
currentUserId: string
roomName?: string
meetingUrl?: string
showMeeting?: boolean
fileDownloadUrl?: string
}, {}, {}, {}, {}, {}, {}, {
header?: () => any
'action-area'?: () => any
}>
export default ChatRoom export default ChatRoom
} }
@@ -119,7 +140,18 @@ declare module 'shared/types' {
export type { export type {
TbWorkcaseDTO, TbWorkcaseDTO,
TbWorkcaseProcessDTO, TbWorkcaseProcessDTO,
TbWorkcaseDeviceDTO TbWorkcaseDeviceDTO,
// 聊天室相关
TbChatRoomDTO,
TbChatMessageDTO,
TbChatRoomMemberDTO,
ChatRoomVO,
ChatMessageVO,
ChatMemberVO,
VideoMeetingVO,
SendMessageParam,
CreateMeetingParam,
MarkReadParam
} from '../../../shared/src/types/workcase' } from '../../../shared/src/types/workcase'
// 重新导出 menu // 重新导出 menu

View File

@@ -0,0 +1,194 @@
import { BaseVO } from '../base'
import { BaseDTO } from '../base'
// ==================== DTO ====================
/**
* 聊天室DTO
*/
export interface TbChatRoomDTO extends BaseDTO {
roomId?: string
workcaseId?: string
roomName?: string
roomType?: string
status?: string
guestId?: string
guestName?: string
aiSessionId?: string
currentAgentId?: string
agentCount?: number
messageCount?: number
unreadCount?: number
lastMessageTime?: string
lastMessage?: string
closedBy?: string
closedTime?: string
}
/**
* 聊天消息DTO
*/
export interface TbChatMessageDTO extends BaseDTO {
messageId?: string
roomId?: string
senderId?: string
senderType?: string
senderName?: string
messageType?: string
content?: string
files?: string[]
contentExtra?: Record<string, any>
replyToMsgId?: string
isAiMessage?: boolean
aiMessageId?: string
status?: string
readCount?: number
sendTime?: string
}
/**
* 聊天室成员DTO
*/
export interface TbChatRoomMemberDTO extends BaseDTO {
memberId?: string
roomId?: string
userId?: string
userType?: string
userName?: string
role?: string
status?: string
unreadCount?: number
lastReadTime?: string
lastReadMsgId?: string
joinTime?: string
leaveTime?: string
}
// ==================== VO ====================
/**
* 聊天室VO
* 用于前端展示聊天室信息
*/
export interface ChatRoomVO extends BaseVO {
roomId?: string
workcaseId?: string
roomName?: string
roomType?: string
status?: string
guestId?: string
guestName?: string
aiSessionId?: string
currentAgentId?: string
currentAgentName?: string
agentCount?: number
messageCount?: number
unreadCount?: number
lastMessageTime?: string
lastMessage?: string
closedBy?: string
closedByName?: string
closedTime?: string
}
/**
* 聊天消息VO
* 用于前端展示聊天消息
*/
export interface ChatMessageVO extends BaseVO {
messageId?: string
roomId?: string
senderId?: string
senderType?: string
senderName?: string
senderAvatar?: string
messageType?: string
content?: string
files?: string[]
fileCount?: number
contentExtra?: Record<string, any>
replyToMsgId?: string
replyToMsgContent?: string
isAiMessage?: boolean
aiMessageId?: string
status?: string
readCount?: number
sendTime?: string
}
/**
* 聊天室成员VO
* 用于前端展示聊天室成员信息
*/
export interface ChatMemberVO extends BaseVO {
memberId?: string
roomId?: string
userId?: string
userType?: string
userName?: string
userAvatar?: string
role?: string
status?: string
unreadCount?: number
lastReadTime?: string
lastReadMsgId?: string
joinTime?: string
leaveTime?: string
}
/**
* 视频会议VO
* 用于前端展示Jitsi Meet会议信息
*/
export interface VideoMeetingVO extends BaseVO {
meetingId?: string
roomId?: string
workcaseId?: string
meetingName?: string
meetingPassword?: string
jwtToken?: string
jitsiRoomName?: string
jitsiServerUrl?: string
status?: string
creatorId?: string
creatorType?: string
creatorName?: string
participantCount?: number
maxParticipants?: number
startTime?: string
endTime?: string
durationSeconds?: number
durationFormatted?: string
iframeUrl?: string
config?: Record<string, any>
}
/**
* 发送消息参数
*/
export interface SendMessageParam {
roomId: string
content: string
files?: string[]
messageType?: string
replyToMsgId?: string
}
/**
* 创建会议参数
*/
export interface CreateMeetingParam {
roomId: string
workcaseId: string
meetingName?: string
meetingPassword?: string
maxParticipants?: number
}
/**
* 标记已读参数
*/
export interface MarkReadParam {
roomId: string
messageIds?: string[]
}

View File

@@ -1 +1,2 @@
export * from "./workcase" export * from "./workcase"
export * from "./chatRoom"

View File

@@ -140,7 +140,18 @@ declare module 'shared/types' {
export type { export type {
TbWorkcaseDTO, TbWorkcaseDTO,
TbWorkcaseProcessDTO, TbWorkcaseProcessDTO,
TbWorkcaseDeviceDTO TbWorkcaseDeviceDTO,
// 聊天室相关
TbChatRoomDTO,
TbChatMessageDTO,
TbChatRoomMemberDTO,
ChatRoomVO,
ChatMessageVO,
ChatMemberVO,
VideoMeetingVO,
SendMessageParam,
CreateMeetingParam,
MarkReadParam
} from '../../../shared/src/types/workcase' } from '../../../shared/src/types/workcase'
// 重新导出 menu // 重新导出 menu