@aspire-ui/element-component-pro 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/ProForm/FormattedNumberInput.vue.d.ts +55 -0
- package/dist/ProForm/ProForm.vue.d.ts +7 -0
- package/dist/ProForm/ProFormItem.vue.d.ts +2 -0
- package/dist/ProForm/index.d.ts +2 -1
- package/dist/element-component-pro.es.js +966 -759
- package/dist/element-component-pro.es.js.map +1 -1
- package/dist/element-component-pro.umd.js +2 -2
- package/dist/element-component-pro.umd.js.map +1 -1
- package/dist/index.d.ts +130 -50
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +13 -2
- package/dist/utils/formattedNumber.d.ts +16 -0
- package/dist/utils/tooltip.d.ts +4 -0
- package/package.json +2 -1
- package/src/ProDescriptions/ProDescriptions.vue +24 -6
- package/src/ProForm/FormattedNumberInput.vue +122 -0
- package/src/ProForm/ProForm.vue +3 -1
- package/src/ProForm/ProFormItem.vue +155 -123
- package/src/ProForm/index.ts +2 -1
- package/src/ProTable/TableAction.vue +2 -5
- package/src/index.ts +5 -2
- package/src/types/index.ts +9 -1
- package/src/utils/formattedNumber.ts +118 -0
- package/src/utils/tooltip.ts +56 -0
- package/src/vite-env.d.ts +5 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-input
|
|
3
|
+
:value="displayText"
|
|
4
|
+
:placeholder="placeholder"
|
|
5
|
+
:disabled="disabled"
|
|
6
|
+
v-bind="$attrs"
|
|
7
|
+
@input="onInput"
|
|
8
|
+
@focus="onFocus"
|
|
9
|
+
@blur="onBlur"
|
|
10
|
+
/>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { ref, watch } from 'vue'
|
|
15
|
+
import type { FormattedNumberRounding } from '../utils/formattedNumber'
|
|
16
|
+
import {
|
|
17
|
+
formatWithThousands,
|
|
18
|
+
normalizeNumericValue,
|
|
19
|
+
numberToEditString,
|
|
20
|
+
sanitizeNumericInput,
|
|
21
|
+
stripNumberGrouping,
|
|
22
|
+
} from '../utils/formattedNumber'
|
|
23
|
+
|
|
24
|
+
const props = withDefaults(
|
|
25
|
+
defineProps<{
|
|
26
|
+
value?: unknown
|
|
27
|
+
placeholder?: string
|
|
28
|
+
disabled?: boolean
|
|
29
|
+
/** 整数部分允许的最大位数,默认 5 */
|
|
30
|
+
integerDigits?: number
|
|
31
|
+
/** 小数保留位数,默认 6 */
|
|
32
|
+
decimalPlaces?: number
|
|
33
|
+
/** 进位方式,默认四舍五入 */
|
|
34
|
+
rounding?: FormattedNumberRounding
|
|
35
|
+
}>(),
|
|
36
|
+
{
|
|
37
|
+
integerDigits: 5,
|
|
38
|
+
decimalPlaces: 6,
|
|
39
|
+
rounding: 'round',
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const emit = defineEmits<{ (e: 'input', value: unknown): void }>()
|
|
44
|
+
|
|
45
|
+
const focused = ref(false)
|
|
46
|
+
const displayText = ref('')
|
|
47
|
+
|
|
48
|
+
const intN = () => Math.max(0, Math.floor(props.integerDigits ?? 5))
|
|
49
|
+
const decM = () => Math.max(0, Math.floor(props.decimalPlaces ?? 6))
|
|
50
|
+
|
|
51
|
+
function parseExternalToNumber(v: unknown): number | null {
|
|
52
|
+
if (v === null || v === undefined || v === '') return null
|
|
53
|
+
if (typeof v === 'number') {
|
|
54
|
+
return Number.isFinite(v) ? v : null
|
|
55
|
+
}
|
|
56
|
+
const s = stripNumberGrouping(String(v))
|
|
57
|
+
if (s === '' || s === '-') return null
|
|
58
|
+
const num = Number(s)
|
|
59
|
+
return Number.isFinite(num) ? num : null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function syncDisplayFromValue() {
|
|
63
|
+
if (focused.value) return
|
|
64
|
+
const num = parseExternalToNumber(props.value)
|
|
65
|
+
if (num === null) {
|
|
66
|
+
displayText.value = ''
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
displayText.value = formatWithThousands(
|
|
70
|
+
normalizeNumericValue(num, intN(), decM(), props.rounding),
|
|
71
|
+
decM()
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
watch(
|
|
76
|
+
() => [props.value, props.integerDigits, props.decimalPlaces, props.rounding],
|
|
77
|
+
() => syncDisplayFromValue(),
|
|
78
|
+
{ immediate: true, deep: true }
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
function onInput(val: string) {
|
|
82
|
+
const clean = sanitizeNumericInput(val)
|
|
83
|
+
displayText.value = clean
|
|
84
|
+
if (clean === '' || clean === '-') return
|
|
85
|
+
const num = Number(clean)
|
|
86
|
+
if (!Number.isFinite(num)) return
|
|
87
|
+
emit('input', num)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function onFocus() {
|
|
91
|
+
focused.value = true
|
|
92
|
+
const raw = stripNumberGrouping(displayText.value)
|
|
93
|
+
const num = parseExternalToNumber(raw === '' ? props.value : raw)
|
|
94
|
+
if (num === null) {
|
|
95
|
+
displayText.value = ''
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
displayText.value = numberToEditString(
|
|
99
|
+
normalizeNumericValue(num, intN(), decM(), props.rounding),
|
|
100
|
+
decM()
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function onBlur() {
|
|
105
|
+
focused.value = false
|
|
106
|
+
const raw = stripNumberGrouping(displayText.value)
|
|
107
|
+
if (raw === '' || raw === '-') {
|
|
108
|
+
displayText.value = ''
|
|
109
|
+
emit('input', undefined)
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
const parsed = Number(sanitizeNumericInput(raw))
|
|
113
|
+
if (!Number.isFinite(parsed)) {
|
|
114
|
+
displayText.value = ''
|
|
115
|
+
emit('input', undefined)
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
const final = normalizeNumericValue(parsed, intN(), decM(), props.rounding)
|
|
119
|
+
displayText.value = formatWithThousands(final, decM())
|
|
120
|
+
emit('input', final)
|
|
121
|
+
}
|
|
122
|
+
</script>
|
package/src/ProForm/ProForm.vue
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<el-col v-if="shouldShow(schema)" :key="schema.field" v-bind="getColProps(schema)"
|
|
10
10
|
:offset="schema.colProps?.offset ?? effectiveProps.baseColProps?.offset ?? 0" :data-field="schema.field">
|
|
11
11
|
<ProFormItem :schema="schema" :form-model="currentFormModel" :form-disabled="effectiveProps.disabled"
|
|
12
|
-
:auto-placeholder="effectiveProps.autoSetPlaceholder" :form-action-type="formActionRef"
|
|
12
|
+
:auto-placeholder="effectiveProps.autoSetPlaceholder" :form-action-type="formActionRef" :colon="effectiveProps.colon"
|
|
13
13
|
:custom-components="formCustomComponents" :on-field-change="handleFieldChange">
|
|
14
14
|
<template v-if="slots[getSlotName(schema)]">
|
|
15
15
|
<slot :name="getSlotName(schema)" :model="currentFormModel" :schema="schema" :field="schema.field"
|
|
@@ -69,6 +69,7 @@ const props = withDefaults(
|
|
|
69
69
|
initialValues?: Record<string, unknown>
|
|
70
70
|
labelWidth?: string
|
|
71
71
|
labelPosition?: 'left' | 'right' | 'top'
|
|
72
|
+
colon?: boolean
|
|
72
73
|
gutter?: number
|
|
73
74
|
size?: 'medium' | 'small' | 'large'
|
|
74
75
|
disabled?: boolean
|
|
@@ -96,6 +97,7 @@ const props = withDefaults(
|
|
|
96
97
|
{
|
|
97
98
|
labelWidth: '120px',
|
|
98
99
|
labelPosition: 'right',
|
|
100
|
+
colon: true,
|
|
99
101
|
gutter: 24,
|
|
100
102
|
size: 'medium',
|
|
101
103
|
autoSetPlaceholder: true,
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
:label-width="schema.labelWidth"
|
|
9
9
|
>
|
|
10
10
|
<template slot="label">
|
|
11
|
-
<span>
|
|
11
|
+
<span>
|
|
12
|
+
{{ schema.label }}<span v-if="showColon" class="ecp-pro-form-item__colon">:</span>
|
|
13
|
+
</span>
|
|
12
14
|
<el-tooltip
|
|
13
15
|
v-if="schema.helpMessage"
|
|
14
16
|
placement="top"
|
|
@@ -35,131 +37,142 @@
|
|
|
35
37
|
<!-- 默认组件渲染 -->
|
|
36
38
|
<template v-else>
|
|
37
39
|
<!-- 自定义 component:组件名或内联组件 -->
|
|
38
|
-
<component
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<el-input
|
|
49
|
-
v-else-if="schema.component === 'input' || !schema.component"
|
|
50
|
-
v-model="formModel[schema.field]"
|
|
51
|
-
:placeholder="schema.placeholder || (autoPlaceholder ? `请输入${schema.label}` : undefined)"
|
|
52
|
-
:disabled="effectiveDisabled"
|
|
53
|
-
v-bind="effectiveComponentProps"
|
|
54
|
-
v-on="effectiveComponentListeners"
|
|
55
|
-
/>
|
|
56
|
-
<el-input-number
|
|
57
|
-
v-else-if="schema.component === 'input-number'"
|
|
58
|
-
v-model="formModel[schema.field]"
|
|
59
|
-
:placeholder="schema.placeholder"
|
|
60
|
-
:disabled="effectiveDisabled"
|
|
61
|
-
v-bind="effectiveComponentProps"
|
|
62
|
-
v-on="effectiveComponentListeners"
|
|
63
|
-
/>
|
|
64
|
-
<el-select
|
|
65
|
-
class="ecp-pro-form-item__select"
|
|
66
|
-
v-else-if="schema.component === 'select'"
|
|
67
|
-
v-model="formModel[schema.field]"
|
|
68
|
-
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
69
|
-
:disabled="effectiveDisabled"
|
|
70
|
-
v-bind="effectiveComponentProps"
|
|
71
|
-
v-on="effectiveComponentListeners"
|
|
72
|
-
>
|
|
73
|
-
<el-option
|
|
74
|
-
v-for="opt in (getOptions(effectiveComponentProps) || [])"
|
|
75
|
-
:key="String(opt.value)"
|
|
76
|
-
:label="opt.label"
|
|
77
|
-
:value="opt.value"
|
|
40
|
+
<component :is="fieldWrapperComponent" v-bind="fieldWrapperProps">
|
|
41
|
+
<component
|
|
42
|
+
v-if="resolvedCustomComponent"
|
|
43
|
+
:is="resolvedCustomComponent"
|
|
44
|
+
:value="formModel[schema.field]"
|
|
45
|
+
@input="setFieldValue"
|
|
46
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请输入${schema.label}` : undefined)"
|
|
47
|
+
:disabled="effectiveDisabled"
|
|
48
|
+
v-bind="effectiveComponentProps"
|
|
49
|
+
v-on="effectiveComponentListeners"
|
|
78
50
|
/>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
end-placeholder="结束日期"
|
|
113
|
-
value-format="yyyy-MM-dd"
|
|
114
|
-
:disabled="effectiveDisabled"
|
|
115
|
-
v-bind="effectiveComponentProps"
|
|
116
|
-
v-on="effectiveComponentListeners"
|
|
117
|
-
/>
|
|
118
|
-
<el-switch
|
|
119
|
-
v-else-if="schema.component === 'switch'"
|
|
120
|
-
v-model="formModel[schema.field]"
|
|
121
|
-
:disabled="effectiveDisabled"
|
|
122
|
-
v-bind="effectiveComponentProps"
|
|
123
|
-
v-on="effectiveComponentListeners"
|
|
124
|
-
/>
|
|
125
|
-
<el-cascader
|
|
126
|
-
v-else-if="schema.component === 'cascader'"
|
|
127
|
-
v-model="formModel[schema.field]"
|
|
128
|
-
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
129
|
-
:disabled="effectiveDisabled"
|
|
130
|
-
v-bind="effectiveComponentProps"
|
|
131
|
-
v-on="effectiveComponentListeners"
|
|
132
|
-
/>
|
|
133
|
-
<el-checkbox-group
|
|
134
|
-
v-else-if="schema.component === 'checkbox'"
|
|
135
|
-
v-model="formModel[schema.field]"
|
|
136
|
-
:disabled="effectiveDisabled"
|
|
137
|
-
v-bind="effectiveComponentProps"
|
|
138
|
-
v-on="effectiveComponentListeners"
|
|
139
|
-
>
|
|
140
|
-
<el-checkbox
|
|
141
|
-
v-for="opt in (getOptions(effectiveComponentProps) || [])"
|
|
142
|
-
:key="String(opt.value)"
|
|
143
|
-
:label="opt.value"
|
|
51
|
+
<el-input
|
|
52
|
+
v-else-if="schema.component === 'input' || !schema.component"
|
|
53
|
+
v-model="formModel[schema.field]"
|
|
54
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请输入${schema.label}` : undefined)"
|
|
55
|
+
:disabled="effectiveDisabled"
|
|
56
|
+
v-bind="effectiveComponentProps"
|
|
57
|
+
v-on="effectiveComponentListeners"
|
|
58
|
+
/>
|
|
59
|
+
<el-input-number
|
|
60
|
+
v-else-if="schema.component === 'input-number'"
|
|
61
|
+
v-model="formModel[schema.field]"
|
|
62
|
+
:placeholder="schema.placeholder"
|
|
63
|
+
:disabled="effectiveDisabled"
|
|
64
|
+
v-bind="effectiveComponentProps"
|
|
65
|
+
v-on="effectiveComponentListeners"
|
|
66
|
+
/>
|
|
67
|
+
<FormattedNumberInput
|
|
68
|
+
v-else-if="schema.component === 'formatted-number'"
|
|
69
|
+
:value="formModel[schema.field]"
|
|
70
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请输入${schema.label}` : undefined)"
|
|
71
|
+
:disabled="effectiveDisabled"
|
|
72
|
+
v-bind="effectiveComponentProps"
|
|
73
|
+
v-on="effectiveComponentListeners"
|
|
74
|
+
@input="setFieldValue"
|
|
75
|
+
/>
|
|
76
|
+
<el-select
|
|
77
|
+
class="ecp-pro-form-item__select"
|
|
78
|
+
v-else-if="schema.component === 'select'"
|
|
79
|
+
v-model="formModel[schema.field]"
|
|
80
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
81
|
+
:disabled="effectiveDisabled"
|
|
82
|
+
v-bind="effectiveComponentProps"
|
|
83
|
+
v-on="effectiveComponentListeners"
|
|
144
84
|
>
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
85
|
+
<el-option
|
|
86
|
+
v-for="opt in (getOptions(effectiveComponentProps) || [])"
|
|
87
|
+
:key="String(opt.value)"
|
|
88
|
+
:label="opt.label"
|
|
89
|
+
:value="opt.value"
|
|
90
|
+
/>
|
|
91
|
+
</el-select>
|
|
92
|
+
<ApiSelect
|
|
93
|
+
v-else-if="schema.component === 'api-select'"
|
|
94
|
+
:value="formModel[schema.field]"
|
|
95
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
96
|
+
:disabled="effectiveDisabled"
|
|
97
|
+
v-bind="effectiveComponentProps"
|
|
98
|
+
v-on="effectiveComponentListeners"
|
|
99
|
+
@input="setFieldValue"
|
|
100
|
+
/>
|
|
101
|
+
<TreeSelect
|
|
102
|
+
v-else-if="schema.component === 'tree-select'"
|
|
103
|
+
:value="formModel[schema.field]"
|
|
104
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
105
|
+
:disabled="effectiveDisabled"
|
|
106
|
+
v-bind="effectiveComponentProps"
|
|
107
|
+
v-on="effectiveComponentListeners"
|
|
108
|
+
@input="setFieldValue"
|
|
109
|
+
/>
|
|
110
|
+
<el-date-picker
|
|
111
|
+
v-else-if="schema.component === 'date-picker'"
|
|
112
|
+
v-model="formModel[schema.field]"
|
|
113
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
114
|
+
:disabled="effectiveDisabled"
|
|
115
|
+
v-bind="effectiveComponentProps"
|
|
116
|
+
v-on="effectiveComponentListeners"
|
|
117
|
+
/>
|
|
118
|
+
<el-date-picker
|
|
119
|
+
v-else-if="schema.component === 'date-range'"
|
|
120
|
+
v-model="formModel[schema.field]"
|
|
121
|
+
type="daterange"
|
|
122
|
+
range-separator="至"
|
|
123
|
+
start-placeholder="开始日期"
|
|
124
|
+
end-placeholder="结束日期"
|
|
125
|
+
value-format="yyyy-MM-dd"
|
|
126
|
+
:disabled="effectiveDisabled"
|
|
127
|
+
v-bind="effectiveComponentProps"
|
|
128
|
+
v-on="effectiveComponentListeners"
|
|
129
|
+
/>
|
|
130
|
+
<el-switch
|
|
131
|
+
v-else-if="schema.component === 'switch'"
|
|
132
|
+
v-model="formModel[schema.field]"
|
|
133
|
+
:disabled="effectiveDisabled"
|
|
134
|
+
v-bind="effectiveComponentProps"
|
|
135
|
+
v-on="effectiveComponentListeners"
|
|
136
|
+
/>
|
|
137
|
+
<el-cascader
|
|
138
|
+
v-else-if="schema.component === 'cascader'"
|
|
139
|
+
v-model="formModel[schema.field]"
|
|
140
|
+
:placeholder="schema.placeholder || (autoPlaceholder ? `请选择${schema.label}` : undefined)"
|
|
141
|
+
:disabled="effectiveDisabled"
|
|
142
|
+
v-bind="effectiveComponentProps"
|
|
143
|
+
v-on="effectiveComponentListeners"
|
|
144
|
+
/>
|
|
145
|
+
<el-checkbox-group
|
|
146
|
+
v-else-if="schema.component === 'checkbox'"
|
|
147
|
+
v-model="formModel[schema.field]"
|
|
148
|
+
:disabled="effectiveDisabled"
|
|
149
|
+
v-bind="effectiveComponentProps"
|
|
150
|
+
v-on="effectiveComponentListeners"
|
|
159
151
|
>
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
152
|
+
<el-checkbox
|
|
153
|
+
v-for="opt in (getOptions(effectiveComponentProps) || [])"
|
|
154
|
+
:key="String(opt.value)"
|
|
155
|
+
:label="opt.value"
|
|
156
|
+
>
|
|
157
|
+
{{ opt.label }}
|
|
158
|
+
</el-checkbox>
|
|
159
|
+
</el-checkbox-group>
|
|
160
|
+
<el-radio-group
|
|
161
|
+
v-else-if="schema.component === 'radio'"
|
|
162
|
+
v-model="formModel[schema.field]"
|
|
163
|
+
:disabled="effectiveDisabled"
|
|
164
|
+
v-bind="effectiveComponentProps"
|
|
165
|
+
v-on="effectiveComponentListeners"
|
|
166
|
+
>
|
|
167
|
+
<el-radio
|
|
168
|
+
v-for="opt in (getOptions(effectiveComponentProps) || [])"
|
|
169
|
+
:key="String(opt.value)"
|
|
170
|
+
:label="opt.value"
|
|
171
|
+
>
|
|
172
|
+
{{ opt.label }}
|
|
173
|
+
</el-radio>
|
|
174
|
+
</el-radio-group>
|
|
175
|
+
</component>
|
|
163
176
|
</template>
|
|
164
177
|
</el-form-item>
|
|
165
178
|
</template>
|
|
@@ -167,11 +180,14 @@
|
|
|
167
180
|
<script setup lang="ts">
|
|
168
181
|
import { computed, useSlots, h } from 'vue'
|
|
169
182
|
import ApiSelect from './ApiSelect.vue'
|
|
183
|
+
import FormattedNumberInput from './FormattedNumberInput.vue'
|
|
170
184
|
import TreeSelect from './TreeSelect.vue'
|
|
171
185
|
import type { ProFormSchema, RenderCallbackParams } from '../types'
|
|
186
|
+
import { normalizeTooltipConfig } from '../utils/tooltip'
|
|
172
187
|
|
|
173
188
|
const BUILT_IN_COMPONENTS: Set<string> = new Set([
|
|
174
189
|
'input', 'select', 'api-select', 'tree-select', 'date-picker', 'date-range', 'input-number',
|
|
190
|
+
'formatted-number',
|
|
175
191
|
'switch', 'cascader', 'checkbox', 'radio',
|
|
176
192
|
])
|
|
177
193
|
|
|
@@ -180,6 +196,7 @@ const props = defineProps<{
|
|
|
180
196
|
formModel: Record<string, unknown>
|
|
181
197
|
formDisabled?: boolean
|
|
182
198
|
autoPlaceholder?: boolean
|
|
199
|
+
colon?: boolean
|
|
183
200
|
formActionType?: import('../types').FormActionType
|
|
184
201
|
onFieldChange?: (field: string, value: unknown) => void
|
|
185
202
|
/** 自定义组件映射(由 ProForm 传入) */
|
|
@@ -248,6 +265,17 @@ const effectiveComponentPropsAndListeners = computed(() => {
|
|
|
248
265
|
|
|
249
266
|
const effectiveComponentProps = computed(() => effectiveComponentPropsAndListeners.value.props)
|
|
250
267
|
const effectiveComponentListeners = computed(() => effectiveComponentPropsAndListeners.value.listeners)
|
|
268
|
+
const showColon = computed(() => props.schema.colon ?? props.colon ?? false)
|
|
269
|
+
|
|
270
|
+
const normalizedTooltip = computed(() => {
|
|
271
|
+
const tooltip = props.schema.tooltip
|
|
272
|
+
if (!tooltip) return null
|
|
273
|
+
const resolved = typeof tooltip === 'function' ? tooltip(renderParams.value) : tooltip
|
|
274
|
+
return normalizeTooltipConfig(resolved, props.formModel[props.schema.field])
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
const fieldWrapperComponent = computed(() => normalizedTooltip.value ? 'el-tooltip' : 'span')
|
|
278
|
+
const fieldWrapperProps = computed(() => normalizedTooltip.value || {})
|
|
251
279
|
|
|
252
280
|
const hasSlot = computed(() => !!slots.default)
|
|
253
281
|
|
|
@@ -286,6 +314,10 @@ const renderComponent = computed(() => {
|
|
|
286
314
|
</script>
|
|
287
315
|
|
|
288
316
|
<style scoped>
|
|
317
|
+
.ecp-pro-form-item__colon {
|
|
318
|
+
margin-right: 2px;
|
|
319
|
+
}
|
|
320
|
+
|
|
289
321
|
.ecp-pro-form-item__help-icon {
|
|
290
322
|
margin-left: 4px;
|
|
291
323
|
color: #909399;
|
package/src/ProForm/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ProForm from './ProForm.vue'
|
|
2
2
|
import ProFormItem from './ProFormItem.vue'
|
|
3
3
|
import FormActions from './FormActions.vue'
|
|
4
|
+
import FormattedNumberInput from './FormattedNumberInput.vue'
|
|
4
5
|
import { useForm } from './useForm'
|
|
5
|
-
export { ProForm, ProFormItem, FormActions, useForm }
|
|
6
|
+
export { ProForm, ProFormItem, FormActions, FormattedNumberInput, useForm }
|
|
6
7
|
export default ProForm
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
import { computed } from 'vue'
|
|
85
85
|
import { MessageBox } from 'element-ui'
|
|
86
86
|
import type { TableActionItem } from './types'
|
|
87
|
+
import { normalizeTooltipConfig } from '../utils/tooltip'
|
|
87
88
|
|
|
88
89
|
const props = withDefaults(
|
|
89
90
|
defineProps<{
|
|
@@ -100,11 +101,7 @@ const props = withDefaults(
|
|
|
100
101
|
)
|
|
101
102
|
|
|
102
103
|
const normalizeTooltip = (tooltip?: TableActionItem['tooltip']) => {
|
|
103
|
-
|
|
104
|
-
if (typeof tooltip === 'string') {
|
|
105
|
-
return { content: tooltip }
|
|
106
|
-
}
|
|
107
|
-
return tooltip as Record<string, unknown>
|
|
104
|
+
return normalizeTooltipConfig(tooltip) || {}
|
|
108
105
|
}
|
|
109
106
|
|
|
110
107
|
const getButtonType = (action: TableActionItem) => {
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { VueConstructor } from 'vue'
|
|
2
2
|
import ProTable, { TableAction } from './ProTable'
|
|
3
|
-
import ProForm, { ProFormItem, FormActions } from './ProForm'
|
|
3
|
+
import ProForm, { ProFormItem, FormActions, FormattedNumberInput } from './ProForm'
|
|
4
4
|
import ProDescriptions from './ProDescriptions'
|
|
5
5
|
import { useForm } from './ProForm/useForm'
|
|
6
6
|
import { useDescription } from './ProDescriptions/useDescription'
|
|
7
7
|
import { useProTable } from './ProTable/useProTable'
|
|
8
8
|
import { useComponentSetting } from './useComponentSetting'
|
|
9
9
|
|
|
10
|
-
export { ProForm, ProFormItem, FormActions, useForm }
|
|
10
|
+
export { ProForm, ProFormItem, FormActions, FormattedNumberInput, useForm }
|
|
11
11
|
export { ProTable, useProTable, TableAction }
|
|
12
12
|
export { ProDescriptions, useDescription }
|
|
13
13
|
export { useComponentSetting }
|
|
@@ -16,6 +16,7 @@ export type { UseProTableReturn, UseProTablePropsReactive } from './ProTable/use
|
|
|
16
16
|
export type { UseDescriptionReturn, UseDescriptionPropsReactive } from './ProDescriptions/useDescription'
|
|
17
17
|
export * from './ProTable/types'
|
|
18
18
|
export * from './types'
|
|
19
|
+
export * from './utils/formattedNumber'
|
|
19
20
|
|
|
20
21
|
const components = [
|
|
21
22
|
{ name: 'ProTable', component: ProTable },
|
|
@@ -23,6 +24,7 @@ const components = [
|
|
|
23
24
|
{ name: 'ProForm', component: ProForm },
|
|
24
25
|
{ name: 'ProFormItem', component: ProFormItem },
|
|
25
26
|
{ name: 'FormActions', component: FormActions },
|
|
27
|
+
{ name: 'FormattedNumberInput', component: FormattedNumberInput },
|
|
26
28
|
{ name: 'ProDescriptions', component: ProDescriptions },
|
|
27
29
|
]
|
|
28
30
|
|
|
@@ -38,4 +40,5 @@ export default {
|
|
|
38
40
|
ProForm,
|
|
39
41
|
ProDescriptions,
|
|
40
42
|
TableAction,
|
|
43
|
+
FormattedNumberInput,
|
|
41
44
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -60,6 +60,7 @@ export interface ProFormProps {
|
|
|
60
60
|
initialValues?: Record<string, unknown>
|
|
61
61
|
labelWidth?: string
|
|
62
62
|
labelPosition?: 'left' | 'right' | 'top'
|
|
63
|
+
colon?: boolean
|
|
63
64
|
gutter?: number
|
|
64
65
|
size?: 'medium' | 'small' | 'large'
|
|
65
66
|
disabled?: boolean
|
|
@@ -92,6 +93,7 @@ export type ProFormBuiltInComponent =
|
|
|
92
93
|
| 'date-picker'
|
|
93
94
|
| 'date-range'
|
|
94
95
|
| 'input-number'
|
|
96
|
+
| 'formatted-number'
|
|
95
97
|
| 'switch'
|
|
96
98
|
| 'cascader'
|
|
97
99
|
| 'checkbox'
|
|
@@ -108,9 +110,11 @@ export interface ProFormSchema {
|
|
|
108
110
|
label: string
|
|
109
111
|
/** 单个表单项标签宽度,优先级高于 Form 的 labelWidth */
|
|
110
112
|
labelWidth?: string
|
|
113
|
+
/** 是否显示 label 冒号,优先级高于 ProForm 的 colon */
|
|
114
|
+
colon?: boolean
|
|
111
115
|
/**
|
|
112
116
|
* 组件类型:
|
|
113
|
-
* - 内置:'input' | 'select' | 'date-picker' | 'date-range' | 'input-number' | 'switch' | 'cascader' | 'checkbox' | 'radio'
|
|
117
|
+
* - 内置:'input' | 'select' | 'date-picker' | 'date-range' | 'input-number' | 'formatted-number' | 'switch' | 'cascader' | 'checkbox' | 'radio'
|
|
114
118
|
* - 自定义组件名:任意字符串,对应全局或 ProForm 传入的 components 中注册的组件
|
|
115
119
|
* - 内联组件:直接传入 Vue 组件选项对象或构造函数
|
|
116
120
|
*/
|
|
@@ -147,6 +151,8 @@ export interface ProFormSchema {
|
|
|
147
151
|
helpMessage?: string | string[]
|
|
148
152
|
/** 温馨提示组件的 props */
|
|
149
153
|
helpComponentProps?: Record<string, unknown>
|
|
154
|
+
/** 表单项 value 的 tooltip,true 时默认展示当前值,支持函数动态返回 */
|
|
155
|
+
tooltip?: boolean | string | Record<string, unknown> | ((params: RenderCallbackParams) => boolean | string | Record<string, unknown>)
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
/** ProDescriptions 描述项配置 */
|
|
@@ -195,6 +201,8 @@ export interface DescriptionSchema {
|
|
|
195
201
|
slot?: string
|
|
196
202
|
/** 自定义渲染 */
|
|
197
203
|
render?: (value: unknown, record: Record<string, unknown>) => VNode | string | number | null | undefined
|
|
204
|
+
/** 描述项 value 的 tooltip,true 时默认展示当前值,支持函数动态返回 */
|
|
205
|
+
tooltip?: boolean | string | Record<string, unknown> | ((params: { value: unknown; record: Record<string, unknown>; schema: DescriptionSchema }) => boolean | string | Record<string, unknown>)
|
|
198
206
|
}
|
|
199
207
|
|
|
200
208
|
/** Description Props */
|