jianghu-ui 1.0.1

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.
Files changed (112) hide show
  1. package/README.md +376 -0
  2. package/dist/jianghu-ui.css +2318 -0
  3. package/dist/jianghu-ui.js +2 -0
  4. package/dist/jianghu-ui.js.LICENSE.txt +1 -0
  5. package/package.json +56 -0
  6. package/src/Design.stories.mdx +195 -0
  7. package/src/Introduction.stories.mdx +148 -0
  8. package/src/components/JhAddressSelect/JhAddressSelect.md +250 -0
  9. package/src/components/JhAddressSelect/JhAddressSelect.stories.js +282 -0
  10. package/src/components/JhAddressSelect/JhAddressSelect.vue +261 -0
  11. package/src/components/JhCard/JhCard.md +246 -0
  12. package/src/components/JhCard/JhCard.stories.js +688 -0
  13. package/src/components/JhCard/JhCard.vue +604 -0
  14. package/src/components/JhCheckCard/JhCheckCard.md +245 -0
  15. package/src/components/JhCheckCard/JhCheckCard.stories.js +750 -0
  16. package/src/components/JhCheckCard/JhCheckCard.vue +476 -0
  17. package/src/components/JhConfirmDialog/JhConfirmDialog.md +70 -0
  18. package/src/components/JhConfirmDialog/JhConfirmDialog.stories.js +550 -0
  19. package/src/components/JhConfirmDialog/JhConfirmDialog.vue +181 -0
  20. package/src/components/JhDateRangePicker/JhDateRangePicker.md +56 -0
  21. package/src/components/JhDateRangePicker/JhDateRangePicker.stories.js +320 -0
  22. package/src/components/JhDateRangePicker/JhDateRangePicker.vue +307 -0
  23. package/src/components/JhDescriptions/JhDescriptions.md +724 -0
  24. package/src/components/JhDescriptions/JhDescriptions.stories.js +858 -0
  25. package/src/components/JhDescriptions/JhDescriptions.vue +933 -0
  26. package/src/components/JhDraggable/JhDraggable.md +66 -0
  27. package/src/components/JhDraggable/JhDraggable.stories.js +161 -0
  28. package/src/components/JhDraggable/JhDraggable.vue +254 -0
  29. package/src/components/JhDrawer/JhDrawer.md +68 -0
  30. package/src/components/JhDrawer/JhDrawer.stories.js +478 -0
  31. package/src/components/JhDrawer/JhDrawer.vue +281 -0
  32. package/src/components/JhDrawerForm/JhDrawerForm.md +69 -0
  33. package/src/components/JhDrawerForm/JhDrawerForm.stories.js +492 -0
  34. package/src/components/JhDrawerForm/JhDrawerForm.vue +297 -0
  35. package/src/components/JhEditableTable/JhEditableTable.md +507 -0
  36. package/src/components/JhEditableTable/JhEditableTable.stories.js +615 -0
  37. package/src/components/JhEditableTable/JhEditableTable.vue +685 -0
  38. package/src/components/JhFileInput/JhFileInput.md +56 -0
  39. package/src/components/JhFileInput/JhFileInput.stories.js +103 -0
  40. package/src/components/JhFileInput/JhFileInput.vue +253 -0
  41. package/src/components/JhForm/JhForm.md +676 -0
  42. package/src/components/JhForm/JhForm.stories.js +1375 -0
  43. package/src/components/JhForm/JhForm.vue +657 -0
  44. package/src/components/JhFormField/JhFormField.stories.js +217 -0
  45. package/src/components/JhFormField/JhFormField.vue +439 -0
  46. package/src/components/JhFormFields/JhFormFields.md +647 -0
  47. package/src/components/JhFormFields/JhFormFields.stories.js +922 -0
  48. package/src/components/JhFormFields/JhFormFields.vue +998 -0
  49. package/src/components/JhFormList/JhFormList.md +303 -0
  50. package/src/components/JhFormList/JhFormList.stories.js +661 -0
  51. package/src/components/JhFormList/JhFormList.vue +1127 -0
  52. package/src/components/JhJsonEditor/JhJsonEditor.md +54 -0
  53. package/src/components/JhJsonEditor/JhJsonEditor.stories.js +157 -0
  54. package/src/components/JhJsonEditor/JhJsonEditor.vue +178 -0
  55. package/src/components/JhLayout/JhLayout.md +580 -0
  56. package/src/components/JhLayout/JhLayout.stories.js +414 -0
  57. package/src/components/JhLayout/JhLayout.vue +387 -0
  58. package/src/components/JhList/JhList.md +441 -0
  59. package/src/components/JhList/JhList.stories.js +524 -0
  60. package/src/components/JhList/JhList.vue +571 -0
  61. package/src/components/JhMarkdownEditor/JhMarkdownEditor.md +56 -0
  62. package/src/components/JhMarkdownEditor/JhMarkdownEditor.stories.js +191 -0
  63. package/src/components/JhMarkdownEditor/JhMarkdownEditor.vue +188 -0
  64. package/src/components/JhMask/JhMask.md +62 -0
  65. package/src/components/JhMask/JhMask.stories.js +270 -0
  66. package/src/components/JhMask/JhMask.vue +123 -0
  67. package/src/components/JhMenu/JhMenu.md +85 -0
  68. package/src/components/JhMenu/JhMenu.stories.js +384 -0
  69. package/src/components/JhMenu/JhMenu.vue +545 -0
  70. package/src/components/JhModal/JhModal.md +68 -0
  71. package/src/components/JhModal/JhModal.stories.js +562 -0
  72. package/src/components/JhModal/JhModal.vue +235 -0
  73. package/src/components/JhModalForm/JhModalForm.md +69 -0
  74. package/src/components/JhModalForm/JhModalForm.stories.js +592 -0
  75. package/src/components/JhModalForm/JhModalForm.vue +298 -0
  76. package/src/components/JhPageContainer/JhPageContainer.md +409 -0
  77. package/src/components/JhPageContainer/JhPageContainer.stories.js +209 -0
  78. package/src/components/JhPageContainer/JhPageContainer.vue +72 -0
  79. package/src/components/JhQueryFilter/JhQueryFilter.md +77 -0
  80. package/src/components/JhQueryFilter/JhQueryFilter.stories.js +684 -0
  81. package/src/components/JhQueryFilter/JhQueryFilter.vue +429 -0
  82. package/src/components/JhScene/JhScene.md +64 -0
  83. package/src/components/JhScene/JhScene.stories.js +317 -0
  84. package/src/components/JhScene/JhScene.vue +376 -0
  85. package/src/components/JhStatisticCard/JhStatisticCard.md +363 -0
  86. package/src/components/JhStatisticCard/JhStatisticCard.stories.js +847 -0
  87. package/src/components/JhStatisticCard/JhStatisticCard.vue +459 -0
  88. package/src/components/JhStepsForm/JhStepsForm.md +666 -0
  89. package/src/components/JhStepsForm/JhStepsForm.stories.js +1224 -0
  90. package/src/components/JhStepsForm/JhStepsForm.vue +749 -0
  91. package/src/components/JhTable/JhTable.md +730 -0
  92. package/src/components/JhTable/JhTable.stories.js +1444 -0
  93. package/src/components/JhTable/JhTable.vue +2298 -0
  94. package/src/components/JhTableAttachment/JhTableAttachment.md +70 -0
  95. package/src/components/JhTableAttachment/JhTableAttachment.stories.js +198 -0
  96. package/src/components/JhTableAttachment/JhTableAttachment.vue +264 -0
  97. package/src/components/JhToast/JhToast.md +67 -0
  98. package/src/components/JhToast/JhToast.stories.js +386 -0
  99. package/src/components/JhToast/JhToast.vue +239 -0
  100. package/src/components/JhTreeSelect/JhTreeSelect.md +82 -0
  101. package/src/components/JhTreeSelect/JhTreeSelect.stories.js +391 -0
  102. package/src/components/JhTreeSelect/JhTreeSelect.vue +727 -0
  103. package/src/components/JhWaterMark/JhWaterMark.md +190 -0
  104. package/src/components/JhWaterMark/JhWaterMark.stories.js +675 -0
  105. package/src/components/JhWaterMark/JhWaterMark.vue +351 -0
  106. package/src/components/README.md +52 -0
  107. package/src/index.js +135 -0
  108. package/src/style/globalCSSJHV4.css +348 -0
  109. package/src/style/globalCSSVuetifyV4.css +637 -0
  110. package/src/style/storybook.css +4 -0
  111. package/src/tailwind.css +3 -0
  112. package/src/utils/vuetify.js +31 -0
@@ -0,0 +1,217 @@
1
+ import JhFormField from './JhFormField.vue';
2
+
3
+ export default {
4
+ title: '数据录入/JhFormField - 单字段组件',
5
+ component: JhFormField,
6
+ parameters: {
7
+ docs: {
8
+ description: {
9
+ component: '通用表单字段组件,通过type属性渲染不同类型的表单组件,支持Vuetify表单组件的所有参数。',
10
+ },
11
+ },
12
+ },
13
+ };
14
+
15
+ // 基础用法
16
+ export const Basic = () => ({
17
+ components: { JhFormField },
18
+ data() {
19
+ return {
20
+ textValue: '',
21
+ numberValue: 0,
22
+ textareaValue: '',
23
+ selectValue: '',
24
+ autocompleteValue: '',
25
+ switchValue: false,
26
+ checkboxValue: false,
27
+ radioValue: '',
28
+ sliderValue: 50,
29
+ rangeValue: [20, 80],
30
+ dateValue: '',
31
+ timeValue: '',
32
+ colorValue: '#000000',
33
+ items: [
34
+ { text: '选项1', value: '1' },
35
+ { text: '选项2', value: '2' },
36
+ { text: '选项3', value: '3' },
37
+ { text: '选项4', value: '4' }
38
+ ]
39
+ };
40
+ },
41
+ template: `
42
+ <div class="pa-4">
43
+ <h2 class="mb-4">JhFormField 基本用法</h2>
44
+
45
+ <!-- 文本输入 -->
46
+ <div class="mb-4">
47
+ <h3 class="text-h6 mb-2">文本输入框</h3>
48
+ <jh-form-field type="text" v-model="textValue" label="文本输入" placeholder="请输入文本"></jh-form-field>
49
+ <div class="mt-2">当前值: {{ textValue }}</div>
50
+ </div>
51
+
52
+ <!-- 数字输入 -->
53
+ <div class="mb-4">
54
+ <h3 class="text-h6 mb-2">数字输入框</h3>
55
+ <jh-form-field type="number" v-model="numberValue" label="数字输入" placeholder="请输入数字"></jh-form-field>
56
+ <div class="mt-2">当前值: {{ numberValue }}</div>
57
+ </div>
58
+
59
+ <!-- 文本域 -->
60
+ <div class="mb-4">
61
+ <h3 class="text-h6 mb-2">文本域</h3>
62
+ <jh-form-field type="textarea" v-model="textareaValue" label="文本域" placeholder="请输入多行文本"></jh-form-field>
63
+ <div class="mt-2">当前值: {{ textareaValue }}</div>
64
+ </div>
65
+
66
+ <!-- 下拉选择 -->
67
+ <div class="mb-4">
68
+ <h3 class="text-h6 mb-2">下拉选择框</h3>
69
+ <jh-form-field
70
+ type="select"
71
+ v-model="selectValue"
72
+ label="下拉选择"
73
+ :items="items"
74
+ placeholder="请选择选项"
75
+ ></jh-form-field>
76
+ <div class="mt-2">当前值: {{ selectValue }}</div>
77
+ </div>
78
+
79
+ <!-- 自动完成 -->
80
+ <div class="mb-4">
81
+ <h3 class="text-h6 mb-2">自动完成</h3>
82
+ <jh-form-field
83
+ type="autocomplete"
84
+ v-model="autocompleteValue"
85
+ label="自动完成"
86
+ :items="items"
87
+ placeholder="请输入或选择"
88
+ ></jh-form-field>
89
+ <div class="mt-2">当前值: {{ autocompleteValue }}</div>
90
+ </div>
91
+
92
+ <!-- 开关 -->
93
+ <div class="mb-4">
94
+ <h3 class="text-h6 mb-2">开关</h3>
95
+ <jh-form-field type="switch" v-model="switchValue" label="开关示例"></jh-form-field>
96
+ <div class="mt-2">当前值: {{ switchValue ? '开启' : '关闭' }}</div>
97
+ </div>
98
+
99
+ <!-- 复选框 -->
100
+ <div class="mb-4">
101
+ <h3 class="text-h6 mb-2">复选框</h3>
102
+ <jh-form-field type="checkbox" v-model="checkboxValue" label="复选框示例"></jh-form-field>
103
+ <div class="mt-2">当前值: {{ checkboxValue ? '选中' : '未选中' }}</div>
104
+ </div>
105
+
106
+ <!-- 单选按钮组 -->
107
+ <div class="mb-4">
108
+ <h3 class="text-h6 mb-2">单选按钮组</h3>
109
+ <jh-form-field
110
+ type="radio"
111
+ v-model="radioValue"
112
+ :items="items"
113
+ label="单选按钮组示例"
114
+ ></jh-form-field>
115
+ <div class="mt-2">当前值: {{ radioValue }}</div>
116
+ </div>
117
+
118
+ <!-- 滑块 -->
119
+ <div class="mb-4">
120
+ <h3 class="text-h6 mb-2">滑块</h3>
121
+ <jh-form-field type="slider" v-model="sliderValue" label="滑块示例"></jh-form-field>
122
+ <div class="mt-2">当前值: {{ sliderValue }}</div>
123
+ </div>
124
+
125
+ <!-- 区间滑块 -->
126
+ <div class="mb-4">
127
+ <h3 class="text-h6 mb-2">区间滑块</h3>
128
+ <jh-form-field type="range-slider" v-model="rangeValue" label="区间滑块示例"></jh-form-field>
129
+ <div class="mt-2">当前值: {{ rangeValue[0] }} - {{ rangeValue[1] }}</div>
130
+ </div>
131
+
132
+ <!-- 日期选择器 -->
133
+ <div class="mb-4">
134
+ <h3 class="text-h6 mb-2">日期选择器</h3>
135
+ <jh-form-field type="date" v-model="dateValue" label="日期选择"></jh-form-field>
136
+ <div class="mt-2">当前值: {{ dateValue }}</div>
137
+ </div>
138
+
139
+ <!-- 时间选择器 -->
140
+ <div class="mb-4">
141
+ <h3 class="text-h6 mb-2">时间选择器</h3>
142
+ <jh-form-field type="time" v-model="timeValue" label="时间选择"></jh-form-field>
143
+ <div class="mt-2">当前值: {{ timeValue }}</div>
144
+ </div>
145
+
146
+ <!-- 颜色选择器 -->
147
+ <div class="mb-4">
148
+ <h3 class="text-h6 mb-2">颜色选择器</h3>
149
+ <jh-form-field type="color" v-model="colorValue" label="颜色选择"></jh-form-field>
150
+ <div class="mt-2">当前值: {{ colorValue }}</div>
151
+ </div>
152
+ </div>
153
+ `
154
+ });
155
+
156
+ // 不同样式
157
+ export const DifferentStyles = () => ({
158
+ components: { JhFormField },
159
+ data() {
160
+ return {
161
+ value1: '',
162
+ value2: '',
163
+ value3: ''
164
+ };
165
+ },
166
+ template: `
167
+ <div class="pa-4">
168
+ <h2 class="mb-4">JhFormField 不同样式</h2>
169
+
170
+ <!-- Filled 样式 -->
171
+ <div class="mb-4">
172
+ <h3 class="text-h6 mb-2">Filled 样式</h3>
173
+ <jh-form-field type="text" v-model="value1" label="Filled 样式" filled></jh-form-field>
174
+ </div>
175
+
176
+ <!-- Outlined 样式 -->
177
+ <div class="mb-4">
178
+ <h3 class="text-h6 mb-2">Outlined 样式</h3>
179
+ <jh-form-field type="text" v-model="value2" label="Outlined 样式" outlined></jh-form-field>
180
+ </div>
181
+
182
+ <!-- Dense 样式 -->
183
+ <div class="mb-4">
184
+ <h3 class="text-h6 mb-2">Dense 样式</h3>
185
+ <jh-form-field type="text" v-model="value3" label="Dense 样式" dense outlined></jh-form-field>
186
+ </div>
187
+ </div>
188
+ `
189
+ });
190
+
191
+ // 禁用和只读
192
+ export const DisabledAndReadonly = () => ({
193
+ components: { JhFormField },
194
+ data() {
195
+ return {
196
+ value1: '禁用状态',
197
+ value2: '只读状态'
198
+ };
199
+ },
200
+ template: `
201
+ <div class="pa-4">
202
+ <h2 class="mb-4">JhFormField 禁用和只读</h2>
203
+
204
+ <!-- 禁用状态 -->
205
+ <div class="mb-4">
206
+ <h3 class="text-h6 mb-2">禁用状态</h3>
207
+ <jh-form-field type="text" v-model="value1" label="禁用状态" disabled></jh-form-field>
208
+ </div>
209
+
210
+ <!-- 只读状态 -->
211
+ <div class="mb-4">
212
+ <h3 class="text-h6 mb-2">只读状态</h3>
213
+ <jh-form-field type="text" v-model="value2" label="只读状态" readonly></jh-form-field>
214
+ </div>
215
+ </div>
216
+ `
217
+ });
@@ -0,0 +1,439 @@
1
+ <template>
2
+ <!-- 日期选择器 -->
3
+ <v-menu
4
+ v-if="type === 'date'"
5
+ v-model="dateMenu"
6
+ :close-on-content-click="false"
7
+ transition="scale-transition"
8
+ offset-y
9
+ min-width="290px"
10
+ >
11
+ <template v-slot:activator="{ on, attrs }">
12
+ <v-text-field
13
+ v-model="internalValue"
14
+ :dense="dense"
15
+ :filled="filled"
16
+ :outlined="outlined"
17
+ :disabled="disabled"
18
+ :single-line="singleLine"
19
+ :placeholder="placeholder"
20
+ :hide-details="hideDetails"
21
+ :rules="rules"
22
+ readonly
23
+ class="jh-v-input"
24
+ v-bind="{ ...attrs, ...customProps }"
25
+ v-on="on"
26
+ ></v-text-field>
27
+ </template>
28
+ <v-date-picker
29
+ v-model="internalValue"
30
+ @input="handleDateInput"
31
+ :locale="locale"
32
+ v-bind="pickerProps"
33
+ ></v-date-picker>
34
+ </v-menu>
35
+
36
+ <!-- 时间选择器 -->
37
+ <v-menu
38
+ v-else-if="type === 'time'"
39
+ v-model="timeMenu"
40
+ :close-on-content-click="false"
41
+ transition="scale-transition"
42
+ offset-y
43
+ min-width="290px"
44
+ >
45
+ <template v-slot:activator="{ on, attrs }">
46
+ <v-text-field
47
+ v-model="internalValue"
48
+ :dense="dense"
49
+ :filled="filled"
50
+ :outlined="outlined"
51
+ :disabled="disabled"
52
+ :placeholder="placeholder"
53
+ :hide-details="hideDetails"
54
+ :rules="rules"
55
+ readonly
56
+ class="jh-v-input"
57
+ v-bind="{ ...attrs, ...customProps }"
58
+ v-on="on"
59
+ ></v-text-field>
60
+ </template>
61
+ <v-time-picker
62
+ v-model="internalValue"
63
+ @input="handleTimeInput"
64
+ format="24hr"
65
+ v-bind="pickerProps"
66
+ ></v-time-picker>
67
+ </v-menu>
68
+
69
+ <!-- 颜色选择器 -->
70
+ <v-menu
71
+ v-else-if="type === 'color'"
72
+ v-model="colorMenu"
73
+ :close-on-content-click="false"
74
+ transition="scale-transition"
75
+ offset-y
76
+ min-width="320px"
77
+ >
78
+ <template v-slot:activator="{ on, attrs }">
79
+ <v-text-field
80
+ v-model="internalValue"
81
+ :dense="dense"
82
+ :filled="filled"
83
+ :outlined="outlined"
84
+ :disabled="disabled"
85
+ :placeholder="placeholder"
86
+ :hide-details="hideDetails"
87
+ :rules="rules"
88
+ readonly
89
+ class="jh-v-input"
90
+ v-on="on"
91
+ v-bind="{ ...attrs, ...customProps }"
92
+ >
93
+ <template v-slot:append>
94
+ <span
95
+ class="jh-color-preview"
96
+ :style="{ backgroundColor: internalValue || '#ffffff' }"
97
+ ></span>
98
+ </template>
99
+ </v-text-field>
100
+ </template>
101
+ <v-color-picker
102
+ v-model="internalValue"
103
+ flat
104
+ :hide-mode-switch="hideModeSwitch"
105
+ @input="handleColorInput"
106
+ v-bind="pickerProps"
107
+ ></v-color-picker>
108
+ </v-menu>
109
+
110
+ <!-- 其他表单组件 -->
111
+ <component
112
+ v-else
113
+ :is="getComponentName"
114
+ v-model="internalValue"
115
+ class="jh-v-input"
116
+ v-bind="componentProps"
117
+ v-on="componentListeners"
118
+ >
119
+ <slot></slot>
120
+ </component>
121
+ </template>
122
+
123
+ <script>
124
+ export default {
125
+ name: 'JhFormField',
126
+
127
+ props: {
128
+ type: {
129
+ type: String,
130
+ default: 'text',
131
+ validator: (v) => [
132
+ 'text', 'number', 'password', 'textarea', 'number', 'select', 'autocomplete',
133
+ 'date', 'time', 'color', 'slider', 'range-slider',
134
+ 'switch', 'checkbox', 'radio'
135
+ ].includes(v)
136
+ },
137
+ value: {
138
+ type: [String, Number, Boolean, Array, Date, Object],
139
+ default: null
140
+ },
141
+ // 通用属性
142
+ dense: {
143
+ type: Boolean,
144
+ default: true
145
+ },
146
+ filled: {
147
+ type: Boolean,
148
+ default: true
149
+ },
150
+ outlined: {
151
+ type: Boolean,
152
+ default: false
153
+ },
154
+ singleLine: {
155
+ type: Boolean,
156
+ default: false
157
+ },
158
+ disabled: {
159
+ type: Boolean,
160
+ default: false
161
+ },
162
+ readonly: {
163
+ type: Boolean,
164
+ default: false
165
+ },
166
+ placeholder: {
167
+ type: String,
168
+ default: ''
169
+ },
170
+ rules: {
171
+ type: Array,
172
+ default: () => []
173
+ },
174
+ hideDetails: {
175
+ type: [Boolean, String],
176
+ default: false
177
+ },
178
+ // select/autocomplete/radio 相关属性
179
+ items: {
180
+ type: Array,
181
+ default: () => []
182
+ },
183
+ itemText: {
184
+ type: String,
185
+ default: 'text'
186
+ },
187
+ itemValue: {
188
+ type: String,
189
+ default: 'value'
190
+ },
191
+ multiple: {
192
+ type: Boolean,
193
+ default: false
194
+ },
195
+ chips: {
196
+ type: Boolean,
197
+ default: false
198
+ },
199
+ // slider 相关属性
200
+ min: {
201
+ type: Number,
202
+ default: 0
203
+ },
204
+ max: {
205
+ type: Number,
206
+ default: 100
207
+ },
208
+ step: {
209
+ type: Number,
210
+ default: 1
211
+ },
212
+ thumbLabel: {
213
+ type: Boolean,
214
+ default: false
215
+ },
216
+ ticks: {
217
+ type: Boolean,
218
+ default: false
219
+ },
220
+ tickSize: {
221
+ type: Number,
222
+ default: 5
223
+ },
224
+ // 开关/复选框/单选框相关属性
225
+ label: {
226
+ type: String,
227
+ default: ''
228
+ },
229
+ color: {
230
+ type: String,
231
+ default: 'primary'
232
+ },
233
+ // 单选按钮组相关属性
234
+ row: {
235
+ type: Boolean,
236
+ default: true
237
+ },
238
+ // 文本域相关属性
239
+ rows: {
240
+ type: Number,
241
+ default: 3
242
+ },
243
+ singleLine: {
244
+ type: Boolean,
245
+ default: undefined
246
+ },
247
+ // 日期选择器相关属性
248
+ locale: {
249
+ type: String,
250
+ default: 'zh-cn'
251
+ },
252
+ // 颜色选择器相关属性
253
+ hideModeSwitch: {
254
+ type: Boolean,
255
+ default: true
256
+ },
257
+ closeOnSelect: {
258
+ type: Boolean,
259
+ default: true
260
+ },
261
+ // 前缀后缀
262
+ prefix: {
263
+ type: String,
264
+ default: ''
265
+ },
266
+ suffix: {
267
+ type: String,
268
+ default: ''
269
+ }
270
+ },
271
+
272
+ data() {
273
+ return {
274
+ internalValue: this.value,
275
+ dateMenu: false,
276
+ timeMenu: false,
277
+ colorMenu: false
278
+ };
279
+ },
280
+
281
+ computed: {
282
+ getComponentName() {
283
+ switch (this.type) {
284
+ case 'textarea':
285
+ return 'v-textarea';
286
+ case 'select':
287
+ return 'v-select';
288
+ case 'autocomplete':
289
+ return 'v-autocomplete';
290
+ case 'switch':
291
+ return 'v-switch';
292
+ case 'checkbox':
293
+ return 'v-checkbox';
294
+ case 'radio':
295
+ return 'v-radio-group';
296
+ case 'slider':
297
+ return 'v-slider';
298
+ case 'range-slider':
299
+ return 'v-range-slider';
300
+ default:
301
+ return 'v-text-field';
302
+ }
303
+ },
304
+ componentProps() {
305
+ // 基础属性
306
+ const props = {
307
+ dense: this.dense,
308
+ filled: this.filled,
309
+ outlined: this.outlined,
310
+ disabled: this.disabled,
311
+ readonly: this.readonly,
312
+ placeholder: this.placeholder,
313
+ rules: this.rules,
314
+ hideDetails: this.hideDetails,
315
+ color: this.color
316
+ };
317
+
318
+ // 类型特定属性
319
+ switch (this.type) {
320
+ case 'text':
321
+ case 'number':
322
+ case 'password':
323
+ case 'textarea':
324
+ props.singleLine = this.singleLine;
325
+ props.prefix = this.prefix;
326
+ props.suffix = this.suffix;
327
+ if (this.type === 'number') {
328
+ props.type = 'number';
329
+ }
330
+ if (this.type === 'textarea') {
331
+ props.rows = this.rows;
332
+ }
333
+ break;
334
+
335
+ case 'select':
336
+ case 'autocomplete':
337
+ props.items = this.items;
338
+ props.itemText = this.itemText;
339
+ props.itemValue = this.itemValue;
340
+ props.multiple = this.multiple;
341
+ props.chips = this.chips;
342
+ break;
343
+
344
+ case 'radio':
345
+ props.row = this.row;
346
+ break;
347
+
348
+ case 'checkbox':
349
+ case 'switch':
350
+ props.label = this.label;
351
+ break;
352
+
353
+ case 'slider':
354
+ case 'range-slider':
355
+ props.min = this.min;
356
+ props.max = this.max;
357
+ props.step = this.step;
358
+ props.thumbLabel = this.thumbLabel;
359
+ props.ticks = this.ticks;
360
+ props.tickSize = this.tickSize;
361
+ break;
362
+ }
363
+
364
+ // 透传其他自定义属性
365
+ return { ...props, ...this.customProps };
366
+ },
367
+ componentListeners() {
368
+ return {
369
+ ...this.$listeners,
370
+ input: (val) => {
371
+ this.internalValue = val;
372
+ this.$emit('input', val);
373
+ this.$emit('change', val);
374
+ }
375
+ };
376
+ },
377
+ // 自定义属性,用于透传给所有组件
378
+ customProps() {
379
+ return Object.keys(this.$attrs)
380
+ .filter(key => !Object.keys(this.$props).includes(key) && key !== 'pickerProps')
381
+ .reduce((acc, key) => {
382
+ acc[key] = this.$attrs[key];
383
+ return acc;
384
+ }, {});
385
+ },
386
+ // 选择器属性,用于透传给日期、时间、颜色选择器
387
+ pickerProps() {
388
+ return this.$attrs.pickerProps || {};
389
+ }
390
+ },
391
+
392
+ watch: {
393
+ value: {
394
+ handler(val) {
395
+ if (val !== this.internalValue) {
396
+ this.internalValue = val;
397
+ }
398
+ },
399
+ immediate: true
400
+ }
401
+ },
402
+
403
+ methods: {
404
+ // 日期选择器输入处理
405
+ handleDateInput(val) {
406
+ this.internalValue = val;
407
+ this.dateMenu = false;
408
+ this.$emit('input', val);
409
+ this.$emit('change', val);
410
+ },
411
+ // 时间选择器输入处理
412
+ handleTimeInput(val) {
413
+ this.internalValue = val;
414
+ this.timeMenu = false;
415
+ this.$emit('input', val);
416
+ this.$emit('change', val);
417
+ },
418
+ // 颜色选择器输入处理
419
+ handleColorInput(val) {
420
+ this.internalValue = val;
421
+ if (this.closeOnSelect !== false) {
422
+ this.colorMenu = false;
423
+ }
424
+ this.$emit('input', val);
425
+ this.$emit('change', val);
426
+ }
427
+ }
428
+ };
429
+ </script>
430
+
431
+ <style scoped>
432
+ .jh-color-preview {
433
+ display: inline-block;
434
+ width: 20px;
435
+ height: 20px;
436
+ border-radius: 4px;
437
+ border: 1px solid rgba(0, 0, 0, 0.2);
438
+ }
439
+ </style>