NumberInput.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <template>
  2. <van-cell
  3. :title="title"
  4. :label="label"
  5. :icon="icon"
  6. :url="url"
  7. :border="border"
  8. :required="required"
  9. :id="com_id"
  10. :class="{'v-input': show_dept_selector}"
  11. >
  12. <template slot="right-icon">
  13. <div class="picker-box" @click="activeIsAdd" v-if="chosePoint&&!isForbidSet">
  14. <div :class="isAdd? 'picker-right':'picker-left'" class="yuan"></div>
  15. <div class="flex-box flex-v-ce">
  16. <span class="red flex-1">奖</span>
  17. <span class="green flex-1">扣</span>
  18. </div>
  19. </div>
  20. </template>
  21. <template slot="default">
  22. <div class="flex-box-ce">
  23. <span v-if="isAdd" class="red">+</span>
  24. <span v-else class="green">-</span>
  25. <van-field style="padding: 0.1rem 0;" @input="onInput" type="digit" :readonly="onReadonly" @blur="onBlur" v-model.number="numVal" placeholder="分值"/>
  26. </div>
  27. <!-- <div @click.stop="show_keyboard">
  28. <span v-if="input_value > 0" class="red">+</span>
  29. <span v-if="input_value < 0" class="green">-</span>
  30. <span v-if="input_value == 0 && isAdd" class="red">+</span>
  31. <span v-if="input_value == 0 && !isAdd" class="green">-</span>
  32. <span v-if="input_value > 0" class="red">{{input_value}}</span>
  33. <span v-if="input_value < 0" class="green">{{input_value * -1}}</span>
  34. <span v-if="input_value == 0">{{input_value}}</span>
  35. <span v-show="show_dept_selector" class="v-focus">|</span>
  36. </div> -->
  37. </template>
  38. <!-- <van-number-keyboard
  39. :id="com_id"
  40. class="diy-key"
  41. ref="selector"
  42. theme="custom"
  43. :maxlength="maxlength"
  44. :show.sync="show_dept_selector"
  45. close-button-text="完成"
  46. @blur="onBlur"
  47. @input="confirm"
  48. @delete="onDelete"
  49. >
  50. </van-number-keyboard> -->
  51. </van-cell>
  52. </template>
  53. <script>
  54. import Vue from 'vue'
  55. import { NumberKeyboard } from 'vant'
  56. Vue.use(NumberKeyboard)
  57. export default {
  58. name: 'NumberInput',
  59. model: {
  60. prop: 'input_value', //别名
  61. event: 'value' //事件
  62. },
  63. props: {
  64. chosePoint: { //能否输出负分
  65. type: Boolean,
  66. default: true
  67. },
  68. input_value: {
  69. default: 0
  70. },
  71. title: {
  72. type: String,
  73. default: ''
  74. },
  75. value: {
  76. type: String,
  77. default: ''
  78. },
  79. label: {
  80. type: String,
  81. default: ''
  82. },
  83. icon: {
  84. type: String,
  85. default: ''
  86. },
  87. url: {
  88. type: String,
  89. default: ''
  90. },
  91. border: {
  92. type: Boolean,
  93. default: true
  94. },
  95. required: {
  96. type: Boolean,
  97. default: false
  98. },
  99. max: {
  100. type: Number,
  101. default: 100000
  102. },
  103. min: {
  104. type: Number,
  105. default: -100000
  106. },
  107. maxlength: {
  108. type: Number,
  109. default: 100000
  110. },
  111. isForbidSet:{ //是否禁止输入
  112. type: Boolean,
  113. default: false
  114. }
  115. },
  116. data () {
  117. return {
  118. com_id: '',
  119. isAdd:true,
  120. show_dept_selector: false,
  121. height: 0,
  122. body_height: 0,
  123. numVal:0,
  124. }
  125. },
  126. computed:{
  127. onReadonly(){
  128. if((this.min&&this.min == this.max)||this.isForbidSet){
  129. return true
  130. }else{
  131. return false
  132. }
  133. }
  134. },
  135. watch: {
  136. input_value: {
  137. handler(val, oldVal) {
  138. this.setCurrentValue(val);
  139. },
  140. immediate: true,
  141. deep: true
  142. },
  143. show_dept_selector (val) {
  144. if (val) {
  145. this.$nextTick(() => {
  146. this.height = document.getElementById(this.com_id).offsetHeight
  147. document.querySelectorAll('body > div').item(0).style.height = 'calc(' + this.body_height + ' - ' + this.height + 'px)'
  148. document.querySelectorAll('body > div').item(0).style.width = 'calc(100% - 0.01rem)'
  149. document.querySelectorAll('body > div').item(0).style.marginRight = '-0.01rem'
  150. setTimeout(() => {
  151. document.querySelectorAll('body > div').item(0).style.width = '100%'
  152. document.querySelectorAll('body > div').item(0).style.marginRight = '0'
  153. }, 100)
  154. })
  155. } else {
  156. document.querySelectorAll('body > div').item(0).style.height = this.body_height
  157. document.querySelectorAll('body > div').item(0).style.width = 'calc(100% - 0.01rem)'
  158. document.querySelectorAll('body > div').item(0).style.marginRight = '-0.01rem'
  159. setTimeout(() => {
  160. document.querySelectorAll('body > div').item(0).style.width = '100%'
  161. document.querySelectorAll('body > div').item(0).style.marginRight = '0'
  162. }, 100)
  163. }
  164. }
  165. },
  166. methods: {
  167. setCurrentValue(value) {
  168. // console.log('value:'+value,this.numVal)
  169. if(value===''){
  170. return false
  171. }
  172. if(this.chosePoint){ //可以正负分
  173. if(value < 0){ //负分
  174. this.isAdd=false;
  175. }else{
  176. this.isAdd=true;
  177. }
  178. }
  179. let num= Math.abs(value)
  180. if (num === this.numVal) return;
  181. this.numVal = num;
  182. },
  183. activeIsAdd(){
  184. let isAdd=!this.isAdd;
  185. let value = this.numVal
  186. if(value===0){
  187. this.isAdd=isAdd;
  188. return false
  189. }
  190. if (!isAdd) {
  191. value = value * 1 * -1
  192. }
  193. if (this.max < value * 1) {
  194. this.numVal=this.max*1
  195. this.$emit('value', this.max*1)
  196. this.$toast('超出范围')
  197. return false
  198. }
  199. if (this.min > value * 1) {
  200. this.numVal=this.min*1
  201. this.$emit('value', this.min*1)
  202. this.$toast('超出范围')
  203. return false
  204. }
  205. this.$emit('value', value)
  206. this.isAdd=isAdd;
  207. },
  208. onInput (val) {
  209. if(!val){
  210. this.$emit('value','');
  211. return false
  212. }
  213. let value = val
  214. if (value.length > this.maxlength) {
  215. return false
  216. }
  217. if (!this.isAdd) {
  218. value = value * 1 * -1
  219. }
  220. // console.log(value,this.numVal,this.max,this.min)
  221. // if (this.min != this.max&&this.max < value * 1) {
  222. // console.log("大")
  223. // this.numVal=this.max*1
  224. // this.$toast('超出范围')
  225. // return false
  226. // }
  227. this.$emit('value', value * 1)
  228. },
  229. onBlur() {
  230. let value=this.numVal;
  231. if (!this.isAdd) {
  232. value = value * 1 * -1
  233. }
  234. if (this.numVal==='') {
  235. this.$toast('积分不能为空')
  236. this.$emit('value', this.min * 1)
  237. return false
  238. }
  239. if (this.max && this.max < value * 1) {
  240. this.$emit('value', this.max * 1)
  241. this.$toast('超出范围')
  242. return false
  243. }
  244. if (this.min > value * 1) {
  245. this.$emit('value', this.min * 1)
  246. this.$toast('超出范围')
  247. return false
  248. }
  249. },
  250. },
  251. }
  252. </script>
  253. <style scoped lang="less">
  254. .picker-box{
  255. width: 55px;
  256. border-radius: 25px;
  257. background-color: #f1f1f1;
  258. position: relative;
  259. height: 30px;
  260. }
  261. .picker-box span{
  262. text-align: center;
  263. line-height: 30px;
  264. font-size: 12px;
  265. }
  266. .yuan{
  267. width: 25px;
  268. height: 25px;
  269. background: #26A2FF;
  270. border-radius: 50px;
  271. position: absolute;
  272. top: 3px;
  273. }
  274. .picker-left{
  275. left: 3px;
  276. }
  277. .picker-right{
  278. right: 3px;
  279. }
  280. /deep/ .van-cell__title {
  281. width: 2rem;
  282. -webkit-box-flex: 0;
  283. -webkit-flex: none;
  284. flex: none;
  285. }
  286. /deep/ .van-cell__value {
  287. text-align: left;
  288. font-size: 0.36rem;
  289. }
  290. .diy-bar {
  291. padding: 0.32rem;
  292. }
  293. .v-focus {
  294. font-size: 0.34rem;
  295. vertical-align: top;
  296. color: #238dfa;
  297. animation: 1s cursor-flicker infinite;
  298. }
  299. @keyframes cursor-flicker {
  300. from {
  301. opacity: 0;
  302. }
  303. 50% {
  304. opacity: 1;
  305. }
  306. 100% {
  307. opacity: 0;
  308. }
  309. }
  310. /deep/ .van-number-keyboard__title {
  311. height: 0.88rem;
  312. border-top: 1px solid #94959a;
  313. background-color: #f0f1f3;
  314. text-align: right;
  315. }
  316. /deep/ .van-number-keyboard__title span {
  317. height: 0.88rem;
  318. line-height: 0.88rem;
  319. }
  320. /deep/ .van-number-keyboard__title-left {
  321. left: unset;
  322. right: 0;
  323. }
  324. /deep/ .van-number-keyboard__title-left a {
  325. padding: 0 0.32rem;
  326. color: #238dfa;
  327. }
  328. </style>