keyboard.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <view class="modal" :animation="animationData1" @touchmove.stop.prevent>
  3. <view class=" content-wrap" :animation="animationData2">
  4. <view class="content-header">
  5. <view class="cancel-btn" @click="close">取消</view>
  6. <view class="input-contant">{{ inputValue.join("") }}</view>
  7. <view class="confirm-btn" @click="confirm">完成</view>
  8. </view>
  9. <view class="key-box">
  10. <view
  11. :class="{
  12. 'handel-btn': ['.', '删除', ''].includes(item),
  13. 'active-btn': activeKey === item,
  14. 'active-handel-btn':
  15. activeKey === item && ['.', '删除'].includes(item),
  16. }"
  17. v-for="(item, index) in keyboardList"
  18. :key="index"
  19. @click="setValue(item)"
  20. >{{ item }}</view
  21. >
  22. </view>
  23. </view>
  24. </view>
  25. </template>
  26. <script>
  27. export default {
  28. data() {
  29. return {
  30. animationData1: {},
  31. animationData2: {},
  32. activeKey: "",
  33. inputValue: [],
  34. };
  35. },
  36. props: {
  37. visible: {
  38. type: Boolean,
  39. default: false,
  40. },
  41. //是否为带小数的数字键盘
  42. decimals: {
  43. type: Boolean,
  44. default: true,
  45. },
  46. //小数点前整数的位数
  47. maxLength: {
  48. type: [Number, String],
  49. default: 9,
  50. },
  51. //小数点后的位数
  52. pointLength: {
  53. type: [Number, String],
  54. default: 2,
  55. },
  56. //最大的值
  57. max: {
  58. type: [Number, String],
  59. default: 999999999,
  60. },
  61. //最小的值
  62. min: {
  63. type: [Number, String],
  64. default: 0,
  65. },
  66. },
  67. computed: {
  68. keyboardList() {
  69. return this.decimals
  70. ? ["1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "删除"]
  71. : ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "删除"];
  72. },
  73. },
  74. watch: {
  75. visible(val) {
  76. this.inputValue = [];
  77. if (val) this.enterAnimate();
  78. else this.leaveAnimate();
  79. },
  80. },
  81. methods: {
  82. setValue(data) {
  83. this.activeKey = data;
  84. let timer = setTimeout(() => {
  85. this.activeKey = "-";
  86. clearTimeout(timer);
  87. }, 100);
  88. if (
  89. !data ||
  90. (data !== "删除" &&
  91. this.inputValue.includes(".") &&
  92. this.inputValue.join("").split(".")[1].length === this.pointLength)
  93. )
  94. return false;
  95. if (
  96. this.inputValue.length === 1 &&
  97. this.inputValue[0] === "0" &&
  98. !["删除", "."].includes(data)
  99. ) {
  100. return (this.inputValue = [data]);
  101. }
  102. if (data !== "删除") {
  103. if (this.inputValue.includes(".")) {
  104. if (
  105. this.inputValue.join("").split(".")[0].length === this.maxLength
  106. ) {
  107. return false;
  108. }
  109. } else if (this.inputValue.length === this.maxLength) {
  110. return false;
  111. }
  112. }
  113. if (data === "删除") {
  114. return this.inputValue.length && this.inputValue.pop();
  115. }
  116. if (data === ".") {
  117. if (!this.inputValue.length || this.inputValue.includes("."))
  118. return false;
  119. }
  120. this.inputValue.push(data);
  121. },
  122. close() {
  123. this.$emit("update:visible", false);
  124. this.$emit("close");
  125. },
  126. confirm() {
  127. let result = Number(this.inputValue.join(""));
  128. if (result < this.min) {
  129. uni.showToast({
  130. title: `最小值为${this.min}`,
  131. duration: 1500,
  132. icon: "none",
  133. });
  134. return;
  135. } else if (result > this.max) {
  136. uni.showToast({
  137. title: `最大值为${this.max}`,
  138. duration: 1500,
  139. icon: "none",
  140. });
  141. return;
  142. }
  143. this.$emit("confirm", result);
  144. this.close();
  145. },
  146. enterAnimate() {
  147. this.animation1 = uni.createAnimation();
  148. this.animation2 = uni.createAnimation();
  149. this.animation1.backgroundColor("rgba(0,0,0,0.5)").step({
  150. duration: 500,
  151. timingFunction: "ease",
  152. });
  153. this.animation2.translateY(0).step({
  154. timingFunction: "ease-out",
  155. duration: 500,
  156. });
  157. this.animationData1 = this.animation1.export();
  158. this.animationData2 = this.animation2.export();
  159. },
  160. leaveAnimate() {
  161. this.animation1 = uni.createAnimation();
  162. this.animation2 = uni.createAnimation();
  163. this.animation1.backgroundColor("rgba(0,0,0,0)").step({
  164. duration: 500,
  165. timingFunction: "ease",
  166. });
  167. this.animation2.translateY(500).step({
  168. timingFunction: "ease-out",
  169. duration: 500,
  170. });
  171. this.animationData1 = this.animation1.export();
  172. this.animationData2 = this.animation2.export();
  173. },
  174. },
  175. };
  176. </script>
  177. <style lang="scss" scoped>
  178. .modal {
  179. position: fixed;
  180. bottom: 0;
  181. width: 100%;
  182. background: rgba(0, 0, 0, 0);
  183. z-index: 9999;
  184. .content-wrap {
  185. position: fixed;
  186. bottom: 0;
  187. left: 0;
  188. width: 100%;
  189. background: #fff;
  190. box-sizing: border-box;
  191. transform: translateY(100%);
  192. .content-header {
  193. width: 100%;
  194. height: 80upx;
  195. background: rgba(255, 255, 255, 1);
  196. float: right;
  197. .input-contant {
  198. text-align: center;
  199. line-height: 80upx;
  200. font-size: 40upx;
  201. }
  202. .cancel-btn {
  203. padding-left: 30upx;
  204. color: #147ff2;
  205. line-height: 80upx;
  206. position: absolute;
  207. top: 0;
  208. left: 0;
  209. }
  210. .confirm-btn {
  211. padding-right: 30upx;
  212. color: #147ff2;
  213. line-height: 80upx;
  214. position: absolute;
  215. top: 0;
  216. right: 0;
  217. }
  218. }
  219. .key-box {
  220. margin-top: 60upx;
  221. display: flex;
  222. flex-flow: wrap;
  223. width: 100%;
  224. view {
  225. width: 251upx;
  226. height: 100upx;
  227. border: 1upx solid rgb(235, 237, 240);
  228. box-sizing: border-box;
  229. text-align: center;
  230. line-height: 100upx;
  231. font-size: 40upx;
  232. font-weight: bold;
  233. margin: 0 -1upx -1upx 0;
  234. &:hover {
  235. z-index: 1;
  236. border: 1upx solid rgb(235, 237, 240);
  237. }
  238. }
  239. .handel-btn {
  240. background: rgb(235, 237, 240);
  241. font-size: 30upx;
  242. }
  243. .active-btn {
  244. background: rgb(235, 237, 240);
  245. }
  246. .active-handel-btn {
  247. background: rgb(252, 252, 252);
  248. }
  249. }
  250. }
  251. }
  252. </style>