Browse Source

测量历史按分组显示和选择

master
zhangjiming 4 months ago
parent
commit
1bb4a88778
  1. 28
      src/components/GroupItem.tsx
  2. 63
      src/components/MeasureGroups.tsx
  3. 45
      src/components/MeasurementItem.tsx
  4. 3
      src/index.tsx
  5. 34
      src/pages/Measure.tsx
  6. 139
      src/pages/Mine2.tsx

28
src/components/GroupItem.tsx

@ -0,0 +1,28 @@
import icon_check_s from '../assets/icon_check_s_s.svg';
import icon_check_u from '../assets/icon_check_s_u.svg';
export default function GroupItem({
title,
editMode = false,
selected = false,
onGroupSelect,
}: {
title: string;
editMode?: boolean;
selected?: boolean;
onGroupSelect?: () => void;
}) {
const select = () => {
if (editMode) {
return <img className="w-[14px]" src={selected ? icon_check_s : icon_check_u} alt="icon" />;
}
return null;
};
return (
<div className="px-5 py-2 text-sm flex gap-x-3" onClick={onGroupSelect}>
{select()}
<span>{title}</span>
</div>
);
}

63
src/components/MeasureGroups.tsx

@ -0,0 +1,63 @@
import { InfiniteScroll, List } from 'antd-mobile';
import { Measurement } from '../services/apiTypes';
import { useNavigate } from 'react-router';
import GroupItem from './GroupItem';
import MeasurementItem from './MeasurementItem';
import * as R from 'ramda';
export default function MeasureGroups({
dataList,
editMode,
hasMore,
loadMore,
onItemSelect,
onGroupSelect,
selectedIds,
}: {
dataList: Array<{ groupName: string; list: Measurement[] }>;
editMode: boolean;
hasMore: boolean;
loadMore: () => Promise<void>;
onItemSelect: (groupIndex: number, id: number) => void;
onGroupSelect: (groupIndex: number) => void;
selectedIds: Array<number>;
}) {
const navigate = useNavigate();
const isSubset = (ids: number[]) => R.intersection(selectedIds, ids).length === ids.length;
return (
<div>
{dataList.length > 0 ? (
<>
{dataList.map((group, idx) => (
<div key={group.groupName}>
<GroupItem
title={group.groupName}
editMode={editMode}
selected={isSubset(group.list.map((item) => item.id))}
onGroupSelect={() => onGroupSelect(idx)}
/>
<List>
{group.list.map((item) => (
<List.Item key={item.id}>
<MeasurementItem
item={item}
editMode={editMode}
selected={selectedIds.includes(item.id)}
onSelected={() => onItemSelect(idx, item.id)}
onDetail={() => navigate(`/measure/record/${item.id}`)}
/>
</List.Item>
))}
</List>
</div>
))}
<InfiniteScroll loadMore={loadMore} hasMore={hasMore} />
</>
) : (
<p className="absolute text-title left-1/2 top-1/3 -translate-x-1/2"></p>
)}
</div>
);
}

45
src/components/MeasurementItem.tsx

@ -0,0 +1,45 @@
import icon_check_s from '../assets/icon_check_s_s.svg';
import icon_check_u from '../assets/icon_check_s_u.svg';
import icon_arr from '../assets/icon_arr_p_r.svg';
import { Measurement } from '../services/apiTypes';
export default function MeasurementItem({
item,
editMode,
selected,
onDetail,
onSelected,
}: {
item: Measurement;
editMode: boolean;
selected: boolean;
onDetail?: () => void;
onSelected?: () => void;
}) {
return (
<div className="flex mx-2 gap-3" onClick={editMode ? onSelected : undefined}>
{editMode && (
<div className="flex justify-center items-center">
<img className="w-[14px]" src={selected ? icon_check_s : icon_check_u} alt="icon" />
</div>
)}
<main className="flex-1">
<header className="flex items-center gap-2">
<h1 className="text-[15px] font-medium ">{item.name}</h1>
{/* <span className="text-sm text-[#b7b7b7]">{item.createAt.replace('T',' ').split(' ')[1]}</span> */}
</header>
<main className="flex mt-2">
<p className="flex-1 text-sm ">{`${item.line}`}</p>
<p className="flex-1 text-sm ">{`${item.section}`}</p>
<p className="flex-1 text-sm ">{`${item.direction}方向`}</p>
</main>
</main>
{!editMode && (
<aside className="flex items-center" onClick={onDetail}>
<span className="mr-2 text-sm text-primary font-medium"></span>
<img src={icon_arr} alt="arr" className="h-[10px]" />
</aside>
)}
</div>
);
}

3
src/index.tsx

@ -17,6 +17,7 @@ import Measure from './pages/Measure';
import Setting from './pages/Setting';
import Bluetooth from './pages/Bluetooth';
import Mine from './pages/Mine';
import Mine2 from './pages/Mine2';
import MeasureSave from './pages/MeasureSave';
import MeasureRecord from './pages/MeasureRecord';
@ -28,7 +29,7 @@ const router = createHashRouter(
<Route path="measure" element={<Measure />}></Route>
<Route path="setting" element={<Setting />}></Route>
<Route path="bluetooth" element={<Bluetooth />}></Route>
<Route path="mine" element={<Mine />}></Route>
<Route path="mine" element={<Mine2 />}></Route>
</Route>
<Route path="measure">
<Route path="save" element={<MeasureSave />}></Route>

34
src/pages/Measure.tsx

@ -14,23 +14,23 @@ import { useAppDispatch, useAppSelector } from '../utils/hooks';
import { updateTaskState } from '../store/features/measureSlice';
import Bridge from '../utils/bridge';
declare global {
interface Window {
ReactNativeWebView: { postMessage: (arg: string) => void };
funcMap: Record<string, any>;
bridgeCall: (func: string, args: any[]) => void;
}
}
window.funcMap = {
add: (a: number, b: number) => a + b,
sub: (a: number, b: number) => a - b,
};
window.bridgeCall = (func, ...args) => {
console.log(func, args);
const res = window.funcMap[func].apply(null, args);
console.log('res:', res);
};
// declare global {
// interface Window {
// ReactNativeWebView: { postMessage: (arg: string) => void };
// funcMap: Record<string, any>;
// bridgeCall: (func: string, args: any[]) => void;
// }
// }
// window.funcMap = {
// add: (a: number, b: number) => a + b,
// sub: (a: number, b: number) => a - b,
// };
// window.bridgeCall = (func, ...args) => {
// console.log(func, args);
// const res = window.funcMap[func].apply(null, args);
// console.log('res:', res);
// };
export default function Measure() {
const navigate = useNavigate();

139
src/pages/Mine2.tsx

@ -0,0 +1,139 @@
import { NavBar, Toast } from 'antd-mobile';
import { useEffect, useRef, useState } from 'react';
import { Measurement } from '../services/apiTypes';
import Bridge from '../utils/bridge';
import MeasureGroups from '../components/MeasureGroups';
import { MoreOutline } from 'antd-mobile-icons';
import * as R from 'ramda';
const PAGE_SIZE = 10;
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,
},
],
},
];
export default function Mine2() {
const [editMode, setEditMode] = useState(false);
const [selectedIds, setSelectedIds] = useState<number[]>([]);
async function loadMoreRecords() {}
const onItemSelect = (groupIdx: number, id: number) => {
if (selectedIds.includes(id)) {
setSelectedIds(R.reject((item) => item === id, selectedIds));
} else {
setSelectedIds([...selectedIds, id]);
}
};
const onGroupSelect = (groupIdx: number) => {
const ids = dataList[groupIdx].list.map((item) => item.id);
if (R.intersection(selectedIds, ids).length === ids.length) {
setSelectedIds(R.difference(selectedIds, ids));
} else {
setSelectedIds(R.union(selectedIds, ids));
}
};
const right = (
<div
onClick={() => setEditMode(!editMode)}
className="flex justify-end"
style={{ fontSize: 24 }}
>
<MoreOutline />
</div>
);
return (
<div>
<NavBar className="bg-white" back={null} right={right}>
</NavBar>
<div className="home-page-content overflow-x-hidden overflow-y-auto">
<MeasureGroups
dataList={dataList}
editMode={editMode}
hasMore={false}
loadMore={loadMoreRecords}
onItemSelect={onItemSelect}
onGroupSelect={onGroupSelect}
selectedIds={selectedIds}
/>
</div>
</div>
);
}
Loading…
Cancel
Save