Browse Source

上传记录页面 mock

master
zhangjiming 4 months ago
parent
commit
c626652464
  1. 152
      src/pages/UploadList.tsx
  2. 1
      src/services/apiTypes.ts
  3. 12
      src/store/features/contextSlice.ts
  4. 44
      src/utils/bridge.ts
  5. 232
      src/utils/constant.ts

152
src/pages/UploadList.tsx

@ -1,25 +1,117 @@
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);
const right = (
@ -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>
);
}

1
src/services/apiTypes.ts

@ -10,6 +10,7 @@ export type Measurement = {
leftPoints: string; // json: 坐标数组
rightPoints: string; // json: 坐标数组
upload: boolean;
syncStatus: 'wait' | 'finish' | 'fail';
};
export type KTJOrg = {

12
src/store/features/contextSlice.ts

@ -68,10 +68,15 @@ export const saveConfig = createAsyncThunk(
async (param: { server: string }, thunkAPI) => {
const res = await Bridge.saveConfig(param);
res.success && thunkAPI.dispatch(fetchConfig());
return res
return res;
}
);
export const refreshSyncProgress = createAsyncThunk('context/refreshSync', async () => {
const res = await Bridge.getSyncProcess();
return res.success ? res.data : null;
});
export const contextSlice = createSlice({
name: 'context',
initialState,
@ -105,6 +110,11 @@ export const contextSlice = createSlice({
state.setting = action.payload;
}
});
builder.addCase(refreshSyncProgress.fulfilled, (state, action) => {
if (action.payload) {
state.syncProgress = action.payload;
}
});
},
});

44
src/utils/bridge.ts

@ -1,7 +1,7 @@
import { Subject } from 'rxjs';
import httpRequest from '../services/httpRequest';
import { Measurement } from '../services/apiTypes';
import { MobileDatagram } from '../services/mobileWsType';
import { MobileDatagram, SyncProgress } from '../services/mobileWsType';
declare global {
interface Window {
@ -257,4 +257,46 @@ export default class Bridge {
params,
});
}
static getSyncTaskList(params: { pageNum: number; size: number }) {
return httpRequest<BridgeBaseResult<{list: Measurement[]}>>({
url: '/api/sync/list',
method: "POST",
params
})
}
static addSyncTask(params: {ids: number[]}) {
return httpRequest<BridgeBaseResult>({
url: '/api/sync/add',
method: "POST",
params
})
}
static getSyncProcess() {
return httpRequest<BridgeBaseResult<SyncProgress["data"]>>({
url: '/api/sync/progress',
method: "POST",
params:{}
})
}
static clearSyncList() {
return httpRequest<BridgeBaseResult>({
url: '/api/sync/empty-all',
method: "POST",
params:{}
})
}
static clearFinishedSync() {
return httpRequest<BridgeBaseResult>({
url: '/api/sync/empty-finish',
method: "POST",
params:{}
})
}
static retryFailureSync() {
return httpRequest<BridgeBaseResult>({
url: '/api/sync/re-fail',
method: "POST",
params:{}
})
}
}

232
src/utils/constant.ts

@ -1734,122 +1734,122 @@ export const sectionList = [
},
];
export const dataListFlat: Measurement[] = [
{
id: 1,
name: '测量名称1',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'A段',
direction: '上行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
{
id: 2,
name: '测量名称2',
createAt: '2025-03-02 12:22',
line: '京沪线',
section: 'B段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
{
id: 3,
name: '测量名称3',
createAt: '2025-03-02 12:20',
line: '京沪线',
section: 'C段',
direction: '上行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
];
// export const dataListFlat: Measurement[] = [
// {
// id: 1,
// name: '测量名称1',
// createAt: '2025-03-02 10:20',
// line: '京沪线',
// section: 'A段',
// direction: '上行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// {
// id: 2,
// name: '测量名称2',
// createAt: '2025-03-02 12:22',
// line: '京沪线',
// section: 'B段',
// direction: '下行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// {
// id: 3,
// name: '测量名称3',
// createAt: '2025-03-02 12:20',
// line: '京沪线',
// section: 'C段',
// direction: '上行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// ];
export const dataList: Array<{ groupName: string; list: Measurement[] }> = [
{
groupName: '2025-03-02',
list: [
{
id: 1,
name: '测量名称1',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'A段',
direction: '上行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
{
id: 2,
name: '测量名称2',
createAt: '2025-03-02 12:22',
line: '京沪线',
section: 'B段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
{
id: 3,
name: '测量名称3',
createAt: '2025-03-02 12:20',
line: '京沪线',
section: 'C段',
direction: '上行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
],
},
{
groupName: '2025-02-01',
list: [
{
id: 4,
name: '测量名称2',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'D段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
{
id: 5,
name: '测量名称2',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'E段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
},
],
},
// {
// groupName: '2025-03-02',
// list: [
// {
// id: 1,
// name: '测量名称1',
// createAt: '2025-03-02 10:20',
// line: '京沪线',
// section: 'A段',
// direction: '上行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// {
// id: 2,
// name: '测量名称2',
// createAt: '2025-03-02 12:22',
// line: '京沪线',
// section: 'B段',
// direction: '下行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// {
// id: 3,
// name: '测量名称3',
// createAt: '2025-03-02 12:20',
// line: '京沪线',
// section: 'C段',
// direction: '上行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// ],
// },
// {
// groupName: '2025-02-01',
// list: [
// {
// id: 4,
// name: '测量名称2',
// createAt: '2025-03-02 10:20',
// line: '京沪线',
// section: 'D段',
// direction: '下行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// {
// id: 5,
// name: '测量名称2',
// createAt: '2025-03-02 10:20',
// line: '京沪线',
// section: 'E段',
// direction: '下行',
// railId: 2,
// leftPoints: '[]',
// rightPoints: '[]',
// bureau: '北京铁路局',
// upload: false,
// },
// ],
// },
];
Loading…
Cancel
Save