|
|
@ -1,24 +1,116 @@ |
|
|
|
import { ActionSheet, InfiniteScroll, List, NavBar, Popup } from 'antd-mobile'; |
|
|
|
import { ActionSheet, Dialog, InfiniteScroll, List, NavBar, Toast } from 'antd-mobile'; |
|
|
|
import { useNavigate } from 'react-router-dom'; |
|
|
|
|
|
|
|
import { MoreOutline } from 'antd-mobile-icons'; |
|
|
|
import { useState } from 'react'; |
|
|
|
import { useCallback, useEffect, useState } from 'react'; |
|
|
|
|
|
|
|
import { dataListFlat } from '../utils/constant'; |
|
|
|
import MeasureGroups from '../components/MeasureGroups'; |
|
|
|
import MeasureItem from '../components/MeasureItem'; |
|
|
|
import { Measurement } from '../services/apiTypes'; |
|
|
|
import Bridge, { bridgeOb } from '../utils/bridge'; |
|
|
|
import { useAppDispatch, useAppSelector } from '../utils/hooks'; |
|
|
|
import { refreshSyncProgress } from '../store/features/contextSlice'; |
|
|
|
|
|
|
|
const PAGE_SIZE = 10; |
|
|
|
|
|
|
|
export default function UploadList() { |
|
|
|
const navigate = useNavigate(); |
|
|
|
const dispatch = useAppDispatch(); |
|
|
|
|
|
|
|
const context = useAppSelector((state) => state.context); |
|
|
|
|
|
|
|
const [showMenu, setShowMenu] = useState(false); |
|
|
|
const [list, setList] = useState<Measurement[]>([]); |
|
|
|
const [noMore, setNoMore] = useState(false); |
|
|
|
|
|
|
|
const actions = [ |
|
|
|
{ text: '重试失败任务', key: 'retry' }, |
|
|
|
{ text: '清空列表', key: 'clear' }, |
|
|
|
{ text: '清空已完成任务', key: 'clearCompleted' }, |
|
|
|
] |
|
|
|
{ |
|
|
|
text: '重试失败任务', |
|
|
|
key: 'retry', |
|
|
|
onClick: async () => { |
|
|
|
setShowMenu(false); |
|
|
|
if (context.syncProgress.fail === 0) { |
|
|
|
return Toast.show('目前没有失败的任务'); |
|
|
|
} |
|
|
|
const res = await Bridge.retryFailureSync(); |
|
|
|
if (!res.success) { |
|
|
|
Toast.show(res.message); |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
text: '清空列表', |
|
|
|
key: 'clear', |
|
|
|
onClick: () => { |
|
|
|
setShowMenu(false); |
|
|
|
if (!context.syncProgress.finish) { |
|
|
|
Dialog.confirm({ |
|
|
|
content: '存在未完成的任务,确定清空?', |
|
|
|
onConfirm: () => { |
|
|
|
Bridge.clearSyncList().then((res) => { |
|
|
|
if (res.success) { |
|
|
|
loadData(); |
|
|
|
} else { |
|
|
|
Toast.show(res.message); |
|
|
|
} |
|
|
|
}); |
|
|
|
}, |
|
|
|
}); |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
text: '清空已完成任务', |
|
|
|
key: 'clearCompleted', |
|
|
|
onClick: async () => { |
|
|
|
setShowMenu(false); |
|
|
|
const res = await Bridge.clearFinishedSync(); |
|
|
|
if (res.success) { |
|
|
|
loadData(); |
|
|
|
} else { |
|
|
|
Toast.show(res.message); |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
]; |
|
|
|
|
|
|
|
const loadData = useCallback(() => { |
|
|
|
dispatch(refreshSyncProgress()); |
|
|
|
Bridge.getSyncTaskList({ pageNum: 1, size: PAGE_SIZE }).then((res) => { |
|
|
|
if (res.success) { |
|
|
|
setList(res.data.list); |
|
|
|
setNoMore(res.data.list.length < PAGE_SIZE); |
|
|
|
} else { |
|
|
|
Toast.show(res.message); |
|
|
|
} |
|
|
|
}); |
|
|
|
}, [dispatch]); |
|
|
|
|
|
|
|
async function loadMoreData() { |
|
|
|
const pageNum = Math.floor(list.length / PAGE_SIZE); |
|
|
|
const res = await Bridge.getSyncTaskList({ pageNum: pageNum + 1, size: PAGE_SIZE }); |
|
|
|
if (res.success) { |
|
|
|
setList(list.concat(res.data.list)); |
|
|
|
setNoMore(res.data.list.length < PAGE_SIZE); |
|
|
|
} else { |
|
|
|
Toast.show(res.message); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
loadData(); |
|
|
|
}, [loadData]); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
const subscription = bridgeOb.subscribe((datagram) => { |
|
|
|
if (datagram.type === 'sync-item-finish') { |
|
|
|
const item = list.find((item) => item.id === datagram.data.id); |
|
|
|
if (item) { |
|
|
|
item.syncStatus = datagram.data.success ? 'finish' : 'fail'; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
return () => subscription.unsubscribe(); |
|
|
|
}, [list]); |
|
|
|
|
|
|
|
const back = () => navigate(-1); |
|
|
|
|
|
|
@ -35,31 +127,37 @@ export default function UploadList() { |
|
|
|
return ( |
|
|
|
<div> |
|
|
|
<NavBar className="bg-white" onBack={back} right={right}> |
|
|
|
上传数据 |
|
|
|
上传记录 |
|
|
|
</NavBar> |
|
|
|
<div className="main-page-content"> |
|
|
|
<header className="h-8 bg-[#EEE] flex items-center px-4"> |
|
|
|
<span>剩余任务10个</span> |
|
|
|
<span>剩余任务{context.syncProgress.remaining}个</span> |
|
|
|
<i className="border-l border-[#999] h-3 mx-2" /> |
|
|
|
<span>失败0个</span> |
|
|
|
<p className="ml-auto text-primary">上传中</p> |
|
|
|
<span>失败{context.syncProgress.fail}个</span> |
|
|
|
<p className="ml-auto text-primary">{context.syncProgress.finish ? '完成' : '上传中'}</p> |
|
|
|
</header> |
|
|
|
<main className=" overflow-x-hidden overflow-y-auto"> |
|
|
|
<List> |
|
|
|
{dataListFlat.map((item) => ( |
|
|
|
<List.Item key={item.id}> |
|
|
|
<MeasureItem item={item} onDetail={() => navigate(`/measure/record/${item.id}`)} /> |
|
|
|
</List.Item> |
|
|
|
))} |
|
|
|
{/* <InfiniteScroll loadMore={loadMore} hasMore={hasMore} /> */} |
|
|
|
</List> |
|
|
|
<main |
|
|
|
className="relative overflow-x-hidden overflow-y-auto" |
|
|
|
style={{ height: 'calc(100% - 32px)' }} |
|
|
|
> |
|
|
|
{list.length > 0 ? ( |
|
|
|
<List> |
|
|
|
{list.map((item) => ( |
|
|
|
<List.Item key={item.id}> |
|
|
|
<MeasureItem |
|
|
|
item={item} |
|
|
|
onDetail={() => navigate(`/measure/record/${item.id}`)} |
|
|
|
/> |
|
|
|
</List.Item> |
|
|
|
))} |
|
|
|
<InfiniteScroll loadMore={loadMoreData} hasMore={!noMore} /> |
|
|
|
</List> |
|
|
|
) : ( |
|
|
|
<p className="absolute text-title left-1/2 top-1/3 -translate-x-1/2">暂无数据</p> |
|
|
|
)} |
|
|
|
</main> |
|
|
|
</div> |
|
|
|
<ActionSheet |
|
|
|
visible={showMenu} |
|
|
|
actions={actions} |
|
|
|
onClose={() => setShowMenu(false)} |
|
|
|
/> |
|
|
|
<ActionSheet visible={showMenu} actions={actions} onClose={() => setShowMenu(false)} /> |
|
|
|
</div> |
|
|
|
); |
|
|
|
} |