Browse Source

feat(icon): added svg icon picker

Vben 4 years ago
parent
commit
1418dc6a59

+ 1 - 8
.vscode/settings.json

@@ -105,17 +105,12 @@
   },
   "stylelint.enable": true,
   "stylelint.packageManager": "yarn",
-  "css.validate": true,
-  "less.validate": true,
-  "scss.validate": true,
   // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   // ===========================================
   // ================ Eslint ===================
   // ===========================================
-  // "eslint.enable": true,
   "eslint.alwaysShowStatus": true,
   "eslint.options": {
-    // 配置
     "plugins": ["html", "vue", "javascript", "jsx", "typescript"],
     "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
   },
@@ -127,7 +122,6 @@
     "html",
     "vue"
   ],
-  // "eslint.autoFixOnSave": true,
   // ===========================================
   // ================ Vetur ====================
   // ===========================================
@@ -139,7 +133,6 @@
   "vetur.format.defaultFormatter.ts": "prettier-tslint",
   "vetur.format.defaultFormatter.js": "prettier",
   "vetur.languageFeatures.codeActions": false,
-  // "vetur.validation.script": false,
   "vetur.format.defaultFormatterOptions": {
     "js-beautify-html": {
       "wrap_attributes": "force-expand-multiline"
@@ -201,6 +194,6 @@
   "i18n-ally.namespace": true,
   "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
   "i18n-ally.enabledParsers": ["ts"],
-  "i18n-ally.sourceLanguage": "zh",
+  "i18n-ally.sourceLanguage": "en",
   "i18n-ally.enabledFrameworks": ["vue", "react"]
 }

+ 4 - 0
CHANGELOG.zh_CN.md

@@ -1,5 +1,9 @@
 ## Wip
 
+### ✨ Features
+
+- 图标选择器新增 svg 模式
+
 ### ✨ Refactor
 
 - 重构项目以解决循环依赖项导致的热更新问题

+ 3 - 3
package.json

@@ -53,7 +53,7 @@
   "devDependencies": {
     "@commitlint/cli": "^12.0.1",
     "@commitlint/config-conventional": "^12.0.1",
-    "@iconify/json": "^1.1.313",
+    "@iconify/json": "^1.1.314",
     "@ls-lint/ls-lint": "^1.9.2",
     "@purge-icons/generated": "^0.7.0",
     "@types/crypto-js": "^4.0.1",
@@ -110,7 +110,7 @@
     "vite-plugin-purge-icons": "^0.7.0",
     "vite-plugin-pwa": "^0.5.6",
     "vite-plugin-style-import": "^0.8.1",
-    "vite-plugin-svg-icons": "^0.3.3",
+    "vite-plugin-svg-icons": "^0.3.4",
     "vite-plugin-theme": "^0.4.8",
     "vite-plugin-windicss": "0.7.1",
     "vue-eslint-parser": "^7.6.0",
@@ -120,7 +120,7 @@
     "//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it",
     "bin-wrapper": "npm:bin-wrapper-china",
     "esbuild": "0.8.57",
-    "rollup": "2.40.0"
+    "rollup": "2.41.0"
   },
   "repository": {
     "type": "git",

+ 1 - 0
src/components/Application/src/search/AppSearch.vue

@@ -13,6 +13,7 @@
     components: { AppSearchModal, Tooltip },
     setup() {
       const showModal = ref(false);
+
       const { getShowSearch } = useHeaderSetting();
       const { t } = useI18n();
 

+ 1 - 2
src/components/Application/src/search/AppSearchFooter.vue

@@ -14,14 +14,13 @@
 
 <script lang="ts">
   import { defineComponent } from 'vue';
-  import Icon from '/@/components/Icon';
   import AppSearchKeyItem from './AppSearchKeyItem.vue';
 
   import { useDesign } from '/@/hooks/web/useDesign';
   import { useI18n } from '/@/hooks/web/useI18n';
   export default defineComponent({
     name: 'AppSearchFooter',
-    components: { Icon, AppSearchKeyItem },
+    components: { AppSearchKeyItem },
     setup() {
       const { prefixCls } = useDesign('app-search-footer');
       const { t } = useI18n();

+ 1 - 1
src/components/Form/src/BasicForm.vue

@@ -47,7 +47,7 @@
     nextTick,
   } from 'vue';
   import { Form, Row } from 'ant-design-vue';
-  import FormItem from './components/FormItem';
+  import FormItem from './components/FormItem.vue';
   import FormAction from './components/FormAction.vue';
 
   import { dateItemType } from './helper';

+ 0 - 337
src/components/Form/src/components/FormItem.tsx

@@ -1,337 +0,0 @@
-import type { PropType, Ref } from 'vue';
-import type { FormActionType, FormProps } from '../types/form';
-import type { FormSchema } from '../types/form';
-import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
-import type { TableActionType } from '/@/components/Table';
-
-import { defineComponent, computed, unref, toRefs } from 'vue';
-import { Form, Col } from 'ant-design-vue';
-import { componentMap } from '../componentMap';
-import { BasicHelp } from '/@/components/Basic';
-
-import { isBoolean, isFunction } from '/@/utils/is';
-import { getSlot } from '/@/utils/helper/tsxHelper';
-import { createPlaceholderMessage, setComponentRuleType } from '../helper';
-import { upperFirst, cloneDeep } from 'lodash-es';
-
-import { useItemLabelWidth } from '../hooks/useLabelWidth';
-import { useI18n } from '/@/hooks/web/useI18n';
-
-export default defineComponent({
-  name: 'BasicFormItem',
-  inheritAttrs: false,
-  props: {
-    schema: {
-      type: Object as PropType<FormSchema>,
-      default: () => {},
-    },
-    formProps: {
-      type: Object as PropType<FormProps>,
-      default: {},
-    },
-    allDefaultValues: {
-      type: Object as PropType<Recordable>,
-      default: {},
-    },
-    formModel: {
-      type: Object as PropType<Recordable>,
-      default: {},
-    },
-    setFormModel: {
-      type: Function as PropType<(key: string, value: any) => void>,
-      default: null,
-    },
-    tableAction: {
-      type: Object as PropType<TableActionType>,
-    },
-    formActionType: {
-      type: Object as PropType<FormActionType>,
-    },
-  },
-  setup(props, { slots }) {
-    const { t } = useI18n();
-
-    const { schema, formProps } = toRefs(props) as {
-      schema: Ref<FormSchema>;
-      formProps: Ref<FormProps>;
-    };
-
-    const itemLabelWidthProp = useItemLabelWidth(schema, formProps);
-
-    const getValues = computed(() => {
-      const { allDefaultValues, formModel, schema } = props;
-      const { mergeDynamicData } = props.formProps;
-      return {
-        field: schema.field,
-        model: formModel,
-        values: {
-          ...mergeDynamicData,
-          ...allDefaultValues,
-          ...formModel,
-        } as Recordable,
-        schema: schema,
-      };
-    });
-
-    const getComponentsProps = computed(() => {
-      const { schema, tableAction, formModel, formActionType } = props;
-      const { componentProps = {} } = schema;
-      if (!isFunction(componentProps)) {
-        return componentProps;
-      }
-      return componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
-    });
-
-    const getDisable = computed(() => {
-      const { disabled: globDisabled } = props.formProps;
-      const { dynamicDisabled } = props.schema;
-      const { disabled: itemDisabled = false } = unref(getComponentsProps);
-      let disabled = !!globDisabled || itemDisabled;
-      if (isBoolean(dynamicDisabled)) {
-        disabled = dynamicDisabled;
-      }
-
-      if (isFunction(dynamicDisabled)) {
-        disabled = dynamicDisabled(unref(getValues));
-      }
-      return disabled;
-    });
-
-    function getShow(): { isShow: boolean; isIfShow: boolean } {
-      const { show, ifShow } = props.schema;
-      const { showAdvancedButton } = props.formProps;
-      const itemIsAdvanced = showAdvancedButton
-        ? isBoolean(props.schema.isAdvanced)
-          ? props.schema.isAdvanced
-          : true
-        : true;
-
-      let isShow = true;
-      let isIfShow = true;
-
-      if (isBoolean(show)) {
-        isShow = show;
-      }
-      if (isBoolean(ifShow)) {
-        isIfShow = ifShow;
-      }
-      if (isFunction(show)) {
-        isShow = show(unref(getValues));
-      }
-      if (isFunction(ifShow)) {
-        isIfShow = ifShow(unref(getValues));
-      }
-      isShow = isShow && itemIsAdvanced;
-      return { isShow, isIfShow };
-    }
-
-    function handleRules(): ValidationRule[] {
-      const {
-        rules: defRules = [],
-        component,
-        rulesMessageJoinLabel,
-        label,
-        dynamicRules,
-        required,
-      } = props.schema;
-
-      if (isFunction(dynamicRules)) {
-        return dynamicRules(unref(getValues)) as ValidationRule[];
-      }
-
-      let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
-
-      if ((!rules || rules.length === 0) && required) {
-        rules = [{ required, type: 'string' }];
-      }
-
-      const requiredRuleIndex: number = rules.findIndex(
-        (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator')
-      );
-      const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
-      if (requiredRuleIndex !== -1) {
-        const rule = rules[requiredRuleIndex];
-        const { isShow } = getShow();
-        if (!isShow) {
-          rule.required = false;
-        }
-        if (rule.required && component) {
-          if (!Reflect.has(rule, 'type')) {
-            rule.type = 'string';
-          }
-          const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
-            ? rulesMessageJoinLabel
-            : globalRulesMessageJoinLabel;
-
-          rule.message =
-            rule.message || createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;
-
-          if (component.includes('Input') || component.includes('Textarea')) {
-            rule.whitespace = true;
-          }
-
-          setComponentRuleType(rule, component);
-        }
-      }
-
-      // Maximum input length rule check
-      const characterInx = rules.findIndex((val) => val.max);
-      if (characterInx !== -1 && !rules[characterInx].validator) {
-        rules[characterInx].message =
-          rules[characterInx].message ||
-          t('component.form.maxTip', [rules[characterInx].max] as Recordable);
-      }
-      return rules;
-    }
-
-    function renderComponent() {
-      const {
-        renderComponentContent,
-        component,
-        field,
-        changeEvent = 'change',
-        valueField,
-      } = props.schema;
-
-      const isCheck = component && ['Switch', 'Checkbox'].includes(component);
-
-      const eventKey = `on${upperFirst(changeEvent)}`;
-
-      const on = {
-        [eventKey]: (e: Nullable<Recordable>) => {
-          if (propsData[eventKey]) {
-            propsData[eventKey](e);
-          }
-
-          const target = e ? e.target : null;
-
-          const value = target ? (isCheck ? target.checked : target.value) : e;
-          props.setFormModel(field, value);
-        },
-      };
-      const Comp = componentMap.get(component) as typeof defineComponent;
-
-      const { autoSetPlaceHolder, size } = props.formProps;
-      const propsData: Recordable = {
-        allowClear: true,
-        getPopupContainer: (trigger: Element) => trigger.parentNode,
-        size,
-        ...unref(getComponentsProps),
-        disabled: unref(getDisable),
-      };
-
-      const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
-      let placeholder;
-      // RangePicker place is an array
-      if (isCreatePlaceholder && component !== 'RangePicker' && component) {
-        placeholder = unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component);
-      }
-      propsData.placeholder = placeholder;
-      propsData.codeField = field;
-      propsData.formValues = unref(getValues);
-
-      const bindValue: Recordable = {
-        [valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
-      };
-
-      const compAttr: Recordable = {
-        ...propsData,
-        ...on,
-        ...bindValue,
-      };
-
-      if (!renderComponentContent) {
-        return <Comp {...compAttr} />;
-      }
-      const compSlot = isFunction(renderComponentContent)
-        ? { ...renderComponentContent(unref(getValues)) }
-        : {
-            default: () => renderComponentContent,
-          };
-
-      return <Comp {...compAttr}>{compSlot}</Comp>;
-    }
-
-    function renderLabelHelpMessage() {
-      const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
-      const renderLabel = subLabel ? (
-        <span>
-          {label} <span style="color:#00000073">{subLabel}</span>
-        </span>
-      ) : (
-        label
-      );
-      if (!helpMessage || (Array.isArray(helpMessage) && helpMessage.length === 0)) {
-        return renderLabel;
-      }
-      return (
-        <span>
-          {renderLabel}
-          <BasicHelp placement="top" class="mx-1" text={helpMessage} {...helpComponentProps} />
-        </span>
-      );
-    }
-
-    function renderItem() {
-      const { itemProps, slot, render, field, suffix } = props.schema;
-      const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
-      const { colon } = props.formProps;
-
-      const getContent = () => {
-        return slot
-          ? getSlot(slots, slot, unref(getValues))
-          : render
-          ? render(unref(getValues))
-          : renderComponent();
-      };
-
-      const showSuffix = !!suffix;
-
-      const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
-
-      return (
-        <Form.Item
-          name={field}
-          colon={colon}
-          class={{ 'suffix-item': showSuffix }}
-          {...(itemProps as Recordable)}
-          label={renderLabelHelpMessage()}
-          rules={handleRules()}
-          labelCol={labelCol}
-          wrapperCol={wrapperCol}
-        >
-          <>
-            {getContent()}
-            {showSuffix && <span class="suffix">{getSuffix}</span>}
-          </>
-        </Form.Item>
-      );
-    }
-    return () => {
-      const { colProps = {}, colSlot, renderColContent, component } = props.schema;
-      if (!componentMap.has(component)) return null;
-
-      const { baseColProps = {} } = props.formProps;
-
-      const realColProps = { ...baseColProps, ...colProps };
-      const { isIfShow, isShow } = getShow();
-
-      const values = unref(getValues);
-      const getContent = () => {
-        return colSlot
-          ? getSlot(slots, colSlot, values)
-          : renderColContent
-          ? renderColContent(values)
-          : renderItem();
-      };
-
-      return (
-        isIfShow && (
-          <Col {...realColProps} v-show={isShow}>
-            {getContent()}
-          </Col>
-        )
-      );
-    };
-  },
-});

+ 340 - 0
src/components/Form/src/components/FormItem.vue

@@ -0,0 +1,340 @@
+<script lang="tsx">
+  import type { PropType, Ref } from 'vue';
+  import type { FormActionType, FormProps } from '../types/form';
+  import type { FormSchema } from '../types/form';
+  import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
+  import type { TableActionType } from '/@/components/Table';
+
+  import { defineComponent, computed, unref, toRefs } from 'vue';
+  import { Form, Col } from 'ant-design-vue';
+  import { componentMap } from '../componentMap';
+  import { BasicHelp } from '/@/components/Basic';
+
+  import { isBoolean, isFunction } from '/@/utils/is';
+  import { getSlot } from '/@/utils/helper/tsxHelper';
+  import { createPlaceholderMessage, setComponentRuleType } from '../helper';
+  import { upperFirst, cloneDeep } from 'lodash-es';
+
+  import { useItemLabelWidth } from '../hooks/useLabelWidth';
+  import { useI18n } from '/@/hooks/web/useI18n';
+
+  export default defineComponent({
+    name: 'BasicFormItem',
+    inheritAttrs: false,
+    props: {
+      schema: {
+        type: Object as PropType<FormSchema>,
+        default: () => {},
+      },
+      formProps: {
+        type: Object as PropType<FormProps>,
+        default: {},
+      },
+      allDefaultValues: {
+        type: Object as PropType<Recordable>,
+        default: {},
+      },
+      formModel: {
+        type: Object as PropType<Recordable>,
+        default: {},
+      },
+      setFormModel: {
+        type: Function as PropType<(key: string, value: any) => void>,
+        default: null,
+      },
+      tableAction: {
+        type: Object as PropType<TableActionType>,
+      },
+      formActionType: {
+        type: Object as PropType<FormActionType>,
+      },
+    },
+    setup(props, { slots }) {
+      const { t } = useI18n();
+
+      const { schema, formProps } = toRefs(props) as {
+        schema: Ref<FormSchema>;
+        formProps: Ref<FormProps>;
+      };
+
+      const itemLabelWidthProp = useItemLabelWidth(schema, formProps);
+
+      const getValues = computed(() => {
+        const { allDefaultValues, formModel, schema } = props;
+        const { mergeDynamicData } = props.formProps;
+        return {
+          field: schema.field,
+          model: formModel,
+          values: {
+            ...mergeDynamicData,
+            ...allDefaultValues,
+            ...formModel,
+          } as Recordable,
+          schema: schema,
+        };
+      });
+
+      const getComponentsProps = computed(() => {
+        const { schema, tableAction, formModel, formActionType } = props;
+        const { componentProps = {} } = schema;
+        if (!isFunction(componentProps)) {
+          return componentProps;
+        }
+        return componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
+      });
+
+      const getDisable = computed(() => {
+        const { disabled: globDisabled } = props.formProps;
+        const { dynamicDisabled } = props.schema;
+        const { disabled: itemDisabled = false } = unref(getComponentsProps);
+        let disabled = !!globDisabled || itemDisabled;
+        if (isBoolean(dynamicDisabled)) {
+          disabled = dynamicDisabled;
+        }
+
+        if (isFunction(dynamicDisabled)) {
+          disabled = dynamicDisabled(unref(getValues));
+        }
+        return disabled;
+      });
+
+      function getShow(): { isShow: boolean; isIfShow: boolean } {
+        const { show, ifShow } = props.schema;
+        const { showAdvancedButton } = props.formProps;
+        const itemIsAdvanced = showAdvancedButton
+          ? isBoolean(props.schema.isAdvanced)
+            ? props.schema.isAdvanced
+            : true
+          : true;
+
+        let isShow = true;
+        let isIfShow = true;
+
+        if (isBoolean(show)) {
+          isShow = show;
+        }
+        if (isBoolean(ifShow)) {
+          isIfShow = ifShow;
+        }
+        if (isFunction(show)) {
+          isShow = show(unref(getValues));
+        }
+        if (isFunction(ifShow)) {
+          isIfShow = ifShow(unref(getValues));
+        }
+        isShow = isShow && itemIsAdvanced;
+        return { isShow, isIfShow };
+      }
+
+      function handleRules(): ValidationRule[] {
+        const {
+          rules: defRules = [],
+          component,
+          rulesMessageJoinLabel,
+          label,
+          dynamicRules,
+          required,
+        } = props.schema;
+
+        if (isFunction(dynamicRules)) {
+          return dynamicRules(unref(getValues)) as ValidationRule[];
+        }
+
+        let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
+
+        if ((!rules || rules.length === 0) && required) {
+          rules = [{ required, type: 'string' }];
+        }
+
+        const requiredRuleIndex: number = rules.findIndex(
+          (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator')
+        );
+        const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
+        if (requiredRuleIndex !== -1) {
+          const rule = rules[requiredRuleIndex];
+          const { isShow } = getShow();
+          if (!isShow) {
+            rule.required = false;
+          }
+          if (rule.required && component) {
+            if (!Reflect.has(rule, 'type')) {
+              rule.type = 'string';
+            }
+            const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
+              ? rulesMessageJoinLabel
+              : globalRulesMessageJoinLabel;
+
+            rule.message =
+              rule.message || createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;
+
+            if (component.includes('Input') || component.includes('Textarea')) {
+              rule.whitespace = true;
+            }
+
+            setComponentRuleType(rule, component);
+          }
+        }
+
+        // Maximum input length rule check
+        const characterInx = rules.findIndex((val) => val.max);
+        if (characterInx !== -1 && !rules[characterInx].validator) {
+          rules[characterInx].message =
+            rules[characterInx].message ||
+            t('component.form.maxTip', [rules[characterInx].max] as Recordable);
+        }
+        return rules;
+      }
+
+      function renderComponent() {
+        const {
+          renderComponentContent,
+          component,
+          field,
+          changeEvent = 'change',
+          valueField,
+        } = props.schema;
+
+        const isCheck = component && ['Switch', 'Checkbox'].includes(component);
+
+        const eventKey = `on${upperFirst(changeEvent)}`;
+
+        const on = {
+          [eventKey]: (e: Nullable<Recordable>) => {
+            if (propsData[eventKey]) {
+              propsData[eventKey](e);
+            }
+
+            const target = e ? e.target : null;
+
+            const value = target ? (isCheck ? target.checked : target.value) : e;
+            props.setFormModel(field, value);
+          },
+        };
+        const Comp = componentMap.get(component) as typeof defineComponent;
+
+        const { autoSetPlaceHolder, size } = props.formProps;
+        const propsData: Recordable = {
+          allowClear: true,
+          getPopupContainer: (trigger: Element) => trigger.parentNode,
+          size,
+          ...unref(getComponentsProps),
+          disabled: unref(getDisable),
+        };
+
+        const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
+        let placeholder;
+        // RangePicker place is an array
+        if (isCreatePlaceholder && component !== 'RangePicker' && component) {
+          placeholder =
+            unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component);
+        }
+        propsData.placeholder = placeholder;
+        propsData.codeField = field;
+        propsData.formValues = unref(getValues);
+
+        const bindValue: Recordable = {
+          [valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
+        };
+
+        const compAttr: Recordable = {
+          ...propsData,
+          ...on,
+          ...bindValue,
+        };
+
+        if (!renderComponentContent) {
+          return <Comp {...compAttr} />;
+        }
+        const compSlot = isFunction(renderComponentContent)
+          ? { ...renderComponentContent(unref(getValues)) }
+          : {
+              default: () => renderComponentContent,
+            };
+
+        return <Comp {...compAttr}>{compSlot}</Comp>;
+      }
+
+      function renderLabelHelpMessage() {
+        const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
+        const renderLabel = subLabel ? (
+          <span>
+            {label} <span style="color:#00000073">{subLabel}</span>
+          </span>
+        ) : (
+          label
+        );
+        if (!helpMessage || (Array.isArray(helpMessage) && helpMessage.length === 0)) {
+          return renderLabel;
+        }
+        return (
+          <span>
+            {renderLabel}
+            <BasicHelp placement="top" class="mx-1" text={helpMessage} {...helpComponentProps} />
+          </span>
+        );
+      }
+
+      function renderItem() {
+        const { itemProps, slot, render, field, suffix } = props.schema;
+        const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
+        const { colon } = props.formProps;
+
+        const getContent = () => {
+          return slot
+            ? getSlot(slots, slot, unref(getValues))
+            : render
+            ? render(unref(getValues))
+            : renderComponent();
+        };
+
+        const showSuffix = !!suffix;
+
+        const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
+
+        return (
+          <Form.Item
+            name={field}
+            colon={colon}
+            class={{ 'suffix-item': showSuffix }}
+            {...(itemProps as Recordable)}
+            label={renderLabelHelpMessage()}
+            rules={handleRules()}
+            labelCol={labelCol}
+            wrapperCol={wrapperCol}
+          >
+            <>
+              {getContent()}
+              {showSuffix && <span class="suffix">{getSuffix}</span>}
+            </>
+          </Form.Item>
+        );
+      }
+      return () => {
+        const { colProps = {}, colSlot, renderColContent, component } = props.schema;
+        if (!componentMap.has(component)) return null;
+
+        const { baseColProps = {} } = props.formProps;
+
+        const realColProps = { ...baseColProps, ...colProps };
+        const { isIfShow, isShow } = getShow();
+
+        const values = unref(getValues);
+        const getContent = () => {
+          return colSlot
+            ? getSlot(slots, colSlot, values)
+            : renderColContent
+            ? renderColContent(values)
+            : renderItem();
+        };
+
+        return (
+          isIfShow && (
+            <Col {...realColProps} v-show={isShow}>
+              {getContent()}
+            </Col>
+          )
+        );
+      };
+    },
+  });
+</script>

+ 26 - 9
src/components/Icon/src/IconPicker.vue

@@ -30,16 +30,17 @@
                 <li
                   v-for="icon in getPaginationList"
                   :key="icon"
-                  :class="currentSelect === icon ? 'bg-primary text-white' : ''"
-                  class="p-2 w-1/8 cursor-pointer mr-1 mt-1 flex justify-center items-center border border-solid hover:bg-primary hover:text-white"
+                  :class="currentSelect === icon ? 'border border-primary' : ''"
+                  class="p-2 w-1/8 cursor-pointer mr-1 mt-1 flex justify-center items-center border border-solid hover:border-primary"
                   @click="handleClick(icon)"
                 >
                   <!-- <Icon :icon="icon" :prefix="prefix" /> -->
-                  <Icon :icon="icon" />
+                  <SvgIcon v-if="isSvgMode" :name="icon" />
+                  <Icon :icon="icon" v-else />
                 </li>
               </ul>
             </ScrollContainer>
-            <div class="flex py-2 items-center justify-center">
+            <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
               <Pagination
                 showLessItems
                 size="small"
@@ -53,7 +54,11 @@
             ><div class="p-5"> <Empty /></div>
           </template>
         </template>
-        <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" />
+
+        <span class="cursor-pointer px-2 py-1 flex items-center" v-if="isSvgMode && currentSelect">
+          <SvgIcon :name="currentSelect" />
+        </span>
+        <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
       </Popover>
     </template>
   </a-input>
@@ -66,6 +71,7 @@
 
   import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
   import Icon from './index.vue';
+  import SvgIcon from './SvgIcon.vue';
 
   import iconsData from '../data/icons.data';
   import { propTypes } from '/@/utils/propTypes';
@@ -74,7 +80,7 @@
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
   import { useMessage } from '/@/hooks/web/useMessage';
-  // import '@iconify/iconify';
+  import svgIcons from 'vite-plugin-svg-icons/client';
 
   function getIcons() {
     const data = iconsData as any;
@@ -88,25 +94,35 @@
     return result;
   }
 
-  const icons = getIcons();
+  function getSvgIcons() {
+    return svgIcons.map((icon) => icon.replace('icon-', ''));
+  }
+
   export default defineComponent({
     name: 'IconPicker',
-    components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty },
+    components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty, SvgIcon },
     inheritAttrs: false,
     props: {
       value: propTypes.string,
       width: propTypes.string.def('100%'),
       pageSize: propTypes.number.def(140),
       copy: propTypes.bool.def(false),
+      mode: propTypes
+        .oneOf<('svg' | 'iconify')[]>(['svg', 'iconify'])
+        .def('iconify'),
     },
     emits: ['change'],
     setup(props, { emit }) {
+      const isSvgMode = props.mode === 'svg';
+      const icons = isSvgMode ? getSvgIcons() : getIcons();
+
       const currentSelect = ref('');
       const visible = ref(false);
       const currentList = ref(icons);
 
-      const { prefixCls } = useDesign('icon-picker');
       const { t } = useI18n();
+      const { prefixCls } = useDesign('icon-picker');
+
       const [debounceHandleSearchChange] = useDebounce(handleSearchChange, 100);
       const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
       const { createMessage } = useMessage();
@@ -153,6 +169,7 @@
         t,
         prefixCls,
         visible,
+        isSvgMode,
         getTotal,
         getPaginationList,
         handlePageChange,

+ 1 - 1
src/components/Tree/src/TreeHeader.vue

@@ -24,7 +24,7 @@
 </template>
 <script lang="ts">
   import type { PropType } from 'vue';
-  import { defineComponent, ref, computed } from 'vue';
+  import { defineComponent, computed } from 'vue';
 
   import { Dropdown, Menu, Input } from 'ant-design-vue';
   import { Icon } from '/@/components/Icon';

+ 1 - 0
src/design/index.less

@@ -37,6 +37,7 @@ a:focus,
 a:active,
 button,
 div,
+svg,
 span {
   outline: none !important;
 }

+ 8 - 2
src/views/demo/feat/icon/index.vue

@@ -21,18 +21,24 @@
       </div>
     </CollapseContainer>
 
-    <CollapseContainer title="svg Sprite" class="my-5">
+    <CollapseContainer title="svg 雪碧图" class="my-5">
       <div class="flex justify-around flex-wrap">
         <SvgIcon name="test" size="32" />
       </div>
     </CollapseContainer>
 
-    <CollapseContainer title="图标选择器" class="my-5">
+    <CollapseContainer title="图标选择器(Iconify)" class="my-5">
       <div class="flex justify-around flex-wrap">
         <IconPicker />
       </div>
     </CollapseContainer>
 
+    <CollapseContainer title="图标选择器(Svg)" class="my-5">
+      <div class="flex justify-around flex-wrap">
+        <IconPicker mode="svg" />
+      </div>
+    </CollapseContainer>
+
     <Alert
       show-icon
       message="推荐使用Iconify组件"

+ 12 - 12
yarn.lock

@@ -1117,10 +1117,10 @@
   dependencies:
     cross-fetch "^3.0.6"
 
-"@iconify/json@^1.1.313":
-  version "1.1.313"
-  resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.313.tgz#c225be3c5ce3280a2c34e753a65dc257b85b6652"
-  integrity sha512-gv00rSX4apKE0i/fUjXp5+sBb8LHzzdJqrXkBNVby7Nl7yzRqeQ/EyY+7ixtSpEu3f1P/co/vrgdbZN6wlw6DA==
+"@iconify/json@^1.1.314":
+  version "1.1.314"
+  resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.314.tgz#43b417e5131b55e879f94b6fc40b09928eea42ad"
+  integrity sha512-KDc2dtNnbUryuUWs4ov1e8xCcEjrU/9r3PLOsElzsRpMjaGe/RfpAvU1NkDlv7Mmriaah+Dj6SVoLeRSUB5q3g==
 
 "@intlify/core-base@9.0.0":
   version "9.0.0"
@@ -7680,10 +7680,10 @@ rollup-plugin-visualizer@^4.2.0:
     source-map "^0.7.3"
     yargs "^16.0.3"
 
-rollup@2.40.0, rollup@^0.63.4, rollup@^2.25.0, rollup@^2.38.5, rollup@^2.40.0:
-  version "2.40.0"
-  resolved "https://registry.npmjs.org/rollup/-/rollup-2.40.0.tgz#efc218eaede7ab590954df50f96195188999c304"
-  integrity sha512-WiOGAPbXoHu+TOz6hyYUxIksOwsY/21TRWoO593jgYt8mvYafYqQl+axaA8y1z2HFazNUUrsMSjahV2A6/2R9A==
+rollup@2.41.0, rollup@^0.63.4, rollup@^2.25.0, rollup@^2.38.5, rollup@^2.40.0:
+  version "2.41.0"
+  resolved "https://registry.npmjs.org/rollup/-/rollup-2.41.0.tgz#b2a398bbabbf227738dedaef099e494aed468982"
+  integrity sha512-Gk76XHTggulWPH95q8V62bw6uqDH6UGvbD6LOa3QUyhuMF3eOuaeDHR7SLm1T9faitkpNrqzUAVYx47klcMnlA==
   optionalDependencies:
     fsevents "~2.3.1"
 
@@ -9160,10 +9160,10 @@ vite-plugin-style-import@^0.8.1:
     es-module-lexer "^0.4.1"
     magic-string "^0.25.7"
 
-vite-plugin-svg-icons@^0.3.3:
-  version "0.3.3"
-  resolved "https://registry.npmjs.org/vite-plugin-svg-icons/-/vite-plugin-svg-icons-0.3.3.tgz#b699e1af244500d893cc32b48a772492c1fae72b"
-  integrity sha512-ZI3FLspeM3PV0OE503m7/11jW5aSSCwxXUEcJZL3RwSYmpkLE0cSsM7UFZf0tx3cRoSB/JpeOlRIRH6G2BhWiQ==
+vite-plugin-svg-icons@^0.3.4:
+  version "0.3.4"
+  resolved "https://registry.npmjs.org/vite-plugin-svg-icons/-/vite-plugin-svg-icons-0.3.4.tgz#505aacff35f19d4e1c81f05a85bded0d6f1f6323"
+  integrity sha512-N4KYqmyF/gnsYIBxvMTyotjWSdur/6EyycE6eJvM2m7oHHxe8Y+SZZlD+XTz8Nl+zfurXYDkrbbHAdtWlpJovw==
   dependencies:
     debug "^4.3.2"
     etag "^1.8.1"