Commit 1418dc6a597a8410711359f07ae66f0fea858977

Authored by Vben
1 parent 970d4049

feat(icon): added svg icon picker

.vscode/settings.json
... ... @@ -105,17 +105,12 @@
105 105 },
106 106 "stylelint.enable": true,
107 107 "stylelint.packageManager": "yarn",
108   - "css.validate": true,
109   - "less.validate": true,
110   - "scss.validate": true,
111 108 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
112 109 // ===========================================
113 110 // ================ Eslint ===================
114 111 // ===========================================
115   - // "eslint.enable": true,
116 112 "eslint.alwaysShowStatus": true,
117 113 "eslint.options": {
118   - // 配置
119 114 "plugins": ["html", "vue", "javascript", "jsx", "typescript"],
120 115 "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
121 116 },
... ... @@ -127,7 +122,6 @@
127 122 "html",
128 123 "vue"
129 124 ],
130   - // "eslint.autoFixOnSave": true,
131 125 // ===========================================
132 126 // ================ Vetur ====================
133 127 // ===========================================
... ... @@ -139,7 +133,6 @@
139 133 "vetur.format.defaultFormatter.ts": "prettier-tslint",
140 134 "vetur.format.defaultFormatter.js": "prettier",
141 135 "vetur.languageFeatures.codeActions": false,
142   - // "vetur.validation.script": false,
143 136 "vetur.format.defaultFormatterOptions": {
144 137 "js-beautify-html": {
145 138 "wrap_attributes": "force-expand-multiline"
... ... @@ -201,6 +194,6 @@
201 194 "i18n-ally.namespace": true,
202 195 "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
203 196 "i18n-ally.enabledParsers": ["ts"],
204   - "i18n-ally.sourceLanguage": "zh",
  197 + "i18n-ally.sourceLanguage": "en",
205 198 "i18n-ally.enabledFrameworks": ["vue", "react"]
206 199 }
... ...
CHANGELOG.zh_CN.md
1 1 ## Wip
2 2  
  3 +### ✨ Features
  4 +
  5 +- 图标选择器新增 svg 模式
  6 +
3 7 ### ✨ Refactor
4 8  
5 9 - 重构项目以解决循环依赖项导致的热更新问题
... ...
package.json
... ... @@ -53,7 +53,7 @@
53 53 "devDependencies": {
54 54 "@commitlint/cli": "^12.0.1",
55 55 "@commitlint/config-conventional": "^12.0.1",
56   - "@iconify/json": "^1.1.313",
  56 + "@iconify/json": "^1.1.314",
57 57 "@ls-lint/ls-lint": "^1.9.2",
58 58 "@purge-icons/generated": "^0.7.0",
59 59 "@types/crypto-js": "^4.0.1",
... ... @@ -110,7 +110,7 @@
110 110 "vite-plugin-purge-icons": "^0.7.0",
111 111 "vite-plugin-pwa": "^0.5.6",
112 112 "vite-plugin-style-import": "^0.8.1",
113   - "vite-plugin-svg-icons": "^0.3.3",
  113 + "vite-plugin-svg-icons": "^0.3.4",
114 114 "vite-plugin-theme": "^0.4.8",
115 115 "vite-plugin-windicss": "0.7.1",
116 116 "vue-eslint-parser": "^7.6.0",
... ... @@ -120,7 +120,7 @@
120 120 "//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it",
121 121 "bin-wrapper": "npm:bin-wrapper-china",
122 122 "esbuild": "0.8.57",
123   - "rollup": "2.40.0"
  123 + "rollup": "2.41.0"
124 124 },
125 125 "repository": {
126 126 "type": "git",
... ...
src/components/Application/src/search/AppSearch.vue
... ... @@ -13,6 +13,7 @@
13 13 components: { AppSearchModal, Tooltip },
14 14 setup() {
15 15 const showModal = ref(false);
  16 +
16 17 const { getShowSearch } = useHeaderSetting();
17 18 const { t } = useI18n();
18 19  
... ...
src/components/Application/src/search/AppSearchFooter.vue
... ... @@ -14,14 +14,13 @@
14 14  
15 15 <script lang="ts">
16 16 import { defineComponent } from 'vue';
17   - import Icon from '/@/components/Icon';
18 17 import AppSearchKeyItem from './AppSearchKeyItem.vue';
19 18  
20 19 import { useDesign } from '/@/hooks/web/useDesign';
21 20 import { useI18n } from '/@/hooks/web/useI18n';
22 21 export default defineComponent({
23 22 name: 'AppSearchFooter',
24   - components: { Icon, AppSearchKeyItem },
  23 + components: { AppSearchKeyItem },
25 24 setup() {
26 25 const { prefixCls } = useDesign('app-search-footer');
27 26 const { t } = useI18n();
... ...
src/components/Form/src/BasicForm.vue
... ... @@ -47,7 +47,7 @@
47 47 nextTick,
48 48 } from 'vue';
49 49 import { Form, Row } from 'ant-design-vue';
50   - import FormItem from './components/FormItem';
  50 + import FormItem from './components/FormItem.vue';
51 51 import FormAction from './components/FormAction.vue';
52 52  
53 53 import { dateItemType } from './helper';
... ...
src/components/Form/src/components/FormItem.tsx renamed to src/components/Form/src/components/FormItem.vue
1   -import type { PropType, Ref } from 'vue';
2   -import type { FormActionType, FormProps } from '../types/form';
3   -import type { FormSchema } from '../types/form';
4   -import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
5   -import type { TableActionType } from '/@/components/Table';
6   -
7   -import { defineComponent, computed, unref, toRefs } from 'vue';
8   -import { Form, Col } from 'ant-design-vue';
9   -import { componentMap } from '../componentMap';
10   -import { BasicHelp } from '/@/components/Basic';
11   -
12   -import { isBoolean, isFunction } from '/@/utils/is';
13   -import { getSlot } from '/@/utils/helper/tsxHelper';
14   -import { createPlaceholderMessage, setComponentRuleType } from '../helper';
15   -import { upperFirst, cloneDeep } from 'lodash-es';
16   -
17   -import { useItemLabelWidth } from '../hooks/useLabelWidth';
18   -import { useI18n } from '/@/hooks/web/useI18n';
19   -
20   -export default defineComponent({
21   - name: 'BasicFormItem',
22   - inheritAttrs: false,
23   - props: {
24   - schema: {
25   - type: Object as PropType<FormSchema>,
26   - default: () => {},
  1 +<script lang="tsx">
  2 + import type { PropType, Ref } from 'vue';
  3 + import type { FormActionType, FormProps } from '../types/form';
  4 + import type { FormSchema } from '../types/form';
  5 + import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
  6 + import type { TableActionType } from '/@/components/Table';
  7 +
  8 + import { defineComponent, computed, unref, toRefs } from 'vue';
  9 + import { Form, Col } from 'ant-design-vue';
  10 + import { componentMap } from '../componentMap';
  11 + import { BasicHelp } from '/@/components/Basic';
  12 +
  13 + import { isBoolean, isFunction } from '/@/utils/is';
  14 + import { getSlot } from '/@/utils/helper/tsxHelper';
  15 + import { createPlaceholderMessage, setComponentRuleType } from '../helper';
  16 + import { upperFirst, cloneDeep } from 'lodash-es';
  17 +
  18 + import { useItemLabelWidth } from '../hooks/useLabelWidth';
  19 + import { useI18n } from '/@/hooks/web/useI18n';
  20 +
  21 + export default defineComponent({
  22 + name: 'BasicFormItem',
  23 + inheritAttrs: false,
  24 + props: {
  25 + schema: {
  26 + type: Object as PropType<FormSchema>,
  27 + default: () => {},
  28 + },
  29 + formProps: {
  30 + type: Object as PropType<FormProps>,
  31 + default: {},
  32 + },
  33 + allDefaultValues: {
  34 + type: Object as PropType<Recordable>,
  35 + default: {},
  36 + },
  37 + formModel: {
  38 + type: Object as PropType<Recordable>,
  39 + default: {},
  40 + },
  41 + setFormModel: {
  42 + type: Function as PropType<(key: string, value: any) => void>,
  43 + default: null,
  44 + },
  45 + tableAction: {
  46 + type: Object as PropType<TableActionType>,
  47 + },
  48 + formActionType: {
  49 + type: Object as PropType<FormActionType>,
  50 + },
27 51 },
28   - formProps: {
29   - type: Object as PropType<FormProps>,
30   - default: {},
31   - },
32   - allDefaultValues: {
33   - type: Object as PropType<Recordable>,
34   - default: {},
35   - },
36   - formModel: {
37   - type: Object as PropType<Recordable>,
38   - default: {},
39   - },
40   - setFormModel: {
41   - type: Function as PropType<(key: string, value: any) => void>,
42   - default: null,
43   - },
44   - tableAction: {
45   - type: Object as PropType<TableActionType>,
46   - },
47   - formActionType: {
48   - type: Object as PropType<FormActionType>,
49   - },
50   - },
51   - setup(props, { slots }) {
52   - const { t } = useI18n();
53   -
54   - const { schema, formProps } = toRefs(props) as {
55   - schema: Ref<FormSchema>;
56   - formProps: Ref<FormProps>;
57   - };
58   -
59   - const itemLabelWidthProp = useItemLabelWidth(schema, formProps);
60   -
61   - const getValues = computed(() => {
62   - const { allDefaultValues, formModel, schema } = props;
63   - const { mergeDynamicData } = props.formProps;
64   - return {
65   - field: schema.field,
66   - model: formModel,
67   - values: {
68   - ...mergeDynamicData,
69   - ...allDefaultValues,
70   - ...formModel,
71   - } as Recordable,
72   - schema: schema,
  52 + setup(props, { slots }) {
  53 + const { t } = useI18n();
  54 +
  55 + const { schema, formProps } = toRefs(props) as {
  56 + schema: Ref<FormSchema>;
  57 + formProps: Ref<FormProps>;
73 58 };
74   - });
75 59  
76   - const getComponentsProps = computed(() => {
77   - const { schema, tableAction, formModel, formActionType } = props;
78   - const { componentProps = {} } = schema;
79   - if (!isFunction(componentProps)) {
80   - return componentProps;
81   - }
82   - return componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
83   - });
84   -
85   - const getDisable = computed(() => {
86   - const { disabled: globDisabled } = props.formProps;
87   - const { dynamicDisabled } = props.schema;
88   - const { disabled: itemDisabled = false } = unref(getComponentsProps);
89   - let disabled = !!globDisabled || itemDisabled;
90   - if (isBoolean(dynamicDisabled)) {
91   - disabled = dynamicDisabled;
92   - }
  60 + const itemLabelWidthProp = useItemLabelWidth(schema, formProps);
  61 +
  62 + const getValues = computed(() => {
  63 + const { allDefaultValues, formModel, schema } = props;
  64 + const { mergeDynamicData } = props.formProps;
  65 + return {
  66 + field: schema.field,
  67 + model: formModel,
  68 + values: {
  69 + ...mergeDynamicData,
  70 + ...allDefaultValues,
  71 + ...formModel,
  72 + } as Recordable,
  73 + schema: schema,
  74 + };
  75 + });
  76 +
  77 + const getComponentsProps = computed(() => {
  78 + const { schema, tableAction, formModel, formActionType } = props;
  79 + const { componentProps = {} } = schema;
  80 + if (!isFunction(componentProps)) {
  81 + return componentProps;
  82 + }
  83 + return componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
  84 + });
  85 +
  86 + const getDisable = computed(() => {
  87 + const { disabled: globDisabled } = props.formProps;
  88 + const { dynamicDisabled } = props.schema;
  89 + const { disabled: itemDisabled = false } = unref(getComponentsProps);
  90 + let disabled = !!globDisabled || itemDisabled;
  91 + if (isBoolean(dynamicDisabled)) {
  92 + disabled = dynamicDisabled;
  93 + }
93 94  
94   - if (isFunction(dynamicDisabled)) {
95   - disabled = dynamicDisabled(unref(getValues));
96   - }
97   - return disabled;
98   - });
99   -
100   - function getShow(): { isShow: boolean; isIfShow: boolean } {
101   - const { show, ifShow } = props.schema;
102   - const { showAdvancedButton } = props.formProps;
103   - const itemIsAdvanced = showAdvancedButton
104   - ? isBoolean(props.schema.isAdvanced)
105   - ? props.schema.isAdvanced
106   - : true
107   - : true;
108   -
109   - let isShow = true;
110   - let isIfShow = true;
111   -
112   - if (isBoolean(show)) {
113   - isShow = show;
114   - }
115   - if (isBoolean(ifShow)) {
116   - isIfShow = ifShow;
117   - }
118   - if (isFunction(show)) {
119   - isShow = show(unref(getValues));
120   - }
121   - if (isFunction(ifShow)) {
122   - isIfShow = ifShow(unref(getValues));
123   - }
124   - isShow = isShow && itemIsAdvanced;
125   - return { isShow, isIfShow };
126   - }
127   -
128   - function handleRules(): ValidationRule[] {
129   - const {
130   - rules: defRules = [],
131   - component,
132   - rulesMessageJoinLabel,
133   - label,
134   - dynamicRules,
135   - required,
136   - } = props.schema;
137   -
138   - if (isFunction(dynamicRules)) {
139   - return dynamicRules(unref(getValues)) as ValidationRule[];
  95 + if (isFunction(dynamicDisabled)) {
  96 + disabled = dynamicDisabled(unref(getValues));
  97 + }
  98 + return disabled;
  99 + });
  100 +
  101 + function getShow(): { isShow: boolean; isIfShow: boolean } {
  102 + const { show, ifShow } = props.schema;
  103 + const { showAdvancedButton } = props.formProps;
  104 + const itemIsAdvanced = showAdvancedButton
  105 + ? isBoolean(props.schema.isAdvanced)
  106 + ? props.schema.isAdvanced
  107 + : true
  108 + : true;
  109 +
  110 + let isShow = true;
  111 + let isIfShow = true;
  112 +
  113 + if (isBoolean(show)) {
  114 + isShow = show;
  115 + }
  116 + if (isBoolean(ifShow)) {
  117 + isIfShow = ifShow;
  118 + }
  119 + if (isFunction(show)) {
  120 + isShow = show(unref(getValues));
  121 + }
  122 + if (isFunction(ifShow)) {
  123 + isIfShow = ifShow(unref(getValues));
  124 + }
  125 + isShow = isShow && itemIsAdvanced;
  126 + return { isShow, isIfShow };
140 127 }
141 128  
142   - let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
  129 + function handleRules(): ValidationRule[] {
  130 + const {
  131 + rules: defRules = [],
  132 + component,
  133 + rulesMessageJoinLabel,
  134 + label,
  135 + dynamicRules,
  136 + required,
  137 + } = props.schema;
  138 +
  139 + if (isFunction(dynamicRules)) {
  140 + return dynamicRules(unref(getValues)) as ValidationRule[];
  141 + }
143 142  
144   - if ((!rules || rules.length === 0) && required) {
145   - rules = [{ required, type: 'string' }];
146   - }
  143 + let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
147 144  
148   - const requiredRuleIndex: number = rules.findIndex(
149   - (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator')
150   - );
151   - const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
152   - if (requiredRuleIndex !== -1) {
153   - const rule = rules[requiredRuleIndex];
154   - const { isShow } = getShow();
155   - if (!isShow) {
156   - rule.required = false;
  145 + if ((!rules || rules.length === 0) && required) {
  146 + rules = [{ required, type: 'string' }];
157 147 }
158   - if (rule.required && component) {
159   - if (!Reflect.has(rule, 'type')) {
160   - rule.type = 'string';
161   - }
162   - const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
163   - ? rulesMessageJoinLabel
164   - : globalRulesMessageJoinLabel;
165   -
166   - rule.message =
167   - rule.message || createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;
168 148  
169   - if (component.includes('Input') || component.includes('Textarea')) {
170   - rule.whitespace = true;
  149 + const requiredRuleIndex: number = rules.findIndex(
  150 + (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator')
  151 + );
  152 + const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
  153 + if (requiredRuleIndex !== -1) {
  154 + const rule = rules[requiredRuleIndex];
  155 + const { isShow } = getShow();
  156 + if (!isShow) {
  157 + rule.required = false;
  158 + }
  159 + if (rule.required && component) {
  160 + if (!Reflect.has(rule, 'type')) {
  161 + rule.type = 'string';
  162 + }
  163 + const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
  164 + ? rulesMessageJoinLabel
  165 + : globalRulesMessageJoinLabel;
  166 +
  167 + rule.message =
  168 + rule.message || createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;
  169 +
  170 + if (component.includes('Input') || component.includes('Textarea')) {
  171 + rule.whitespace = true;
  172 + }
  173 +
  174 + setComponentRuleType(rule, component);
171 175 }
  176 + }
172 177  
173   - setComponentRuleType(rule, component);
  178 + // Maximum input length rule check
  179 + const characterInx = rules.findIndex((val) => val.max);
  180 + if (characterInx !== -1 && !rules[characterInx].validator) {
  181 + rules[characterInx].message =
  182 + rules[characterInx].message ||
  183 + t('component.form.maxTip', [rules[characterInx].max] as Recordable);
174 184 }
  185 + return rules;
175 186 }
176 187  
177   - // Maximum input length rule check
178   - const characterInx = rules.findIndex((val) => val.max);
179   - if (characterInx !== -1 && !rules[characterInx].validator) {
180   - rules[characterInx].message =
181   - rules[characterInx].message ||
182   - t('component.form.maxTip', [rules[characterInx].max] as Recordable);
183   - }
184   - return rules;
185   - }
186   -
187   - function renderComponent() {
188   - const {
189   - renderComponentContent,
190   - component,
191   - field,
192   - changeEvent = 'change',
193   - valueField,
194   - } = props.schema;
195   -
196   - const isCheck = component && ['Switch', 'Checkbox'].includes(component);
197   -
198   - const eventKey = `on${upperFirst(changeEvent)}`;
199   -
200   - const on = {
201   - [eventKey]: (e: Nullable<Recordable>) => {
202   - if (propsData[eventKey]) {
203   - propsData[eventKey](e);
204   - }
205   -
206   - const target = e ? e.target : null;
207   -
208   - const value = target ? (isCheck ? target.checked : target.value) : e;
209   - props.setFormModel(field, value);
210   - },
211   - };
212   - const Comp = componentMap.get(component) as typeof defineComponent;
213   -
214   - const { autoSetPlaceHolder, size } = props.formProps;
215   - const propsData: Recordable = {
216   - allowClear: true,
217   - getPopupContainer: (trigger: Element) => trigger.parentNode,
218   - size,
219   - ...unref(getComponentsProps),
220   - disabled: unref(getDisable),
221   - };
  188 + function renderComponent() {
  189 + const {
  190 + renderComponentContent,
  191 + component,
  192 + field,
  193 + changeEvent = 'change',
  194 + valueField,
  195 + } = props.schema;
  196 +
  197 + const isCheck = component && ['Switch', 'Checkbox'].includes(component);
  198 +
  199 + const eventKey = `on${upperFirst(changeEvent)}`;
  200 +
  201 + const on = {
  202 + [eventKey]: (e: Nullable<Recordable>) => {
  203 + if (propsData[eventKey]) {
  204 + propsData[eventKey](e);
  205 + }
  206 +
  207 + const target = e ? e.target : null;
  208 +
  209 + const value = target ? (isCheck ? target.checked : target.value) : e;
  210 + props.setFormModel(field, value);
  211 + },
  212 + };
  213 + const Comp = componentMap.get(component) as typeof defineComponent;
  214 +
  215 + const { autoSetPlaceHolder, size } = props.formProps;
  216 + const propsData: Recordable = {
  217 + allowClear: true,
  218 + getPopupContainer: (trigger: Element) => trigger.parentNode,
  219 + size,
  220 + ...unref(getComponentsProps),
  221 + disabled: unref(getDisable),
  222 + };
  223 +
  224 + const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
  225 + let placeholder;
  226 + // RangePicker place is an array
  227 + if (isCreatePlaceholder && component !== 'RangePicker' && component) {
  228 + placeholder =
  229 + unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component);
  230 + }
  231 + propsData.placeholder = placeholder;
  232 + propsData.codeField = field;
  233 + propsData.formValues = unref(getValues);
  234 +
  235 + const bindValue: Recordable = {
  236 + [valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
  237 + };
  238 +
  239 + const compAttr: Recordable = {
  240 + ...propsData,
  241 + ...on,
  242 + ...bindValue,
  243 + };
  244 +
  245 + if (!renderComponentContent) {
  246 + return <Comp {...compAttr} />;
  247 + }
  248 + const compSlot = isFunction(renderComponentContent)
  249 + ? { ...renderComponentContent(unref(getValues)) }
  250 + : {
  251 + default: () => renderComponentContent,
  252 + };
222 253  
223   - const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
224   - let placeholder;
225   - // RangePicker place is an array
226   - if (isCreatePlaceholder && component !== 'RangePicker' && component) {
227   - placeholder = unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component);
  254 + return <Comp {...compAttr}>{compSlot}</Comp>;
228 255 }
229   - propsData.placeholder = placeholder;
230   - propsData.codeField = field;
231   - propsData.formValues = unref(getValues);
232   -
233   - const bindValue: Recordable = {
234   - [valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
235   - };
236 256  
237   - const compAttr: Recordable = {
238   - ...propsData,
239   - ...on,
240   - ...bindValue,
241   - };
242   -
243   - if (!renderComponentContent) {
244   - return <Comp {...compAttr} />;
245   - }
246   - const compSlot = isFunction(renderComponentContent)
247   - ? { ...renderComponentContent(unref(getValues)) }
248   - : {
249   - default: () => renderComponentContent,
250   - };
251   -
252   - return <Comp {...compAttr}>{compSlot}</Comp>;
253   - }
254   -
255   - function renderLabelHelpMessage() {
256   - const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
257   - const renderLabel = subLabel ? (
258   - <span>
259   - {label} <span style="color:#00000073">{subLabel}</span>
260   - </span>
261   - ) : (
262   - label
263   - );
264   - if (!helpMessage || (Array.isArray(helpMessage) && helpMessage.length === 0)) {
265   - return renderLabel;
  257 + function renderLabelHelpMessage() {
  258 + const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
  259 + const renderLabel = subLabel ? (
  260 + <span>
  261 + {label} <span style="color:#00000073">{subLabel}</span>
  262 + </span>
  263 + ) : (
  264 + label
  265 + );
  266 + if (!helpMessage || (Array.isArray(helpMessage) && helpMessage.length === 0)) {
  267 + return renderLabel;
  268 + }
  269 + return (
  270 + <span>
  271 + {renderLabel}
  272 + <BasicHelp placement="top" class="mx-1" text={helpMessage} {...helpComponentProps} />
  273 + </span>
  274 + );
266 275 }
267   - return (
268   - <span>
269   - {renderLabel}
270   - <BasicHelp placement="top" class="mx-1" text={helpMessage} {...helpComponentProps} />
271   - </span>
272   - );
273   - }
274   -
275   - function renderItem() {
276   - const { itemProps, slot, render, field, suffix } = props.schema;
277   - const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
278   - const { colon } = props.formProps;
279   -
280   - const getContent = () => {
281   - return slot
282   - ? getSlot(slots, slot, unref(getValues))
283   - : render
284   - ? render(unref(getValues))
285   - : renderComponent();
286   - };
287 276  
288   - const showSuffix = !!suffix;
289   -
290   - const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
291   -
292   - return (
293   - <Form.Item
294   - name={field}
295   - colon={colon}
296   - class={{ 'suffix-item': showSuffix }}
297   - {...(itemProps as Recordable)}
298   - label={renderLabelHelpMessage()}
299   - rules={handleRules()}
300   - labelCol={labelCol}
301   - wrapperCol={wrapperCol}
302   - >
303   - <>
304   - {getContent()}
305   - {showSuffix && <span class="suffix">{getSuffix}</span>}
306   - </>
307   - </Form.Item>
308   - );
309   - }
310   - return () => {
311   - const { colProps = {}, colSlot, renderColContent, component } = props.schema;
312   - if (!componentMap.has(component)) return null;
313   -
314   - const { baseColProps = {} } = props.formProps;
315   -
316   - const realColProps = { ...baseColProps, ...colProps };
317   - const { isIfShow, isShow } = getShow();
318   -
319   - const values = unref(getValues);
320   - const getContent = () => {
321   - return colSlot
322   - ? getSlot(slots, colSlot, values)
323   - : renderColContent
324   - ? renderColContent(values)
325   - : renderItem();
  277 + function renderItem() {
  278 + const { itemProps, slot, render, field, suffix } = props.schema;
  279 + const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
  280 + const { colon } = props.formProps;
  281 +
  282 + const getContent = () => {
  283 + return slot
  284 + ? getSlot(slots, slot, unref(getValues))
  285 + : render
  286 + ? render(unref(getValues))
  287 + : renderComponent();
  288 + };
  289 +
  290 + const showSuffix = !!suffix;
  291 +
  292 + const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
  293 +
  294 + return (
  295 + <Form.Item
  296 + name={field}
  297 + colon={colon}
  298 + class={{ 'suffix-item': showSuffix }}
  299 + {...(itemProps as Recordable)}
  300 + label={renderLabelHelpMessage()}
  301 + rules={handleRules()}
  302 + labelCol={labelCol}
  303 + wrapperCol={wrapperCol}
  304 + >
  305 + <>
  306 + {getContent()}
  307 + {showSuffix && <span class="suffix">{getSuffix}</span>}
  308 + </>
  309 + </Form.Item>
  310 + );
  311 + }
  312 + return () => {
  313 + const { colProps = {}, colSlot, renderColContent, component } = props.schema;
  314 + if (!componentMap.has(component)) return null;
  315 +
  316 + const { baseColProps = {} } = props.formProps;
  317 +
  318 + const realColProps = { ...baseColProps, ...colProps };
  319 + const { isIfShow, isShow } = getShow();
  320 +
  321 + const values = unref(getValues);
  322 + const getContent = () => {
  323 + return colSlot
  324 + ? getSlot(slots, colSlot, values)
  325 + : renderColContent
  326 + ? renderColContent(values)
  327 + : renderItem();
  328 + };
  329 +
  330 + return (
  331 + isIfShow && (
  332 + <Col {...realColProps} v-show={isShow}>
  333 + {getContent()}
  334 + </Col>
  335 + )
  336 + );
326 337 };
327   -
328   - return (
329   - isIfShow && (
330   - <Col {...realColProps} v-show={isShow}>
331   - {getContent()}
332   - </Col>
333   - )
334   - );
335   - };
336   - },
337   -});
  338 + },
  339 + });
  340 +</script>
... ...
src/components/Icon/src/IconPicker.vue
... ... @@ -30,16 +30,17 @@
30 30 <li
31 31 v-for="icon in getPaginationList"
32 32 :key="icon"
33   - :class="currentSelect === icon ? 'bg-primary text-white' : ''"
34   - 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"
  33 + :class="currentSelect === icon ? 'border border-primary' : ''"
  34 + class="p-2 w-1/8 cursor-pointer mr-1 mt-1 flex justify-center items-center border border-solid hover:border-primary"
35 35 @click="handleClick(icon)"
36 36 >
37 37 <!-- <Icon :icon="icon" :prefix="prefix" /> -->
38   - <Icon :icon="icon" />
  38 + <SvgIcon v-if="isSvgMode" :name="icon" />
  39 + <Icon :icon="icon" v-else />
39 40 </li>
40 41 </ul>
41 42 </ScrollContainer>
42   - <div class="flex py-2 items-center justify-center">
  43 + <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
43 44 <Pagination
44 45 showLessItems
45 46 size="small"
... ... @@ -53,7 +54,11 @@
53 54 ><div class="p-5"> <Empty /></div>
54 55 </template>
55 56 </template>
56   - <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" />
  57 +
  58 + <span class="cursor-pointer px-2 py-1 flex items-center" v-if="isSvgMode && currentSelect">
  59 + <SvgIcon :name="currentSelect" />
  60 + </span>
  61 + <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
57 62 </Popover>
58 63 </template>
59 64 </a-input>
... ... @@ -66,6 +71,7 @@
66 71  
67 72 import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
68 73 import Icon from './index.vue';
  74 + import SvgIcon from './SvgIcon.vue';
69 75  
70 76 import iconsData from '../data/icons.data';
71 77 import { propTypes } from '/@/utils/propTypes';
... ... @@ -74,7 +80,7 @@
74 80 import { useI18n } from '/@/hooks/web/useI18n';
75 81 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
76 82 import { useMessage } from '/@/hooks/web/useMessage';
77   - // import '@iconify/iconify';
  83 + import svgIcons from 'vite-plugin-svg-icons/client';
78 84  
79 85 function getIcons() {
80 86 const data = iconsData as any;
... ... @@ -88,25 +94,35 @@
88 94 return result;
89 95 }
90 96  
91   - const icons = getIcons();
  97 + function getSvgIcons() {
  98 + return svgIcons.map((icon) => icon.replace('icon-', ''));
  99 + }
  100 +
92 101 export default defineComponent({
93 102 name: 'IconPicker',
94   - components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty },
  103 + components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty, SvgIcon },
95 104 inheritAttrs: false,
96 105 props: {
97 106 value: propTypes.string,
98 107 width: propTypes.string.def('100%'),
99 108 pageSize: propTypes.number.def(140),
100 109 copy: propTypes.bool.def(false),
  110 + mode: propTypes
  111 + .oneOf<('svg' | 'iconify')[]>(['svg', 'iconify'])
  112 + .def('iconify'),
101 113 },
102 114 emits: ['change'],
103 115 setup(props, { emit }) {
  116 + const isSvgMode = props.mode === 'svg';
  117 + const icons = isSvgMode ? getSvgIcons() : getIcons();
  118 +
104 119 const currentSelect = ref('');
105 120 const visible = ref(false);
106 121 const currentList = ref(icons);
107 122  
108   - const { prefixCls } = useDesign('icon-picker');
109 123 const { t } = useI18n();
  124 + const { prefixCls } = useDesign('icon-picker');
  125 +
110 126 const [debounceHandleSearchChange] = useDebounce(handleSearchChange, 100);
111 127 const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
112 128 const { createMessage } = useMessage();
... ... @@ -153,6 +169,7 @@
153 169 t,
154 170 prefixCls,
155 171 visible,
  172 + isSvgMode,
156 173 getTotal,
157 174 getPaginationList,
158 175 handlePageChange,
... ...
src/components/Tree/src/TreeHeader.vue
... ... @@ -24,7 +24,7 @@
24 24 </template>
25 25 <script lang="ts">
26 26 import type { PropType } from 'vue';
27   - import { defineComponent, ref, computed } from 'vue';
  27 + import { defineComponent, computed } from 'vue';
28 28  
29 29 import { Dropdown, Menu, Input } from 'ant-design-vue';
30 30 import { Icon } from '/@/components/Icon';
... ...
src/design/index.less
... ... @@ -37,6 +37,7 @@ a:focus,
37 37 a:active,
38 38 button,
39 39 div,
  40 +svg,
40 41 span {
41 42 outline: none !important;
42 43 }
... ...
src/views/demo/feat/icon/index.vue
... ... @@ -21,18 +21,24 @@
21 21 </div>
22 22 </CollapseContainer>
23 23  
24   - <CollapseContainer title="svg Sprite" class="my-5">
  24 + <CollapseContainer title="svg 雪碧图" class="my-5">
25 25 <div class="flex justify-around flex-wrap">
26 26 <SvgIcon name="test" size="32" />
27 27 </div>
28 28 </CollapseContainer>
29 29  
30   - <CollapseContainer title="图标选择器" class="my-5">
  30 + <CollapseContainer title="图标选择器(Iconify)" class="my-5">
31 31 <div class="flex justify-around flex-wrap">
32 32 <IconPicker />
33 33 </div>
34 34 </CollapseContainer>
35 35  
  36 + <CollapseContainer title="图标选择器(Svg)" class="my-5">
  37 + <div class="flex justify-around flex-wrap">
  38 + <IconPicker mode="svg" />
  39 + </div>
  40 + </CollapseContainer>
  41 +
36 42 <Alert
37 43 show-icon
38 44 message="推荐使用Iconify组件"
... ...
yarn.lock
... ... @@ -1117,10 +1117,10 @@
1117 1117 dependencies:
1118 1118 cross-fetch "^3.0.6"
1119 1119  
1120   -"@iconify/json@^1.1.313":
1121   - version "1.1.313"
1122   - resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.313.tgz#c225be3c5ce3280a2c34e753a65dc257b85b6652"
1123   - integrity sha512-gv00rSX4apKE0i/fUjXp5+sBb8LHzzdJqrXkBNVby7Nl7yzRqeQ/EyY+7ixtSpEu3f1P/co/vrgdbZN6wlw6DA==
  1120 +"@iconify/json@^1.1.314":
  1121 + version "1.1.314"
  1122 + resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.314.tgz#43b417e5131b55e879f94b6fc40b09928eea42ad"
  1123 + integrity sha512-KDc2dtNnbUryuUWs4ov1e8xCcEjrU/9r3PLOsElzsRpMjaGe/RfpAvU1NkDlv7Mmriaah+Dj6SVoLeRSUB5q3g==
1124 1124  
1125 1125 "@intlify/core-base@9.0.0":
1126 1126 version "9.0.0"
... ... @@ -7680,10 +7680,10 @@ rollup-plugin-visualizer@^4.2.0:
7680 7680 source-map "^0.7.3"
7681 7681 yargs "^16.0.3"
7682 7682  
7683   -rollup@2.40.0, rollup@^0.63.4, rollup@^2.25.0, rollup@^2.38.5, rollup@^2.40.0:
7684   - version "2.40.0"
7685   - resolved "https://registry.npmjs.org/rollup/-/rollup-2.40.0.tgz#efc218eaede7ab590954df50f96195188999c304"
7686   - integrity sha512-WiOGAPbXoHu+TOz6hyYUxIksOwsY/21TRWoO593jgYt8mvYafYqQl+axaA8y1z2HFazNUUrsMSjahV2A6/2R9A==
  7683 +rollup@2.41.0, rollup@^0.63.4, rollup@^2.25.0, rollup@^2.38.5, rollup@^2.40.0:
  7684 + version "2.41.0"
  7685 + resolved "https://registry.npmjs.org/rollup/-/rollup-2.41.0.tgz#b2a398bbabbf227738dedaef099e494aed468982"
  7686 + integrity sha512-Gk76XHTggulWPH95q8V62bw6uqDH6UGvbD6LOa3QUyhuMF3eOuaeDHR7SLm1T9faitkpNrqzUAVYx47klcMnlA==
7687 7687 optionalDependencies:
7688 7688 fsevents "~2.3.1"
7689 7689  
... ... @@ -9160,10 +9160,10 @@ vite-plugin-style-import@^0.8.1:
9160 9160 es-module-lexer "^0.4.1"
9161 9161 magic-string "^0.25.7"
9162 9162  
9163   -vite-plugin-svg-icons@^0.3.3:
9164   - version "0.3.3"
9165   - resolved "https://registry.npmjs.org/vite-plugin-svg-icons/-/vite-plugin-svg-icons-0.3.3.tgz#b699e1af244500d893cc32b48a772492c1fae72b"
9166   - integrity sha512-ZI3FLspeM3PV0OE503m7/11jW5aSSCwxXUEcJZL3RwSYmpkLE0cSsM7UFZf0tx3cRoSB/JpeOlRIRH6G2BhWiQ==
  9163 +vite-plugin-svg-icons@^0.3.4:
  9164 + version "0.3.4"
  9165 + resolved "https://registry.npmjs.org/vite-plugin-svg-icons/-/vite-plugin-svg-icons-0.3.4.tgz#505aacff35f19d4e1c81f05a85bded0d6f1f6323"
  9166 + integrity sha512-N4KYqmyF/gnsYIBxvMTyotjWSdur/6EyycE6eJvM2m7oHHxe8Y+SZZlD+XTz8Nl+zfurXYDkrbbHAdtWlpJovw==
9167 9167 dependencies:
9168 9168 debug "^4.3.2"
9169 9169 etag "^1.8.1"
... ...