VKeyboard.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <view :class="keyboardStyle">
  3. <view class="digit-keyboard" v-if="mode === 'digit' || digital">
  4. <view class="digit-button-box">
  5. <template v-for="(digit, index) in digits">
  6. <view :key="index" class="key-button digit" @tap="typing('.')" v-if="index === 9">.</view>
  7. <view :key="index" class="key-button digit" @tap="typing(digit)">{{digit}}</view>
  8. </template>
  9. <view class="key-button digit">
  10. <i class="iconfont icon-shouqijianpan middle" v-if="digital" @tap="deactivate"></i>
  11. <i class="iconfont icon-ABC middle" v-else @tap="typingLetter"></i>
  12. </view>
  13. </view>
  14. <view class="special-button-box">
  15. <view class="key-button special-button gray" @tap="backspace"><i class="iconfont icon-backspace large"></i></view>
  16. <view class="key-button special-button gray" @tap="enter"><i class="iconfont icon-huiche large"></i></view>
  17. </view>
  18. </view>
  19. <view class="full-keyboard" v-else>
  20. <view class="line" v-for="(letters, index) in lines" :key="index">
  21. <view class="letter key-button special-key gray" v-if="index === 3 && mode === 'letter'" @tap="toggleCase"><i :class="'iconfont ' + (lowercase ? 'icon-xiaoxie' : 'icon-daxie')"></i></view>
  22. <view class="letter key-button normal" v-for="letter in letters" @tap="typing(letter)" :key="letter">{{letter}}</view>
  23. <view class="letter key-button special-key gray" v-if="index === 3" @tap="backspace"><i class="iconfont icon-backspace"></i></view>
  24. </view>
  25. <view class="line special-line">
  26. <view class="letter key-button swith-key gray">
  27. <i class="iconfont icon-fuhao" @tap="typingSymbol" v-if="mode === 'letter'"></i>
  28. <i class="iconfont icon-ABC" @tap="typingLetter" v-if="mode === 'symbol'"></i>
  29. </view>
  30. <view class="letter key-button space" @tap="typing(' ')"><text class="logo">Magician 安全键盘</text></view>
  31. <view class="letter key-button swith-key gray" @tap="typingDigit"><i class="iconfont icon-shuzi"></i></view>
  32. <view class="letter key-button swith-key gray" @tap="enter"><i class="iconfont icon-huiche"></i></view>
  33. </view>
  34. </view>
  35. </view>
  36. </template>
  37. <script>
  38. import './css.scss'
  39. import { natural, order, disorder, symbols, digits, KEYBOARD_MODE } from './utils'
  40. export default {
  41. props: {
  42. //是否为纯数字键盘
  43. digital: {
  44. type: [ Boolean, String ],
  45. default: false
  46. },
  47. //是否无序的排序键盘
  48. disorderly: {
  49. type: [ Boolean, String ],
  50. default: false
  51. }/* ,
  52. value: String */
  53. },
  54. //app中不生效,不知道为什么
  55. /* model: {
  56. prop: 'value',
  57. event: 'typing'
  58. }, */
  59. computed: {
  60. keyboardStyle() {
  61. return 'v-keyboard ' + this.cls;
  62. }
  63. },
  64. data() {
  65. return {
  66. cls: '',
  67. visible: false, //是否显示
  68. digits: [], //自然数数组
  69. lines: [], //字母+数字数组
  70. lowercase: true, //是否小写输入状态
  71. mode: KEYBOARD_MODE.LETTER, //键盘模式
  72. keys: [] //键入的键值
  73. }
  74. },
  75. methods: {
  76. //大小写转换
  77. toggleCase() {
  78. this.lowercase = !this.lowercase;
  79. },
  80. //输入符号
  81. typingSymbol() {
  82. this.mode = KEYBOARD_MODE.SYMBOL;
  83. this.lines = symbols;
  84. },
  85. //输入字母
  86. typingLetter() {
  87. this.mode = KEYBOARD_MODE.LETTER;
  88. this.lines = this.disorderly ? disorder() : order;
  89. },
  90. //键入数字
  91. typingDigit() {
  92. this.mode = KEYBOARD_MODE.DIGIT;
  93. },
  94. //键盘键入
  95. typing(input) {
  96. this.keys.push(input);
  97. //app中v-model不生效,改用事件方式在外处理
  98. //this.$emit('typing', this.keys.join(''));
  99. this.$emit('typing', {
  100. backspace: false,
  101. char: input
  102. })
  103. },
  104. //退格键
  105. backspace() {
  106. if (this.keys.length) {
  107. this.keys.pop()
  108. }
  109. //this.$emit('typing', this.keys.join(''));
  110. this.$emit('typing', {
  111. backspace: true
  112. })
  113. },
  114. //键入回车
  115. enter() {
  116. //this.deactivate();
  117. this.$emit('enter');
  118. },
  119. //激活键盘
  120. activate() {
  121. // #ifdef APP-PLUS
  122. plus.key.hideSoftKeybord();
  123. // #endif
  124. this.visible = true;
  125. },
  126. //隐藏键盘
  127. deactivate() {
  128. this.visible = false;
  129. }
  130. },
  131. watch: {
  132. lowercase(val) {
  133. let [...temp ] = this.lines;
  134. temp.forEach(line => {
  135. line.forEach((letter, index) => {
  136. line[index] = val ? letter.toLowerCase() : letter.toUpperCase();
  137. });
  138. });
  139. this.lines = temp;
  140. },
  141. visible(val) {
  142. this.cls = val ? 'slideup' : 'slidedown';
  143. }
  144. },
  145. created() {
  146. this.lines = this.disorderly ? disorder() : order;
  147. this.digits = this.disorderly ? digits() : natural;
  148. }
  149. }
  150. </script>
  151. <style lang="scss" scoped>
  152. .key-button {
  153. display: inline-block;
  154. overflow: hidden;
  155. vertical-align: middle;
  156. border: 1px solid #e6e6e6;
  157. color: #333;
  158. background-color: #fff;
  159. box-shadow: 0 2px 2px rgba(230,230,230,.7);
  160. border-radius: 0.35em;
  161. text-align: center;
  162. white-space: nowrap;
  163. user-select: none;
  164. cursor: pointer;
  165. &:active {
  166. background: #d6d6d6;
  167. scale: 0.7;
  168. }
  169. }
  170. .v-keyboard {
  171. transform: translateY(100%);
  172. width: 100%;
  173. position: absolute;
  174. bottom: 0;
  175. left: 0;
  176. background: #f5f5f5;
  177. padding: .5em 0;
  178. z-index: 100;
  179. /*全键盘*/
  180. .full-keyboard {
  181. .line {
  182. text-align: center;
  183. &:not(:last-child) {
  184. margin-bottom: 0.5em;
  185. }
  186. .letter {
  187. height: 1.7em;
  188. line-height: 1.7em;
  189. font-size: 1em;
  190. &:not(:last-child) {
  191. margin-right: 0.2em;
  192. }
  193. }
  194. .normal {
  195. width: 1.65em;
  196. }
  197. .special-key {
  198. width: 2.6em;
  199. }
  200. }
  201. .special-line {
  202. padding: 0 0.35em;
  203. display: flex!important;
  204. justify-content: space-around;
  205. .space {
  206. flex: 1;
  207. display: flex;
  208. align-items: center;
  209. justify-content: center;
  210. }
  211. .swith-key {
  212. width: 2.6em;
  213. }
  214. .logo {
  215. font-size: 12px;
  216. }
  217. }
  218. }
  219. /*数字键盘*/
  220. .digit-keyboard {
  221. display: flex;
  222. flex-direction: row;
  223. .digit-button-box {
  224. padding: 0 .35em;
  225. flex: 80;
  226. .digit {
  227. width: 4.46em;
  228. height: 2.5em;
  229. line-height: 2.5em;
  230. margin-bottom: .35em;
  231. &:nth-child(10),
  232. &:nth-child(11),
  233. &:nth-child(12) {
  234. margin-bottom: 0;
  235. }
  236. &:not(:last-child) {
  237. margin-right: .35em;
  238. }
  239. }
  240. }
  241. .special-button-box {
  242. flex: 20;
  243. padding: 0 .35em 0 0;
  244. .special-button {
  245. display: block;
  246. line-height: 5.5em;
  247. height: 5.5em;
  248. width: 4em;
  249. &:not(:last-child) {
  250. margin-bottom: .35em;
  251. }
  252. }
  253. }
  254. }
  255. .gray {
  256. background: #e1e1e1!important;
  257. &:active {
  258. background: #fff!important;
  259. }
  260. }
  261. .large {
  262. font-size: 2em!important;
  263. }
  264. .middle {
  265. font-size: 1.2em!important;
  266. display: block;
  267. }
  268. }
  269. </style>