猪齿鱼:实现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';
        },
      },
    },
  };
};
相关推荐
AI_零食15 小时前
番茄钟鸿蒙PC Electron框架完成:状态机、定时器管理与专注力工具设计
前端·javascript·华为·electron·开源·鸿蒙·鸿蒙系统
提子拌饭13315 小时前
逛三园游戏——基于鸿蒙PC Electron框架实现
前端·javascript·游戏·华为·electron·鸿蒙
llz_11215 小时前
web-第三次课后作业
前端·后端·web
遗憾随她而去.15 小时前
Web地图全体系深度梳理:引擎、数据源、图层、投影核心知识
前端
爱因斯坦乐16 小时前
Vue项目整合
前端·javascript·vue.js
FlyWIHTSKY16 小时前
TS、TSX、JS、JSX 文件扩展名详解
开发语言·javascript·ecmascript
无风听海16 小时前
IndexedDB 深度指南 浏览器中的事务型对象数据库
前端·数据库
ct97817 小时前
组件间的通信
前端·javascript·vue.js
左手吻左脸。17 小时前
Vue 全栈面试题大全(2026 最新版最详细)
前端·javascript·vue.js
Aphasia31117 小时前
手写KeepAlive组件
前端·react.js·面试