猪齿鱼:实现table分页勾选

一、需求

1、表格分页勾选

二、效果图

三、代码

1、index.tsx

javascript 复制代码
import React, { useEffect, useMemo } from 'react';
import { useRef, useState } from 'react';
import {
  Modal,
  Button,
  message,
  DataSet,
  useDataSet,
  Form,
  TextArea,
  Lov,
  Table,
  TextField,
  Icon,
  Spin,
} from 'choerodon-ui/pro';
import { SelectionMode } from 'choerodon-ui/pro/lib/table/enum';
import { ButtonColor } from 'choerodon-ui/pro/lib/button/enum';
import { QueryBar } from '@ino/ltc-component-paas';
import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum';
import {
  COMMON_CANCEL,
  COMMON_CONFIRM,
  languageConfig,
} from '@/language/language';
import styles from '@/assets/styles/global.less';
import { FieldType } from 'choerodon-ui/dataset/data-set/enum';
import { postAdminTransferSubmit } from '@/api/affiliationApplication';
import LoadingSpinner from '@/components/Loading';
import { adminQueryList, adminTableList } from '../adminTransferStore';
import { useColumns } from './useColumns';

let modal;
export const useAdminTransferModal = ({ onSelect }) => {
  const dsRef = useRef<DataSet | null>(null);
  const tableDsRef = useRef<DataSet | null>(null);
  const [buttonLoading, setButtonLoading] = useState<boolean>(false);

  const handleOpenModal = () => {
    modal = Modal.open({
      className: styles.prmCaSelectCustomerModal,
      style: { width: '1100px' },
      drawer: true,
      header: (
        <div className={styles.prmCa_customerModal_header_modalTitle}>
          <div>
            {languageConfig(
              'affiliationApplication.btn.adminTransfer',
              '管理员转办',
            )}
          </div>
          <div>
            <Icon
              type="close"
              style={{
                fontWeight: '400',
                fontSize: '20px',
                cursor: 'pointer',
              }}
              onClick={() => modal?.close()}
            />
          </div>
        </div>
      ),
      children: (
        <AdminTransferModal
          formRef={dsRef}
          tableDsRef={tableDsRef}
          loading={buttonLoading}
        />
      ),
      footer: (
        <div style={{ textAlign: 'right' }}>
          <Button
            color={ButtonColor.primary}
            loading={buttonLoading}
            onClick={handleSubmit}
          >
            {COMMON_CONFIRM()}
          </Button>
          <Button loading={buttonLoading} onClick={() => modal?.close()}>
            {COMMON_CANCEL()}
          </Button>
        </div>
      ),
    });
  };

  const handleSubmit = async () => {
    // 1、获取 Table 数据集
    const currentTableDs = tableDsRef.current;

    // 2、校验是否选择了数据
    const selectedRecords = currentTableDs?.selected || [];

    if (selectedRecords.length === 0) {
      message.error(
        languageConfig(
          'adminTransfer.tips.selectData',
          '请至少选择一条数据进行转办!',
        ),
        undefined,
        undefined,
        'top',
      );
      return false;
    }

    setButtonLoading(true);

    try {
      console.log('提交数据:');

      // 1、从 Ref 获取数据集实例
      const formDs = dsRef.current;
      if (!formDs) {
        message.error(
          '表单数据加载失败,请重新打开弹框',
          undefined,
          undefined,
          'top',
        );
        return false;
      }

      // 2、表单校验
      const isvalidate = await formDs.validate();
      if (!isvalidate) {
        return false;
      }

      // 3、获取表单数据
      const { remark, auditPerson } = formDs.current?.toData() || {};
      const ids = selectedRecords.map(record => record.get('instanceId')) || [];

      const params = {
        instanceIds: ids?.join(','),
        auditPerson: [
          {
            empNo: auditPerson.employeeNum,
            loginName: auditPerson.loginName,
            showName: auditPerson.name,
          },
        ],
        remark,
      };

      const res = await postAdminTransferSubmit(params);
      if (res.failed) {
        message.error(res.message, undefined, undefined, 'top');
        return false;
      }
      modal?.close();
      onSelect();
    } catch (error) {
      console.error('提交出错:', error);
    } finally {
      setButtonLoading(false);
    }
  };

  return {
    open: handleOpenModal,
    close: () => modal?.close(),
  };
};

/** 内容 */
const AdminTransferModal: React.FC<{ formRef; tableDsRef; loading }> = ({
  formRef,
  tableDsRef,
  loading = false,
}) => {
  const transferFormDs = useDataSet(
    () => ({
      autoCreate: true,
      fields: [
        {
          name: 'auditPerson',
          type: FieldType.object,
          lovCode: 'LTC.HPFM.EMPLOYEE',
          label: languageConfig('return.modal.auditPerson.label', '转办人'),
          placeholder: languageConfig(
            'return.modal.auditPerson.placeholder',
            '请选择转办人',
          ),
          required: true,
        },
        {
          name: 'remark',
          type: FieldType.string,
          label: languageConfig(
            'return.modal.auditPersonRemark.label',
            '转办备注',
          ),
          placeholder: languageConfig(
            'return.modal.auditPersonRemark.placeholder',
            '请输入转办备注',
          ),
        },
      ],
    }),
    [],
  );

  /** 查询 ds */
  const querySearchList = async data => {
    const queryParameters = {
      downstreamChannelName: data.downstreamChannelName,
      currentProcessor: data?.currentProcessor?.userInfo
        ? data?.currentProcessor?.userInfo
        : '',
    };

    Object.entries(queryParameters).forEach(([key, value]): void => {
      tableDs.setQueryParameter(key, value);
    });
    console.log('queryParameters', queryParameters);

    await tableDs.query();
  };
  const onChange = async ({ record }) => {
    querySearchList(record.toData());
  };
  const queryListDs = useMemo(() => new DataSet(adminQueryList(onChange)), []);
  const queryConfig = [
    {
      name: 'downstreamChannelName',
      dom: TextField,
      clearButton: true,
    },
    {
      name: 'currentProcessor',
      dom: Lov,
      clearButton: true,
      onChange: value => {
        queryListDs.setQueryParameter(
          'currentProcessor',
          value?.userInfo || '',
        );
      },
    },
  ];

  /** table ds */
  const { columnList } = useColumns();
  const tableDs = useMemo(() => new DataSet(adminTableList()), []);
  const columns: any = useMemo(() => {
    return [...columnList];
  }, []);

  formRef.current = transferFormDs;

  useMemo(() => {
    tableDsRef.current = tableDs;
  }, [tableDs, tableDsRef]);

  // 【勾选核心】
  useEffect(() => {
    // 方法一:获取所有选中记录的数组
    // const selectedRecords = tableDs.selection;
    // console.log('选中的记录对象数组:', selectedRecords);

    // 获取选中的主键值数组(常用)
    const selectedIds = tableDs.selected;
    console.log('选中的主键数组:', selectedIds);

    // 如果只需要选中的数据(toData()会将Record转换为普通对象)
    const selectedData = tableDs.selected?.map(record => record.toData());
    console.log('选中的纯数据数组:', selectedData);

    // 获取选中记录的数量
    const selectedCount = tableDs?.selected?.length;
    console.log('选中数量:', selectedCount);
  }, [tableDs?.selected?.length]);

  return (
    <>
      <div className="ltc-c7n-style">
        <Spin spinning={loading}>
          <div className={styles.prmCa}>
            <QueryBar
              formConfig={{ labelLayout: LabelLayout.float }}
              onQuery={querySearchList}
              queryConfig={queryConfig}
              queryBarDs={queryListDs}
            />
            <Table
              dataSet={tableDs}
              columns={columns}
              selectionMode={SelectionMode.rowbox}
              rowNumber={true}
            />
          </div>

          <Form dataSet={transferFormDs}>
            <Lov name="auditPerson" />
            <TextArea name="remark" rows={2} />
          </Form>
        </Spin>
      </div>
    </>
  );
};

2、store.ts

javascript 复制代码
import { getAdminTransferList } from '@/api/affiliationApplication';
import { languageConfig } from '@/language/language';
import { getProductAuthTypeOptions } from '@/public/store';
import { DataSetProps } from 'choerodon-ui/dataset/data-set/DataSet';
import {
  DataSetSelection,
  FieldType,
} from 'choerodon-ui/dataset/data-set/enum';
import moment from 'moment';

/** ds 查询 */
export const adminQueryList = (onChange): DataSetProps => {
  return {
    autoCreate: true,
    fields: [
      {
        name: 'downstreamChannelName',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.query.label.downstreamChannelName',
          '下游渠道',
        ),
        placeholder: languageConfig(
          'affiliationApplication.query.label.downstreamChannelName',
          '下游渠道',
        ),
      },
      {
        name: 'currentProcessor',
        type: FieldType.object,
        lovCode: 'LTC.HPFM.EMPLOYEE',
        label: languageConfig(
          'affiliationApplication.query.label.currentProcessor',
          '当前处理人',
        ),
        placeholder: languageConfig(
          'affiliationApplication.query.label.currentProcessor',
          '当前处理人',
        ),
      },
    ],
    events: {
      update: onChange,
    },
  };
};

export const adminTableList = () => {
  return {
    autoQuery: true,
    selection: DataSetSelection.multiple,
    primaryKey: 'id', // 【勾选核心】
    // pageSize: 10,
    // dataKey: 'content',
    cacheSelection: true, // 【勾选核心】
    fields: [
      {
        name: 'applyNo',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.applyNo',
          '申请单号',
        ),
      },
      {
        name: 'downstreamChannelName',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.downstreamChannelName',
          '下游渠道',
        ),
      },
      {
        name: 'divisionName',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.divisionName',
          '事业部',
        ),
      },
      {
        name: 'zoneName',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.zoneName',
          '战区',
        ),
      },
      {
        name: 'businessDeptName',
        type: FieldType.string,
      },
      {
        name: 'businessUnitName',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.businessUnitName',
          '所属业务单元',
        ),
      },
      {
        name: 'affiliationType',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.affiliationType',
          '挂靠类型',
        ),
        lookupCode: 'PRM_CA_AFFILIATION_TYPE',
      },
      {
        name: 'openAccountApplyNo',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.openAccountApplyNo',
          '关联开户申请单',
        ),
      },
      {
        name: 'upstreamChannelNames',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.upstreamChannelName',
          '上游渠道',
        ),
      },
      {
        name: 'productAuthCategoryIds',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.productAuthCategoryNames',
          '产品授权类别',
        ),
        textField: 'authCategoryName',
        valueField: 'id',
        options: getProductAuthTypeOptions(),
      },
      {
        name: 'submitUser',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.submitUser',
          '申请人',
        ),
      },
      {
        name: 'submitTime',
        type: FieldType.date,
        label: languageConfig(
          'affiliationApplication.table.label.submitTime',
          '申请时间',
        ),
        transfer: (value: string) => {
          if (value) {
            return moment(value).format('YYYY-MM-DD');
          }
          return '';
        },
      },
      {
        name: 'status',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.status',
          '挂靠状态',
        ),
        lookupCode: 'PRM_CA_STATUS',
      },
      {
        name: 'instanceStatus',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.instanceStatus',
          '流程状态',
        ),
        lookupCode: 'PRM_CA_INSTANCESTATUS',
      },
      {
        name: 'currentProcessor',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.currentProcessor',
          '当前处理人',
        ),
      },
      {
        name: 'hasAffiliationRecord',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.hasAffiliationRecord',
          '是否有挂靠记录',
        ),
      },
      {
        name: 'isUpstreamApproval',
        type: FieldType.string,
        label: languageConfig(
          'affiliationApplication.table.label.isUpstreamApproval',
          '是否上游审批',
        ),
      },
    ],
    transport: {
      read: config => {
        const params = {
          page: config.params.page,
          size: config.params.size,
          ...config?.data,
          instanceStatus: 'AFOOT', // 流程状态:查询中(固定)
        };

        // params.currentProcessor = params?.currentProcessor?.userInfo
        //   ? params?.currentProcessor?.userInfo
        //   : '';

        return {
          ...getAdminTransferList(),
          data: params,
        };
      },
    },
    record: {
      dynamicProps: {
        selectable: record => {
          return record.get('isUpstreamApproval') === 'N';
        },
      },
    },
  };
};
相关推荐
wicb91wJ61 小时前
手写一个Promise,彻底掌握异步原理
开发语言·前端·javascript
上海云盾-小余1 小时前
Web 业务常见 SQL 注入攻击原理详解及 WAF 防护部署实战教程
前端·数据库·sql
zs宝来了1 小时前
Next.js SSR/SSG:路由与渲染模式深度解析
前端·javascript·框架
ZC跨境爬虫2 小时前
UI前端美化技能提升日志day5:从布局优化到CSS继承原理深度解析
前端·css·ui·html·状态模式
易生一世2 小时前
Kiro CLI的context详解
前端
huangql5202 小时前
CSS布局(六):Grid —— 像围棋一样布局
前端·css
谢尔登2 小时前
【Next】客户端组件和服务端组件
前端·javascript·react.js·架构
Mintopia2 小时前
合合信息蜜蜂 AI 最新资讯(2026.4.22 官方发布)
前端
Mintopia2 小时前
如何用第一性原理提升问题解决能力
前端