refactor: the resource list display style in mobile

This commit is contained in:
2025-10-29 17:46:22 +08:00
parent d9f4f643b9
commit 9c83ba38b7

View File

@@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import { Layout, Typography, Table, Grid, InputNumber, Button, Space, Tag, message, Modal, Dropdown } from 'antd'; import { Layout, Typography, Table, Grid, InputNumber, Button, Space, Tag, message, Modal, Dropdown, Input } from 'antd';
import type { ColumnsType, ColumnType } from 'antd/es/table'; import type { ColumnsType, ColumnType } from 'antd/es/table';
import type { FilterDropdownProps } from 'antd/es/table/interface'; import type { FilterDropdownProps } from 'antd/es/table/interface';
import type { TableProps } from 'antd'; import type { TableProps } from 'antd';
import { SearchOutlined, EllipsisOutlined, DeleteOutlined } from '@ant-design/icons'; import { SearchOutlined, EllipsisOutlined, DeleteOutlined, ManOutlined, WomanOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
import './MainContent.css'; import './MainContent.css';
import InputDrawer from './InputDrawer.tsx'; import InputDrawer from './InputDrawer.tsx';
import { getPeoples } from '../apis'; import { getPeoples } from '../apis';
@@ -513,7 +513,7 @@ const ResourceList: React.FC<Props> = ({ inputOpen = false, onCloseInput, contai
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const [data, setData] = React.useState<Resource[]>([]); const [data, setData] = React.useState<Resource[]>([]);
const [pagination, setPagination] = React.useState<{ current: number; pageSize: number }>({ current: 1, pageSize: 10 }); const [pagination, setPagination] = React.useState<{ current: number; pageSize: number }>({ current: 1, pageSize: 10 });
const [inputResult, setInputResult] = React.useState<any>(null); // const [inputResult, setInputResult] = React.useState<any>(null);
const [swipedRowId, setSwipedRowId] = React.useState<string | null>(null); const [swipedRowId, setSwipedRowId] = React.useState<string | null>(null);
const touchStartRef = React.useRef<{ x: number; y: number } | null>(null); const touchStartRef = React.useRef<{ x: number; y: number } | null>(null);
@@ -570,32 +570,59 @@ const ResourceList: React.FC<Props> = ({ inputOpen = false, onCloseInput, contai
title: '姓名', title: '姓名',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
filters: !isMobile ? data filterIcon: <SearchOutlined />,
.filter(item => item.name) // 过滤掉 name 为空的项 filterDropdown: ({ selectedKeys, setSelectedKeys, confirm }) => {
.map((item) => ({ text: item.name!, value: item.name! })) : undefined, return (
filterSearch: !isMobile, <div className="byte-table-custom-filter">
onFilter: (filterValue: React.Key | boolean, record: Resource) => !isMobile && String(record.name).includes(String(filterValue)), <Input.Search
render: (text: string) => <span style={{ fontWeight: 600 }}>{text}</span>, placeholder="搜索资源..."
}, value={selectedKeys[0] || ""}
{ onChange={(e) => {
title: '性别', setSelectedKeys(e.target.value ? [e.target.value] : []);
dataIndex: 'gender', }}
key: 'gender', onSearch={() => {
filters: [ confirm();
{ text: '男', value: '男' }, }}
{ text: '女', value: '女' }, />
{ text: '其他/保密', value: '其他/保密' }, </div>
], );
onFilter: (value: React.Key | boolean, record: Resource) => String(record.gender) === String(value), },
render: (g: string) => { onFilter: (filterValue: React.Key | boolean, record: Resource) => String(record.name).includes(String(filterValue)),
const color = g === '男' ? 'blue' : g === '女' ? 'magenta' : 'default'; render: (text: string, record: Resource) => {
return <Tag color={color}>{g}</Tag>; if (!isMobile) return <span style={{ fontWeight: 600 }}>{text}</span>;
const g = record.gender;
const icon = g === '男'
? <ManOutlined style={{ color: '#1677ff' }} />
: g === '女'
? <WomanOutlined style={{ color: '#eb2f96' }} />
: <ExclamationCircleOutlined style={{ color: '#9ca3af' }} />;
return (
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
<span style={{ fontWeight: 600 }}>{text}</span>
{icon}
</span>
);
}, },
}, },
buildNumberRangeFilter('age', '年龄'),
// 非移动端显示更多列 // 非移动端显示更多列
...(!isMobile ...(!isMobile
? [ ? [
{
title: '性别',
dataIndex: 'gender',
key: 'gender',
filters: [
{ text: '男', value: '男' },
{ text: '女', value: '女' },
{ text: '其他/保密', value: '其他/保密' },
],
onFilter: (value: React.Key | boolean, record: Resource) => String(record.gender) === String(value),
render: (g: string) => {
const color = g === '男' ? 'blue' : g === '女' ? 'magenta' : 'default';
return <Tag color={color}>{g}</Tag>;
},
},
buildNumberRangeFilter('age', '年龄'),
buildNumberRangeFilter('height', '身高'), buildNumberRangeFilter('height', '身高'),
{ {
title: '婚姻状况', title: '婚姻状况',
@@ -608,6 +635,24 @@ const ResourceList: React.FC<Props> = ({ inputOpen = false, onCloseInput, contai
title: '联系人', title: '联系人',
dataIndex: 'contact', dataIndex: 'contact',
key: 'contact', key: 'contact',
filterIcon: <SearchOutlined />,
filterDropdown: ({ selectedKeys, setSelectedKeys, confirm }) => {
return (
<div className="byte-table-custom-filter">
<Input.Search
placeholder="搜索联系人..."
value={selectedKeys[0] || ""}
onChange={(e) => {
setSelectedKeys(e.target.value ? [e.target.value] : []);
}}
onSearch={() => {
confirm();
}}
/>
</div>
);
},
onFilter: (filterValue: React.Key | boolean, record: Resource) => String(record.contact).includes(String(filterValue)),
render: (v: string, record: Resource) => { render: (v: string, record: Resource) => {
if (!isMobile) return v ? v : '-'; if (!isMobile) return v ? v : '-';
return ( return (
@@ -722,8 +767,9 @@ const ResourceList: React.FC<Props> = ({ inputOpen = false, onCloseInput, contai
<div style={{ padding: '8px 24px' }}> <div style={{ padding: '8px 24px' }}>
{isMobile && ( {isMobile && (
<div style={{ display: 'flex', gap: 16, marginBottom: 12, color: '#434343ff' }}> <div style={{ display: 'flex', gap: 16, marginBottom: 12, color: '#434343ff' }}>
{record.height !== undefined && <div>: {record.height}</div>} {record.age !== undefined && <div><span style={{ color: '#000000ff', fontWeight: 600 }}>:</span> <span style={{ color: '#2d2d2dff' }}>{record.age}</span></div>}
{record.marital_status && <div>: {record.marital_status}</div>} {record.height !== undefined && <div><span style={{ color: '#000000ff', fontWeight: 600 }}>:</span> <span style={{ color: '#2d2d2dff' }}>{record.height}</span></div>}
{record.marital_status && <div><span style={{ color: '#000000ff', fontWeight: 600 }}>:</span> <span style={{ color: '#2d2d2dff' }}>{record.marital_status}</span></div>}
</div> </div>
)} )}
{intro.length > 0 ? ( {intro.length > 0 ? (
@@ -764,7 +810,7 @@ const ResourceList: React.FC<Props> = ({ inputOpen = false, onCloseInput, contai
open={inputOpen} open={inputOpen}
onClose={onCloseInput || (() => {})} onClose={onCloseInput || (() => {})}
onResult={(list: any) => { onResult={(list: any) => {
setInputResult(list); // setInputResult(list);
const mapped = transformPeoples(Array.isArray(list) ? list : []); const mapped = transformPeoples(Array.isArray(list) ? list : []);
setData(mapped); setData(mapped);
// 回到第一页,保证用户看到最新结果 // 回到第一页,保证用户看到最新结果