xm-keyboard-box.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. <template>
  2. <view class="xm-keyboard-box">
  3. <view
  4. class="xm-keyboard-box-line"
  5. v-for="(line, li) in lines[mode]"
  6. :key="li"
  7. :style="{
  8. marginLeft: diffSize(line.diff) + 'px',
  9. marginRight: diffSize(line.diff) / -1 + 'px'
  10. }"
  11. >
  12. <view
  13. v-for="(item, index) in line.list"
  14. :key="index"
  15. class="xm-keyboard-box-item"
  16. :class="{
  17. 'xm-keyboard-box-item-empty': item == '',
  18. 'xm-keyboard-box-item-disable': disable.indexOf(item) != -1
  19. }"
  20. :style="{
  21. width: btnWidth + 'px',
  22. height: btnHeight + 'px'
  23. }"
  24. @click="toClick(item)"
  25. >
  26. {{ item }}
  27. </view>
  28. </view>
  29. <view class="xm-keyboard-box-line xm-keyboard-box-toolbar">
  30. <view
  31. v-if="showCancelBtn"
  32. class="xm-keyboard-box-item xm-keyboard-box-btn xm-keyboard-box-btn-cancel"
  33. :style="{
  34. marginRight: btnWidth / ratio + 'px',
  35. height: btnHeight + 'px'
  36. }"
  37. @click="toCancel()"
  38. >
  39. 取消
  40. </view>
  41. <view
  42. class="xm-keyboard-box-item xm-keyboard-box-btn xm-keyboard-box-btn-clear"
  43. :style="{
  44. marginRight: btnWidth / ratio + 'px',
  45. height: btnHeight + 'px'
  46. }"
  47. @click="toClear()"
  48. >
  49. 清空
  50. </view>
  51. <view
  52. class="xm-keyboard-box-item xm-keyboard-box-btn-over"
  53. :style="{
  54. marginRight: btnWidth / ratio + 'px',
  55. height: btnHeight + 'px'
  56. }"
  57. @click="toConfirm()"
  58. >
  59. 完成
  60. </view>
  61. </view>
  62. <view
  63. v-if="showChangeBtn"
  64. class="xm-keyboard-box-item xm-keyboard-box-btn xm-keyboard-box-btn-change"
  65. :style="{
  66. width: handlerWidth + 'px',
  67. height: btnHeight + 'px',
  68. bottom: 'calc(20px + ' + btnHeight + 'px)'
  69. }"
  70. @click="changeMode()"
  71. >
  72. <i class="iconxmk2 icon-xm-k2-jianpan" style="font-size: 24px"></i>
  73. </view>
  74. <view
  75. class="xm-keyboard-box-item xm-keyboard-box-btn xm-keyboard-box-btn-del"
  76. :style="{
  77. width: handlerWidth + 'px',
  78. height: btnHeight + 'px',
  79. bottom: 'calc(20px + ' + btnHeight + 'px)'
  80. }"
  81. @click="toDel()"
  82. >
  83. <i class="iconxmk2 icon-xm-k2-backspace" style="font-size: 24px"></i>
  84. </view>
  85. </view>
  86. </template>
  87. <script>
  88. export default {
  89. name: 'xm-keyboard-box',
  90. emits: ['add', 'del', 'confirm', 'cancel', 'clear'],
  91. props: {
  92. // 是否开启震动效果
  93. vibration: {
  94. type: Boolean,
  95. default: false
  96. },
  97. // 是否显示切换按钮
  98. showChangeBtn: {
  99. type: Boolean,
  100. default: true
  101. },
  102. // 是否显示取消按钮
  103. showCancelBtn: {
  104. type: Boolean,
  105. default: true
  106. },
  107. // 禁用某些按钮
  108. disable: {
  109. required: false,
  110. default: () => ''
  111. }
  112. },
  113. data() {
  114. return {
  115. mode: 0,
  116. ratio: 7,
  117. max: 10,
  118. gutter: 10,
  119. btnWidth: 10,
  120. btnHeight: 10,
  121. handlerWidth: 10,
  122. lines: [
  123. [
  124. {
  125. list: ['京', '沪', '浙', '苏', '粤', '鲁', '晋', '冀', '豫', '川'],
  126. diff: 0
  127. },
  128. {
  129. list: ['渝', '辽', '吉', '黑', '皖', '鄂', '津', '贵', '云', '桂'],
  130. diff: 0
  131. },
  132. {
  133. list: ['琼', '青', '新', '藏', '蒙', '宁', '甘', '陕', '闽', '赣'],
  134. diff: 0
  135. },
  136. {
  137. list: ['湘', '使', '领', '警', '学', '挂', '...', '', '', ''],
  138. diff: 3
  139. }
  140. ],
  141. [
  142. {
  143. list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
  144. diff: 0
  145. },
  146. {
  147. list: ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
  148. diff: 0
  149. },
  150. {
  151. list: ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ''],
  152. diff: 1
  153. },
  154. {
  155. list: ['Z', 'X', 'C', 'V', 'B', 'N', 'M', '', '', ''],
  156. diff: 3
  157. }
  158. ],
  159. [
  160. {
  161. list: ['港', '澳', '台', '临', '试', '', '', '', '', ''],
  162. diff: 0
  163. },
  164. {
  165. list: ['', '', '', '', '', '', '', '', '', ''],
  166. diff: 0
  167. },
  168. {
  169. list: ['', '', '', '', '', '', '', '', '', ''],
  170. diff: 0
  171. },
  172. {
  173. list: ['', '', '', '', '', '', '...', '', '', ''],
  174. diff: 3
  175. }
  176. ]
  177. ]
  178. }
  179. },
  180. methods: {
  181. diffSize(pos) {
  182. if (pos == 0) {
  183. return 0
  184. }
  185. return (pos * this.btnWidth + (pos * this.btnWidth) / this.ratio) / 2
  186. },
  187. changeMode(v) {
  188. this.mode = v == void 0 ? (this.mode == 0 ? 1 : 0) : v
  189. },
  190. toClick(item) {
  191. if (item === '') {
  192. return
  193. }
  194. if (item === '...') {
  195. this.mode = this.mode == 2 ? 0 : 2
  196. return
  197. }
  198. if (this.disable && this.disable.indexOf && this.disable.indexOf(item) !== -1) {
  199. return
  200. }
  201. this.toEmit('add', item)
  202. },
  203. toDel() {
  204. this.toEmit('del')
  205. },
  206. toCancel() {
  207. this.toEmit('cancel')
  208. },
  209. toConfirm() {
  210. this.toEmit('confirm')
  211. },
  212. toClear() {
  213. this.toEmit('clear')
  214. },
  215. toEmit(type, params) {
  216. this.toVibration()
  217. this.$emit(type, params)
  218. },
  219. toVibration() {
  220. if (this.vibration && uni.vibrateShort) {
  221. uni.vibrateShort()
  222. }
  223. }
  224. },
  225. mounted() {
  226. const { windowWidth } = uni.getSystemInfoSync()
  227. let _width = ((windowWidth - this.gutter * 2) * this.ratio) / (this.max * this.ratio + this.max - 1)
  228. this.btnWidth = _width.toFixed(2)
  229. this.btnHeight = ((_width / 3) * 4).toFixed(2)
  230. this.handlerWidth = (_width * 1.5 + _width / (this.ratio * 2)).toFixed(2)
  231. }
  232. }
  233. </script>
  234. <style lang="scss" scoped>
  235. @import url(../../styles/iconfont/iconfont.css);
  236. .xm-keyboard-box {
  237. $gutter: 10px;
  238. background-color: #d4d5d9;
  239. padding: $gutter;
  240. position: relative;
  241. .xm-flex {
  242. display: flex;
  243. align-items: center;
  244. }
  245. &-line {
  246. @extend .xm-flex;
  247. justify-content: space-between;
  248. margin-bottom: $gutter;
  249. &:last-child {
  250. margin-bottom: 0;
  251. }
  252. }
  253. &-item {
  254. background-color: #fcffff;
  255. @extend .xm-flex;
  256. justify-content: center;
  257. border-radius: 4px;
  258. box-shadow: 0px 2px 2px #999;
  259. position: relative;
  260. &:active {
  261. background-color: rgba(0, 0, 0, 0.1);
  262. }
  263. &-empty {
  264. background-color: unset;
  265. box-shadow: unset;
  266. &:active {
  267. background-color: unset;
  268. }
  269. }
  270. &-disable {
  271. background-color: #bdbec3;
  272. }
  273. }
  274. &-btn {
  275. background-color: #b6bcc4;
  276. &:active {
  277. background-color: rgba(182, 188, 196, 0.8);
  278. }
  279. }
  280. &-btn-del {
  281. position: absolute;
  282. right: $gutter;
  283. }
  284. &-btn-change {
  285. position: absolute;
  286. left: $gutter;
  287. }
  288. &-btn-over {
  289. // position: absolute;
  290. background-color: #f37b1d;
  291. color: #fff;
  292. &:active {
  293. background-color: rgba(243, 123, 29, 0.8);
  294. }
  295. }
  296. &-toolbar {
  297. margin-bottom: 0;
  298. .xm-keyboard-box-item {
  299. width: 100%;
  300. &:last-child {
  301. margin-right: 0 !important;
  302. }
  303. }
  304. }
  305. }
  306. </style>