<template>
<div :class="$options.name">
<div class="keyboard">
<div class="key-row">
<div class="key" v-for="(a, i) in rows[0]" :key="i" @mousedown="mousedown(a)">
{{ a }}
</div>
</div>
<div class="key-row" v-for="(a, i) in rows" :key="i">
<div
class="key"
v-for="(key, subIndex) in rows[i + 1]"
:key="subIndex"
@mousedown="mousedown(getChar(key))"
>
{{ getChar(key) }}
</div>
</div>
<div class="key-row">
<div
class="key key-wide capsLock"
:capsLock="capsLock"
:active="capsLock"
@mousedown="toggleCaps"
>
切换为{{ capsLock ? `小` : `大` }}写
</div>
<div class="key key-space" @mousedown="mousedown(` `)">空格</div>
<div class="key key-wide back-btn" @mousedown="handleBackspace">退格</div>
<div class="key key-wide clear-btn" @mousedown="clearAll">清空</div>
</div>
<div class="close-btn" @click="$emit(`close`, true)" v-if="showCloseBtn">
<i class="el-icon-close" />
</div>
</div>
</div>
</template>
<script>
export default {
name: `sgKeyboard`,
data() {
return {
keyword: ``,
capsLock: false,
rows: [
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
[`a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`, `i`, `j`],
[`k`, `l`, `m`, `n`, `o`, `p`, `q`, `r`, `s`, `t`],
[`u`, `v`, `w`, `x`, `y`, `z`],
],
showCloseBtn: false,
};
},
props: [`value`, `data`],
watch: {
value: {
handler(d) {
this.keyword = d;
},
deep: true,
immediate: true,
},
keyword(d) {
this.$emit(`input`, d);
},
data: {
handler(newValue, oldValue) {
//console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
if (Object.keys(newValue || {}).length) {
this.form = this.$g.deepCopy(newValue);
this.$g.cF2CP(`disabled`, this);
this.$g.cF2CP(`showCloseBtn`, this);
}
},
deep: true,
immediate: true,
},
},
methods: {
getChar(char) {
return this.capsLock ? char.toUpperCase() : char;
},
mousedown(char) {
this.keyword += char;
},
handleBackspace() {
this.keyword.length > 0 &&
(this.keyword = this.keyword.slice(0, this.keyword.length - 1));
},
toggleCaps() {
this.capsLock = !this.capsLock;
},
clearAll() {
this.keyword = ``;
},
},
};
</script>
<style lang="scss" scoped>
.sgKeyboard {
.keyboard {
position: relative;
width: max-content;
height: max-content;
box-sizing: border-box;
border: 1px solid #c6d1de;
box-shadow: 0 5px 11px 0 #00000033;
padding: 10px;
background-color: #efefef;
border-radius: 6px;
color: #5e6d82;
.key-row {
display: flex;
gap: 4px;
margin-bottom: 4px;
}
.key {
display: flex;
justify-content: center;
align-items: center;
min-width: 36px;
height: 36px;
text-align: center;
background-color: #fff;
border: none;
border-radius: 4px;
font-size: 14px;
font-family: Microsoft YaHei;
box-shadow: 0 3px 5px 0 #00000044;
cursor: pointer;
box-sizing: border-box;
border: 1px solid transparent;
&:hover {
background-color: #fafafa;
}
&:active,
&[active] {
transform: translate(0px, 1px);
/*从上往下线性渐变背景*/
background: linear-gradient(white, lightgray);
box-shadow: 0 2px 3px 0 #00000022;
}
&[active] {
border-color: #555;
border-top: none;
}
}
.key-wide {
padding: 0 10px;
}
.capsLock {
&[capsLock] {
color: white;
background: #7d7d7d;
}
}
.key-space {
flex-grow: 1;
}
.back-btn {
width: 50px;
}
.clear-btn {
width: 50px;
}
.close-btn {
position: absolute;
right: -10px;
top: -10px;
color: #c6d1de;
background-color: white;
box-sizing: border-box;
border: 1px solid #c6d1de;
box-shadow: 0 5px 10px 0 #00000033;
border-radius: 88px;
box-sizing: border-box;
width: 20px;
height: 20px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
i {
font-size: 12px;
}
&:hover {
color: white;
background-color: #c6d1de;
}
&:active {
transform: translate(1px, 1px);
opacity: 0.618;
}
}
}
}
</style>