2025-10-30 19:34:04 +08:00
|
|
|
|
import request from '/@/utils/request';
|
|
|
|
|
|
import { getObj } from '/@/api/pm/pmTask';
|
2025-12-26 13:50:07 +08:00
|
|
|
|
import { queryTask } from '/@/api/flow/task';
|
2025-10-30 19:34:04 +08:00
|
|
|
|
import { useUserInfo } from '/@/stores/userInfo';
|
|
|
|
|
|
import router from '/@/router';
|
|
|
|
|
|
|
|
|
|
|
|
export const CategoryRoute: Record<number, string> = {
|
|
|
|
|
|
1: '/project/detail',
|
|
|
|
|
|
2: '/task/pending',
|
|
|
|
|
|
4: '/invite',
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export enum MessageType {
|
|
|
|
|
|
NOTICE = 1,
|
|
|
|
|
|
REMIND = 2,
|
|
|
|
|
|
TODO = 3,
|
|
|
|
|
|
}
|
|
|
|
|
|
//0:公告,1:项目,2:任务,3:里程碑,4:组织
|
|
|
|
|
|
export enum MessageCategory {
|
|
|
|
|
|
NOTICE = 0,
|
|
|
|
|
|
PROJECT = 1,
|
|
|
|
|
|
TASK = 2,
|
|
|
|
|
|
MILESTONE = 3,
|
|
|
|
|
|
ORGANIZATION = 4,
|
2025-12-17 10:16:13 +08:00
|
|
|
|
SPDM = 99, // SPDM CODE
|
2025-10-30 19:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export enum MessageRead {
|
|
|
|
|
|
UNREAD = 0,
|
|
|
|
|
|
READ = 1,
|
|
|
|
|
|
IGNORE = 2,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SourcePicker 组件内部类型定义
|
|
|
|
|
|
export enum SourcePickerTypeEnum {
|
|
|
|
|
|
user = 0,
|
|
|
|
|
|
dept = 1,
|
|
|
|
|
|
role = 2,
|
|
|
|
|
|
project = 3,
|
|
|
|
|
|
}
|
|
|
|
|
|
export const SourcePickerTypeValue = {
|
|
|
|
|
|
USER: 'user',
|
|
|
|
|
|
DEPT: 'dept',
|
|
|
|
|
|
ROLE: 'role',
|
|
|
|
|
|
PROJECT: 'project',
|
|
|
|
|
|
} as const;
|
|
|
|
|
|
export type SourcePickerType = keyof typeof SourcePickerTypeEnum;
|
|
|
|
|
|
|
|
|
|
|
|
enum TaskLink {
|
|
|
|
|
|
Started = '/task/started',
|
|
|
|
|
|
Completed = '/task/completed',
|
|
|
|
|
|
Pending = '/task/pending',
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface ReceiveObj {
|
|
|
|
|
|
id: string;
|
|
|
|
|
|
name: string;
|
|
|
|
|
|
type: number;
|
|
|
|
|
|
[property: string]: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* MessageConfigDetailVo
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface MessageConfigDetailVo {
|
|
|
|
|
|
configStatus?: number;
|
|
|
|
|
|
createTime?: number;
|
|
|
|
|
|
delayTime?: string;
|
|
|
|
|
|
delFlag?: string;
|
|
|
|
|
|
id?: string;
|
|
|
|
|
|
msgContent?: string;
|
|
|
|
|
|
msgTitle?: string;
|
|
|
|
|
|
msgType?: number;
|
|
|
|
|
|
receiveObj?: Array<ReceiveObj>;
|
|
|
|
|
|
receiveRole?: string;
|
|
|
|
|
|
receiveRoleName?: string;
|
|
|
|
|
|
receiveTerminal?: string;
|
|
|
|
|
|
sendTime?: string;
|
|
|
|
|
|
sendTimeType?: number;
|
|
|
|
|
|
triggerConditions?: string;
|
|
|
|
|
|
updateTime?: number;
|
|
|
|
|
|
[property: string]: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface MessageListVo {
|
|
|
|
|
|
configId?: string;
|
|
|
|
|
|
createTime?: string;
|
|
|
|
|
|
delFlag?: string;
|
|
|
|
|
|
id?: string;
|
|
|
|
|
|
msgCategory?: number;
|
|
|
|
|
|
msgContent?: string;
|
|
|
|
|
|
msgTitle?: string;
|
|
|
|
|
|
msgType?: number;
|
|
|
|
|
|
receiveObj?: Array<ReceiveObj>;
|
|
|
|
|
|
receiveRoleName?: string;
|
|
|
|
|
|
receiveTerminal?: string;
|
|
|
|
|
|
sendTime?: string;
|
|
|
|
|
|
sendTimeType?: number;
|
|
|
|
|
|
status?: number;
|
|
|
|
|
|
triggerConditions?: string;
|
|
|
|
|
|
updateTime?: string;
|
|
|
|
|
|
[property: string]: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 消息对象接口定义
|
|
|
|
|
|
export interface MessageUserVo {
|
|
|
|
|
|
id: string;
|
|
|
|
|
|
listId: string;
|
|
|
|
|
|
msgTitle: string;
|
|
|
|
|
|
msgCategory: number;
|
|
|
|
|
|
userId: string;
|
|
|
|
|
|
phone: string;
|
|
|
|
|
|
username: string;
|
|
|
|
|
|
isRead: number;
|
|
|
|
|
|
sendTime: string;
|
|
|
|
|
|
receiveTime?: string;
|
|
|
|
|
|
readTime?: string;
|
|
|
|
|
|
msgBody?: string;
|
|
|
|
|
|
msgType: number;
|
|
|
|
|
|
intervalTime?: string;
|
|
|
|
|
|
params: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 通过id获取消息配置 /msg/message/config/1887329384892542978
|
|
|
|
|
|
export const getMessageConfigById = (id: string) => {
|
|
|
|
|
|
return request.get(`/msg/message/config/${id}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 添加消息配置 /msg/message/config/add
|
|
|
|
|
|
export const addMessageConfig = (obj?: Partial<MessageConfigDetailVo>) => {
|
|
|
|
|
|
return request.post('/msg/message/config/add', obj);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 修改消息配置 /msg/message/config/edit
|
|
|
|
|
|
export const editMessageConfig = (obj?: Partial<MessageConfigDetailVo>) => {
|
|
|
|
|
|
return request.post('/msg/message/config/edit', obj);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 消息配置列表 /msg/message/config/page
|
|
|
|
|
|
export const getMessageConfigPage = (params: { size: number; current: number; msgTitle: string }) => {
|
|
|
|
|
|
return request.get(`/msg/message/config/page`, { params });
|
|
|
|
|
|
};
|
|
|
|
|
|
// 修改消息配置状态
|
|
|
|
|
|
export const editMessageConfigStatus = (obj: { id: string; configStatus: number }) => {
|
|
|
|
|
|
return request.post('/msg/message/config/edit/status', obj);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 获取系统消息全局变量集合 /msg/message/args/get
|
|
|
|
|
|
export const getMessageArgs = () => {
|
|
|
|
|
|
return request.get('/msg/message/args/get');
|
|
|
|
|
|
};
|
|
|
|
|
|
// 删除消息配置 /msg/message/config/delete/1887329384892542978
|
|
|
|
|
|
export const deleteMessageConfig = (id: string) => {
|
|
|
|
|
|
return request.post(`/msg/message/config/delete/${id}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 公告列表
|
|
|
|
|
|
// 消息列表 /msg/message/list/page
|
|
|
|
|
|
export const getMessageListPage = (params: { size: number; current: number; msgTitle: string }) => {
|
|
|
|
|
|
return request.get('/msg/message/list/page', { params });
|
|
|
|
|
|
};
|
|
|
|
|
|
// 公告模板 /msg/message/config/notices
|
|
|
|
|
|
export const getMessageNotices = () => {
|
|
|
|
|
|
return request.get('/msg/message/config/notices');
|
|
|
|
|
|
};
|
|
|
|
|
|
// 保持发布公告 /msg/message/list/announcement
|
|
|
|
|
|
export const addMessageAnnouncement = (obj: Partial<MessageListVo>) => {
|
|
|
|
|
|
return request.post('/msg/message/list/announcement', obj);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 修改消息信息 /msg/message/list/edit
|
|
|
|
|
|
export const editMessageList = (obj: Partial<MessageListVo>) => {
|
|
|
|
|
|
return request.post('/msg/message/list/edit', obj);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 消息明细 /msg/message/list/item/page
|
|
|
|
|
|
export const getMessageItemPage = (params: { size: number; current: number; listId: string }) => {
|
|
|
|
|
|
return request.get('/msg/message/list/item/page', { params });
|
|
|
|
|
|
};
|
|
|
|
|
|
// 删除消息 /msg/message/list/delete/1887382479743557633
|
|
|
|
|
|
export const deleteMessageList = (id: string) => {
|
|
|
|
|
|
return request.post(`/msg/message/list/delete/${id}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 用户消息 /msg/message/list/user/page
|
2026-01-07 17:18:06 +08:00
|
|
|
|
export const getMessageUserPage = (params: { size: number; current: number; msgCategory?: string; isRead?: string, userId?: string; }) => {
|
2025-10-30 19:34:04 +08:00
|
|
|
|
return request.get('/msg/message/list/user/page', { params });
|
|
|
|
|
|
};
|
|
|
|
|
|
// 修改消息状态 /msg/message/list/item/isRead
|
|
|
|
|
|
export const editMessageUserIsRead = (obj: { id: string; isRead: number }) => {
|
|
|
|
|
|
return request.post('/msg/message/list/item/isRead', obj);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 标记全部为已读 /msg/message/list/item/isRead/all
|
|
|
|
|
|
export const isReadAll = () => {
|
|
|
|
|
|
return request.post('/msg/message/list/item/isRead/all');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取未读消息数量 /msg/message/list/user/unread-num
|
|
|
|
|
|
export const getMessageUserUnreadNum = () => {
|
|
|
|
|
|
return request.get('/msg/message/list/user/unread-num');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const eventSourceMap = new Map<string, EventSource>();
|
|
|
|
|
|
|
|
|
|
|
|
export const msgSSE = (userId: string, callback: (data: any) => void, errorCallback?: (error: any) => void) => {
|
|
|
|
|
|
console.log('发起SSE连接=> ');
|
|
|
|
|
|
const baseUrl = import.meta.env.VITE_API_URL;
|
|
|
|
|
|
// 生成一个随机数
|
|
|
|
|
|
const requestId = Math.random().toString(36).substring(2, 15);
|
|
|
|
|
|
if (eventSourceMap.has(userId)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
eventSourceMap.set(userId, new EventSource(`${baseUrl}/msg/sse/connect?userId=${userId}&requestId=${requestId}`));
|
|
|
|
|
|
// 监听自定义事件 "new-message"
|
|
|
|
|
|
eventSourceMap.get(userId)?.addEventListener('new-message', function (event) {
|
|
|
|
|
|
callback(event);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
eventSourceMap.get(userId)?.addEventListener('error', function (error) {
|
|
|
|
|
|
errorCallback && errorCallback(error);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 跳转任务逻辑
|
|
|
|
|
|
export const taskAdjust = async (item: any, readType: number = MessageRead.READ) => {
|
|
|
|
|
|
// 忽略、公告不跳转
|
|
|
|
|
|
if (readType === MessageRead.IGNORE || item.msgCategory === MessageCategory.NOTICE) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-28 11:05:14 +08:00
|
|
|
|
const params = JSON.parse(item.params || '{}');
|
2025-10-30 19:34:04 +08:00
|
|
|
|
if (item.msgCategory === MessageCategory.TASK) {
|
|
|
|
|
|
// 通过id查询任务详情
|
|
|
|
|
|
const res = await getObj(params.taskId);
|
|
|
|
|
|
// 创建人跳转发起任务
|
|
|
|
|
|
if (res.data.createBy === useUserInfo().userInfos.user.userId) {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: TaskLink.Started,
|
|
|
|
|
|
query: {
|
|
|
|
|
|
title: res.data.title,
|
|
|
|
|
|
id: res.data.id,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 跳转代办任务
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: res.data.taskStatus === '3' ? TaskLink.Completed : TaskLink.Pending,
|
|
|
|
|
|
query: {
|
|
|
|
|
|
title: res.data.title,
|
|
|
|
|
|
id: res.data.id,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-12-17 10:16:13 +08:00
|
|
|
|
} else if (item.msgCategory === MessageCategory.SPDM) { // SPDM CODE
|
2026-01-13 15:11:00 +08:00
|
|
|
|
if (item.msgTitle === '任务通知') {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: '/spdm/task/execute'
|
|
|
|
|
|
});
|
|
|
|
|
|
} else if (item.msgTitle === '数据通知') {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: '/spdm/system/storage'
|
|
|
|
|
|
});
|
|
|
|
|
|
} else if (item.msgTitle === '作业通知') {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: '/spdm/task/execution'
|
|
|
|
|
|
});
|
|
|
|
|
|
} else if (params?.taskId) {
|
2025-12-26 14:38:53 +08:00
|
|
|
|
queryTask(params.taskId, false).then((res) => {
|
|
|
|
|
|
if (item.msgTitle === '审批通知') {
|
|
|
|
|
|
localStorage.setItem('SPDM_MSG_TASK_TYPE', 'flow');
|
|
|
|
|
|
localStorage.setItem('SPDM_MSG_TASK_PARAMS', JSON.stringify(params));
|
2026-01-22 19:15:14 +08:00
|
|
|
|
const path = res.data.endTime ? TaskLink.Completed : TaskLink.Pending;
|
|
|
|
|
|
if (location.pathname === path) {
|
|
|
|
|
|
router.go(0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
router.replace({
|
|
|
|
|
|
path,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-12-26 14:38:53 +08:00
|
|
|
|
}
|
2025-12-17 10:16:13 +08:00
|
|
|
|
});
|
2025-12-26 14:38:53 +08:00
|
|
|
|
}
|
2025-10-30 19:34:04 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: CategoryRoute[item.msgCategory],
|
|
|
|
|
|
query: params,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|