123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- <template>
- <view
- class="fs-field"
- :class="{
- 'fs-field-tighten': tighten
- }"
- :style="{ 'background-color': bgColor, borderRadius: round ? '80rpx' : '' }"
- >
- <view
- v-if="type === 'textarea'"
- class="fs-field-textarea"
- :class="{ 'fs-field-padding': !formItemPosition }"
- :style="{ height: height }"
- >
- <slot name="before"></slot>
- <textarea
- class="fs-textarea"
- placeholder-class="fs-ph-class"
- :class="{ clearable, 'fs-field-border': border }"
- :name="name"
- :placeholder="placeholder"
- :maxlength="maxlength"
- :disabled="disabled"
- :value="modelValue"
- :auto-height="autoHeight"
- :fixed="fixed"
- @input="handleInput"
- @focus="handleFocus"
- @blur="handleBlur"
- @confirm="handleConfirm"
- />
- <fs-icon
- class="fs-field-icon fs-field-icon-close"
- type="icon-guanbi2fill"
- size="20px"
- @touchstart="handleClear"
- v-if="clearable"
- ></fs-icon>
- <slot name="after"></slot>
- </view>
- <view class="fs-field-input" :class="{ 'fs-field-padding': !formItemPosition }" v-else>
- <view v-if="slots.before" style="padding-right: 10rpx;"><slot name="before"></slot></view>
- <input
- class="fs-input"
- placeholder-class="fs-ph-class"
- :class="{ clearable, 'fs-field-border': border }"
- :value="modelValue"
- :type="type"
- :password="type === 'password'"
- :placeholder="placeholder"
- :name="name"
- :maxlength="maxlength"
- :disabled="disabled"
- @input="handleInput"
- @focus="handleFocus"
- @blur="handleBlur"
- @confirm="handleConfirm"
- />
- <fs-icon
- class="fs-field-icon fs-field-icon-close"
- type="icon-close-circle"
- size="20px"
- @touchstart="handleClear"
- v-if="clearable && modelValue"
- ></fs-icon>
- <view v-if="slots.after" style="padding-left: 10rpx;"><slot name="after"></slot></view>
- </view>
- </view>
- </template>
- <script>
- /**
- * 输入框组件
- * @description 输入框组件
- * @property {String} placeholder 占位符
- * @property {String} type 输入框类型
- * @property {Number, String} maxlength 输入的最大字符数
- * @property {Boolean} disabled 是否禁用
- * @property {Boolean} border 是否显示边框
- * @property {Boolean} clearable 是否启用清除图标,点击清除图标后会清空输入框
- * @property {Boolean} autoHeight 仅对type=textarea有效
- * @property {Boolean} tighten 是否紧凑
- * @property {Boolean} fixed 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true
- * @property {Boolean} round 是否圆角
- * @property {String} height 输入框高度
- * @property {String} bgColor 背景颜色
- * @event {Function} focus 输入框聚焦事件
- * @event {Function} blur 输入框失去焦点事件
- * @event {Function} confirm 点击完成事件
- */
- export default {
- name: 'fs-field'
- }
- </script>
- <script setup>
- import { inject, computed, useSlots } from 'vue'
- const props = defineProps({
- modelValue: String,
- placeholder: String,
- name: String,
- type: {
- type: String,
- default: 'text'
- },
- maxlength: {
- type: [Number, String],
- default: 140
- },
- disabled: Boolean,
- border: Boolean,
- clearable: Boolean,
- autoHeight: Boolean,
- tighten: Boolean,
- fixed: Boolean,
- round: Boolean,
- height: {
- type: String,
- default: '70rpx'
- },
- bgColor: {
- type: String,
- default: '#fff'
- }
- })
- const emits = defineEmits(['update:modelValue', 'focus', 'blur', 'confirm'])
- const slots = useSlots()
- const formItemPosition = inject('form-item-position', '')
- const position = computed(() => props.labelPosition || formItemPosition)
- const handleInput = e => {
- emits('update:modelValue', e.detail.value)
- }
- const handleFocus = () => {
- emits('focus')
- }
- const handleBlur = e => {
- emits('blur', e.detail.value)
- }
- const handleConfirm = () => {
- emits('confirm')
- }
- const handleClear = () => {
- emits('update:modelValue', '')
- }
- </script>
- <style lang="scss" scoped>
- .fs-field {
- box-sizing: border-box;
- font-size: var(--content-size);
- overflow: hidden;
- &-input {
- display: flex;
- height: 70rpx;
- align-items: center;
- position: relative;
- background-color: inherit;
- }
- &-textarea {
- display: flex;
- width: 100%;
- align-items: center;
- position: relative;
- }
- &-padding {
- padding: 20rpx 30rpx;
- height: 90rpx;
- }
- &-border {
- border: 2rpx solid var(--border-color) !important;
- border-radius: 4rpx !important;
- &.fs-input,
- &.fs-textarea {
- padding: 20rpx;
- }
- }
- &-icon {
- position: absolute;
- top: 50%;
- transform: translateY(-50%);
- color: var(--sub);
- z-index: 10;
- }
- &-icon-close {
- right: var(--gutter);
- }
- &-opacity {
- background-color: rgba(255, 255, 255, 0.5);
- color: #fff;
- .fs-ph-class {
- color: #fff;
- }
- }
- &-tighten {
- padding: 0 var(--tighten-gutter);
- }
- &-round {
- border-radius: 35px;
- }
- }
- .fs-textarea,
- .fs-input {
- width: 100%;
- height: 100%;
- flex: 1;
- box-sizing: border-box !important;
- border-radius: 6rpx;
- border: none;
- outline: none;
- }
- .fs-input {
- background: transparent;
- &.fs-clearable {
- padding-right: 70rpx;
- }
- }
- .fs-ph-class {
- color: #c0c5ce;
- font-size: var(--content-size);
- }
- </style>
|