index.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <template>
  2. <div :style="{ width: item.width ? item.width + 'px' : '100%' }">
  3. <v-text-field
  4. v-model.trim="value"
  5. variant="outlined"
  6. :density="item.dense || 'compact'"
  7. :type="inputType"
  8. :rules="item.rules"
  9. :disabled="item.disabled"
  10. :style="{width: item.width}"
  11. :color="item.color || 'primary'"
  12. :label="item.label"
  13. :placeholder="item.placeholder || item.label"
  14. :autofocus="item.autofocus"
  15. :required="item.required"
  16. :class="item.class"
  17. :suffix="item.suffix"
  18. :append-icon="item.appendIcon"
  19. :append-inner-icon="item.appendInnerIcon"
  20. :clearable="item.clearable"
  21. :readonly="item.readonly"
  22. :counter="item.counter"
  23. :prepend-inner-icon="item.prependInnerIcon"
  24. hide-spin-buttons
  25. :hide-details="item.hideDetails || false"
  26. @wheel="$event => handleWheel($event, item)"
  27. @update:modelValue="modelValueUpDate"
  28. @click:append="appendClick"
  29. @click:append-inner="appendInnerClick"
  30. @keyup.enter="handleKeyup"
  31. @click:clear="handleClear"
  32. @blur="handleBlur"
  33. @focus="handleFocus"
  34. >
  35. <slot name="default"></slot>
  36. </v-text-field>
  37. </div>
  38. </template>
  39. <script setup>
  40. import { useI18n } from '@/hooks/web/useI18n'; const { t } = useI18n()
  41. import { debounce } from 'lodash'
  42. import { ref, watch } from 'vue';
  43. defineOptions({ name:'FormUI-v-text-field'})
  44. const props = defineProps({item: Object, modelValue: [String, Number]})
  45. const emit = defineEmits(['update:modelValue', 'change', 'appendClick', 'appendInnerClick', 'enter', 'blur', 'focus'])
  46. const item = props.item
  47. const inputType = ref(item.type === 'phoneNumber' ? 'number' : item.type)
  48. const value = ref('')
  49. if (props.modelValue && typeof props.modelValue === 'string') value.value = props.modelValue.replace(/&amp;/g, '&')
  50. const searchDebouncedTime = item?.searchDebouncedTime === 0 ? ref(0) : ref(500)
  51. if (inputType.value === 'number' && item.integer) searchDebouncedTime.value = 0
  52. const valueDeal = (val) => {
  53. let dealData = val
  54. if (inputType.value === 'number') {
  55. if (item.integer) { // 为true时只能输入整型
  56. dealData = val.replace(/\D/g,'') - 0
  57. }
  58. }
  59. return dealData
  60. }
  61. watch(() => props.modelValue, (newVal) => {
  62. const dealData = valueDeal(newVal)
  63. value.value = dealData ? typeof dealData === 'string' ? dealData.replace(/&amp;/g, '&') : dealData : ''
  64. })
  65. const modelValueUpDate = (val) => {
  66. value.value = val
  67. emit('update:modelValue', value.value)
  68. debouncedCallbackUpDate(value.value) // emit('change', value.value)
  69. }
  70. const debouncedCallbackUpDate = debounce(newValue => {
  71. emit('change', newValue)
  72. }, searchDebouncedTime.value)
  73. const appendClick = () => {
  74. if (item.appendClick) item.appendClick()
  75. emit('appendClick', value.value)
  76. }
  77. const appendInnerClick = () => {
  78. if (item.password) {
  79. inputType.value = inputType.value === 'password' ? 'text' : 'password'
  80. item.appendInnerIcon = inputType.value === 'password' ? 'mdi-eye-off-outline' : 'mdi-eye-outline'
  81. }
  82. if (item.appendInnerClick) item.appendInnerClick(value.value)
  83. else emit('appendInnerClick', value.value)
  84. }
  85. const handleClear = () => {
  86. emit('enter', value.value)
  87. }
  88. const handleKeyup = () => {
  89. emit('enter', value.value)
  90. }
  91. const handleBlur = () => {
  92. emit('blur', props.item, value.value)
  93. }
  94. const handleFocus = () => {
  95. emit('focus', props.item, value.value)
  96. }
  97. const handleWheel = (event, item) => {
  98. if (item.type !== 'number') return
  99. event.preventDefault()
  100. if (event.deltaY > 0) {
  101. item.value--
  102. } else {
  103. item.value++
  104. }
  105. }
  106. if (item.type === 'phoneNumber') {
  107. const phoneRules = [v => !v || v?.length <= 11 && /^1[3456789]\d{9}$/.test(v) || t('login.correctPhoneNumber')]
  108. item.rules = item.rules ? [ ...phoneRules, ...item.rules] : phoneRules
  109. item.counter = item.counter ? item.counter : 11
  110. }
  111. </script>
  112. <style lang="scss" scoped>
  113. </style>