@@ -265,8 +265,9 @@ | |||||
window.ipcRenderer.invoke('re-sync-file', contextMsg); | window.ipcRenderer.invoke('re-sync-file', contextMsg); | ||||
return; | return; | ||||
} | } | ||||
if (false) { // 下载 | |||||
if (contextMsg.notifyType === 1) { // 下载 | |||||
window.ipcRenderer.invoke('download-file', contextMsg); | window.ipcRenderer.invoke('download-file', contextMsg); | ||||
return; | |||||
} | } | ||||
}); | }); | ||||
@@ -283,22 +284,14 @@ | |||||
contextMsg = message; | contextMsg = message; | ||||
resetDomStatus(); | resetDomStatus(); | ||||
let runningMethod = noop; | let runningMethod = noop; | ||||
// todo | |||||
switch (message.taskSyncStatus) { | |||||
case 'success': | |||||
runningMethod = renderTaskSuccess; | |||||
break; | |||||
case 'error': | |||||
runningMethod = renderTaskError; | |||||
break; | |||||
case 'incomming': | |||||
runningMethod = renderTaskError; | |||||
break; | |||||
case 'conflict': | |||||
runningMethod = renderTaskError; | |||||
break; | |||||
default: | |||||
break; | |||||
if(message.notifyType === 1) { | |||||
runningMethod = renderTaskIncoming; | |||||
} else if(message.notifyType === 2 || message.notifyType === 3) { | |||||
runningMethod = renderConflictMsg; | |||||
} else if(message.taskSyncStatus === 'TASK_SYNC_STATUS_FINISH') { | |||||
runningMethod = renderTaskSuccess; | |||||
} else if(message.taskSyncStatus === 'TASK_SYNC_STATUS_FAIL') { | |||||
runningMethod = renderTaskError; | |||||
} | } | ||||
runningMethod(message); | runningMethod(message); | ||||
} | } | ||||
@@ -337,7 +330,7 @@ | |||||
useView(syncIncoming); | useView(syncIncoming); | ||||
syncMsgFileName.innerText = fileFullName(message); | syncMsgFileName.innerText = fileFullName(message); | ||||
syncMsgDate.innerText = message.taskCreateDateStr; | syncMsgDate.innerText = message.taskCreateDateStr; | ||||
syncIncoming.innerText = '某某人同步了「某某文件」'; | |||||
syncIncoming.innerText = message.notifyMessage; | |||||
} | } | ||||
function renderConflictMsg(message) { | function renderConflictMsg(message) { | ||||
useView(conflictMsgView); | useView(conflictMsgView); | ||||
@@ -34,7 +34,17 @@ const errorHandler = (error: ResponseError) => { | |||||
if (response && response.status) { | if (response && response.status) { | ||||
const errorText = codeMessage[response.status] || response.statusText; | const errorText = codeMessage[response.status] || response.statusText; | ||||
const { status, url } = response; | const { status, url } = response; | ||||
if (response.status === 401) { | |||||
notification.error({ | |||||
message: '登录超时', | |||||
description: '登录状态超时,请重新登录', | |||||
}); | |||||
logout(false); | |||||
return { | |||||
code: response.status, | |||||
message: errorText, | |||||
}; | |||||
} | |||||
notification.error({ | notification.error({ | ||||
message: `请求错误 ${status}: ${url}`, | message: `请求错误 ${status}: ${url}`, | ||||
description: errorText, | description: errorText, | ||||
@@ -45,7 +55,7 @@ const errorHandler = (error: ResponseError) => { | |||||
}; | }; | ||||
} | } | ||||
if (data && typeof data === 'object' && 'error' in data) return data; | if (data && typeof data === 'object' && 'error' in data) return data; | ||||
// todo 报错都不走error, 改为构建成data; | |||||
// 报错都不走error, 改为构建成data; | |||||
if (!response) { | if (!response) { | ||||
notification.error({ | notification.error({ | ||||
description: '您的网络发生异常,无法连接服务器', | description: '您的网络发生异常,无法连接服务器', | ||||
@@ -6,8 +6,8 @@ import FileIcon from '../FileIcon'; | |||||
import ATooltip from '../Tooltip'; | import ATooltip from '../Tooltip'; | ||||
import styles from './FileStatus.less'; | import styles from './FileStatus.less'; | ||||
import { CloseCircleFilled, CheckCircleFilled } from '@ant-design/icons'; | import { CloseCircleFilled, CheckCircleFilled } from '@ant-design/icons'; | ||||
import { Progress, Button } from 'antd'; | |||||
import { TaskStatus, TaskType } from '@/services/API.helper'; | |||||
import { Progress, Button, ButtonProps } from 'antd'; | |||||
import { NotificationType, TaskStatus, TaskType } from '@/services/API.helper'; | |||||
import { DATA } from '@/services/API'; | import { DATA } from '@/services/API'; | ||||
import { identity } from 'lodash'; | import { identity } from 'lodash'; | ||||
import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||
@@ -39,6 +39,10 @@ export default function FileStatus(props: FileStatusProps) { | |||||
fetchLocalApi('restartTask', { taskIds: data.taskId }); | fetchLocalApi('restartTask', { taskIds: data.taskId }); | ||||
}, [data.taskId]); | }, [data.taskId]); | ||||
const downloadFile = useCallback(() => { | |||||
fetchLocalApi('downloadFileFromMsg', { fileObject: data.originData }); | |||||
}, [data.taskId]); | |||||
const checkFile = useCallback(() => { | const checkFile = useCallback(() => { | ||||
system.openFilePosition(data); | system.openFilePosition(data); | ||||
}, [data]); | }, [data]); | ||||
@@ -60,43 +64,35 @@ export default function FileStatus(props: FileStatusProps) { | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div className={styles.mid}> | <div className={styles.mid}> | ||||
<LoadDesc | |||||
type={data.taskType} | |||||
loadingState={data.taskSyncStatus} | |||||
progress={data.taskSyncProgress} | |||||
{...restProps} | |||||
/> | |||||
{data.taskSyncStatus === TaskStatus.FINISH ? ( | |||||
{data.notifyType ? ( | |||||
<span>{data.notifyMessage}</span> | |||||
) : ( | |||||
<LoadDesc | |||||
type={data.taskType} | |||||
loadingState={data.taskSyncStatus} | |||||
progress={data.taskSyncProgress} | |||||
{...restProps} | |||||
/> | |||||
)} | |||||
{data.taskSyncStatus === TaskStatus.FINISH || data.notifyType ? ( | |||||
<Time time={data.taskCreateDate} /> | <Time time={data.taskCreateDate} /> | ||||
) : null} | ) : null} | ||||
</div> | </div> | ||||
<div className={styles.right}> | <div className={styles.right}> | ||||
{/* 查看1: 已下载 文件打开文件夹 */} | {/* 查看1: 已下载 文件打开文件夹 */} | ||||
{data.taskSyncStatus === TaskStatus.FINISH ? ( | {data.taskSyncStatus === TaskStatus.FINISH ? ( | ||||
<Button | |||||
type="link" | |||||
className={styles.button} | |||||
size="small" | |||||
onClick={checkFile} | |||||
> | |||||
查看 | |||||
</Button> | |||||
<ActionButton onClick={checkFile}>查看</ActionButton> | |||||
) : null} | ) : null} | ||||
{/* 查看2: 未下载 且 已删除 文件跳转到web端 */} | |||||
{/* 下载: 未下载 且 未删除 文件 */} | |||||
{/* 重新下载: 下载失败时出现 */} | {/* 重新下载: 下载失败时出现 */} | ||||
{/* 重新上传: 上传失败时出现 */} | {/* 重新上传: 上传失败时出现 */} | ||||
{data.taskSyncStatus === TaskStatus.FAILED ? ( | {data.taskSyncStatus === TaskStatus.FAILED ? ( | ||||
<Button | |||||
type="link" | |||||
className={styles.button} | |||||
size="small" | |||||
onClick={redoTask} | |||||
> | |||||
<ActionButton onClick={redoTask}> | |||||
{data.taskType === TaskType.DOWNLOAD ? '重新下载' : '重新上传'} | {data.taskType === TaskType.DOWNLOAD ? '重新下载' : '重新上传'} | ||||
</Button> | |||||
</ActionButton> | |||||
) : null} | |||||
{data.notifyType && data.notifyType === NotificationType.SYNC ? ( | |||||
<ActionButton onClick={downloadFile}>下载</ActionButton> | |||||
) : null} | ) : null} | ||||
{/* <Button type="link" className={styles.button} size="small">重新上传</Button> */} | |||||
{/* <Button type="link" className={styles.button} size="small">暂停</Button> */} | {/* <Button type="link" className={styles.button} size="small">暂停</Button> */} | ||||
{/* <Button type="link" className={styles.button} size="small">取消</Button> */} | {/* <Button type="link" className={styles.button} size="small">取消</Button> */} | ||||
</div> | </div> | ||||
@@ -104,9 +100,32 @@ export default function FileStatus(props: FileStatusProps) { | |||||
); | ); | ||||
} | } | ||||
const Time = memo((props: { time: Dayjs }) => ( | |||||
<span className={styles.time}>{props.time.format('HH:mm:ss')}</span> | |||||
)); | |||||
function ActionButton({ onClick, children }: ButtonProps) { | |||||
return ( | |||||
<Button | |||||
type="link" | |||||
className={styles.button} | |||||
size="small" | |||||
onClick={onClick} | |||||
> | |||||
{children} | |||||
</Button> | |||||
); | |||||
} | |||||
interface TimeProps { | |||||
time: Dayjs; | |||||
} | |||||
const Time = memo(({ time }: TimeProps) => { | |||||
const now = dayjs(); | |||||
const isToday = time.isSame(now, 'day'); | |||||
const isSameYear = time.isSame(now, 'year'); | |||||
const formatStr = useMemo(() => { | |||||
if (isToday) return 'HH:mm:ss'; | |||||
if (isSameYear) return 'MM/DD HH:mm:ss'; | |||||
return 'YYYY/MM/DD HH:mm:ss'; | |||||
}, [isToday, isSameYear]); | |||||
return <span className={styles.time}>{time.format(formatStr)}</span>; | |||||
}); | |||||
interface LoadDescProps { | interface LoadDescProps { | ||||
type: TaskType; | type: TaskType; | ||||
@@ -1,9 +1,14 @@ | |||||
import React from 'react' | |||||
import FileStatus from '@/components/FileStatus'; | |||||
import { useNotificationMessages } from '@/utils/hooks'; | |||||
import styles from './messages.less'; | |||||
export default function MessagesView() { | export default function MessagesView() { | ||||
const list = useNotificationMessages(); | |||||
return ( | return ( | ||||
<div> | |||||
消息通知界面 | |||||
<div className={styles.messages}> | |||||
{list.map((data) => ( | |||||
<FileStatus key={data.taskId} className={styles.item} data={data} /> | |||||
))} | |||||
</div> | </div> | ||||
) | |||||
} | |||||
); | |||||
} |
@@ -0,0 +1,8 @@ | |||||
.messages { | |||||
height: 100%; | |||||
padding: 0 12px; | |||||
.item { | |||||
margin-top: 12px; | |||||
margin-bottom: 8px; | |||||
} | |||||
} |
@@ -6,11 +6,11 @@ import syncSuccessImg from './assets/sync.success.png'; | |||||
import syncErrorImg from './assets/sync.error.png'; | import syncErrorImg from './assets/sync.error.png'; | ||||
import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
import SyncModal from '@/components/SyncModal'; | import SyncModal from '@/components/SyncModal'; | ||||
import { useSocketMessages } from '@/services/socket'; | |||||
import FileStatus from '@/components/FileStatus'; | import FileStatus from '@/components/FileStatus'; | ||||
import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
import { TaskStatus } from '@/services/API.helper'; | import { TaskStatus } from '@/services/API.helper'; | ||||
import { DATA } from '@/services/API'; | import { DATA } from '@/services/API'; | ||||
import { useSocketMessages } from '@/utils/hooks'; | |||||
enum SyncType { | enum SyncType { | ||||
Syncing = 'syncing', | Syncing = 'syncing', | ||||
@@ -89,9 +89,9 @@ export default function SyncView() { | |||||
))} | ))} | ||||
</div> | </div> | ||||
<div className={styles.right}> | <div className={styles.right}> | ||||
<div className={styles.date}> | |||||
{/* <div className={styles.date}> // 由于现在消息列表没有清除功能,优先考虑使用虚拟滚动以保证页面性能 | |||||
<div>2021年6月14日</div> | <div>2021年6月14日</div> | ||||
</div> | |||||
</div> */} | |||||
{curretList.map((data) => ( | {curretList.map((data) => ( | ||||
<FileStatus key={data.taskId} className={styles.item} data={data} /> | <FileStatus key={data.taskId} className={styles.item} data={data} /> | ||||
))} | ))} | ||||
@@ -54,7 +54,7 @@ | |||||
flex: 1; | flex: 1; | ||||
overflow: auto; | overflow: auto; | ||||
padding: 0 12px; | padding: 0 12px; | ||||
.item ~ .item { | |||||
.item { | |||||
margin-top: 12px; | margin-top: 12px; | ||||
margin-bottom: 8px; | margin-bottom: 8px; | ||||
} | } | ||||
@@ -1,5 +1,5 @@ | |||||
import { Dayjs } from 'dayjs'; | import { Dayjs } from 'dayjs'; | ||||
import { TaskStatus, TaskType } from './API.helper'; | |||||
import { NotificationType, TaskStatus, TaskType } from './API.helper'; | |||||
declare namespace API { | declare namespace API { | ||||
export interface ResponseData<T> { | export interface ResponseData<T> { | ||||
@@ -81,5 +81,15 @@ declare namespace DATA { | |||||
absolutePath: string; // 绝对路径 | absolutePath: string; // 绝对路径 | ||||
version: number; // 1, | version: number; // 1, | ||||
workStatus: number; // 1 | workStatus: number; // 1 | ||||
/* 消息通知型数据补完 */ | |||||
originData: any; // 用于消息通知 | |||||
/** | |||||
* 通知类型 | |||||
*/ | |||||
notifyType: NotificationType; | |||||
/** | |||||
* 通知消息内容 | |||||
*/ | |||||
notifyMessage: string; | |||||
} | } | ||||
} | } |
@@ -26,3 +26,8 @@ export enum TaskType { | |||||
// 上传 | // 上传 | ||||
UPLOAD = 'UPLOAD', | UPLOAD = 'UPLOAD', | ||||
} | } | ||||
export enum NotificationType { | |||||
SYNC = 1, | |||||
UPLOAD_CONFLICT = 2, | |||||
DOWNLOAD_CONFLICT = 3, | |||||
} |
@@ -1,56 +1,9 @@ | |||||
import { firstCharToLowerCase, Subject } from '@/utils/tool'; | |||||
import dayjs from 'dayjs'; | |||||
import { useEffect, useState } from 'react'; | |||||
import { DATA } from './API'; | |||||
import { isClient } from './system'; | |||||
import { fileMng, msgNotifySubject } from '@/utils/hooks'; | |||||
import { firstCharToLowerCase } from '@/utils/tool'; | |||||
const gatewayPort = window.systemConfig?.gatewayPort || 7888; | const gatewayPort = window.systemConfig?.gatewayPort || 7888; | ||||
const skUrl = `ws://127.0.0.1:${gatewayPort}/websocket/subscriptionTaskSync`; | |||||
class FileMessageManager extends Subject { | |||||
public list: DATA.SocketFileMsg[] = []; | |||||
// 主键 taskId | |||||
public fileMap = new Map(); | |||||
addFileMsg(message: DATA.SocketFileMsg) { | |||||
this.fileMap.set(message.taskId, message); | |||||
this.list = [message].concat(this.list); | |||||
this.notifyObservers(this.list); | |||||
} | |||||
updateFileMsg(message: DATA.SocketFileMsg) { | |||||
this.fileMap.set(message.taskId, message); | |||||
this.list = this.list.map((msg) => | |||||
msg.taskId === message.taskId ? message : msg, | |||||
); | |||||
this.notifyObservers(this.list); | |||||
} | |||||
receiveMessage(messageStr: string) { | |||||
try { | |||||
const message = firstCharToLowerCase( | |||||
JSON.parse(messageStr), | |||||
) as DATA.SocketFileMsg; | |||||
// 数据处理 | |||||
message.taskCreateDate = dayjs((message.taskCreateUnixTime || 0) * 1000); | |||||
// 给消息窗口使用 | |||||
message.taskCreateDateStr = | |||||
message.taskCreateDate.format('YY/MM/DD HH:mm:ss'); | |||||
const existMsg = this.fileMap.get(message.taskId); | |||||
if (existMsg) { | |||||
this.updateFileMsg(message); | |||||
} else { | |||||
this.addFileMsg(message); | |||||
} | |||||
// todo: 临时测试 | |||||
if (isClient) { | |||||
window.ipcRenderer.invoke('notify', message); | |||||
} | |||||
} catch (e) { | |||||
console.error('message 解析失败:', e, messageStr); | |||||
} | |||||
} | |||||
} | |||||
const fileMng = new FileMessageManager(); | |||||
const taskSyncSkUrl = `ws://127.0.0.1:${gatewayPort}/websocket/subscriptionTaskSync`; | |||||
const msgNotifySkUrl = `ws://127.0.0.1:${gatewayPort}/websocket/subscriptionMessageNotify`; | |||||
enum SocketState { | enum SocketState { | ||||
CONNECTING = 0, // 连接尚未建立 | CONNECTING = 0, // 连接尚未建立 | ||||
@@ -60,8 +13,9 @@ enum SocketState { | |||||
} | } | ||||
let taskSyncSocket: WebSocket; | let taskSyncSocket: WebSocket; | ||||
let msgNotifySocket: WebSocket; | |||||
function initTaskSyncSocket() { | function initTaskSyncSocket() { | ||||
taskSyncSocket = new WebSocket(skUrl); | |||||
taskSyncSocket = new WebSocket(taskSyncSkUrl); | |||||
taskSyncSocket.onopen = () => { | taskSyncSocket.onopen = () => { | ||||
console.log('taskSyncSocket connection'); | console.log('taskSyncSocket connection'); | ||||
}; | }; | ||||
@@ -76,6 +30,28 @@ function initTaskSyncSocket() { | |||||
setTimeout(() => initTaskSyncSocket(), 5000); | setTimeout(() => initTaskSyncSocket(), 5000); | ||||
}; | }; | ||||
} | } | ||||
function initMessageNotifySocket() { | |||||
msgNotifySocket = new WebSocket(msgNotifySkUrl); | |||||
msgNotifySocket.onopen = () => { | |||||
console.log('taskSyncSocket connection'); | |||||
}; | |||||
msgNotifySocket.onmessage = ({ data }) => { | |||||
// fileMng.receiveMessage(data); | |||||
try { | |||||
const originNotifyMessage = firstCharToLowerCase(JSON.parse(data)) as any; | |||||
msgNotifySubject.notifyObservers(originNotifyMessage); | |||||
} catch (e) { | |||||
console.error('socket notify message 解析失败:', e, data); | |||||
} | |||||
}; | |||||
msgNotifySocket.onerror = (...args) => { | |||||
console.log('taskSyncSocket error:', args); | |||||
}; | |||||
msgNotifySocket.onclose = (...args) => { | |||||
console.log('taskSyncSocket close:', args); | |||||
setTimeout(() => initTaskSyncSocket(), 5000); | |||||
}; | |||||
} | |||||
export function sendSocketMessage(message: string) { | export function sendSocketMessage(message: string) { | ||||
if (taskSyncSocket && taskSyncSocket.readyState === SocketState.OPEN) { | if (taskSyncSocket && taskSyncSocket.readyState === SocketState.OPEN) { | ||||
taskSyncSocket.send(message); | taskSyncSocket.send(message); | ||||
@@ -83,17 +59,7 @@ export function sendSocketMessage(message: string) { | |||||
} | } | ||||
export function initialWebsocket() { | export function initialWebsocket() { | ||||
initTaskSyncSocket(); | initTaskSyncSocket(); | ||||
initMessageNotifySocket(); | |||||
} | } | ||||
export function useSocketMessages() { | |||||
const [list, setList] = useState(fileMng.list); | |||||
// console.log(list); | |||||
useEffect(() => { | |||||
fileMng.addObserver(setList); | |||||
return () => { | |||||
fileMng.removeObserver(setList); | |||||
}; | |||||
}, []); | |||||
return list; | |||||
} | |||||
// export function use |
@@ -66,8 +66,10 @@ export async function login(account: string, password: string) { | |||||
return res; | return res; | ||||
} | } | ||||
export function logout() { | |||||
storage.clear(); | |||||
export function logout(clearStorage = true) { | |||||
if (clearStorage) { | |||||
storage.clear(); | |||||
} | |||||
system.logout(); | system.logout(); | ||||
// window.location.href = '/login'; | // window.location.href = '/login'; | ||||
history.replace('/login'); | history.replace('/login'); | ||||
@@ -0,0 +1,160 @@ | |||||
import { useCallback, useEffect, useState } from 'react'; | |||||
import { | |||||
firstCharToLowerCase, | |||||
firstCharToUpperCase, | |||||
Subject, | |||||
} from '@/utils/tool'; | |||||
import { API, DATA } from '@/services/API'; | |||||
import dayjs from 'dayjs'; | |||||
import { isClient } from '@/services/system'; | |||||
import { throttle } from 'lodash'; | |||||
import { fetchApi } from './request'; | |||||
import storage from './storage'; | |||||
// // let workspacePath = ''; | |||||
// // 暂时不用 待定 | |||||
// export function useWorkspacePath() { | |||||
// const ctx = useState(''); | |||||
// // const setPath = useCallback((value: string) => { | |||||
// // setThePath(value); | |||||
// // workspacePath = value; | |||||
// // }, [setThePath]); | |||||
// useEffect(() => { | |||||
// // 获取当前使用的路径; 这里的接口需要做一层防抖 | |||||
// }, []); | |||||
// return ctx; | |||||
// } | |||||
class FileMessageManager extends Subject { | |||||
public list: DATA.SocketFileMsg[] = []; | |||||
// 主键 taskId | |||||
public fileMap = new Map(); | |||||
addFileMsg(message: DATA.SocketFileMsg) { | |||||
this.fileMap.set(message.taskId, message); | |||||
this.list = [message].concat(this.list); | |||||
this.notifyObservers(this.list); | |||||
} | |||||
updateFileMsg(message: DATA.SocketFileMsg) { | |||||
this.fileMap.set(message.taskId, message); | |||||
this.list = this.list.map((msg) => | |||||
msg.taskId === message.taskId ? message : msg, | |||||
); | |||||
this.notifyObservers(this.list); | |||||
} | |||||
receiveMessage(messageStr: string) { | |||||
try { | |||||
const message = firstCharToLowerCase( | |||||
JSON.parse(messageStr), | |||||
) as DATA.SocketFileMsg; | |||||
// 数据处理 | |||||
message.taskCreateDate = dayjs((message.taskCreateUnixTime || 0) * 1000); | |||||
// 给消息窗口使用 | |||||
message.taskCreateDateStr = | |||||
message.taskCreateDate.format('YY/MM/DD HH:mm:ss'); | |||||
const existMsg = this.fileMap.get(message.taskId); | |||||
if (existMsg) { | |||||
this.updateFileMsg(message); | |||||
} else { | |||||
this.addFileMsg(message); | |||||
} | |||||
} catch (e) { | |||||
console.error('message 解析失败:', e, messageStr); | |||||
} | |||||
} | |||||
} | |||||
export const fileMng = new FileMessageManager(); | |||||
export const msgNotifySubject = new Subject(); | |||||
msgNotifySubject.addObserver((upperNotifyMessage) => { | |||||
if (!isClient) { | |||||
return; | |||||
} | |||||
const message = transformNotifyMessage(upperNotifyMessage); | |||||
if (!message) { | |||||
return; | |||||
} | |||||
window.ipcRenderer.invoke('notify', message); | |||||
}); | |||||
function transformNotifyMessage(notifyMessage: any) { | |||||
try { | |||||
if (!notifyMessage.parameter) return null; | |||||
const fileMsg = firstCharToLowerCase( | |||||
JSON.parse(notifyMessage.parameter), | |||||
) as DATA.SocketFileMsg; | |||||
fileMsg.originData = notifyMessage.parameter; | |||||
fileMsg.notifyType = notifyMessage.type; | |||||
fileMsg.notifyMessage = notifyMessage.body; | |||||
// 数据处理 | |||||
fileMsg.taskCreateDate = dayjs((notifyMessage.unixTime || 0) * 1000); | |||||
// 给消息窗口使用 | |||||
fileMsg.taskCreateDateStr = | |||||
fileMsg.taskCreateDate.format('YY/MM/DD HH:mm:ss'); | |||||
return fileMsg; | |||||
} catch (e) { | |||||
console.error('transformNotifyMessage 解析失败:', e, notifyMessage); | |||||
return null; | |||||
} | |||||
} | |||||
export function useSocketMessages() { | |||||
const [list, setList] = useState(fileMng.list); | |||||
useEffect(() => { | |||||
fileMng.addObserver(setList); | |||||
return () => { | |||||
fileMng.removeObserver(setList); | |||||
}; | |||||
}, []); | |||||
return list; | |||||
} | |||||
export function useNotificationMessages() { | |||||
const [list, setList] = useState<Array<DATA.SocketFileMsg>>([]); | |||||
const fetchMessages = useCallback( | |||||
throttle(async () => { | |||||
const accountId = storage.get('accountId'); | |||||
const [headList, hisList] = await Promise.all< | |||||
API.ResponseData<any[]>, | |||||
API.ResponseData<any[]> | |||||
>([ | |||||
fetchApi('lockingmsg/queryLockingMsgListByFilter', { | |||||
userId: accountId, | |||||
status: 1, | |||||
}), | |||||
fetchApi('lockingmsg/queryLockingMsgListByFilter', { | |||||
userId: accountId, | |||||
status: 2, | |||||
}), | |||||
]); | |||||
const finalList = headList.data | |||||
?.concat(hisList.data || []) | |||||
.reduce((arr, notifyMessage) => { | |||||
const message = transformNotifyMessage(notifyMessage); | |||||
if (!message) return arr; | |||||
arr.push(message); | |||||
return arr; | |||||
}, []) as DATA.SocketFileMsg[]; | |||||
setList(finalList); | |||||
}, 500), | |||||
[], | |||||
); | |||||
console.log(list); | |||||
useEffect(() => { | |||||
msgNotifySubject.addObserver(fetchMessages); | |||||
return () => { | |||||
msgNotifySubject.removeObserver(fetchMessages); | |||||
}; | |||||
}, []); | |||||
useEffect(() => { | |||||
fetchMessages(); | |||||
}, []); | |||||
return list; | |||||
} |