npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kne/super-select-plus

v0.1.2

Published

基于 super-select 的 React 业务选择器组件库,提供职能、行业、城市选择器与枚举显示组件,支持国际化与拼音搜索

Readme

super-select-plus

描述

基于 super-select 的 React 业务选择器组件库,提供职能、行业、城市选择器与枚举显示组件,支持国际化与拼音搜索

安装

npm i --save @kne/super-select-plus

概述

@kne/super-select-plus 是一个基于 @kne/super-select 封装的 React 业务选择器组件库,提供职能、行业、城市等常见业务场景的选择器组件和枚举值显示组件。所有组件均支持国际化、拼音搜索、单选/多选等功能,枚举显示组件使用 react-fetch 统一管理数据加载和缓存。

主要特性

  • 丰富的业务选择器:提供职能选择器、行业选择器、城市选择器三大核心组件
  • 枚举值显示组件:提供地址、职能、行业等枚举值的统一显示组件
  • 级联选择支持:职能和行业选择器基于级联选择器实现,支持多级数据选择
  • 智能搜索:支持中英文搜索、拼音搜索、首字母搜索
  • 国际化支持:内置中英文切换,可根据语言环境自动切换显示内容
  • 灵活的展示模式:支持下拉菜单和弹窗两种展示模式
  • 数量限制:支持设置最大选择数量
  • 单选/多选:所有组件均支持单选和多选模式
  • 数据缓存:枚举显示组件内置多层缓存机制,提升性能
  • 自定义渲染:枚举显示组件支持自定义渲染函数,灵活展示
  • 批量显示:枚举显示组件支持 names 数组,一次转换多个编码为 label

组件列表

| 组件名称 | 功能描述 | |----------------|-------------------| | SelectFunction | 职能选择器,支持多级职能数据选择 | | SelectIndustry | 行业选择器,支持多级行业数据选择 | | SelectAddress | 城市选择器,支持国内外城市搜索选择 | | AddressEnum | 地址枚举显示,用于显示城市名称 | | FunctionEnum | 职能枚举显示,用于显示职能名称 | | IndustryEnum | 行业枚举显示,用于显示行业名称 | | EnumDisplay | 通用枚举显示,支持自定义数据源 |

数据来源

组件内置了丰富的业务数据:

  • 职能数据:包含完整的职位职能分类,支持三级职能体系
  • 行业数据:覆盖主要行业分类,支持多级行业结构
  • 城市数据:包含国内外主要城市,支持按省份、国家分类

所有数据支持中英文双语,可通过组件的静态方法获取原始数据进行自定义处理。

示例

示例代码

  • SelectFunction 职能选择器
  • 基于级联选择器的职能选择组件,支持多级职能数据的选择、值回显、搜索、单选/多选等功能
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],antd(antd)
const { SelectFunction, FunctionEnum, enumItemsToSelectValue, enumItemToSelectValue } = _SuperSelectPlus;
const { Flex, Divider, Tag, Switch } = antd;
const { useState } = React;

// 模拟后端接口返回的职能编码
const savedFunctionCodes = ['001001001', '001001002', '001001003'];
const savedFunctionCode = '001001001';

// 基础多选示例
const BasicMultiExample = ({ isPopup }) => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>多选职能:</span>
      <SelectFunction
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择职能"
        style={{ width: 320 }}
      />
      {value.length > 0 && (
        <Flex wrap gap={4}>
          {value.map((item) => (
            <Tag key={item.id} color="blue">
              {item.name}
            </Tag>
          ))}
        </Flex>
      )}
    </Flex>
  );
};

// 单选示例
const SingleSelectExample = ({ isPopup }) => {
  const [value, setValue] = useState(null);

  return (
    <Flex vertical gap={8}>
      <span>单选职能:</span>
      <SelectFunction
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择职能"
        style={{ width: 320 }}
      />
      {value && <Tag color="green">已选:{value.name}</Tag>}
    </Flex>
  );
};

// 数量限制示例
const MaxLimitExample = ({ isPopup }) => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>最多选择 3 个职能:</span>
      <SelectFunction
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        maxLength={3}
        placeholder="请选择职能(最多3项)"
        style={{ width: 320 }}
      />
      <Tag color={value.length >= 3 ? 'red' : 'blue'}>
        已选择 {value.length}/3 项
      </Tag>
    </Flex>
  );
};

// 弹窗模式示例
const PopupModeExample = () => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>弹窗模式:</span>
      <SelectFunction
        value={value}
        onChange={setValue}
        isPopup={false}
        placeholder="点击打开弹窗选择"
        style={{ width: 320 }}
      />
      {value.length > 0 && (
        <div>已选:{value.map((item) => item.name).join('、')}</div>
      )}
    </Flex>
  );
};

// 值回显 - 仅传 id,组件自动从 options 解析名称
const ValueEchoByIdExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedFunctionCodes.map((id) => ({ id })));

  return (
    <Flex vertical gap={8}>
      <span>值回显(仅编码 {&#96;{ id }&#96;}):</span>
      <Tag color="default">后端编码:{savedFunctionCodes.join('、')}</Tag>
      <SelectFunction
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择职能"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 仅传编码字符串数组
const ValueEchoByCodesExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedFunctionCodes);

  return (
    <Flex vertical gap={8}>
      <span>值回显(编码字符串数组):</span>
      <Tag color="default">后端编码:{savedFunctionCodes.join('、')}</Tag>
      <SelectFunction
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择职能"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(对象编码)
const SingleValueEchoExample = ({ isPopup }) => {
  const [value, setValue] = useState({ id: '001001001' });

  return (
    <Flex vertical gap={8}>
      <span>单选值回显({&#96;{ id: '001001001' }&#96;}):</span>
      <SelectFunction
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择职能"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(字符串编码)
const SingleValueEchoByCodeExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedFunctionCode);

  return (
    <Flex vertical gap={8}>
      <span>单选值回显(编码字符串):</span>
      <SelectFunction
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择职能"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(FunctionEnum name)
const SingleValueEchoWithEnumExample = ({ isPopup }) => {
  const [value, setValue] = useState();

  return (
    <Flex vertical gap={8}>
      <span>单选值回显(FunctionEnum name):</span>
      <Tag color="default">后端编码:{savedFunctionCode}</Tag>
      <FunctionEnum name={savedFunctionCode}>
        {(item) => {
          const resolved = enumItemToSelectValue(item);
          if (!resolved) return <span>加载中...</span>;
          return (
            <SelectFunction
              single
              value={value ?? resolved}
              onChange={setValue}
              isPopup={isPopup}
              placeholder="请选择职能"
              style={{ width: 320 }}
            />
          );
        }}
      </FunctionEnum>
    </Flex>
  );
};

// 值回显 - 结合 FunctionEnum,仅传编码数组 names={[code, code]}
const ValueEchoWithEnumExample = ({ isPopup }) => {
  const [value, setValue] = useState();

  return (
    <Flex vertical gap={8}>
      <span>值回显(FunctionEnum names):</span>
      <Tag color="default">后端编码:{savedFunctionCodes.join('、')}</Tag>
      <FunctionEnum names={savedFunctionCodes}>
        {(items) => {
          const resolved = enumItemsToSelectValue(items);
          if (!resolved.length) return <span>加载中...</span>;
          return (
            <SelectFunction
              value={value ?? resolved}
              onChange={setValue}
              isPopup={isPopup}
              placeholder="请选择职能"
              style={{ width: 320 }}
            />
          );
        }}
      </FunctionEnum>
    </Flex>
  );
};

const BaseExample = () => {
  const [isPopup, setIsPopup] = useState(true);

  return (
    <Flex vertical gap={24}>
      <Flex align="center" gap={12}>
        <span>展示模式:</span>
        <Switch
          checked={isPopup}
          onChange={setIsPopup}
          checkedChildren="下拉"
          unCheckedChildren="弹窗"
        />
        <span style={{ color: '#666', fontSize: 12 }}>
          {isPopup ? '点击输入框展开下拉菜单' : '点击输入框打开弹窗'}
        </span>
      </Flex>
      <Divider />
      <BasicMultiExample isPopup={isPopup} />
      <Divider />
      <SingleSelectExample isPopup={isPopup} />
      <Divider />
      <MaxLimitExample isPopup={isPopup} />
      <Divider />
      <span style={{ fontWeight: 500 }}>单选值回显</span>
      <SingleValueEchoExample isPopup={isPopup} />
      <Divider />
      <SingleValueEchoByCodeExample isPopup={isPopup} />
      <Divider />
      <SingleValueEchoWithEnumExample isPopup={isPopup} />
      <Divider />
      <span style={{ fontWeight: 500 }}>多选值回显</span>
      <ValueEchoByIdExample isPopup={isPopup} />
      <Divider />
      <ValueEchoByCodesExample isPopup={isPopup} />
      <Divider />
      <ValueEchoWithEnumExample isPopup={isPopup} />
      <Divider />
      <PopupModeExample />
    </Flex>
  );
};

render(<BaseExample />);
  • SelectIndustry 行业选择器
  • 基于级联选择器的行业选择组件,支持多级行业数据的选择、值回显、搜索、单选/多选等功能
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],antd(antd)
const { SelectIndustry, IndustryEnum, enumItemsToSelectValue, enumItemToSelectValue } = _SuperSelectPlus;
const { Flex, Divider, Tag, Switch } = antd;
const { useState } = React;

// 模拟后端接口返回的行业编码
const savedIndustryCodes = ['001', '003', '004'];
const savedIndustryCode = '001';

// 基础多选示例
const BasicMultiExample = ({ isPopup }) => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>多选行业:</span>
      <SelectIndustry
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择行业"
        style={{ width: 320 }}
      />
      {value.length > 0 && (
        <Flex wrap gap={4}>
          {value.map((item) => (
            <Tag key={item.id} color="blue">
              {item.name}
            </Tag>
          ))}
        </Flex>
      )}
    </Flex>
  );
};

// 单选示例
const SingleSelectExample = ({ isPopup }) => {
  const [value, setValue] = useState(null);

  return (
    <Flex vertical gap={8}>
      <span>单选行业:</span>
      <SelectIndustry
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择行业"
        style={{ width: 320 }}
      />
      {value && <Tag color="green">已选:{value.name}</Tag>}
    </Flex>
  );
};

// 数量限制示例
const MaxLimitExample = ({ isPopup }) => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>最多选择 3 个行业:</span>
      <SelectIndustry
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        maxLength={3}
        placeholder="请选择行业(最多3项)"
        style={{ width: 320 }}
      />
      <Tag color={value.length >= 3 ? 'red' : 'blue'}>
        已选择 {value.length}/3 项
      </Tag>
    </Flex>
  );
};

// 值回显 - 仅传 id,组件自动从 options 解析名称
const ValueEchoByIdExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedIndustryCodes.map((id) => ({ id })));

  return (
    <Flex vertical gap={8}>
      <span>值回显(仅编码 {&#96;{ id }&#96;}):</span>
      <Tag color="default">后端编码:{savedIndustryCodes.join('、')}</Tag>
      <SelectIndustry
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择行业"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 仅传编码字符串数组
const ValueEchoByCodesExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedIndustryCodes);

  return (
    <Flex vertical gap={8}>
      <span>值回显(编码字符串数组):</span>
      <Tag color="default">后端编码:{savedIndustryCodes.join('、')}</Tag>
      <SelectIndustry
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择行业"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(对象编码)
const SingleValueEchoExample = ({ isPopup }) => {
  const [value, setValue] = useState({ id: '001' });

  return (
    <Flex vertical gap={8}>
      <span>单选值回显({&#96;{ id: '001' }&#96;}):</span>
      <SelectIndustry
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择行业"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(字符串编码)
const SingleValueEchoByCodeExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedIndustryCode);

  return (
    <Flex vertical gap={8}>
      <span>单选值回显(编码字符串):</span>
      <SelectIndustry
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择行业"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(IndustryEnum name)
const SingleValueEchoWithEnumExample = ({ isPopup }) => {
  const [value, setValue] = useState();

  return (
    <Flex vertical gap={8}>
      <span>单选值回显(IndustryEnum name):</span>
      <Tag color="default">后端编码:{savedIndustryCode}</Tag>
      <IndustryEnum name={savedIndustryCode}>
        {(item) => {
          const resolved = enumItemToSelectValue(item);
          if (!resolved) return <span>加载中...</span>;
          return (
            <SelectIndustry
              single
              value={value ?? resolved}
              onChange={setValue}
              isPopup={isPopup}
              placeholder="请选择行业"
              style={{ width: 320 }}
            />
          );
        }}
      </IndustryEnum>
    </Flex>
  );
};

// 值回显 - 结合 IndustryEnum,仅传编码数组 names={[code, code]}
const ValueEchoWithEnumExample = ({ isPopup }) => {
  const [value, setValue] = useState();

  return (
    <Flex vertical gap={8}>
      <span>值回显(IndustryEnum names):</span>
      <Tag color="default">后端编码:{savedIndustryCodes.join('、')}</Tag>
      <IndustryEnum names={savedIndustryCodes}>
        {(items) => {
          const resolved = enumItemsToSelectValue(items);
          if (!resolved.length) return <span>加载中...</span>;
          return (
            <SelectIndustry
              value={value ?? resolved}
              onChange={setValue}
              isPopup={isPopup}
              placeholder="请选择行业"
              style={{ width: 320 }}
            />
          );
        }}
      </IndustryEnum>
    </Flex>
  );
};

const BaseExample = () => {
  const [isPopup, setIsPopup] = useState(true);

  return (
    <Flex vertical gap={24}>
      <Flex align="center" gap={12}>
        <span>展示模式:</span>
        <Switch
          checked={isPopup}
          onChange={setIsPopup}
          checkedChildren="下拉"
          unCheckedChildren="弹窗"
        />
        <span style={{ color: '#666', fontSize: 12 }}>
          {isPopup ? '点击输入框展开下拉菜单' : '点击输入框打开弹窗'}
        </span>
      </Flex>
      <Divider />
      <BasicMultiExample isPopup={isPopup} />
      <Divider />
      <SingleSelectExample isPopup={isPopup} />
      <Divider />
      <MaxLimitExample isPopup={isPopup} />
      <Divider />
      <span style={{ fontWeight: 500 }}>单选值回显</span>
      <SingleValueEchoExample isPopup={isPopup} />
      <Divider />
      <SingleValueEchoByCodeExample isPopup={isPopup} />
      <Divider />
      <SingleValueEchoWithEnumExample isPopup={isPopup} />
      <Divider />
      <span style={{ fontWeight: 500 }}>多选值回显</span>
      <ValueEchoByIdExample isPopup={isPopup} />
      <Divider />
      <ValueEchoByCodesExample isPopup={isPopup} />
      <Divider />
      <ValueEchoWithEnumExample isPopup={isPopup} />
    </Flex>
  );
};

render(<BaseExample />);
  • SelectAddress 城市选择器
  • 城市地址选择组件,支持国内外城市搜索选择、值回显,具备拼音搜索、首字母搜索等功能
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],(@kne/current-lib_super-select-plus/dist/index.css),antd(antd)
const { SelectAddress, AddressEnum, addressEnumToSelectValue, addressEnumToSelectValueSingle } = _SuperSelectPlus;
const { Flex, Divider, Tag, Switch } = antd;
const { useState } = React;

// 模拟后端接口返回的城市编码
const savedCityCodes = ['010', '020'];
const savedCityCode = '010';

// 基础多选示例
const BasicMultiExample = ({ isPopup }) => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>多选城市:</span>
      <SelectAddress
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择城市"
        style={{ width: 320 }}
      />
      {value.length > 0 && (
        <Flex wrap gap={4}>
          {value.map((item) => (
            <Tag key={item.code} color="blue">
              {item.name}
            </Tag>
          ))}
        </Flex>
      )}
    </Flex>
  );
};

// 单选示例
const SingleSelectExample = ({ isPopup }) => {
  const [value, setValue] = useState(null);

  return (
    <Flex vertical gap={8}>
      <span>单选城市:</span>
      <SelectAddress
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择城市"
        style={{ width: 320 }}
      />
      {value && <Tag color="green">已选:{value.name}</Tag>}
    </Flex>
  );
};

// 数量限制示例
const MaxLimitExample = ({ isPopup }) => {
  const [value, setValue] = useState([]);

  return (
    <Flex vertical gap={8}>
      <span>最多选择 5 个城市:</span>
      <SelectAddress
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        maxLength={5}
        placeholder="请选择城市(最多5项)"
        style={{ width: 320 }}
      />
      <Tag color={value.length >= 5 ? 'red' : 'blue'}>
        已选择 {value.length}/5 项
      </Tag>
    </Flex>
  );
};

// 值回显 - 仅传 value 编码,组件自动解析 label
const ValueEchoByCodeExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedCityCodes.map((code) => ({ value: code })));

  return (
    <Flex vertical gap={8}>
      <span>值回显(仅编码 {&#96;{ value }&#96;}):</span>
      <Tag color="default">后端编码:{savedCityCodes.join('、')}</Tag>
      <SelectAddress
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择城市"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 完整对象(表单已缓存 label)
const cachedCityValue = [
  { value: '010', label: '北京' },
  { value: '020', label: '上海' }
];

const ValueEchoWithLabelExample = ({ isPopup }) => {
  const [value, setValue] = useState(cachedCityValue);

  return (
    <Flex vertical gap={8}>
      <span>值回显(含 label):</span>
      <Tag color="default">后端编码:{savedCityCodes.join('、')}</Tag>
      <SelectAddress
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择城市"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 结合 AddressEnum,仅传编码数组 names={[code, code]}
const ValueEchoWithEnumExample = ({ isPopup }) => {
  const [value, setValue] = useState();

  return (
    <Flex vertical gap={8}>
      <span>值回显(AddressEnum names):</span>
      <Tag color="default">后端编码:{savedCityCodes.join('、')}</Tag>
      <AddressEnum names={savedCityCodes}>
        {(outputs) => {
          const resolved = addressEnumToSelectValue(outputs);
          if (!resolved.length) return <span>加载中...</span>;
          return (
            <SelectAddress
              value={value ?? resolved}
              onChange={setValue}
              isPopup={isPopup}
              placeholder="请选择城市"
              style={{ width: 320 }}
            />
          );
        }}
      </AddressEnum>
    </Flex>
  );
};

// 值回显 - 单选(仅编码)
const SingleValueEchoExample = ({ isPopup }) => {
  const [value, setValue] = useState({ value: '010' });

  return (
    <Flex vertical gap={8}>
      <span>单选值回显({&#96;{ value: '010' }&#96;}):</span>
      <SelectAddress
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择城市"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(字符串编码)
const SingleValueEchoByCodeExample = ({ isPopup }) => {
  const [value, setValue] = useState(savedCityCode);

  return (
    <Flex vertical gap={8}>
      <span>单选值回显(编码字符串):</span>
      <SelectAddress
        single
        value={value}
        onChange={setValue}
        isPopup={isPopup}
        placeholder="请选择城市"
        style={{ width: 320 }}
      />
    </Flex>
  );
};

// 值回显 - 单选(AddressEnum name)
const SingleValueEchoWithEnumExample = ({ isPopup }) => {
  const [value, setValue] = useState();

  return (
    <Flex vertical gap={8}>
      <span>单选值回显(AddressEnum name):</span>
      <Tag color="default">后端编码:{savedCityCode}</Tag>
      <AddressEnum name={savedCityCode}>
        {(output) => {
          const resolved = addressEnumToSelectValueSingle(output);
          if (!resolved) return <span>加载中...</span>;
          return (
            <SelectAddress
              single
              value={value ?? resolved}
              onChange={setValue}
              isPopup={isPopup}
              placeholder="请选择城市"
              style={{ width: 320 }}
            />
          );
        }}
      </AddressEnum>
    </Flex>
  );
};

const BaseExample = () => {
  const [isPopup, setIsPopup] = useState(true);

  return (
    <Flex vertical gap={24}>
      <Flex align="center" gap={12}>
        <span>展示模式:</span>
        <Switch
          checked={isPopup}
          onChange={setIsPopup}
          checkedChildren="下拉"
          unCheckedChildren="弹窗"
        />
        <span style={{ color: '#666', fontSize: 12 }}>
          {isPopup ? '点击输入框展开下拉菜单' : '点击输入框打开弹窗'}
        </span>
      </Flex>
      <Divider />
      <BasicMultiExample isPopup={isPopup} />
      <Divider />
      <SingleSelectExample isPopup={isPopup} />
      <Divider />
      <MaxLimitExample isPopup={isPopup} />
      <Divider />
      <span style={{ fontWeight: 500 }}>单选值回显</span>
      <SingleValueEchoExample isPopup={isPopup} />
      <Divider />
      <SingleValueEchoByCodeExample isPopup={isPopup} />
      <Divider />
      <SingleValueEchoWithEnumExample isPopup={isPopup} />
      <Divider />
      <span style={{ fontWeight: 500 }}>多选值回显</span>
      <ValueEchoByCodeExample isPopup={isPopup} />
      <Divider />
      <ValueEchoWithLabelExample isPopup={isPopup} />
      <Divider />
      <ValueEchoWithEnumExample isPopup={isPopup} />
    </Flex>
  );
};

render(<BaseExample />);
  • AddressEnum 地址枚举显示
  • 用于显示城市名称的枚举组件,支持国际化、显示父级、自定义渲染等功能
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],antd(antd),remoteLoader(@kne/remote-loader)
const { AddressEnum } = _SuperSelectPlus;
const { createWithRemoteLoader } = remoteLoader;
const { Flex } = antd;

const BaseExample = createWithRemoteLoader({
  modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage']
})(({ remoteModules }) => {
  const [PureGlobal, InfoPage] = remoteModules;
  
  return (
    <PureGlobal preset={{
      ajax: async api => {
        return { data: { code: 0, data: await api.loader() } };
      },
      apis: {
        cityData: {
          loader: async () => {
            const module = await import('@kne/super-select-plus/src/SelectAddress/city.json');
            return module.default || module;
          }
        }
      }
    }}>
      <InfoPage>
        <InfoPage.Part title="基本用法">
          <Flex vertical gap={12}>
            <p>北京(编码:010):<AddressEnum name="010" /></p>
            <p>上海(编码:020):<AddressEnum name="020" /></p>
            <p>广州(编码:050020):<AddressEnum name="050020" /></p>
            <p>深圳(编码:050090):<AddressEnum name="050090" /></p>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="自定义渲染">
          <Flex vertical gap={12}>
            <p>带样式渲染:</p>
            <AddressEnum name="010">
              {({ city, parent }, { getLabelForLocal, locale }) => city && (
                <span style={{ padding: '4px 8px', background: '#f0f0f0', borderRadius: '4px' }}>
                  {getLabelForLocal(city, locale)}
                  {parent && <span style={{ fontSize: '12px', color: '#666', marginLeft: '8px' }}>({getLabelForLocal(parent, locale)})</span>}
                </span>
              )}
            </AddressEnum>
            
            <p>带图标显示:</p>
            <AddressEnum name="020">
              {({ city }, { getLabelForLocal, locale }) => city && (
                <span>📍 {getLabelForLocal(city, locale)}</span>
              )}
            </AddressEnum>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="实际业务场景">
          <div style={{ lineHeight: '32px' }}>
            <div><strong>姓名:</strong>张三</div>
            <div><strong>所在城市:</strong><AddressEnum name="010" /></div>
            <div><strong>期望工作城市:</strong><AddressEnum name="020" /></div>
            <div><strong>可接受城市:</strong><AddressEnum names={['010', '020', '050020']} /></div>
          </div>
        </InfoPage.Part>

        <InfoPage.Part title="批量显示 names">
          <Flex vertical gap={12}>
            <p>默认渲染:<AddressEnum names={['010', '020', '050020']} /></p>
            <AddressEnum names={['010', '020']}>
              {(outputs, { labels }) => (
                <Flex gap={8} wrap="wrap">
                  {labels.map(label => (
                    <span key={label} style={{ padding: '4px 8px', background: '#f6ffed', borderRadius: '4px' }}>
                      {label}
                    </span>
                  ))}
                </Flex>
              )}
            </AddressEnum>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="错误处理">
          <p>不存在的城市编码 999999:<AddressEnum name="999999" /></p>
        </InfoPage.Part>
      </InfoPage>
    </PureGlobal>
  );
});

render(<BaseExample />);
  • FunctionEnum 职能枚举显示
  • 用于显示职能名称的枚举组件,支持国际化、自定义渲染及 names 批量显示
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],antd(antd),remoteLoader(@kne/remote-loader)
const { FunctionEnum } = _SuperSelectPlus;
const { createWithRemoteLoader } = remoteLoader;
const { Flex } = antd;

const BaseExample = createWithRemoteLoader({
  modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage']
})(({ remoteModules }) => {
  const [PureGlobal, InfoPage] = remoteModules;
  
  return (
    <PureGlobal preset={{
      ajax: async api => {
        return { data: { code: 0, data: await api.loader() } };
      },
      apis: {
        functionData: {
          loader: async () => {
            const module = await import('@kne/super-select-plus/src/SelectFunction/function.json');
            return module.default || module;
          }
        }
      }
    }}>
      <InfoPage>
        <InfoPage.Part title="基本用法">
          <Flex vertical gap={12}>
            <p>CEO(编码:001001001):<FunctionEnum name="001001001" /></p>
            <p>副总裁(编码:001001002):<FunctionEnum name="001001002" /></p>
            <p>COO(编码:001001003):<FunctionEnum name="001001003" /></p>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="自定义渲染">
          <Flex vertical gap={12}>
            <p>带样式渲染:</p>
            <FunctionEnum name="001001001">
              {(item, { locale }) => item && (
                <span style={{ padding: '4px 8px', background: '#e6f7ff', borderRadius: '4px' }}>
                  {item.label}
                  {item.enName && <span style={{ marginLeft: '8px', color: '#666' }}>({item.enName})</span>}
                </span>
              )}
            </FunctionEnum>
            
            <p>带层级显示:</p>
            <FunctionEnum name="001001002">
              {(item, { mapping }) => {
                if (!item) return null;
                const parent = item.parentId ? mapping.get(item.parentId) : null;
                return (
                  <div>
                    {parent && <span style={{ fontSize: '12px', color: '#999' }}>{parent.label} &gt; </span>}
                    <span style={{ color: '#1890ff' }}>{item.label}</span>
                  </div>
                );
              }}
            </FunctionEnum>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="实际业务场景">
          <div style={{ lineHeight: '32px' }}>
            <div><strong>姓名:</strong>李四</div>
            <div><strong>当前职能:</strong><FunctionEnum name="001001001" /></div>
            <div><strong>期望职能:</strong><FunctionEnum name="001001002" /></div>
            <div><strong>可胜任职能:</strong><FunctionEnum names={['001001001', '001001002', '001001003']} /></div>
          </div>
        </InfoPage.Part>

        <InfoPage.Part title="批量显示 names">
          <Flex vertical gap={12}>
            <p>默认渲染:<FunctionEnum names={['001001001', '001001002', '001001003']} /></p>
            <FunctionEnum names={['001001001', '001001002']}>
              {(items, { labels }) => (
                <Flex gap={8} wrap="wrap">
                  {labels.map(label => (
                    <span key={label} style={{ padding: '4px 8px', background: '#e6f7ff', borderRadius: '4px' }}>
                      {label}
                    </span>
                  ))}
                </Flex>
              )}
            </FunctionEnum>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="国际化支持">
          <FunctionEnum name="001001003">
            {(item, { locale }) => item && (
              <div>
                <div>当前语言:{locale}</div>
                <div>显示名称:{item.label}</div>
                {item.chName && <div>中文名:{item.chName}</div>}
                {item.enName && <div>英文名:{item.enName}</div>}
              </div>
            )}
          </FunctionEnum>
        </InfoPage.Part>
      </InfoPage>
    </PureGlobal>
  );
});

render(<BaseExample />);
  • IndustryEnum 行业枚举显示
  • 用于显示行业名称的枚举组件,支持国际化、自定义渲染及 names 批量显示
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],antd(antd),remoteLoader(@kne/remote-loader)
const { IndustryEnum } = _SuperSelectPlus;
const { createWithRemoteLoader } = remoteLoader;
const { Flex } = antd;

const BaseExample = createWithRemoteLoader({
  modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage']
})(({ remoteModules }) => {
  const [PureGlobal, InfoPage] = remoteModules;
  
  return (
    <PureGlobal preset={{
      ajax: async api => {
        return { data: { code: 0, data: await api.loader() } };
      },
      apis: {
        industryData: {
          loader: async () => {
            const module = await import('@kne/super-select-plus/src/SelectIndustry/industry.json');
            return module.default || module;
          }
        }
      }
    }}>
      <InfoPage>
        <InfoPage.Part title="基本用法">
          <Flex vertical gap={12}>
            <p>互联网/电子通信/软件(编码:001):<IndustryEnum name="001" /></p>
            <p>房地产/建筑/物业(编码:003):<IndustryEnum name="003" /></p>
            <p>金融(编码:004):<IndustryEnum name="004" /></p>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="自定义渲染">
          <Flex vertical gap={12}>
            <p>带样式渲染:</p>
            <IndustryEnum name="001">
              {(item, { locale }) => item && (
                <span style={{ padding: '4px 8px', background: '#f6ffed', borderRadius: '4px' }}>
                  {item.label}
                  {item.enName && <span style={{ marginLeft: '8px', color: '#666' }}>({item.enName})</span>}
                </span>
              )}
            </IndustryEnum>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="实际业务场景">
          <div style={{ lineHeight: '32px' }}>
            <div><strong>企业名称:</strong>某某科技有限公司</div>
            <div><strong>所属行业:</strong><IndustryEnum name="001" /></div>
            <div><strong>期望行业:</strong><IndustryEnum name="004" /></div>
          </div>
        </InfoPage.Part>
        
        <InfoPage.Part title="行业标签展示">
          <Flex gap={8} wrap="wrap">
            <IndustryEnum names={['001', '003', '004']}>
              {(items, { labels }) => labels.map(label => (
                <span key={label} style={{ padding: '4px 8px', background: '#e6f7ff', borderRadius: '4px' }}>
                  {label}
                </span>
              ))}
            </IndustryEnum>
          </Flex>
        </InfoPage.Part>

        <InfoPage.Part title="批量显示 names">
          <Flex vertical gap={12}>
            <p>默认渲染(逗号分隔):<IndustryEnum names={['001', '003', '004']} /></p>
            <IndustryEnum names={['001', '004']}>
              {(items, { labels, locale }) => (
                <div>
                  <div style={{ marginBottom: 8 }}>当前语言:{locale}</div>
                  <div>{labels.join(' · ')}</div>
                </div>
              )}
            </IndustryEnum>
          </Flex>
        </InfoPage.Part>
      </InfoPage>
    </PureGlobal>
  );
});

render(<BaseExample />);
  • EnumDisplay 通用枚举显示
  • 通用枚举显示组件,支持自定义数据源、国际化、缓存及 names 批量显示
  • _SuperSelectPlus(@kne/current-lib_super-select-plus)[import * as _SuperSelectPlus from "@kne/super-select-plus"],antd(antd),remoteLoader(@kne/remote-loader)
const { EnumDisplay } = _SuperSelectPlus;
const { createWithRemoteLoader } = remoteLoader;
const { Flex } = antd;

const BaseExample = createWithRemoteLoader({
  modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage']
})(({ remoteModules }) => {
  const [PureGlobal, InfoPage] = remoteModules;
  
  // 自定义枚举数据示例
  const customEnumData = [
    { code: '1', name: '本科', enName: 'Bachelor' },
    { code: '2', name: '硕士', enName: 'Master' },
    { code: '3', name: '博士', enName: 'Doctor' }
  ];
  
  // 学历枚举配置
  const educationEnumApi = {
    cache: 'EDUCATION_DATA',
    isLocal: true,
    loader: async () => customEnumData
  };
  
  return (
    <PureGlobal preset={{
      ajax: async api => {
        return { data: { code: 0, data: await api.loader() } };
      }
    }}>
      <InfoPage>
        <InfoPage.Part title="基本用法">
          <Flex vertical gap={12}>
            <p>学历 - 本科(编码:1):<EnumDisplay name="1" type="education" {...educationEnumApi} /></p>
            <p>学历 - 硕士(编码:2):<EnumDisplay name="2" type="education" {...educationEnumApi} /></p>
            <p>学历 - 博士(编码:3):<EnumDisplay name="3" type="education" {...educationEnumApi} /></p>
          </Flex>
        </InfoPage.Part>
        
        <InfoPage.Part title="自定义 getLabel 函数">
          <EnumDisplay
            name="1"
            type="education"
            {...educationEnumApi}
            getLabel={(item, locale) => locale === 'en-US' ? (item.enName || item.name) : item.name}
          >
            {(item, { locale }) => item && (
              <div>
                <div>当前语言:{locale}</div>
                <div>显示名称:{item.label}</div>
              </div>
            )}
          </EnumDisplay>
        </InfoPage.Part>
        
        <InfoPage.Part title="自定义渲染">
          <EnumDisplay name="2" type="education" {...educationEnumApi}>
            {(item) => item && (
              <span style={{ padding: '4px 8px', background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', borderRadius: '4px', color: '#fff' }}>
                {item.name} {item.enName && &#96;(${item.enName})&#96;}
              </span>
            )}
          </EnumDisplay>
        </InfoPage.Part>
        
        <InfoPage.Part title="实际业务场景">
          <div style={{ lineHeight: '32px' }}>
            <div><strong>姓名:</strong>赵六</div>
            <div><strong>最高学历:</strong><EnumDisplay name="3" type="education" {...educationEnumApi} /></div>
            <div><strong>第二学历:</strong><EnumDisplay name="2" type="education" {...educationEnumApi} /></div>
            <div><strong>全部学历:</strong><EnumDisplay names={['3', '2', '1']} type="education" {...educationEnumApi} /></div>
          </div>
        </InfoPage.Part>

        <InfoPage.Part title="批量显示 names">
          <Flex vertical gap={12}>
            <p>默认渲染(label 数组 toString,逗号分隔):</p>
            <p>学历编码 ['1', '2', '3']:<EnumDisplay names={['1', '2', '3']} type="education" {...educationEnumApi} /></p>
            <p>学历编码 ['1', '3']:<EnumDisplay names={['1', '3']} type="education" {...educationEnumApi} /></p>
            <p>空数组:<EnumDisplay names={[]} type="education" {...educationEnumApi} /></p>
          </Flex>
        </InfoPage.Part>

        <InfoPage.Part title="names 自定义渲染">
          <EnumDisplay names={['1', '2', '3']} type="education" {...educationEnumApi}>
            {(items, { labels, mapping, locale }) => (
              <Flex vertical gap={8}>
                <div>当前语言:{locale}</div>
                <div>labels:{labels.join(' / ')}</div>
                <Flex gap={8} wrap="wrap">
                  {items.map((item, index) => item && (
                    <span
                      key={item.code}
                      style={{ padding: '4px 8px', background: '#f0f5ff', borderRadius: '4px' }}
                    >
                      {item.label}
                      {mapping.get(item.code)?.enName && &#96; (${mapping.get(item.code).enName})&#96;}
                    </span>
                  ))}
                </Flex>
              </Flex>
            )}
          </EnumDisplay>
        </InfoPage.Part>
        
        <InfoPage.Part title="错误处理">
          <Flex vertical gap={12}>
            <p>单个无效编码:</p>
            <EnumDisplay name="999" type="education" {...educationEnumApi}>
              {(item) => <span>{item ? item.label : '未知学历'}</span>}
            </EnumDisplay>
            <p>批量含无效编码(默认跳过无效项):</p>
            <EnumDisplay names={['1', '999', '3']} type="education" {...educationEnumApi} />
            <p>批量含无效编码(自定义处理):</p>
            <EnumDisplay names={['1', '999', '3']} type="education" {...educationEnumApi}>
              {(items, { labels }) => (
                <span>
                  {items.map((item, index) => (
                    <span key={index}>
                      {index > 0 && '、'}
                      {item ? item.label : '未知'}
                    </span>
                  ))}
                </span>
              )}
            </EnumDisplay>
          </Flex>
        </InfoPage.Part>
      </InfoPage>
    </PureGlobal>
  );
});

render(<BaseExample />);

API

SelectFunction 职能选择器

基于级联选择器的职能选择组件,支持多级职能数据的搜索和选择,适用于招聘、HR系统等业务场景。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | value | array | object | [] | 当前选中的值,单选时为对象,多选时为数组 | | onChange | function | - | 选中值变化时的回调函数 | | single | boolean | false | 是否单选模式 | | placeholder | string | '请选择职能' | 输入框占位符 | | isPopup | boolean | true | 是否下拉模式,false 为弹窗模式 | | overlayWidth | string | number | '320px' | 选择器宽度 | | onSearch | function | - | 自定义搜索函数,参数为 (searchText, { mapping }) | | maxLength | number | - | 多选时最多可选数量 | | disabled | boolean | false | 是否禁用 | | style | object | - | 自定义样式 | | className | string | - | 自定义类名 |

静态方法

| 方法 | 说明 | |------|------| | SelectFunction.defaultData() | 获取默认职能数据,返回 Promise | | SelectFunction.defaultProps | 组件默认属性配置 |

数据结构

组件内部使用扁平化的职能数据结构,通过 codeparentCode 建立层级关系:

{
  code: '001001001',        // 职能编码
  parentCode: '001001',     // 父级编码
  chName: '首席执行官CEO',  // 中文名称
  enName: 'CEO',           // 英文名称
  pinyin: 'shouzhixingguan', // 拼音
  spelling: 'szxg'         // 首字母缩写
}

值回显

value 每项需包含 id(职能编码)和 name(显示名称)。编辑场景下后端通常只返回编码,组件会在 options 加载后自动解析 name:

// 方式一:仅传编码,组件加载 options 后自动解析 name
const value = ['001001001', '001001002'];
// 或对象形式
const value = [{ id: '001001001' }, { id: '001001002' }];

// 方式二:单选回显
const singleValue = { id: '001001001' };
// 或字符串编码
const singleValue = '001001001';

// 方式三:结合 FunctionEnum name,单选编码回显
<FunctionEnum name="001001001">
  {(item) => (
    <SelectFunction
      single
      value={enumItemToSelectValue(item)}
      onChange={setValue}
    />
  )}
</FunctionEnum>

// 方式四:结合 FunctionEnum names,多选编码数组回显(推荐)
const savedCodes = ['001001001', '001001002'];

<FunctionEnum names={savedCodes}>
  {(items) => {
    const resolved = enumItemsToSelectValue(items);
    return (
      <SelectFunction
        value={value ?? resolved}
        onChange={setValue}
      />
    );
  }}
</FunctionEnum>

SelectIndustry 行业选择器

基于级联选择器的行业选择组件,支持多级行业数据的搜索和选择,适用于招聘、企业信息管理等业务场景。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | value | array | object | [] | 当前选中的值,单选时为对象,多选时为数组 | | onChange | function | - | 选中值变化时的回调函数 | | single | boolean | false | 是否单选模式 | | placeholder | string | '请选择行业' | 输入框占位符 | | isPopup | boolean | true | 是否下拉模式,false 为弹窗模式 | | overlayWidth | string | number | '320px' | 选择器宽度 | | onSearch | function | - | 自定义搜索函数,参数为 (searchText, { mapping }) | | maxLength | number | - | 多选时最多可选数量 | | disabled | boolean | false | 是否禁用 | | style | object | - | 自定义样式 | | className | string | - | 自定义类名 |

静态方法

| 方法 | 说明 | |------|------| | SelectIndustry.defaultData() | 获取默认行业数据,返回 Promise | | SelectIndustry.defaultProps() | 组件默认属性配置 |

数据结构

组件内部使用扁平化的行业数据结构,通过 codeparentCode 建立层级关系:

{
  code: '001',              // 行业编码
  parentCode: '',           // 父级编码
  chName: '互联网/电子通信/软件', // 中文名称
  enName: 'Internet/Telecoms/Software', // 英文名称
  pinyin: 'hulianwang',     // 拼音
  spelling: 'hlw'          // 首字母缩写
}

值回显

value 每项需包含 id(行业编码)和 name(显示名称)。编辑场景下后端通常只返回编码,组件会在 options 加载后自动解析 name:

// 方式一:仅传编码,组件加载 options 后自动解析 name
const value = ['001', '003'];
// 或对象形式
const value = [{ id: '001' }, { id: '003' }];

// 方式二:单选回显
const singleValue = { id: '001' };
// 或字符串编码
const singleValue = '001';

// 方式三:结合 IndustryEnum name,单选编码回显
<IndustryEnum name="001">
  {(item) => (
    <SelectIndustry
      single
      value={enumItemToSelectValue(item)}
      onChange={setValue}
    />
  )}
</IndustryEnum>

// 方式四:结合 IndustryEnum names,多选编码数组回显(推荐)
const savedCodes = ['001', '003'];

<IndustryEnum names={savedCodes}>
  {(items) => {
    const resolved = enumItemsToSelectValue(items);
    return (
      <SelectIndustry
        value={value ?? resolved}
        onChange={setValue}
      />
    );
  }}
</IndustryEnum>

SelectAddress 城市选择器

城市地址选择组件,支持国内外城市的搜索和选择,具备拼音搜索、首字母搜索等功能,适用于地址填写、城市筛选等业务场景。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | value | array | object | [] | 当前选中的值,单选时为对象,多选时为数组 | | onChange | function | - | 选中值变化时的回调函数 | | single | boolean | false | 是否单选模式 | | placeholder | string | '请选择城市' | 输入框占位符 | | isPopup | boolean | true | 是否下拉模式,false 为弹窗模式 | | overlayWidth | string | number | '320px' | 选择器宽度 | | searchPlaceholder | string | - | 搜索框占位符 | | maxLength | number | - | 多选时最多可选数量 | | disabled | boolean | false | 是否禁用 | | style | object | - | 自定义样式 | | className | string | - | 自定义类名 |

静态方法

| 方法 | 说明 | |------|------| | SelectAddress.defaultData() | 获取默认城市数据,返回 Promise | | SelectAddress.createAddressApi(cityData) | 根据城市数据创建地址 API 实例 | | SelectAddress.defaultProps | 组件默认属性配置 |

Address API

createAddressApi 方法返回的对象包含以下方法:

| 方法 | 参数 | 返回值 | 说明 | |------|------|--------|------| | getCity(id) | string: 城市ID | object: { city, parent } | 根据ID获取城市信息 | | searchCities(value) | string: 搜索关键词 | array: 城市列表 | 搜索城市,支持拼音和首字母 | | getCityList() | - | array: 城市列表 | 获取所有城市列表 |

数据结构

城市数据包含国内外主要城市:

{
  code: '010',             // 城市编码
  name: '北京',            // 城市名称
  enName: 'Beijing',       // 英文名称
  parentCode: '410',       // 父级编码
  pinyin: 'beijing',       // 拼音
  spelling: 'bj'           // 首字母缩写
}

值回显

编辑场景下后端通常只返回编码,组件会在数据加载后自动解析 label:

// 方式一:仅传编码,组件加载数据后自动解析 label
const value = [{ value: '010' }, { value: '020' }];

// 方式二:单选回显
const singleValue = { value: '010' };
// 或字符串编码
const singleValue = '010';

// 方式三:结合 AddressEnum name,单选编码回显
<AddressEnum name="010">
  {(output) => (
    <SelectAddress
      single
      value={addressEnumToSelectValueSingle(output)}
      onChange={setValue}
    />
  )}
</AddressEnum>

// 方式四:结合 AddressEnum names,多选编码数组回显(推荐)
const savedCodes = ['010', '020'];

<AddressEnum names={savedCodes}>
  {(outputs) => {
    const resolved = addressEnumToSelectValue(outputs);
    return (
      <SelectAddress
        value={value ?? resolved}
        onChange={setValue}
      />
    );
  }}
</AddressEnum>

AddressEnum 地址枚举显示组件

用于显示城市名称的枚举组件,使用 react-fetch 加载数据,支持缓存和国际化。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | name | string | - | 城市编码,与 names 二选一 | | names | string[] | - | 城市编码数组,与 name 二选一,默认 label 数组 toString 输出 | | displayParent | boolean | false | 是否显示父级城市名称 | | force | boolean | false | 是否强制刷新缓存 | | children | function | - | 自定义渲染函数 | | api | object | - | 自定义 API 配置 |

自定义渲染函数

// 单个编码 name
children={({ city, parent }, { displayParent, locale, getLabelForLocal }) => {
  // city: 城市数据对象
  // parent: 父级城市数据对象
  return <span>{getLabelForLocal(city, locale)}</span>;
}}

// 批量编码 names
children={(outputs, { labels, locale, getLabelForLocal }) => {
  // outputs: [{ city, parent }, ...] 数组
  // labels: 有效项的 label 字符串数组
  return <span>{labels.join('、')}</span>;
}}

静态方法

| 方法 | 说明 | |------|------| | AddressEnum.getLabelForLocal(item, locale) | 获取本地化标签 | | AddressEnum.addressDefaultApi | 默认 API 配置 |

使用示例

// 基本用法
<AddressEnum name="010" />

// 批量显示
<AddressEnum names={['010', '020']} />

// 显示父级
<AddressEnum name="010" displayParent />

// 结合 SelectAddress 值回显
<AddressEnum names={['010', '020']}>
  {(outputs) => (
    <SelectAddress value={addressEnumToSelectValue(outputs)} />
  )}
</AddressEnum>

FunctionEnum 职能枚举显示组件

用于显示职能名称的枚举组件,使用 react-fetch 加载数据,支持缓存和国际化。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | name | string | - | 职能编码,与 names 二选一 | | names | string[] | - | 职能编码数组,与 name 二选一,默认 label 数组 toString 输出 | | force | boolean | false | 是否强制刷新缓存 | | children | function | - | 自定义渲染函数 | | api | object | - | 自定义 API 配置 |

自定义渲染函数

// 单个编码 name
children={(item, { locale, mapping, labels, names }) => {
  // item: 职能数据对象,包含 label, chName, enName 等
  // locale: 当前语言环境
  // mapping: 所有职能数据的 Map 对象
  // labels: 当前项的 label 数组
  return <span>{item.label}</span>;
}}

// 批量编码 names
children={(items, { locale, mapping, labels, names }) => {
  // items: 职能数据对象数组,无效编码对应 undefined
  // labels: 有效项的 label 字符串数组
  return <span>{labels.join('、')}</span>;
}}

静态方法

| 方法 | 说明 | |------|------| | FunctionEnum.getLabelForLocal(item, locale) | 获取本地化标签 | | FunctionEnum.defaultFunctionApi | 默认 API 配置 |

使用示例

// 基本用法
<FunctionEnum name="001001001" />

// 批量显示
<FunctionEnum names={['001001001', '001001002', '001001003']} />

// 自定义渲染
<FunctionEnum name="001001001">
  {(item, { locale }) => (
    <div>
      <span>{item.label}</span>
      {item.enName && <span>({item.enName})</span>}
    </div>
  )}
</FunctionEnum>

// 批量自定义渲染
<FunctionEnum names={['001001001', '001001002']}>
  {(items, { labels }) => labels.join(' / ')}
</FunctionEnum>

IndustryEnum 行业枚举显示组件

用于显示行业名称的枚举组件,使用 react-fetch 加载数据,支持缓存和国际化。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | name | string | - | 行业编码,与 names 二选一 | | names | string[] | - | 行业编码数组,与 name 二选一,默认 label 数组 toString 输出 | | force | boolean | false | 是否强制刷新缓存 | | children | function | - | 自定义渲染函数 | | api | object | - | 自定义 API 配置 |

自定义渲染函数

// 单个编码 name
children={(item, { locale, mapping, labels, names }) => {
  // item: 行业数据对象,包含 label, chName, enName 等
  // locale: 当前语言环境
  // mapping: 所有行业数据的 Map 对象
  // labels: 当前项的 label 数组
  return <span>{item.label}</span>;
}}

// 批量编码 names
children={(items, { locale, mapping, labels, names }) => {
  // items: 行业数据对象数组,无效编码对应 undefined
  // labels: 有效项的 label 字符串数组
  return <span>{labels.join('、')}</span>;
}}

静态方法

| 方法 | 说明 | |------|------| | IndustryEnum.getLabelForLocal(item, locale) | 获取本地化标签 | | IndustryEnum.defaultIndustryApi | 默认 API 配置 |

使用示例

// 基本用法
<IndustryEnum name="001" />

// 批量显示
<IndustryEnum names={['001', '003', '004']} />

// 自定义渲染
<IndustryEnum name="001">
  {(item, { locale }) => (
    <div>
      <span>{item.label}</span>
      {item.enName && <span>({item.enName})</span>}
    </div>
  )}
</IndustryEnum>

// 批量自定义渲染
<IndustryEnum names={['001', '004']}>
  {(items, { labels }) => labels.join(' · ')}
</IndustryEnum>

EnumDisplay 通用枚举显示组件

通用的枚举显示组件,支持自定义数据源、国际化、缓存等功能。

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|-------|------| | name | string | - | 单个枚举值编码,与 names 二选一 | | names | string[] | - | 多个枚举值编码,与 name 二选一,默认 label 数组 toString 输出 | | type | string | - | 枚举类型标识 | | cache | string | 'ENUM_DATA' | 缓存键名 | | force | boolean | false | 是否强制刷新缓存 | | children | function | - | 自定义渲染函数 | | api | object | - | API 配置对象 | | getLabel | function | - | 自定义标签获取函数 |

API 配置

api={{
  cache: 'CUSTOM_DATA',      // 缓存键名
  isLocal: true,             // 是否本地数据
  ttl: 1000 * 60 * 60 * 24,  // 缓存时间(毫秒)
  loader: async () => {      // 数据加载函数
    return data;
  }
}}

// 或远程 API
api={{
  cache: 'REMOTE_DATA',
  url: '/api/enum',          // API 地址
  method: 'GET',             // 请求方法
  dataFormat: (data) => data // 数据格式化函数
}}

自定义渲染函数

// 单个编码 name
children={(item, { locale, mapping, labels, names }) => {
  // item: 枚举数据对象
  // locale: 当前语言环境
  // mapping: 所有枚举数据的 Map 对象
  // labels: 当前项的 label 数组
  return <span>{item.label}</span>;
}}

// 批量编码 names
children={(items, { locale, mapping, labels, names }) => {
  // items: 枚举数据对象数组,无效编码对应 undefined
  // labels: 有效项的 label 字符串数组
  // names: 传入的编码数组
  return <span>{labels.join('、')}</span>;
}}

使用示例

// 基本用法
<EnumDisplay
  name="1"
  type="education"
  api={{
    cache: 'EDUCATION_DATA',
    loader: async () => [
      { code: '1', name: '本科', enName: 'Bachelor' },
      { code: '2', name: '硕士', enName: 'Master' }
    ]
  }}
/>

// 批量显示
<EnumDisplay
  names={['1', '2', '3']}
  type="education"
  api={educationEnumApi}
/>

// 自定义 getLabel
<EnumDisplay
  name="1"
  type="education"
  api={api}
  getLabel={(item, locale) => {
    return locale === 'en-US' ? item.enName : item.name;
  }}
/>

// 批量自定义渲染
<EnumDisplay names={['1', '2', '3']} type="education" api={api}>
  {(items, { labels }) => labels.join(' / ')}
</EnumDisplay>

工具函数

用于将 names={[code, code]} 解析结果转为选择器 value

| 函数 | 说明 | |------|------| | enumItemsToSelectValue(items, options?) | 将 FunctionEnum / IndustryEnum 的 items 转为 { id, name }[],可选 valueKey / labelKey | | enumItemToSelectValue(item, options?) | 单选:将 FunctionEnum / IndustryEnum 的 item 转为 { id, name } | | addressEnumToSelectValue(outputs) | 将 AddressEnum 解析结果转为 SelectAddress 的 { value, label }[](支持 name 单值或 names 数组) | | addressEnumToSelectValueSingle(output) | 单选:将 AddressEnum name 解析结果转为 { value, label } |

import { enumItemsToSelectValue, addressEnumToSelectValue } from '@kne/super-select-plus';

// 职能/行业选择器回显
<FunctionEnum names={['001001001', '001001002']}>
  {(items) => (
    <SelectFunction value={enumItemsToSelectValue(items)} />
  )}
</FunctionEnum>

// 城市选择器回显
<AddressEnum names={['010', '020']}>
  {(outputs) => (
    <SelectAddress value={addressEnumToSelectValue(outputs)} />
  )}
</AddressEnum>

国际化支持

所有组件均支持国际化,通过 @kne/react-intl 实现:

支持的语言

  • 中文(zh-CN):默认语言
  • 英文(en-US):备用语言

使用方式

组件会根据当前 locale 自动切换语言:

  • 中文名称(chName)优先显示中文环境
  • 英文名称(enName)优先显示英文环境
  • 当对应语言不存在时,会使用备选语言

搜索功能

所有组件的搜索功能均支持:

  • 中文名称搜索(chName)
  • 英文名称搜索(enName)
  • 拼音搜索(pinyin)
  • 首字母搜索(spelling)