tang-ui-x 1.1.4 → 1.1.5

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.
@@ -5,6 +5,7 @@
5
5
  import TSwitch from '../TSwitch/index.uvue'
6
6
  import TRate from '../TRate/index.uvue'
7
7
  import TSlider from '../TSlider/index.uvue'
8
+ import TSelect from '../TSelect/index.uvue'
8
9
  import type { FormOption, FormSchema, TFormProps, ComponentProps } from './type.uts'
9
10
  import { useI18n } from '../../composables/useI18n.uts'
10
11
 
@@ -52,23 +53,9 @@
52
53
  return $t('form.inputPlaceholder', { label: item.label })
53
54
  }
54
55
 
55
- const handleRange = (item : FormSchema) => {
56
+ const getSelectOptions = (item : FormSchema) => {
56
57
  const options = item.componentProps?.options as FormOption[] | undefined
57
- return options?.map(o => o.label) || []
58
- }
59
-
60
- const getSelectLabel = (item : FormSchema) => {
61
- const options = item.componentProps?.options as FormOption[] | undefined
62
- const opt = options?.find(o => o.value === model.value[item.field])
63
- return opt?.label || ''
64
- }
65
-
66
- const onSelectChange = (e : any, item : FormSchema) => {
67
- const index = e.detail.value as number
68
- const options = item.componentProps?.options as FormOption[] | undefined
69
- const value = options?.[index]?.value ?? ''
70
- model.value[item.field] = value
71
- validateField(item)
58
+ return options?.map(o => ({ label: o.label, value: o.value })) || []
72
59
  }
73
60
 
74
61
  const onTimeChange = (e : any, item : FormSchema) => {
@@ -79,11 +66,23 @@
79
66
  const validateField = (item : FormSchema) => {
80
67
  if (item.required && !model.value[item.field]) {
81
68
  errors[item.field] = $t('form.requiredError', { label: item.label })
69
+ // 触发抖动动画
70
+ triggerShake(item.field)
82
71
  } else {
83
72
  delete errors[item.field]
84
73
  }
85
74
  }
86
75
 
76
+ // 抖动动画状态
77
+ const shakeFields = reactive<Record<string, boolean>>({})
78
+
79
+ const triggerShake = (field : string) => {
80
+ shakeFields[field] = true
81
+ setTimeout(() => {
82
+ shakeFields[field] = false
83
+ }, 500)
84
+ }
85
+
87
86
  const onRadioChange = (value : string | number) => {
88
87
  // 值已通过 v-model 更新,只需验证
89
88
  }
@@ -164,7 +163,9 @@
164
163
  <template>
165
164
  <view class="t-form">
166
165
  <form @submit="onFormSubmit" @reset="onFormReset">
167
- <view v-for="(item, index) in schemas" class="form-item" :key="index">
166
+ <view v-for="(item, index) in schemas" class="form-item"
167
+ :class="{ 'form-item-error': errors[item.field], 'form-item-shake': shakeFields[item.field] }"
168
+ :key="index">
168
169
  <view class="form-item-content" :class="`form-item--${getItemLayout(item)}`">
169
170
  <view class="form-label" >
170
171
  <text class="text" :style="{ width: getItemLayout(item) === 'horizontal' ? getItemLabelWidth(item) : labelWidth }">{{ item.label }}</text>
@@ -192,13 +193,12 @@
192
193
  v-bind="item.componentProps || {}" @input="validateField(item)"></textarea>
193
194
 
194
195
  <!-- 下拉选择 -->
195
- <picker v-else-if="item.component === 'Select'" mode="selector" :name="item.field"
196
- :range="handleRange(item)" v-bind="item.componentProps || {}"
197
- @change="onSelectChange($event, item)">
198
- <view class="picker">
199
- {{ getSelectLabel(item) || $t('form.selectPlaceholder') }}
200
- </view>
201
- </picker>
196
+ <TSelect v-else-if="item.component === 'Select'"
197
+ v-model="model[item.field]"
198
+ :options="getSelectOptions(item)"
199
+ :placeholder="item.componentProps?.placeholder || $t('form.selectPlaceholder')"
200
+ v-bind="item.componentProps || {}"
201
+ @change="validateField(item)" />
202
202
 
203
203
  <!-- 日期选择 -->
204
204
  <picker v-else-if="item.component === 'Date'" mode="date" :name="item.field"
@@ -245,7 +245,7 @@
245
245
 
246
246
  <!-- 错误提示 -->
247
247
  <view v-if="errors[item.field]" class="error-message">
248
- <text>{{ errors[item.field] }}</text>
248
+ <text class="error-text">{{ errors[item.field] }}</text>
249
249
  </view>
250
250
  </view>
251
251
 
@@ -265,6 +265,31 @@
265
265
 
266
266
  .form-item {
267
267
  margin-bottom: 32rpx;
268
+ padding: 24rpx;
269
+ border-radius: 12rpx;
270
+ border: 2rpx solid transparent;
271
+ transition: all 0.3s ease;
272
+
273
+ &.form-item-error {
274
+ border-color: #ff4d4f;
275
+ background-color: #fff1f0;
276
+ }
277
+
278
+ &.form-item-shake {
279
+ animation: shake 0.5s ease-in-out;
280
+ }
281
+ }
282
+
283
+ @keyframes shake {
284
+ 0%, 100% {
285
+ transform: translateX(0);
286
+ }
287
+ 10%, 30%, 50%, 70%, 90% {
288
+ transform: translateX(-8rpx);
289
+ }
290
+ 20%, 40%, 60%, 80% {
291
+ transform: translateX(8rpx);
292
+ }
268
293
  }
269
294
 
270
295
  .form-item-content {
@@ -324,8 +349,7 @@
324
349
  }
325
350
 
326
351
  .input,
327
- .textarea,
328
- .picker {
352
+ .textarea {
329
353
  width: 100%;
330
354
  padding: 20rpx 24rpx;
331
355
  font-size: 28rpx;
@@ -346,13 +370,6 @@
346
370
  min-height: 120rpx;
347
371
  }
348
372
 
349
- .picker {
350
- display: flex;
351
- align-items: center;
352
- }
353
-
354
-
355
-
356
373
  .error-message {
357
374
  margin-top: 8rpx;
358
375
  font-size: 24rpx;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tang-ui-x",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "UniApp X UI 组件库 - 基于 uni-app x 的移动端 UI 组件库",
5
5
  "main": "index.uts",
6
6
  "module": "index.uts",