index.tsx 2.61 KB
// REQ-USR-003: 用户列表页面容器(组合工具栏/筛选栏/表格+分页,对接 GET /api/usr/users)
import { useState } from 'react';
import { Button } from 'antd';
import { useNavigate } from 'react-router-dom';
import type { UserVO } from '../../../api/types';
import UserToolbar from './UserToolbar';
import UserFilterBar from './UserFilterBar';
import UserTable from './UserTable';
import { useUserList } from './useUserList';
import { TEXT_ERROR } from './constants';
import styles from './UserList.module.css';

export default function UserListPage() {
  const navigate = useNavigate();
  const {
    list,
    total,
    loading,
    error,
    query,
    exporting,
    search,
    refresh,
    clear,
    setQueryField,
    setMatchType,
    setQueryValue,
    changePage,
    exportExcel,
  } = useUserList();

  // 单选标记仅服务「进单据」语义,不参与查询(spec D8)
  const [selectedRowKey, setSelectedRowKey] = useState<number | null>(null);

  const handleRowDoubleClick = (row: UserVO) => {
    // BR12: 进入编辑单据。列表行 UserVO 已含单据预填所需全部字段,
    // 经 navigate state 透传给详情页走 presetUser 分支;
    // 不能仅靠 :id(路由 :id 为用户主键,而读端点 GET /api/usr/users 的 queryField
    // 无主键选项,按主键去查「用户号」列在真实后端必然返回空 → 误报 40401),
    // 详见 FE-04 / docs/05 REQ-USR-002。
    navigate('/usr/users/' + row.id, { state: { user: row } });
  };

  return (
    <div className={styles.page}>
      <UserToolbar
        onRefresh={refresh}
        onAdd={() => navigate('/usr/users/new')} // BR13
        onExport={() => void exportExcel()}
        exporting={exporting}
        loading={loading}
      />
      <UserFilterBar
        query={query}
        onChangeQueryField={setQueryField}
        onChangeMatchType={setMatchType}
        onChangeQueryValue={setQueryValue}
        onSearch={search}
        onClear={clear}
      />
      {error ? (
        <div className={styles.errorBox} data-testid="userlist-error">
          <span className={styles.errorText}>{TEXT_ERROR}</span>
          <Button type="primary" onClick={() => refresh()}>
            点击重试
          </Button>
        </div>
      ) : (
        <UserTable
          rows={list}
          loading={loading}
          total={total}
          pageNum={query.pageNum}
          pageSize={query.pageSize}
          onChangePage={changePage}
          onRowDoubleClick={handleRowDoubleClick}
          selectedRowKey={selectedRowKey}
          onSelectRow={setSelectedRowKey}
        />
      )}
    </div>
  );
}