键盘组件
<template>
<div
v-if="showKeyboard"
class="keyboard"
id="keyboardComp"
:class="[isHttp ? 'isHttp' : '', type + '_keyboard']"
@mousedown="handleTouchstart"
@touchstart="handleTouchstart"
>
<!--数字键盘-->
<div v-if="showNumKeycode" class="keyboard-num">
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td
:key="item.value"
:class="'td_' + item.value"
v-for="(item, index) in keycode.list['value0']"
@click="numkeycodeHandle(item)"
@touchstart="numkeycodeHandle(item)"
>
<div class="td-div">
<template v-if="item.value != 'del'">{{ item.label }}</template>
<template v-else>
<div
class="keyboard-num-del"
@mousedown="longPress('del')"
@mouseup="removePress('del')"
@touchstart="longPress('del')"
@touchend="removePress('del')"
>
<em class="iconfont icon-changyongicon-"></em>
</div>
</template>
</div>
</td>
</tr>
<tr>
<td
:key="item.value"
:rowspan="index == 3 ? 3 : 1"
v-for="(item, index) in keycode.list['value1']"
:class="'td_' + item.value"
@click="numkeycodeHandle(item)"
@touchstart="numkeycodeHandle(item)"
>
<div class="td-div">
<p>{{ item.label }}</p>
<p v-if="item.value == 'comfirm'">Enter</p>
</div>
</td>
</tr>
<tr>
<td
:key="item.value"
:class="'td_' + item.value"
v-for="(item, index) in keycode.list['value2']"
@click="numkeycodeHandle(item)"
@touchstart="numkeycodeHandle(item)"
>
<div class="td-div">{{ item.label }}</div>
</td>
</tr>
<tr>
<td
:key="item.value"
:class="'td_' + item.value"
:colspan="type == 'onlyNum_negative' ? 0 : index == 0 ? 2 : 1"
v-for="(item, index) in keycode.list['value3']"
@click.stop="numkeycodeHandle(item)"
@touchstart.stop.prevent="numkeycodeHandle(item)"
>
<div class="td-div" v-if="item.value != 'toggle'">
{{ item.label }}
</div>
<template v-else>
<div
v-if="showPoint"
class="point-item td-div"
@click.stop="numkeycodeHandle({ value: '.', label: '.' })"
@touchstart.stop="numkeycodeHandle({ value: '.', label: '.' })"
>
.
</div>
<div v-else class="toggle-item td-div">
<div class="toggle-item-num">数</div>
<div class="toggle-item-english">/英</div>
</div>
</template>
</td>
</tr>
</table>
</div>
<!--英文键盘-->
<div
v-if="showEnglishKeycode"
class="keyboard-english"
id="keyboardEnglish"
>
<!--数字-->
<div
v-if="type != 'showAll' && type != 'hotkey'"
class="keyboard-english-num"
>
<div
class="english-item"
v-for="item in englishKeycode.numlist"
:key="item.value"
@click="numkeycodeHandle(item)"
@touchstart="numkeycodeHandle(item)"
>
{{ item.label }}
</div>
</div>
<!--英文-->
<div class="english">
<div class="keyboard-english-num keyboard-english-english">
<div
class="english-item"
v-for="item in englishKeycode.englishlist"
:key="item.value"
@click="englishkeycodeHandle(item)"
@touchstart="englishkeycodeHandle(item)"
>
{{ item[isuppercase] }}
</div>
</div>
<div
class="keyboard-english-num keyboard-english-english secondenglishlist"
>
<div
class="english-item"
v-for="item in englishKeycode.secondenglishlist"
:key="item.value"
@click="englishkeycodeHandle(item)"
@touchstart="englishkeycodeHandle(item)"
>
{{ item[isuppercase] }}
</div>
</div>
<div
class="keyboard-english-num keyboard-english-english thirdenglishlist"
>
<div
class="english-item"
v-for="item in englishKeycode.thirdenglishlist"
:key="item.value"
@click="englishkeycodeHandle(item)"
@touchstart="englishkeycodeHandle(item)"
:class="{
toggleItem: item.value == 'toggle' || item.value == 'del'
}"
>
<div v-if="item.value == 'toggle'" class="english-item-toggle">
<em class="iconfont icon-ic_shift"></em>
</div>
{{ item[isuppercase] }}
<div
@mousedown="longPress(item.value)"
@mouseup="removePress(item.value)"
@touchstart="longPress(item.value)"
@touchend="removePress(item.value)"
v-if="item.value == 'del'"
class="english-item-toggle english-del-item"
>
<em class="iconfont icon-changyongicon-"></em>
</div>
</div>
</div>
<div
class="keyboard-english-num keyboard-english-english forthenglishlist"
>
<!--切换-->
<div
class="english-item toggleItem"
@click="toggleKeyCode(true, false, 'english')"
@touchstart="toggleKeyCode(true, false, 'english')"
v-if="type != 'showAll'"
>
<div class="toggleItem-num">数 /</div>
<div class="toggleItem-english">英</div>
</div>
<!--特殊字符-->
<div
class="english-item special-item"
@click="
toggleChar({
value: '#+=',
label: '#+=',
char: ''
})
"
@touchstart="
toggleChar({
value: '#+=',
label: '#+=',
char: ''
})
"
>
#+=
</div>
<div
v-if="isHttp"
class="english-item special-item colon-item"
@click="numkeycodeHandle({ value: ':', label: ':' })"
@touchstart="numkeycodeHandle({ value: ':', label: ':' })"
>
:
</div>
<!--空格-->
<div
class="english-item spacing-item"
@click="numkeycodeHandle({ value: ' ', label: 'spacing' })"
@touchstart="numkeycodeHandle({ value: ' ', label: 'spacing' })"
>
空格
</div>
<!--.-->
<div
class="english-item special-item"
v-if="type != 'showAll'"
@click="numkeycodeHandle({ value: '.', label: '.' })"
@touchstart="numkeycodeHandle({ value: '.', label: '.' })"
>
.
</div>
<!--搜索-->
<div
v-if="isHttp"
class="english-item toggleItem searchItem httpItem"
@click="numkeycodeHandle({ value: 'http://', label: 'http://' })"
@touchstart="
numkeycodeHandle({ value: 'http://', label: 'http://' })
"
>
http://
</div>
<!--全键盘显示收起键盘按钮-->
<div
v-if="type == 'showAll'"
class="english-item toggleItem hideItem"
@click="numkeycodeHandle({ value: 'hide', label: 'hide' })"
@touchstart="numkeycodeHandle({ value: 'hide', label: 'hide' })"
>
<em class="iconfont icon-ic_keyboard_expand"></em>
</div>
<div
v-else
class="english-item toggleItem searchItem"
@click="numkeycodeHandle({ value: 'search', label: 'search' })"
@touchstart="numkeycodeHandle({ value: 'search', label: 'search' })"
>
{{ type == 'login' ? '确定' : '搜索' }}
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {
reactive,
ref,
defineEmits,
defineExpose,
defineProps,
onMounted,
computed
} from 'vue'
import { useSoftwareStore } from '@/store/software'
const software = useSoftwareStore()
const props = defineProps<{
type: string
isHttp?: boolean // http格式
alwaysShow?: boolean // 是否一直显示键盘,不用区分键盘和触屏模式
showType?: string // 显示键盘类型
showSettingPage?: boolean // F1设置页面中展示键盘
isToogle?: boolean // 是否需要中英文切换
isLowercase?: boolean // 是否需要中英文切换
}>()
const showKeyboard = ref<boolean>(false) // 是否显示键盘
if (
software.softwareType == 1 ||
software.softwareType == 0 ||
// props.type == 'login' ||
// props.type == 'pay' ||
props.alwaysShow ||
props.showSettingPage
) {
showKeyboard.value = true // 触摸屏键盘都显示
}
onMounted(() => {
if (props.isLowercase) {
isuppercase.value = 'lowercase'
} else {
isuppercase.value = 'uppercase'
}
})
const handleTouchstart = (e: any) => {
e.preventDefault() // 阻止默认事件,解决点击键盘input会失去焦点
}
// 是否显示点
let showPoint = computed(() => {
return (
props.type == 'showAll' ||
props.type == 'pay' ||
props.type == 'changeGoodInfo' ||
props.type == 'memberRecharge' ||
props.type == 'onlyNum' ||
props.type == 'onlyNum_negative'
)
})
const showNumKeycode = ref<boolean>(true)
const showEnglishKeycode = ref<boolean>(false)
const keycode = reactive({
list: {
value0: [
{ value: 7, label: 7 },
{ value: 8, label: 8 },
{ value: 9, label: 9 },
{ value: 'del', label: 'del' }
],
value1: [
{ value: 4, label: 4 },
{ value: 5, label: 5 },
{ value: 6, label: 6 },
{ value: 'comfirm', label: '确定' }
],
value2: [
{ value: 1, label: 1 },
{ value: 2, label: 2 },
{ value: 3, label: 3 }
],
value3: [
{ value: 0, label: 0 },
// { value: '-', label: '-' },
{ value: 'toggle', label: 'toggle' }
]
}
})
// 负数键盘
if (props.type == 'onlyNum_negative') {
keycode.list.value3 = [
{ value: 0, label: 0 },
{ value: '-', label: '-' },
{ value: 'toggle', label: 'toggle' }
]
}
const emits = defineEmits([
'numkeycodeHandle',
'englishkeycodeHandle',
'handleLongPress',
'toggleKeyCode'
])
const toggleKeyCode = (
numKeycode: boolean,
englishKeycode: boolean,
type?: string
) => {
// if (props.type == 'category') return
if (type == 'char') {
// 特殊字符
} else {
if (!props.isToogle) {
showNumKeycode.value = numKeycode
}
showEnglishKeycode.value = englishKeycode
emits('toggleKeyCode', type)
}
}
// 数字键盘
const numkeycodeHandle = (item: {
value: string | number
label: string | number
}) => {
if (item.value == 'toggle' && !showPoint.value) {
if (props.type == 'showAll') return // 全部键盘显示的时候不切换
toggleKeyCode(false, true, 'num')
return
}
item.value != 'toggle' && emits('numkeycodeHandle', item)
}
// 英文键盘
const isuppercase = ref<string>('uppercase')
const englishKeycode = reactive<any>({
numlist: [
{ value: 1, label: 1 },
{ value: 2, label: 2 },
{ value: 3, label: 3 },
{ value: 4, label: 4 },
{ value: 5, label: 5 },
{ value: 6, label: 6 },
{ value: 7, label: 7 },
{ value: 8, label: 8 },
{ value: 9, label: 9 },
{ value: 0, label: 0 }
],
englishlist: [
{ value: 'Q', uppercase: 'Q', lowercase: 'q', char: '[' },
{ value: 'W', uppercase: 'W', lowercase: 'w', char: ']' },
{ value: 'E', uppercase: 'E', lowercase: 'e', char: '{' },
{ value: 'R', uppercase: 'R', lowercase: 'r', char: '}' },
{ value: 'T', uppercase: 'T', lowercase: 't', char: '#' },
{ value: 'Y', uppercase: 'Y', lowercase: 'y', char: '%' },
{ value: 'U', uppercase: 'U', lowercase: 'u', char: '^' },
{ value: 'I', uppercase: 'I', lowercase: 'i', char: '*' },
{ value: 'O', uppercase: 'O', lowercase: 'o', char: '+' },
{ value: 'P', uppercase: 'P', lowercase: 'p', char: '=' }
],
secondenglishlist: [
{ value: 'A', uppercase: 'A', lowercase: 'a', char: '-' },
{ value: 'S', uppercase: 'S', lowercase: 's', char: "'" },
{ value: 'D', uppercase: 'D', lowercase: 'd', char: '|' },
{ value: 'F', uppercase: 'F', lowercase: 'f', char: '~' },
{ value: 'G', uppercase: 'G', lowercase: 'g', char: '<' },
{ value: 'H', uppercase: 'H', lowercase: 'h', char: '>' },
{ value: 'J', uppercase: 'J', lowercase: 'j', char: '&' },
{ value: 'K', uppercase: 'K', lowercase: 'k', char: '¥' },
{ value: 'L', uppercase: 'L', lowercase: 'l', char: '·' }
],
thirdenglishlist: [
{ value: 'toggle', uppercase: '', lowercase: '' },
{ value: 'Z', uppercase: 'Z', lowercase: 'z', char: '.' },
{ value: 'X', uppercase: 'X', lowercase: 'x', char: ',' },
{ value: 'C', uppercase: 'C', lowercase: 'c', char: '_' },
{ value: 'V', uppercase: 'V', lowercase: 'v', char: '!' },
{ value: 'B', uppercase: 'B', lowercase: 'b', char: '/' },
{ value: 'N', uppercase: 'N', lowercase: 'n', char: ':' },
{ value: 'M', uppercase: 'M', lowercase: 'm', char: ';' },
{ value: 'del', uppercase: '', lowercase: '' }
]
})
const englishkeycodeHandle = (item: {
value: string | number
label?: string | number
uppercase?: string
lowercase?: string
char: string
}) => {
if (item.value == 'toggle') {
isuppercase.value =
isuppercase.value == 'uppercase' ? 'lowercase' : 'uppercase'
return
}
if (item.value == 'del') {
numkeycodeHandle({ value: 'del', label: 'del' })
return
}
emits('englishkeycodeHandle', item, isuppercase.value)
}
// 切换特殊字符
const toggleChar = (item: {
value: string | number
label?: string | number
uppercase?: string
lowercase?: string
char: string
}) => {
isuppercase.value = isuppercase.value == 'char' ? 'uppercase' : 'char'
}
// 长按删除
const timer = ref<any>(0)
const longPress = (type: string) => {
if (type == 'del') {
timer.value = setTimeout(() => {
emits('handleLongPress', type, true)
}, 500)
}
}
const removePress = (type: string) => {
if (type == 'del') {
clearTimeout(timer.value)
emits('handleLongPress', type, false)
}
}
// 显示英文键盘--键盘触屏都显示
const toShowEnglishKeycode = () => {
if (
software.softwareType == 1 ||
software.softwareType == 0 ||
props.alwaysShow ||
props.showSettingPage
) {
if (!props.isToogle) {
showNumKeycode.value = false
}
showEnglishKeycode.value = true
}
}
// 显示数字键盘--键盘触屏都显示
const toShowNumKeycode = () => {
if (
software.softwareType == 1 ||
software.softwareType == 0 ||
props.alwaysShow ||
props.showSettingPage
) {
showNumKeycode.value = true
showEnglishKeycode.value = false
}
}
// 显示全键盘--键盘触屏都显示
const toShowAll = () => {
if (
software.softwareType == 1 ||
software.softwareType == 0 ||
props.alwaysShow ||
props.showSettingPage
) {
showNumKeycode.value = true
showEnglishKeycode.value = true
}
}
const toHideAll = () => {
showNumKeycode.value = false
showEnglishKeycode.value = false
}
// 默认显示数字键盘
if (props.alwaysShow && props.showType == 'num') {
toShowNumKeycode()
}
defineExpose({
toShowNumKeycode,
toShowEnglishKeycode,
toShowAll,
toHideAll
})
</script>
<style lang="less" scoped>
@import '../style.less';
.keyboard {
&-num {
display: flex;
width: 100%;
table {
width: 100%;
margin: 0 auto;
border: none;
border-radius: 2px;
}
table td {
color: var(--keycode-english-item-textcolor);
background: var(--keycode-numtable-td-bg);
border: 2.5px solid var(--keycode-numtable-td-border); /*gitignore*/
height: 60px;
width: 80px;
text-align: center;
font-size: 20px;
border-radius: 2px;
cursor: pointer;
.td-div {
flex-direction: column;
}
}
.td_comfirm {
background-color: var(--keycode-num-td_comfirm-bg);
color: var(--keycode-num-td_comfirm-textcolor);
}
.toggle-item {
flex-direction: column;
flex: 1;
&-num {
padding-right: 20px;
margin-top: 5px;
}
&-english {
font-size: 14px;
color: var(--keycode-english-toggleItem-numcolor);
padding-left: 20px;
margin-top: -10px;
}
}
.point-item {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
&-del {
position: relative;
width: 100%;
height: 100%;
em {
font-size: 45px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
&-english {
position: fixed;
bottom: 0;
left: 0;
right: 0;
width: 100%;
/*background-color: var(--keycode-goodinfo-td-border);*/
padding: 5px 20px;
.english-item {
width: 10%;
height: 64px;
background: var(--keycode-english-item-bg);
border-radius: 2px;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: var(--keycode-english-item-textcolor);
cursor: pointer;
margin: 0.5%;
&-toggle {
.iconfont {
font-size: 34px;
color: var(--keycode-english-item-textcolor);
}
.icon-ic_shift {
font-size: 28px;
}
}
.english-del-item {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.toggleItem {
background-color: var(--keycode-english-toggleItem-bg);
width: 15.3%;
display: flex;
flex-direction: column;
&-num {
font-size: 14px;
color: var(--keycode-english-toggleItem-numcolor);
padding-right: 20px;
margin-top: 5px;
}
&-english {
padding-left: 20px;
margin-top: -10px;
}
}
.special-item {
background-color: var(--keycode-english-specialItem-bg);
color: var(--keycode-english-specialItem-textcolor);
}
.searchItem {
background-color: var(--keycode-num-td_comfirm-bg);
color: var(--keycode-num-td_comfirm-textcolor);
}
.httpItem {
background-color: var(--keycode-english-toggleItem-bg);
color: var(--keycode-english-toggleItem-numcolor);
}
.spacing-item {
width: 54.5%;
}
&-num {
display: flex;
align-items: center;
justify-content: space-between;
}
&-english {
}
.secondenglishlist {
padding: 0 4.8%;
}
}
.td_del {
.td-div {
width: 100%;
height: 100%;
}
}
}
.showAll_keyboard,
.onlyNum_keyboard,
.onlyNum_negative_keyboard {
background-color: var(--keycode-goodinfo-td-border);
height: 310px;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 30;
.keyboard-num {
position: fixed !important;
bottom: 0 !important;
right: 0 !important;
top: auto !important;
padding: 0 15px 8px;
width: 430px;
table {
border: none;
td {
width: 93px;
height: 73px;
border: 5px solid var(--keycode-goodinfo-td-border);
background-color: var(--keycode-english-item-bg);
border-radius: 6px;
}
.td_comfirm {
background-color: var(--keycode-num-td_comfirm-bg);
color: var(--keycode-num-td_comfirm-textcolor);
}
}
}
.keyboard-english {
width: 942px;
padding: 15px;
padding-top: 0;
padding-bottom: 8px;
.english-item {
}
.special-item,
.searchItem {
width: 15%;
}
.spacing-item {
/*width: 641px;*/
width: 53.5%;
}
.hideItem {
/*width: 16.3%;*/
em {
font-size: 40px;
}
}
.httpItem,
.colon-item {
width: 9.6%;
}
.httpItem {
color: var(--keycode-english-specialItem-textcolor);
}
}
}
.showAll_keyboard {
.keyboard-english {
.hideItem {
width: 15%;
}
.httpItem {
width: 9.8%;
}
.colon-item {
width: 9.9%;
}
}
}
.onlyNum_keyboard,
.onlyNum_negative_keyboard {
.keyboard-num {
left: 50%;
transform: translateX(-50%);
width: 662px;
td {
font-size: 32px;
}
}
}
.isHttp_keyboard {
.keyboard-english {
/*.colon-item {*/
/* width: 82px;*/
/*}*/
/*.spacing-item {*/
/* width: 546px;*/
/*}*/
background-color: var(--keycode-english-bg1);
}
}
.showAll_keyboard {
background-color: var(--keycode-english-bg1);
.keyboard-num {
table {
td {
border: 5px solid var(--keycode-english-bg1);
}
}
}
}
.category_keyboard {
width: 100%;
.keyboard-num {
padding: 0.6%;
table {
border: none;
td {
height: 78px;
border: 5px solid var(--keycode-goodinfo-td-border);
background-color: var(--keycode-english-item-bg);
font-size: 29px;
}
.td_comfirm {
background-color: var(--keycode-num-td_comfirm-bg);
color: var(--keycode-num-td_comfirm-textcolor);
}
.toggle-item-english {
font-size: 22px;
}
}
}
.keyboard-english {
position: static;
padding: 0.8%;
.english-item {
height: 56px;
}
.secondenglishlist {
}
.toggleItem {
}
.spacing-item {
}
}
}
.pay_keyboard,
.changeGoodInfo_keyboard {
.keyboard-num {
table {
td {
background-color: transparent;
width: 115px;
height: 90px;
font-size: 32px;
.td-div {
border-radius: 2px;
display: flex;
justify-content: center;
align-items: center;
}
}
.td_comfirm {
background-color: transparent;
.td-div {
background-color: var(--keycode-num-td_comfirm-bg);
color: var(--keycode-num-td_comfirm-textcolor);
}
}
.toggle-item-english {
font-size: 22px;
}
}
}
}
.pay_keyboard {
.keyboard-num {
table {
td {
width: 124px;
height: 86px;
border: none;
.td-div {
width: 92%;
height: 88%;
background-color: var(--keycode-pay-bg);
}
}
.td_0 {
.td-div {
width: 96%;
}
}
.td_del {
.td-div {
width: 100%;
}
}
.td_comfirm {
.td-div {
width: 100%;
height: 96%;
}
}
}
}
}
.memberRecharge_keyboard {
.keyboard-num {
table {
border: 4px solid var(--keycode-goodinfo-td-border);
td {
width: 115px;
height: 74px;
border: 6px solid var(--keycode-goodinfo-td-border);
background-color: var(--keycode-english-item-bg);
font-size: 32px;
border-radius: 8px;
}
.td_comfirm {
font-size: 24px;
background-color: var(--keycode-num-td_comfirm-bg);
color: var(--keycode-num-td_comfirm-textcolor);
}
.toggle-item-num {
font-size: 24px;
}
.toggle-item-english {
font-size: 18px;
}
}
}
}
.changeGoodInfo_keyboard {
.keyboard-num {
table {
td {
width: 166px;
height: 70px;
border: none;
.td-div {
width: 94%;
height: 86%;
background-color: var(--keycode-numtable-td-bg);
}
}
.td_0 {
.td-div {
width: 96.5%;
}
}
.td_comfirm {
font-size: 24px;
.td-div {
height: 97%;
}
}
}
}
}
.login_keyboard {
.keyboard-num {
position: absolute;
width: 418px;
height: 334px;
background: var(--login-keyboard-bg);
right: -326px;
top: -25px;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
padding: 0px 6px;
&:before {
content: '';
width: 0;
height: 0;
border: 10px solid;
border-color: transparent var(--login-keyboard-bg) transparent transparent;
position: absolute;
left: -19px;
top: 18px;
transition: all 0.3s;
}
table {
td {
width: 101px;
height: 81px;
border-color: var(--login-keyboard-bg);
background-color: var(--login-keyboard-td-bg);
color: var(--login-keyboard-td-font);
font-size: 28px;
}
.td_comfirm {
background-color: var(--login-keyboard-tdCorfirm-bg);
color: var(--login-keyboard-tdCorfirm-font);
}
}
}
.keyboard-english {
.english-item {
height: 55px;
}
}
}
</style>