• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SkylerHu / antd-restful / #85

22 Sep 2025 05:07AM UTC coverage: 82.996% (+0.3%) from 82.661%
#85

push

web-flow
fix: 修复 RestTable 和 RouteBaseTable 处理路由参数

- perf: 优化 RestTable 和 RouteBaseTable 处理路由参数
    - 升级 query-string@9, `parseOptions` 支持通过 `types` 配置字段类型(连带打包无需额外安装)
    - 默认会根据 `columns` 或是 `filterFormProps.fields` 的配置类型初始化 `types`
- fix: 统一 `NumberRange` 和 `RangeStrPicker` 默认值的处理,并提供 `defaultEmptyValue` 配置单项的默认值
- fix: `parser.queryString` 使用 `query-sting` 默认参数中去掉了 `{skipNull:true, skipEmptyString: true}`
    - 为了解决 Range 组件有null值的场景,例如 [null, 1] 需要处理成 ",1"
    - 会在 RestTable 组件中自行调用 `clearEmptyValue` 处理远程请求时去掉空值
- fix: 修复 RangeStrPicker 在 antd>=5 版本场景下,dayjs 未正确处理 format 的问题
- fix: 修复 `typeTools.isNumber` 判断问题,`""` 不是数值

1329 of 1688 branches covered (78.73%)

Branch coverage included in aggregate %.

111 of 117 new or added lines in 11 files covered. (94.87%)

1 existing line in 1 file now uncovered.

1751 of 2023 relevant lines covered (86.55%)

66.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.17
/src/components/FieldsSetting.jsx
1
import React, { useEffect, useMemo, useState } from "react";
2
import PropTypes from "prop-types";
3
import { Button, Checkbox, Space, Tooltip } from "antd";
4
import { QuestionCircleOutlined, SettingOutlined } from "@ant-design/icons";
5
import { dequal as deepEqual } from "dequal";
6
import { genColumnKey } from "src/common/parser";
7
import { isFunction } from "src/common/typeTools";
8
import { useSettingsStorage } from "src/hooks/index";
9

10

11
export const initFileds = (fields) => {
3✔
12
  return fields?.map((field) => {
596!
13
    const key = genColumnKey(field);
713✔
14
    return {
713✔
15
      key,
16
      value: key,
17
      label: field.label || field.title || key,
1,197!
18
      tip: field.tip,
19
      // 如果强制设置的 false,则禁止配置
20
      disabled: field.hidden === false,
21
    };
22
  }) || [];
23
};
24

25

26
const FieldsSetting = ({ style, className, title, storageKey, value, onChange, children }) => {
3✔
27

28
  const [fields, setFields] = useState(initFileds(value));
434✔
29

30
  const { keys, setKeys, allKeys } = useSettingsStorage(storageKey, fields);
434✔
31

32
  useEffect(() => {
434✔
33
    setFields(oldV => {
162✔
34
      const newV = initFileds(value);
162✔
35
      if (deepEqual(newV, oldV)) {
162✔
36
        return oldV;
152✔
37
      }
38
      return newV || [];
10!
39
    });
40
  }, [value]);
41

42
  // 全选
43
  const checkAll = useMemo(() => deepEqual(keys, allKeys), [keys, allKeys]);
434✔
44
  // 部分选中
45
  const checkIndeterminate = useMemo(() => keys.length > 0 && !checkAll, [keys, checkAll]);
434✔
46

47
  const data = useMemo(() => {
434✔
48
    const options = fields?.map((field) => {
107✔
49
      return {
128✔
50
        ...field,
51
        label: (
52
          <div style={{ width: 100 }}>
53
            {field.label}
54
            &nbsp;&nbsp;
55
            {field.tip && (
141✔
56
              <Tooltip title={field.tip}>
57
                <QuestionCircleOutlined />
58
              </Tooltip>
59
            )}
60
          </div>
61
        ),
62
      };
63
    });
64
    const forceChecks = fields?.filter((option) => option.disabled).map((option) => option.value);
128✔
65
    return {
107✔
66
      options,
67
      forceChecks,
68
    };
69
  }, [fields]);
70

71
  useEffect(() => {
434✔
72
    if (isFunction(onChange)) {
97!
73
      onChange(keys);
97✔
74
    }
75
  }, [keys, onChange]);
76

77
  return (
434✔
78
    <Tooltip
79
      style={style}
80
      className={className}
81
      trigger="click"
82
      color="white"
83
      title={
84
        <Space direction="vertical" style={{ width: 400 }}>
85
          <div style={{ color: "black" }}>{title || "设置"}</div>
434!
86
          <Checkbox
87
            indeterminate={checkIndeterminate}
88
            checked={checkAll}
89
            onChange={(e) => {
90
              setKeys(e.target.checked ? allKeys : data.forceChecks);
×
91
            }}
92
          >
93
            全选
94
          </Checkbox>
95
          <Checkbox.Group
96
            value={keys}
97
            options={data.options}
98
            onChange={(v) => {
NEW
99
              setKeys(v);
×
100
            }}
101
          />
102
        </Space>
103
      }
104
    >
105
      {children || <Button icon={<SettingOutlined />} />}
434!
106
    </Tooltip>
107
  );
108
};
109

110
FieldsSetting.propTypes = {
3✔
111
  style: PropTypes.object,
112
  className: PropTypes.string,
113

114
  title: PropTypes.string,
115
  storageKey: PropTypes.string.isRequired,
116
  // 字段配置,key为字段名,label为字段名,hidden为是否隐藏
117
  value: PropTypes.arrayOf(
118
    PropTypes.shape({
119
      key: PropTypes.string,
120
      label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
121
      hidden: PropTypes.bool,
122
    })
123
  ),
124

125
  onChange: PropTypes.func,
126
  children: PropTypes.node,
127
};
128

129
export default FieldsSetting;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc