fs-field.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <template>
  2. <view
  3. class="fs-field"
  4. :class="{
  5. 'fs-field-tighten': tighten
  6. }"
  7. :style="{ 'background-color': bgColor, borderRadius: round ? '80rpx' : '' }"
  8. >
  9. <view
  10. v-if="type === 'textarea'"
  11. class="fs-field-textarea"
  12. :class="{ 'fs-field-padding': !formItemPosition }"
  13. :style="{ height: height }"
  14. >
  15. <slot name="before"></slot>
  16. <textarea
  17. class="fs-textarea"
  18. placeholder-class="fs-ph-class"
  19. :class="{ clearable, 'fs-field-border': border }"
  20. :name="name"
  21. :placeholder="placeholder"
  22. :maxlength="maxlength"
  23. :disabled="disabled"
  24. :value="modelValue"
  25. :auto-height="autoHeight"
  26. :fixed="fixed"
  27. @input="handleInput"
  28. @focus="handleFocus"
  29. @blur="handleBlur"
  30. @confirm="handleConfirm"
  31. />
  32. <fs-icon
  33. class="fs-field-icon fs-field-icon-close"
  34. type="icon-guanbi2fill"
  35. size="20px"
  36. @touchstart="handleClear"
  37. v-if="clearable"
  38. ></fs-icon>
  39. <slot name="after"></slot>
  40. </view>
  41. <view class="fs-field-input" :class="{ 'fs-field-padding': !formItemPosition }" v-else>
  42. <view v-if="slots.before" style="padding-right: 10rpx;"><slot name="before"></slot></view>
  43. <input
  44. class="fs-input"
  45. placeholder-class="fs-ph-class"
  46. :class="{ clearable, 'fs-field-border': border }"
  47. :value="modelValue"
  48. :type="type"
  49. :password="type === 'password'"
  50. :placeholder="placeholder"
  51. :name="name"
  52. :maxlength="maxlength"
  53. :disabled="disabled"
  54. @input="handleInput"
  55. @focus="handleFocus"
  56. @blur="handleBlur"
  57. @confirm="handleConfirm"
  58. />
  59. <fs-icon
  60. class="fs-field-icon fs-field-icon-close"
  61. type="icon-close-circle"
  62. size="20px"
  63. @touchstart="handleClear"
  64. v-if="clearable && modelValue"
  65. ></fs-icon>
  66. <view v-if="slots.after" style="padding-left: 10rpx;"><slot name="after"></slot></view>
  67. </view>
  68. </view>
  69. </template>
  70. <script>
  71. /**
  72. * 输入框组件
  73. * @description 输入框组件
  74. * @property {String} placeholder 占位符
  75. * @property {String} type 输入框类型
  76. * @property {Number, String} maxlength 输入的最大字符数
  77. * @property {Boolean} disabled 是否禁用
  78. * @property {Boolean} border 是否显示边框
  79. * @property {Boolean} clearable 是否启用清除图标,点击清除图标后会清空输入框
  80. * @property {Boolean} autoHeight 仅对type=textarea有效
  81. * @property {Boolean} tighten 是否紧凑
  82. * @property {Boolean} fixed 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true
  83. * @property {Boolean} round 是否圆角
  84. * @property {String} height 输入框高度
  85. * @property {String} bgColor 背景颜色
  86. * @event {Function} focus 输入框聚焦事件
  87. * @event {Function} blur 输入框失去焦点事件
  88. * @event {Function} confirm 点击完成事件
  89. */
  90. export default {
  91. name: 'fs-field'
  92. }
  93. </script>
  94. <script setup>
  95. import { inject, computed, useSlots } from 'vue'
  96. const props = defineProps({
  97. modelValue: String,
  98. placeholder: String,
  99. name: String,
  100. type: {
  101. type: String,
  102. default: 'text'
  103. },
  104. maxlength: {
  105. type: [Number, String],
  106. default: 140
  107. },
  108. disabled: Boolean,
  109. border: Boolean,
  110. clearable: Boolean,
  111. autoHeight: Boolean,
  112. tighten: Boolean,
  113. fixed: Boolean,
  114. round: Boolean,
  115. height: {
  116. type: String,
  117. default: '70rpx'
  118. },
  119. bgColor: {
  120. type: String,
  121. default: '#fff'
  122. }
  123. })
  124. const emits = defineEmits(['update:modelValue', 'focus', 'blur', 'confirm'])
  125. const slots = useSlots()
  126. const formItemPosition = inject('form-item-position', '')
  127. const position = computed(() => props.labelPosition || formItemPosition)
  128. const handleInput = e => {
  129. emits('update:modelValue', e.detail.value)
  130. }
  131. const handleFocus = () => {
  132. emits('focus')
  133. }
  134. const handleBlur = e => {
  135. emits('blur', e.detail.value)
  136. }
  137. const handleConfirm = () => {
  138. emits('confirm')
  139. }
  140. const handleClear = () => {
  141. emits('update:modelValue', '')
  142. }
  143. </script>
  144. <style lang="scss" scoped>
  145. .fs-field {
  146. box-sizing: border-box;
  147. font-size: var(--content-size);
  148. overflow: hidden;
  149. &-input {
  150. display: flex;
  151. height: 70rpx;
  152. align-items: center;
  153. position: relative;
  154. background-color: inherit;
  155. }
  156. &-textarea {
  157. display: flex;
  158. width: 100%;
  159. align-items: center;
  160. position: relative;
  161. }
  162. &-padding {
  163. padding: 20rpx 30rpx;
  164. height: 90rpx;
  165. }
  166. &-border {
  167. border: 2rpx solid var(--border-color) !important;
  168. border-radius: 4rpx !important;
  169. &.fs-input,
  170. &.fs-textarea {
  171. padding: 20rpx;
  172. }
  173. }
  174. &-icon {
  175. position: absolute;
  176. top: 50%;
  177. transform: translateY(-50%);
  178. color: var(--sub);
  179. z-index: 10;
  180. }
  181. &-icon-close {
  182. right: var(--gutter);
  183. }
  184. &-opacity {
  185. background-color: rgba(255, 255, 255, 0.5);
  186. color: #fff;
  187. .fs-ph-class {
  188. color: #fff;
  189. }
  190. }
  191. &-tighten {
  192. padding: 0 var(--tighten-gutter);
  193. }
  194. &-round {
  195. border-radius: 35px;
  196. }
  197. }
  198. .fs-textarea,
  199. .fs-input {
  200. width: 100%;
  201. height: 100%;
  202. flex: 1;
  203. box-sizing: border-box !important;
  204. border-radius: 6rpx;
  205. border: none;
  206. outline: none;
  207. }
  208. .fs-input {
  209. background: transparent;
  210. &.fs-clearable {
  211. padding-right: 70rpx;
  212. }
  213. }
  214. .fs-ph-class {
  215. color: #c0c5ce;
  216. font-size: var(--content-size);
  217. }
  218. </style>