tang-ui-x 1.0.6 → 1.1.0
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/components/TForm/README.md +644 -0
- package/components/TForm/index.uvue +379 -0
- package/components/TForm/type.uts +80 -0
- package/index.uts +108 -107
- package/package.json +1 -1
- package/components/VbenFrom/index.uvue +0 -392
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
<script setup lang="uts">
|
|
2
|
+
import TRadioButton from '../TRadioButton/index.uvue'
|
|
3
|
+
import TCheckbox from '../TCheckbox/index.uvue'
|
|
4
|
+
import TSwitch from '../TSwitch/index.uvue'
|
|
5
|
+
import TRate from '../TRate/index.uvue'
|
|
6
|
+
import TSlider from '../TSlider/index.uvue'
|
|
7
|
+
import type { FormOption, FormSchema, TFormProps, ComponentProps } from './type.uts'
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(defineProps<TFormProps>(), {
|
|
10
|
+
labelWidth: '160rpx',
|
|
11
|
+
hideButtons: false,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits(['submit', 'reset'])
|
|
15
|
+
|
|
16
|
+
const model = defineModel<Record<string, any>>({ default: () => ({}) })
|
|
17
|
+
const errors = reactive<Record<string, string>>({})
|
|
18
|
+
|
|
19
|
+
const handlePlaceholder = (item: FormSchema): string => {
|
|
20
|
+
return item.componentProps?.placeholder || `请输入${item.label}`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const handleRange = (item: FormSchema) => {
|
|
24
|
+
const options = item.componentProps?.options as FormOption[] | undefined
|
|
25
|
+
return options?.map(o => o.label) || []
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const getSelectLabel = (item: FormSchema) => {
|
|
29
|
+
const options = item.componentProps?.options as FormOption[] | undefined
|
|
30
|
+
const opt = options?.find(o => o.value === model.value[item.field])
|
|
31
|
+
return opt?.label || ''
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const onSelectChange = (e: any, item: FormSchema) => {
|
|
35
|
+
const index = e.detail.value as number
|
|
36
|
+
const options = item.componentProps?.options as FormOption[] | undefined
|
|
37
|
+
const value = options?.[index]?.value ?? ''
|
|
38
|
+
model.value[item.field] = value
|
|
39
|
+
validateField(item)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const onTimeChange = (e: any, item: FormSchema) => {
|
|
43
|
+
model.value[item.field] = e.detail.value
|
|
44
|
+
validateField(item)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const validateField = (item: FormSchema) => {
|
|
48
|
+
if (item.required && !model.value[item.field]) {
|
|
49
|
+
errors[item.field] = `请输入${item.label}`
|
|
50
|
+
} else {
|
|
51
|
+
delete errors[item.field]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const onRadioChange = (value: string | number, item: FormSchema) => {
|
|
56
|
+
model.value[item.field] = value
|
|
57
|
+
validateField(item)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const onCheckboxChange = (values: (string | number)[], item: FormSchema) => {
|
|
61
|
+
model.value[item.field] = values
|
|
62
|
+
validateField(item)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const onSwitchChange = (value: boolean, item: FormSchema) => {
|
|
66
|
+
model.value[item.field] = value
|
|
67
|
+
validateField(item)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const onRateChange = (value: number, item: FormSchema) => {
|
|
71
|
+
model.value[item.field] = value
|
|
72
|
+
validateField(item)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const onSliderChange = (value: number, item: FormSchema) => {
|
|
76
|
+
model.value[item.field] = value
|
|
77
|
+
validateField(item)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const onFormSubmit = async (e: UniFormSubmitEvent): Promise<{ valid: boolean, values: any }> => {
|
|
81
|
+
Object.keys(errors).forEach(k => delete errors[k])
|
|
82
|
+
|
|
83
|
+
let hasError = false
|
|
84
|
+
for (const item of props.schemas) {
|
|
85
|
+
validateField(item)
|
|
86
|
+
if (item.required && !model.value[item.field]) {
|
|
87
|
+
hasError = true
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (hasError) {
|
|
92
|
+
console.warn('表单验证失败')
|
|
93
|
+
return { valid: false, values: null }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
await emit('submit', model.value)
|
|
98
|
+
return { valid: true, values: model.value }
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.error('表单提交失败:', err)
|
|
101
|
+
return { valid: false, values: null }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const onFormReset = () => {
|
|
106
|
+
Object.keys(model.value).forEach(k => (model.value[k] = ''))
|
|
107
|
+
Object.keys(errors).forEach(k => delete errors[k])
|
|
108
|
+
emit('reset')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
defineExpose({
|
|
112
|
+
submit: async () => {
|
|
113
|
+
return await onFormSubmit({} as UniFormSubmitEvent)
|
|
114
|
+
},
|
|
115
|
+
reset: () => {
|
|
116
|
+
onFormReset()
|
|
117
|
+
},
|
|
118
|
+
validate: () => {
|
|
119
|
+
Object.keys(errors).forEach(k => delete errors[k])
|
|
120
|
+
let hasError = false
|
|
121
|
+
for (const item of props.schemas) {
|
|
122
|
+
validateField(item)
|
|
123
|
+
if (item.required && !model.value[item.field]) {
|
|
124
|
+
hasError = true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return !hasError
|
|
128
|
+
},
|
|
129
|
+
getFormData: () => ({ ...model.value }),
|
|
130
|
+
getErrors: () => ({ ...errors })
|
|
131
|
+
})
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<template>
|
|
135
|
+
<view class="t-form">
|
|
136
|
+
<form @submit="onFormSubmit" @reset="onFormReset">
|
|
137
|
+
<view v-for="(item, index) in schemas" class="form-item" :key="index">
|
|
138
|
+
<view class="form-label" :style="{ width: labelWidth }">
|
|
139
|
+
<text>{{ item.label }}</text>
|
|
140
|
+
<text v-if="item.required" class="required">*</text>
|
|
141
|
+
</view>
|
|
142
|
+
|
|
143
|
+
<view class="form-control">
|
|
144
|
+
<!-- 自定义插槽 -->
|
|
145
|
+
<slot v-if="$slots[item.field]" :name="item.field" :item="item" :value="model[item.field]" :error="errors[item.field]"></slot>
|
|
146
|
+
|
|
147
|
+
<!-- 输入框 -->
|
|
148
|
+
<input v-else-if="item.component === 'Input'"
|
|
149
|
+
v-model="model[item.field]"
|
|
150
|
+
:placeholder="handlePlaceholder(item)"
|
|
151
|
+
:name="item.field"
|
|
152
|
+
class="input"
|
|
153
|
+
v-bind="item.componentProps || {}"
|
|
154
|
+
@input="validateField(item)" />
|
|
155
|
+
|
|
156
|
+
<!-- 数字输入 -->
|
|
157
|
+
<input v-else-if="item.component === 'InputNumber'"
|
|
158
|
+
v-model="model[item.field]"
|
|
159
|
+
:placeholder="handlePlaceholder(item)"
|
|
160
|
+
type="number"
|
|
161
|
+
:name="item.field"
|
|
162
|
+
class="input"
|
|
163
|
+
v-bind="item.componentProps || {}"
|
|
164
|
+
@input="validateField(item)" />
|
|
165
|
+
|
|
166
|
+
<!-- 文本域 -->
|
|
167
|
+
<textarea v-else-if="item.component === 'Textarea'"
|
|
168
|
+
v-model="model[item.field]"
|
|
169
|
+
:placeholder="handlePlaceholder(item)"
|
|
170
|
+
:name="item.field"
|
|
171
|
+
class="textarea"
|
|
172
|
+
v-bind="item.componentProps || {}"
|
|
173
|
+
@input="validateField(item)"></textarea>
|
|
174
|
+
|
|
175
|
+
<!-- 下拉选择 -->
|
|
176
|
+
<picker v-else-if="item.component === 'Select'"
|
|
177
|
+
mode="selector"
|
|
178
|
+
:name="item.field"
|
|
179
|
+
:range="handleRange(item)"
|
|
180
|
+
v-bind="item.componentProps || {}"
|
|
181
|
+
@change="onSelectChange($event, item)">
|
|
182
|
+
<view class="picker">
|
|
183
|
+
{{ getSelectLabel(item) || '请选择' }}
|
|
184
|
+
</view>
|
|
185
|
+
</picker>
|
|
186
|
+
|
|
187
|
+
<!-- 日期选择 -->
|
|
188
|
+
<picker v-else-if="item.component === 'Date'"
|
|
189
|
+
mode="date"
|
|
190
|
+
:name="item.field"
|
|
191
|
+
:value="model[item.field]"
|
|
192
|
+
v-bind="item.componentProps || {}"
|
|
193
|
+
@change="onTimeChange($event, item)">
|
|
194
|
+
<view class="picker">
|
|
195
|
+
{{ model[item.field] || '请选择日期' }}
|
|
196
|
+
</view>
|
|
197
|
+
</picker>
|
|
198
|
+
|
|
199
|
+
<!-- 时间选择 -->
|
|
200
|
+
<picker v-else-if="item.component === 'Time'"
|
|
201
|
+
mode="time"
|
|
202
|
+
:name="item.field"
|
|
203
|
+
:value="model[item.field]"
|
|
204
|
+
v-bind="item.componentProps || {}"
|
|
205
|
+
@change="onTimeChange($event, item)">
|
|
206
|
+
<view class="picker">
|
|
207
|
+
{{ model[item.field] || '请选择时间' }}
|
|
208
|
+
</view>
|
|
209
|
+
</picker>
|
|
210
|
+
|
|
211
|
+
<!-- 单选 -->
|
|
212
|
+
<view v-else-if="item.component === 'Radio'" class="radio-group">
|
|
213
|
+
<TRadioButton
|
|
214
|
+
v-for="opt in (item.componentProps?.options as FormOption[])"
|
|
215
|
+
:key="opt.value"
|
|
216
|
+
:label="opt.label"
|
|
217
|
+
:value="opt.value"
|
|
218
|
+
:checked="model[item.field] === opt.value"
|
|
219
|
+
v-bind="item.componentProps || {}"
|
|
220
|
+
@change="onRadioChange(opt.value, item)" />
|
|
221
|
+
</view>
|
|
222
|
+
|
|
223
|
+
<!-- 多选 -->
|
|
224
|
+
<view v-else-if="item.component === 'Checkbox'" class="checkbox-group">
|
|
225
|
+
<TCheckbox
|
|
226
|
+
v-for="opt in (item.componentProps?.options as FormOption[])"
|
|
227
|
+
:key="opt.value"
|
|
228
|
+
:label="opt.label"
|
|
229
|
+
:value="opt.value"
|
|
230
|
+
:checked="(model[item.field] || []).includes(opt.value)"
|
|
231
|
+
v-bind="item.componentProps || {}"
|
|
232
|
+
@change="(checked) => {
|
|
233
|
+
const values = model[item.field] || []
|
|
234
|
+
if (checked) {
|
|
235
|
+
values.push(opt.value)
|
|
236
|
+
} else {
|
|
237
|
+
const index = values.indexOf(opt.value)
|
|
238
|
+
if (index > -1) values.splice(index, 1)
|
|
239
|
+
}
|
|
240
|
+
onCheckboxChange(values, item)
|
|
241
|
+
}" />
|
|
242
|
+
</view>
|
|
243
|
+
|
|
244
|
+
<!-- 开关 -->
|
|
245
|
+
<TSwitch v-else-if="item.component === 'Switch'"
|
|
246
|
+
:checked="model[item.field]"
|
|
247
|
+
v-bind="item.componentProps || {}"
|
|
248
|
+
@change="onSwitchChange($event, item)" />
|
|
249
|
+
|
|
250
|
+
<!-- 评分 -->
|
|
251
|
+
<TRate v-else-if="item.component === 'Rate'"
|
|
252
|
+
:value="model[item.field] || 0"
|
|
253
|
+
v-bind="item.componentProps || {}"
|
|
254
|
+
@change="onRateChange($event, item)" />
|
|
255
|
+
|
|
256
|
+
<!-- 滑块 -->
|
|
257
|
+
<TSlider v-else-if="item.component === 'Slider'"
|
|
258
|
+
:value="model[item.field] || 0"
|
|
259
|
+
v-bind="item.componentProps || {}"
|
|
260
|
+
@change="onSliderChange($event, item)" />
|
|
261
|
+
</view>
|
|
262
|
+
|
|
263
|
+
<!-- 错误提示 -->
|
|
264
|
+
<view v-if="errors[item.field]" class="error-message">
|
|
265
|
+
<text>{{ errors[item.field] }}</text>
|
|
266
|
+
</view>
|
|
267
|
+
</view>
|
|
268
|
+
|
|
269
|
+
<!-- 按钮区域 -->
|
|
270
|
+
<view v-if="!hideButtons" class="form-footer">
|
|
271
|
+
<button class="btn btn-submit" form-type="submit">提交</button>
|
|
272
|
+
<button class="btn btn-reset" form-type="reset">重置</button>
|
|
273
|
+
</view>
|
|
274
|
+
</form>
|
|
275
|
+
</view>
|
|
276
|
+
</template>
|
|
277
|
+
|
|
278
|
+
<style lang="scss" scoped>
|
|
279
|
+
.t-form {
|
|
280
|
+
padding: 32rpx;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.form-item {
|
|
284
|
+
margin-bottom: 32rpx;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.form-label {
|
|
288
|
+
display: flex;
|
|
289
|
+
flex-direction: row;
|
|
290
|
+
align-items: center;
|
|
291
|
+
margin-bottom: 16rpx;
|
|
292
|
+
font-size: 28rpx;
|
|
293
|
+
color: #333;
|
|
294
|
+
font-weight: 500;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.required {
|
|
298
|
+
color: #ff4d4f;
|
|
299
|
+
margin-left: 4rpx;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.form-control {
|
|
303
|
+
width: 100%;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.input,
|
|
307
|
+
.textarea,
|
|
308
|
+
.picker {
|
|
309
|
+
width: 100%;
|
|
310
|
+
padding: 20rpx 24rpx;
|
|
311
|
+
font-size: 28rpx;
|
|
312
|
+
color: #333;
|
|
313
|
+
background-color: #f5f5f5;
|
|
314
|
+
border-radius: 8rpx;
|
|
315
|
+
border: 1rpx solid #e0e0e0;
|
|
316
|
+
transition: all 0.3s;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.input:focus,
|
|
320
|
+
.textarea:focus {
|
|
321
|
+
background-color: #fff;
|
|
322
|
+
border-color: #007aff;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.textarea {
|
|
326
|
+
min-height: 120rpx;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.picker {
|
|
330
|
+
display: flex;
|
|
331
|
+
align-items: center;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.radio-group,
|
|
335
|
+
.checkbox-group {
|
|
336
|
+
display: flex;
|
|
337
|
+
flex-direction: column;
|
|
338
|
+
gap: 16rpx;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.error-message {
|
|
342
|
+
margin-top: 8rpx;
|
|
343
|
+
font-size: 24rpx;
|
|
344
|
+
color: #ff4d4f;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.form-footer {
|
|
348
|
+
display: flex;
|
|
349
|
+
flex-direction: row;
|
|
350
|
+
gap: 24rpx;
|
|
351
|
+
margin-top: 48rpx;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.btn {
|
|
355
|
+
flex: 1;
|
|
356
|
+
height: 88rpx;
|
|
357
|
+
line-height: 88rpx;
|
|
358
|
+
text-align: center;
|
|
359
|
+
font-size: 32rpx;
|
|
360
|
+
border-radius: 8rpx;
|
|
361
|
+
transition: all 0.3s;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.btn-submit {
|
|
365
|
+
background-color: #007aff;
|
|
366
|
+
color: #fff;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.btn-reset {
|
|
370
|
+
background-color: #fff;
|
|
371
|
+
color: #007aff;
|
|
372
|
+
border: 1rpx solid #007aff;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.btn:active {
|
|
376
|
+
opacity: 0.7;
|
|
377
|
+
transform: scale(0.98);
|
|
378
|
+
}
|
|
379
|
+
</style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 表单选项类型
|
|
3
|
+
*/
|
|
4
|
+
export type FormOption = {
|
|
5
|
+
label: string
|
|
6
|
+
value: string | number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 组件通用属性
|
|
11
|
+
*/
|
|
12
|
+
export type ComponentProps = {
|
|
13
|
+
/** 占位符 */
|
|
14
|
+
placeholder?: string
|
|
15
|
+
/** 是否禁用 */
|
|
16
|
+
disabled?: boolean
|
|
17
|
+
/** 选项列表(用于 select、radio、checkbox) */
|
|
18
|
+
options?: FormOption[]
|
|
19
|
+
/** 输入类型(用于 input) */
|
|
20
|
+
type?: string
|
|
21
|
+
/** 最大长度(用于 input、textarea) */
|
|
22
|
+
maxlength?: number
|
|
23
|
+
/** 最小值(用于 number、slider) */
|
|
24
|
+
min?: number
|
|
25
|
+
/** 最大值(用于 number、slider、rate) */
|
|
26
|
+
max?: number
|
|
27
|
+
/** 步长(用于 slider) */
|
|
28
|
+
step?: number
|
|
29
|
+
/** 是否自动聚焦(用于 input、textarea) */
|
|
30
|
+
focus?: boolean
|
|
31
|
+
/** 确认按钮文字(用于 input) */
|
|
32
|
+
confirmType?: string
|
|
33
|
+
/** 是否自动高度(用于 textarea) */
|
|
34
|
+
autoHeight?: boolean
|
|
35
|
+
/** 是否显示确认栏(用于 textarea) */
|
|
36
|
+
showConfirmBar?: boolean
|
|
37
|
+
/** 开始日期(用于 date) */
|
|
38
|
+
start?: string
|
|
39
|
+
/** 结束日期(用于 date) */
|
|
40
|
+
end?: string
|
|
41
|
+
/** 激活颜色(用于 switch) */
|
|
42
|
+
color?: string
|
|
43
|
+
/** 是否允许半星(用于 rate) */
|
|
44
|
+
allowHalf?: boolean
|
|
45
|
+
/** 是否显示值(用于 slider) */
|
|
46
|
+
showValue?: boolean
|
|
47
|
+
/** 其他扩展属性 */
|
|
48
|
+
[key: string]: any
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 表单字段配置
|
|
53
|
+
*/
|
|
54
|
+
export type FormSchema = {
|
|
55
|
+
/** 字段名 */
|
|
56
|
+
field: string
|
|
57
|
+
/** 标签文本 */
|
|
58
|
+
label: string
|
|
59
|
+
/** 组件类型 */
|
|
60
|
+
component: 'Input' | 'Textarea' | 'Select' | 'Date' | 'Time' | 'Radio' | 'Checkbox' | 'Switch' | 'Rate' | 'Slider' | 'InputNumber'
|
|
61
|
+
/** 是否必填 */
|
|
62
|
+
required?: boolean
|
|
63
|
+
/** 组件属性 */
|
|
64
|
+
componentProps?: ComponentProps
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 表单组件属性
|
|
69
|
+
*/
|
|
70
|
+
export type TFormProps = {
|
|
71
|
+
/** 表单配置 */
|
|
72
|
+
schemas: FormSchema[]
|
|
73
|
+
/** 标签宽度 */
|
|
74
|
+
labelWidth?: string
|
|
75
|
+
/** 是否隐藏默认按钮 */
|
|
76
|
+
hideButtons?: boolean
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 导出所有类型
|
|
80
|
+
export { FormOption, ComponentProps, FormSchema, TFormProps }
|
package/index.uts
CHANGED
|
@@ -1,107 +1,108 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tang UI - UniApp X UI 组件库
|
|
3
|
-
* @description 基于 uni-app x 的移动端 UI 组件库
|
|
4
|
-
* @version 1.0.2
|
|
5
|
-
* @author sugar258596
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 注意:uni-app x 项目推荐使用 easycom 自动导入组件
|
|
10
|
-
*
|
|
11
|
-
* 在 pages.json 中配置:
|
|
12
|
-
* {
|
|
13
|
-
* "easycom": {
|
|
14
|
-
* "autoscan": true,
|
|
15
|
-
* "custom": {
|
|
16
|
-
* "^T(.*)": "tang-ui-x/components/T$1/index.uvue"
|
|
17
|
-
* }
|
|
18
|
-
* }
|
|
19
|
-
* }
|
|
20
|
-
*
|
|
21
|
-
* 然后在页面中直接使用:
|
|
22
|
-
* <TButton type="primary">按钮</TButton>
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
// 导出工具函数
|
|
26
|
-
export * from './utils/index.uts'
|
|
27
|
-
|
|
28
|
-
// 导出 composables
|
|
29
|
-
export { useTheme } from './composables/useTheme.uts'
|
|
30
|
-
export { useToast } from './composables/useToast.uts'
|
|
31
|
-
export { useModal } from './composables/useModal.uts'
|
|
32
|
-
|
|
33
|
-
// 版本信息
|
|
34
|
-
export const version: string = '1.0.5'
|
|
35
|
-
|
|
36
|
-
// 组件列表(用于文档和类型提示)
|
|
37
|
-
export const components: string[] = [
|
|
38
|
-
// 基础组件
|
|
39
|
-
'TButton',
|
|
40
|
-
'TIcon',
|
|
41
|
-
'TText',
|
|
42
|
-
'TImage',
|
|
43
|
-
'TDivider',
|
|
44
|
-
|
|
45
|
-
// 布局组件
|
|
46
|
-
'TCard',
|
|
47
|
-
'TList',
|
|
48
|
-
'TListItem',
|
|
49
|
-
'TCell',
|
|
50
|
-
'TGrid',
|
|
51
|
-
'TGridItem',
|
|
52
|
-
'TRow',
|
|
53
|
-
'TCol',
|
|
54
|
-
|
|
55
|
-
// 表单组件
|
|
56
|
-
'TInput',
|
|
57
|
-
'TNumberInput',
|
|
58
|
-
'TTextarea',
|
|
59
|
-
'TSearchBar',
|
|
60
|
-
'TSwitch',
|
|
61
|
-
'TCheckbox',
|
|
62
|
-
'TCheckboxGroup',
|
|
63
|
-
'TRadioButton',
|
|
64
|
-
'TRadioGroup',
|
|
65
|
-
'TSelect',
|
|
66
|
-
'TSlider',
|
|
67
|
-
'TRate',
|
|
68
|
-
'TPicker',
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'
|
|
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
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Tang UI - UniApp X UI 组件库
|
|
3
|
+
* @description 基于 uni-app x 的移动端 UI 组件库
|
|
4
|
+
* @version 1.0.2
|
|
5
|
+
* @author sugar258596
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 注意:uni-app x 项目推荐使用 easycom 自动导入组件
|
|
10
|
+
*
|
|
11
|
+
* 在 pages.json 中配置:
|
|
12
|
+
* {
|
|
13
|
+
* "easycom": {
|
|
14
|
+
* "autoscan": true,
|
|
15
|
+
* "custom": {
|
|
16
|
+
* "^T(.*)": "tang-ui-x/components/T$1/index.uvue"
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* 然后在页面中直接使用:
|
|
22
|
+
* <TButton type="primary">按钮</TButton>
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// 导出工具函数
|
|
26
|
+
export * from './utils/index.uts'
|
|
27
|
+
|
|
28
|
+
// 导出 composables
|
|
29
|
+
export { useTheme } from './composables/useTheme.uts'
|
|
30
|
+
export { useToast } from './composables/useToast.uts'
|
|
31
|
+
export { useModal } from './composables/useModal.uts'
|
|
32
|
+
|
|
33
|
+
// 版本信息
|
|
34
|
+
export const version: string = '1.0.5'
|
|
35
|
+
|
|
36
|
+
// 组件列表(用于文档和类型提示)
|
|
37
|
+
export const components: string[] = [
|
|
38
|
+
// 基础组件
|
|
39
|
+
'TButton',
|
|
40
|
+
'TIcon',
|
|
41
|
+
'TText',
|
|
42
|
+
'TImage',
|
|
43
|
+
'TDivider',
|
|
44
|
+
|
|
45
|
+
// 布局组件
|
|
46
|
+
'TCard',
|
|
47
|
+
'TList',
|
|
48
|
+
'TListItem',
|
|
49
|
+
'TCell',
|
|
50
|
+
'TGrid',
|
|
51
|
+
'TGridItem',
|
|
52
|
+
'TRow',
|
|
53
|
+
'TCol',
|
|
54
|
+
|
|
55
|
+
// 表单组件
|
|
56
|
+
'TInput',
|
|
57
|
+
'TNumberInput',
|
|
58
|
+
'TTextarea',
|
|
59
|
+
'TSearchBar',
|
|
60
|
+
'TSwitch',
|
|
61
|
+
'TCheckbox',
|
|
62
|
+
'TCheckboxGroup',
|
|
63
|
+
'TRadioButton',
|
|
64
|
+
'TRadioGroup',
|
|
65
|
+
'TSelect',
|
|
66
|
+
'TSlider',
|
|
67
|
+
'TRate',
|
|
68
|
+
'TPicker',
|
|
69
|
+
'TForm',
|
|
70
|
+
|
|
71
|
+
// 数据展示
|
|
72
|
+
'Tags',
|
|
73
|
+
'TBadge',
|
|
74
|
+
'TAvatar',
|
|
75
|
+
'TProgress',
|
|
76
|
+
'TNoticeBar',
|
|
77
|
+
'TCollapse',
|
|
78
|
+
'TCollapseItem',
|
|
79
|
+
'TEmpty',
|
|
80
|
+
'TErrorState',
|
|
81
|
+
'TSwiper',
|
|
82
|
+
|
|
83
|
+
// 反馈组件
|
|
84
|
+
'TLoading',
|
|
85
|
+
'TToast',
|
|
86
|
+
'TDialog',
|
|
87
|
+
'TPopup',
|
|
88
|
+
'TActionSheet',
|
|
89
|
+
|
|
90
|
+
// 导航组件
|
|
91
|
+
'Tabs',
|
|
92
|
+
'TNavBar'
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Tang UI 插件
|
|
97
|
+
*/
|
|
98
|
+
const TangUI = {
|
|
99
|
+
install(app: any) {
|
|
100
|
+
// uni-app x 使用 easycom 自动导入组件,这里不需要注册组件
|
|
101
|
+
console.log('Tang UI X installed, version:', version)
|
|
102
|
+
},
|
|
103
|
+
version,
|
|
104
|
+
components
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 默认导出
|
|
108
|
+
export default TangUI
|