59 lines
2.8 KiB
Vue
59 lines
2.8 KiB
Vue
<template>
|
|
<view
|
|
class="scan-target-input"
|
|
:class="{ 'scan-target-input-active': active }"
|
|
@tap="$emit('activate', name)"
|
|
>
|
|
<view class="scan-target-icon" aria-hidden="true">
|
|
<view class="scan-target-corner corner-tl"></view>
|
|
<view class="scan-target-corner corner-tr"></view>
|
|
<view class="scan-target-corner corner-bl"></view>
|
|
<view class="scan-target-corner corner-br"></view>
|
|
<view class="scan-target-line"></view>
|
|
</view>
|
|
<input
|
|
class="scan-target-value"
|
|
:value="modelValue"
|
|
:placeholder="placeholder"
|
|
:aria-label="`${label},支持扫码或人工输入`"
|
|
confirm-type="done"
|
|
@focus="$emit('activate', name)"
|
|
@input="handleInput"
|
|
@confirm="handleConfirm"
|
|
/>
|
|
<text v-if="active" class="scan-target-badge">当前扫码</text>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
emits: ['activate', 'update:modelValue', 'submit'],
|
|
props: {
|
|
name: { type: String, required: true },
|
|
modelValue: { type: String, default: '' },
|
|
label: { type: String, default: '扫码输入框' },
|
|
placeholder: { type: String, default: '扫描或人工输入' },
|
|
active: Boolean
|
|
},
|
|
methods: {
|
|
handleInput(event) { this.$emit('update:modelValue', event.detail.value) },
|
|
handleConfirm(event) { this.$emit('submit', event.detail.value) }
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.scan-target-input { position: relative; box-sizing: border-box; width: 100%; height: 48px; border: 1px solid #cfd8e3; border-radius: 8px; background: #ffffff; }
|
|
.scan-target-input-active { border: 2px solid #135ee8; background: #f8fbff; box-shadow: 0 0 0 2px rgba(19, 94, 232, 0.14); }
|
|
.scan-target-icon { position: absolute; z-index: 1; left: 12px; top: 12px; width: 22px; height: 22px; color: #8190a3; pointer-events: none; }
|
|
.scan-target-input-active .scan-target-icon { left: 11px; top: 11px; color: #135ee8; }
|
|
.scan-target-corner { position: absolute; box-sizing: border-box; width: 6px; height: 6px; border-color: currentColor; }
|
|
.corner-tl { top: 0; left: 0; border-top: 2px solid; border-left: 2px solid; }
|
|
.corner-tr { top: 0; right: 0; border-top: 2px solid; border-right: 2px solid; }
|
|
.corner-bl { bottom: 0; left: 0; border-bottom: 2px solid; border-left: 2px solid; }
|
|
.corner-br { right: 0; bottom: 0; border-right: 2px solid; border-bottom: 2px solid; }
|
|
.scan-target-line { position: absolute; left: 4px; top: 10px; width: 14px; height: 2px; background: currentColor; }
|
|
.scan-target-value { box-sizing: border-box; width: 100%; height: 46px; padding: 0 82px 0 42px; border: 0; color: #27384d; font-size: 15px; background: transparent; }
|
|
.scan-target-badge { position: absolute; right: 8px; top: 12px; padding: 3px 6px; border-radius: 4px; color: #135ee8; font-size: 10px; font-weight: 700; line-height: 16px; pointer-events: none; background: #e7f0ff; }
|
|
</style>
|