Commit 1418dc6a597a8410711359f07ae66f0fea858977

Authored by Vben
1 parent 970d4049

feat(icon): added svg icon picker

.vscode/settings.json
@@ -105,17 +105,12 @@ @@ -105,17 +105,12 @@
105 }, 105 },
106 "stylelint.enable": true, 106 "stylelint.enable": true,
107 "stylelint.packageManager": "yarn", 107 "stylelint.packageManager": "yarn",
108 - "css.validate": true,  
109 - "less.validate": true,  
110 - "scss.validate": true,  
111 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 108 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
112 // =========================================== 109 // ===========================================
113 // ================ Eslint =================== 110 // ================ Eslint ===================
114 // =========================================== 111 // ===========================================
115 - // "eslint.enable": true,  
116 "eslint.alwaysShowStatus": true, 112 "eslint.alwaysShowStatus": true,
117 "eslint.options": { 113 "eslint.options": {
118 - // 配置  
119 "plugins": ["html", "vue", "javascript", "jsx", "typescript"], 114 "plugins": ["html", "vue", "javascript", "jsx", "typescript"],
120 "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"] 115 "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
121 }, 116 },
@@ -127,7 +122,6 @@ @@ -127,7 +122,6 @@
127 "html", 122 "html",
128 "vue" 123 "vue"
129 ], 124 ],
130 - // "eslint.autoFixOnSave": true,  
131 // =========================================== 125 // ===========================================
132 // ================ Vetur ==================== 126 // ================ Vetur ====================
133 // =========================================== 127 // ===========================================
@@ -139,7 +133,6 @@ @@ -139,7 +133,6 @@
139 "vetur.format.defaultFormatter.ts": "prettier-tslint", 133 "vetur.format.defaultFormatter.ts": "prettier-tslint",
140 "vetur.format.defaultFormatter.js": "prettier", 134 "vetur.format.defaultFormatter.js": "prettier",
141 "vetur.languageFeatures.codeActions": false, 135 "vetur.languageFeatures.codeActions": false,
142 - // "vetur.validation.script": false,  
143 "vetur.format.defaultFormatterOptions": { 136 "vetur.format.defaultFormatterOptions": {
144 "js-beautify-html": { 137 "js-beautify-html": {
145 "wrap_attributes": "force-expand-multiline" 138 "wrap_attributes": "force-expand-multiline"
@@ -201,6 +194,6 @@ @@ -201,6 +194,6 @@
201 "i18n-ally.namespace": true, 194 "i18n-ally.namespace": true,
202 "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}", 195 "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
203 "i18n-ally.enabledParsers": ["ts"], 196 "i18n-ally.enabledParsers": ["ts"],
204 - "i18n-ally.sourceLanguage": "zh", 197 + "i18n-ally.sourceLanguage": "en",
205 "i18n-ally.enabledFrameworks": ["vue", "react"] 198 "i18n-ally.enabledFrameworks": ["vue", "react"]
206 } 199 }
CHANGELOG.zh_CN.md
1 ## Wip 1 ## Wip
2 2
  3 +### ✨ Features
  4 +
  5 +- 图标选择器新增 svg 模式
  6 +
3 ### ✨ Refactor 7 ### ✨ Refactor
4 8
5 - 重构项目以解决循环依赖项导致的热更新问题 9 - 重构项目以解决循环依赖项导致的热更新问题
package.json
@@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
53 "devDependencies": { 53 "devDependencies": {
54 "@commitlint/cli": "^12.0.1", 54 "@commitlint/cli": "^12.0.1",
55 "@commitlint/config-conventional": "^12.0.1", 55 "@commitlint/config-conventional": "^12.0.1",
56 - "@iconify/json": "^1.1.313", 56 + "@iconify/json": "^1.1.314",
57 "@ls-lint/ls-lint": "^1.9.2", 57 "@ls-lint/ls-lint": "^1.9.2",
58 "@purge-icons/generated": "^0.7.0", 58 "@purge-icons/generated": "^0.7.0",
59 "@types/crypto-js": "^4.0.1", 59 "@types/crypto-js": "^4.0.1",
@@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
110 "vite-plugin-purge-icons": "^0.7.0", 110 "vite-plugin-purge-icons": "^0.7.0",
111 "vite-plugin-pwa": "^0.5.6", 111 "vite-plugin-pwa": "^0.5.6",
112 "vite-plugin-style-import": "^0.8.1", 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 "vite-plugin-theme": "^0.4.8", 114 "vite-plugin-theme": "^0.4.8",
115 "vite-plugin-windicss": "0.7.1", 115 "vite-plugin-windicss": "0.7.1",
116 "vue-eslint-parser": "^7.6.0", 116 "vue-eslint-parser": "^7.6.0",
@@ -120,7 +120,7 @@ @@ -120,7 +120,7 @@
120 "//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it", 120 "//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it",
121 "bin-wrapper": "npm:bin-wrapper-china", 121 "bin-wrapper": "npm:bin-wrapper-china",
122 "esbuild": "0.8.57", 122 "esbuild": "0.8.57",
123 - "rollup": "2.40.0" 123 + "rollup": "2.41.0"
124 }, 124 },
125 "repository": { 125 "repository": {
126 "type": "git", 126 "type": "git",
src/components/Application/src/search/AppSearch.vue
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 components: { AppSearchModal, Tooltip }, 13 components: { AppSearchModal, Tooltip },
14 setup() { 14 setup() {
15 const showModal = ref(false); 15 const showModal = ref(false);
  16 +
16 const { getShowSearch } = useHeaderSetting(); 17 const { getShowSearch } = useHeaderSetting();
17 const { t } = useI18n(); 18 const { t } = useI18n();
18 19
src/components/Application/src/search/AppSearchFooter.vue
@@ -14,14 +14,13 @@ @@ -14,14 +14,13 @@
14 14
15 <script lang="ts"> 15 <script lang="ts">
16 import { defineComponent } from 'vue'; 16 import { defineComponent } from 'vue';
17 - import Icon from '/@/components/Icon';  
18 import AppSearchKeyItem from './AppSearchKeyItem.vue'; 17 import AppSearchKeyItem from './AppSearchKeyItem.vue';
19 18
20 import { useDesign } from '/@/hooks/web/useDesign'; 19 import { useDesign } from '/@/hooks/web/useDesign';
21 import { useI18n } from '/@/hooks/web/useI18n'; 20 import { useI18n } from '/@/hooks/web/useI18n';
22 export default defineComponent({ 21 export default defineComponent({
23 name: 'AppSearchFooter', 22 name: 'AppSearchFooter',
24 - components: { Icon, AppSearchKeyItem }, 23 + components: { AppSearchKeyItem },
25 setup() { 24 setup() {
26 const { prefixCls } = useDesign('app-search-footer'); 25 const { prefixCls } = useDesign('app-search-footer');
27 const { t } = useI18n(); 26 const { t } = useI18n();
src/components/Form/src/BasicForm.vue
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 nextTick, 47 nextTick,
48 } from 'vue'; 48 } from 'vue';
49 import { Form, Row } from 'ant-design-vue'; 49 import { Form, Row } from 'ant-design-vue';
50 - import FormItem from './components/FormItem'; 50 + import FormItem from './components/FormItem.vue';
51 import FormAction from './components/FormAction.vue'; 51 import FormAction from './components/FormAction.vue';
52 52
53 import { dateItemType } from './helper'; 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,16 +30,17 @@
30 <li 30 <li
31 v-for="icon in getPaginationList" 31 v-for="icon in getPaginationList"
32 :key="icon" 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 @click="handleClick(icon)" 35 @click="handleClick(icon)"
36 > 36 >
37 <!-- <Icon :icon="icon" :prefix="prefix" /> --> 37 <!-- <Icon :icon="icon" :prefix="prefix" /> -->
38 - <Icon :icon="icon" /> 38 + <SvgIcon v-if="isSvgMode" :name="icon" />
  39 + <Icon :icon="icon" v-else />
39 </li> 40 </li>
40 </ul> 41 </ul>
41 </ScrollContainer> 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 <Pagination 44 <Pagination
44 showLessItems 45 showLessItems
45 size="small" 46 size="small"
@@ -53,7 +54,11 @@ @@ -53,7 +54,11 @@
53 ><div class="p-5"> <Empty /></div> 54 ><div class="p-5"> <Empty /></div>
54 </template> 55 </template>
55 </template> 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 </Popover> 62 </Popover>
58 </template> 63 </template>
59 </a-input> 64 </a-input>
@@ -66,6 +71,7 @@ @@ -66,6 +71,7 @@
66 71
67 import { Input, Popover, Pagination, Empty } from 'ant-design-vue'; 72 import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
68 import Icon from './index.vue'; 73 import Icon from './index.vue';
  74 + import SvgIcon from './SvgIcon.vue';
69 75
70 import iconsData from '../data/icons.data'; 76 import iconsData from '../data/icons.data';
71 import { propTypes } from '/@/utils/propTypes'; 77 import { propTypes } from '/@/utils/propTypes';
@@ -74,7 +80,7 @@ @@ -74,7 +80,7 @@
74 import { useI18n } from '/@/hooks/web/useI18n'; 80 import { useI18n } from '/@/hooks/web/useI18n';
75 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; 81 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
76 import { useMessage } from '/@/hooks/web/useMessage'; 82 import { useMessage } from '/@/hooks/web/useMessage';
77 - // import '@iconify/iconify'; 83 + import svgIcons from 'vite-plugin-svg-icons/client';
78 84
79 function getIcons() { 85 function getIcons() {
80 const data = iconsData as any; 86 const data = iconsData as any;
@@ -88,25 +94,35 @@ @@ -88,25 +94,35 @@
88 return result; 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 export default defineComponent({ 101 export default defineComponent({
93 name: 'IconPicker', 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 inheritAttrs: false, 104 inheritAttrs: false,
96 props: { 105 props: {
97 value: propTypes.string, 106 value: propTypes.string,
98 width: propTypes.string.def('100%'), 107 width: propTypes.string.def('100%'),
99 pageSize: propTypes.number.def(140), 108 pageSize: propTypes.number.def(140),
100 copy: propTypes.bool.def(false), 109 copy: propTypes.bool.def(false),
  110 + mode: propTypes
  111 + .oneOf<('svg' | 'iconify')[]>(['svg', 'iconify'])
  112 + .def('iconify'),
101 }, 113 },
102 emits: ['change'], 114 emits: ['change'],
103 setup(props, { emit }) { 115 setup(props, { emit }) {
  116 + const isSvgMode = props.mode === 'svg';
  117 + const icons = isSvgMode ? getSvgIcons() : getIcons();
  118 +
104 const currentSelect = ref(''); 119 const currentSelect = ref('');
105 const visible = ref(false); 120 const visible = ref(false);
106 const currentList = ref(icons); 121 const currentList = ref(icons);
107 122
108 - const { prefixCls } = useDesign('icon-picker');  
109 const { t } = useI18n(); 123 const { t } = useI18n();
  124 + const { prefixCls } = useDesign('icon-picker');
  125 +
110 const [debounceHandleSearchChange] = useDebounce(handleSearchChange, 100); 126 const [debounceHandleSearchChange] = useDebounce(handleSearchChange, 100);
111 const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value); 127 const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
112 const { createMessage } = useMessage(); 128 const { createMessage } = useMessage();
@@ -153,6 +169,7 @@ @@ -153,6 +169,7 @@
153 t, 169 t,
154 prefixCls, 170 prefixCls,
155 visible, 171 visible,
  172 + isSvgMode,
156 getTotal, 173 getTotal,
157 getPaginationList, 174 getPaginationList,
158 handlePageChange, 175 handlePageChange,
src/components/Tree/src/TreeHeader.vue
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 </template> 24 </template>
25 <script lang="ts"> 25 <script lang="ts">
26 import type { PropType } from 'vue'; 26 import type { PropType } from 'vue';
27 - import { defineComponent, ref, computed } from 'vue'; 27 + import { defineComponent, computed } from 'vue';
28 28
29 import { Dropdown, Menu, Input } from 'ant-design-vue'; 29 import { Dropdown, Menu, Input } from 'ant-design-vue';
30 import { Icon } from '/@/components/Icon'; 30 import { Icon } from '/@/components/Icon';
src/design/index.less
@@ -37,6 +37,7 @@ a:focus, @@ -37,6 +37,7 @@ a:focus,
37 a:active, 37 a:active,
38 button, 38 button,
39 div, 39 div,
  40 +svg,
40 span { 41 span {
41 outline: none !important; 42 outline: none !important;
42 } 43 }
src/views/demo/feat/icon/index.vue
@@ -21,18 +21,24 @@ @@ -21,18 +21,24 @@
21 </div> 21 </div>
22 </CollapseContainer> 22 </CollapseContainer>
23 23
24 - <CollapseContainer title="svg Sprite" class="my-5"> 24 + <CollapseContainer title="svg 雪碧图" class="my-5">
25 <div class="flex justify-around flex-wrap"> 25 <div class="flex justify-around flex-wrap">
26 <SvgIcon name="test" size="32" /> 26 <SvgIcon name="test" size="32" />
27 </div> 27 </div>
28 </CollapseContainer> 28 </CollapseContainer>
29 29
30 - <CollapseContainer title="图标选择器" class="my-5"> 30 + <CollapseContainer title="图标选择器(Iconify)" class="my-5">
31 <div class="flex justify-around flex-wrap"> 31 <div class="flex justify-around flex-wrap">
32 <IconPicker /> 32 <IconPicker />
33 </div> 33 </div>
34 </CollapseContainer> 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 <Alert 42 <Alert
37 show-icon 43 show-icon
38 message="推荐使用Iconify组件" 44 message="推荐使用Iconify组件"
yarn.lock
@@ -1117,10 +1117,10 @@ @@ -1117,10 +1117,10 @@
1117 dependencies: 1117 dependencies:
1118 cross-fetch "^3.0.6" 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 "@intlify/core-base@9.0.0": 1125 "@intlify/core-base@9.0.0":
1126 version "9.0.0" 1126 version "9.0.0"
@@ -7680,10 +7680,10 @@ rollup-plugin-visualizer@^4.2.0: @@ -7680,10 +7680,10 @@ rollup-plugin-visualizer@^4.2.0:
7680 source-map "^0.7.3" 7680 source-map "^0.7.3"
7681 yargs "^16.0.3" 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 optionalDependencies: 7687 optionalDependencies:
7688 fsevents "~2.3.1" 7688 fsevents "~2.3.1"
7689 7689
@@ -9160,10 +9160,10 @@ vite-plugin-style-import@^0.8.1: @@ -9160,10 +9160,10 @@ vite-plugin-style-import@^0.8.1:
9160 es-module-lexer "^0.4.1" 9160 es-module-lexer "^0.4.1"
9161 magic-string "^0.25.7" 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 dependencies: 9167 dependencies:
9168 debug "^4.3.2" 9168 debug "^4.3.2"
9169 etag "^1.8.1" 9169 etag "^1.8.1"