One, foreword

In the past, when I redeveloped multiple batch processing operations for tables, I implemented them one by one, extracting some common functions. When I was doing requirement design recently, I had an inspiration and realized that if the subsequent operations of batch processing were consistent, could it be made into a complete process? The differences could be distinguished according to type.

Batch operation, before the actual operation, actually do some special checks, like a step bar. The first step is to verify whether the table data is selected. Usually, batch operations are not allowed when no data is selected. We will prompt “Please select at least one item”. The second step, the second confirmation prompt, is not present in most development requirements, but is required in this development. The third step is to verify the correctness of data state, such as batch cancellation operation. In the order platform, completed orders are not allowed to be canceled, so data state verification must be carried out, and batch operation can be continued only when all selected data are correct.

Before I judge by conditions into the next phase of the operation, such development soon, but if the product would like to add a step after a step, so I need to change two place, the next step in the current step to change the new steps, the next step in the original into the new step, the article is equivalent to the step off again after restructuring. So why don’t I just make a chain call, and each time I add a step, I just reorganize the step bar.

Function implementation based on the React framework, component development using hooks function components.

Second, demand analysis

2.1 the UI

2.2 Requirement Analysis

After summarizing the requirements, I presented all the requirements in the form of a table, which is more intuitive and easy to understand:

operation Select list data Secondary confirmation Status check
Batch cancelled 1) If no data is selected, prompt: Please select at least one item; 2) When there is selected data, a second confirmation prompt will be given Tip: Do you want to cancel all selected orders? 1) The payment status of all selected data is to be paid, and batch cancellation operation can be carried out; 2) If the selected data is not complete, the payment status is to be paid, and a reminder is given: The order number XXXX and XXXX cannot be selected
Batch delivery 1) If no data is selected, prompt: Please select at least one item; 2) When there are selected data, give a second confirmation prompt.” No hint 1) The payment status of all selected data is paid and the order status is completed, so batch push operation can be carried out; 2) If the selected data is not all, the payment status is paid or the status of the incomplete order is completed. Note: the order number XXXX and XXXX cannot be selected

Where all state values of payment state and order state are as follows:

State the category The status value State values map numeric values
Payment status To be paid 1
Have to pay 2
Has been cancelled 3
The order status For outbound 1
Has been completed 2
Has been cancelled 3

It is easy to see from the requirement list that all the three steps of batch operation are similar, and the difference between the two operations can be controlled by setting switch variables.

Iii. Development and design

From the above requirement analysis, it is not difficult to see that batch operation is similar to the single linked list in the data structure, and the pointer of each node points to the next node, so the function development of this time adopts the way of chain programming. The operations of each layer are maintained in the array, and the next operation is fetched after each layer succeeds.

Fourth, concrete implementation

4.1 Setting Category Objects for Batch Operations

/ * *@name Perform batch operations on classified objects */
const batchObj = {
  cancel: {
    confirmTips: 'Do you want to cancel all selected orders? '.// Double confirmation prompt, skip double confirmation if empty
    failedTips: 'Not selectable'.// The verification fails
    inspectionFlag: false.// Check whether the flag passes
    payStatusList: [1].// List of payment states to verify
  },
  push: {
    confirmTips: ' '.failedTips: 'Not selectable'.// The verification fails
    inspectionFlag: false.// Check whether the flag passes
    payStatusList: [1].// List of payment states to verify
    orderStatusList: [2].// List of order status to verify}};Copy the code

4.2 button group

Add click events for each button.

<div onClick={() = > batchOperate('cancel'}> Cancel </div><div onClick={()= >BatchOperate ('push')}> Batch push</div>
Copy the code

4.3 Button Click Event

/** **@param {string} Type Key value * of the operation button@return {void} No * /
const batchOperate = type= > {
  return applyChainCall(type, [batchCheckboxOptions, batchDoubleConfirm, batchInspection]);
};
Copy the code

4.4 Triggering the chain call event

The default is to start from the first, and the trigger position can be adjusted. For example, if a batch operation may start with the second method, the value of type can be used as a condition for resetting index to 2.

When the function is called, the function is executed *@param {Array} ChainCalls list of all chain functions *@param {string} Type Indicates the button type *@param {number} The index chain function call defaults to the first *@return {void} No * /
const applyChainCall = (type, chainCalls, index = 0) = > {
  return chainCalls[index](type, chainCalls)();
};
Copy the code

4.5 Obtaining the processing event of the next function

Chain functions as all the steps in the list variable method, and then call the method, the function name can be passed to this method, can get into function in the chain function index on the list, the next step method is the method of the index value increased by 1, direct execution can get to the next step by calculation method into the next operation.

/** * get the next function's processing event to perform the next operation *@param {string} Type Indicates the button type *@param {Array} ChainCalls list of all chain functions *@param {Function} FuncType The method name * of the current step@return {Function} The next method executes */
const goToNext = (type, chainCalls, funcType) = > {
  let funcIndex = 0;
  chainCalls.forEach((chainItem, chainIndex) = > {
    if(chainItem === funcType) { funcIndex = chainIndex; }});return chainCalls[funcIndex + 1](type, chainCalls)();
};
Copy the code

4.6 Table Select Data Events

// 1) Define a variable to store the selected data in the table.
/ * *@name Table selected data */
const [batchSelectList, setBatchSelectList] = useState([]);

// 2) Because my project uses antD framework, I directly call ANTD to provide API interface to obtain the selected item data.
// Get the selection through the onChange event of rowSelection and update the data to the batchSelectList variable.
/** * Table multi-select operation - set selection data *@param {void} No *@return {void} No * /
const rowSelection = {
  onChange: (selectedRowKeys, selectedRows) = >{ setBatchSelectList(selectedRows); }};Copy the code

4.7 Whether to select table Data events

Determine whether the table data is selected according to the array length of the data variable batchSelectList selected in the table. If the value is 0, none of the items is selected and a prompt will be given; otherwise, the selected data will be identified and the next step will be performed.

/** * Batch operation - Whether to select list data *@param {string} Type Indicates the button type *@param {Array} ChainCalls list of all chain functions *@return {void} No * /
const batchCheckboxOptions = (type, chainCalls) = > {
  return () = > {
    // => true: if none of the items in the list is selected, a prompt window will be displayed. Otherwise, go to the next step
    if (batchSelectList.length === 0) {
      Modal.confirm({
        keyboard: true.maskClosable: true.title: 'tip'.content: 'Please select at least one'}); }else {
      returngoToNext(type, chainCalls, batchCheckboxOptions); }}; };Copy the code

4.8 Confirming events twice

Whether the confirmTips event is executed can be judged according to whether the confirmTips variable in the batch operation classification object is empty. If it is not empty, the confirmTips window will be displayed; otherwise, the next step will be directly entered.

/** * Batch operation - double confirmation *@param {string} Type Indicates the button type *@param {Array} ChainCalls list of all chain functions *@return {void} No * /
const batchDoubleConfirm = (type, chainCalls) = > {
  return () = > {
    const batchItem = batchObj[type];
    // => true: If there is a secondary prompt, the secondary prompt window will pop up. If there is a secondary prompt window, go to the next step
    if (batchItem.confirmTips) {
      Modal.confirm({
        keyboard: true.maskClosable: true.title: 'tip'.content: batchItem.confirmTips,
        onOk: () = > {
          returngoToNext(type, chainCalls, batchDoubleConfirm); }}); }else {
      returngoToNext(type, chainCalls, batchDoubleConfirm); }}; };Copy the code

4.9 Verification Operation Events

Call different methods based on the length of the checksum failure list. If the array length of the checksum failed list is not 0, it indicates that the table data of the checksum failed exists, the checksum failed method is called; otherwise, the checksum successful method is called.

/** * Batch operation - check operation *@param {string} Type Indicates the button type *@return {void} No * /
const batchInspection = type= > {
  return () = > {
    const batchItem = batchObj[type];
    / * *@name Verification failure list */
    const failedList = batchSelectList.filter(item= >! getIncludesFlag(batchItem, item));/ * *@name Verification success list */
    const passedList = batchSelectList.filter(item= > getIncludesFlag(batchItem, item));
    // =>true: If the array length of the checksum failed list is not 0, the checksum failed table data exists. Otherwise, the checksum successful method is called
    if(failedList.length ! = =0) {
      batchInspectionFailed(type, failedList);
    } else{ batchInspectionPassed(type, passedList); }}; };Copy the code

According to requirements, different batch operations have different types of state verification, so I have refined the state verification into a separate method for maintenance.

/** * Batch operation - filter status *@param {Object} BatchItem Batch object *@param {Object} Item filter object *@return {boolean} Filter state Boolean value */
const getIncludesFlag = (batchItem, item) = > {
  const payStatusList = batchItem.payStatusList;
  const orderStatusList = batchItem.orderStatusList;
  consthasPayStatus = !! payStatusList;consthasOrderStatus = !! orderStatusList;let flag = false;
  //=>true: If the verification status exists, check whether the verification status list contains the status value to be verified
  if((! hasPayStatus || (hasPayStatus && payStatusList.includes(item.payStatus))) && (! hasOrderStatus || (hasOrderStatus && orderStatusList.includes(item.orderStatus)))) { flag =true;
  }
  return flag;
};

Copy the code

Verification success method

/** * Batch operation - Verification passed *@param {string} Type Indicates the button type *@param {Array} List List of data that passes the verification *@return {void} No * /
const batchInspectionPassed = (type, list) = > {
  // Call the interface, which normally processes the selected table data into the format of the input parameter required by the back end.
};
Copy the code

Verification failure method

/** * Batch operation - The verification fails *@param {string} Type Indicates the button type *@param {Array} List List of data that did not pass the verification *@return {void} No * /
const batchInspectionFailed = (type, list) = > {
  const batchItem = batchObj[type];
  let contentList = [];
  list.forEach(item= > {
    contentList.push(item.adjustNo);
  });
  contentList = contentList.map(item= > 'Order Number' + item);
  const content = contentList.join(', ') + batchItem.failedTips;
  Modal.confirm({
    keyboard: true.maskClosable: true.title: 'tip'.content: content,
  });
};
Copy the code

Above, the operation of batch processing is all completed.

Five, the summary

To summarize the main functions of the chain method above:

1) The function is executed only when called;

2) You can control the number of functions to start from;

3) Support to skip a function;

4) For the new operation steps, the change cost is small, convenient for later maintenance.

In addition, by setting classified objects to manage modules or operations with similar functions in different categories, the code is concise, easy to read, and easy to maintain.

If you have any good suggestions, please leave a message. ━(‘ ∀´) Blue!