index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <template>
  2. <QStemplate :title="title" :titleHide="titleHide" :fontSize="fontSize" :width="width" :titleFlex="titleFlex"
  3. :contentFlex="contentFlex" :titleStyle="titleStyle" :contentStyle="contentStyle" :required="required" :requiredSign="requiredSign"
  4. :layout="layout" :titleLayout="titleLayout" :itemDisabled="itemDisabled" :titleColor="titleColor">
  5. <view class="flex_row_none_c transition_point6s width100 padding_10rpx_15rpx" :style="
  6. 'border-bottom: 1px solid ' +
  7. (focusBl?
  8. (focusBorderColor||'#999'):
  9. (blurBorderColor||'#f2f2f2')) + ';'">
  10. <view class="flex_row_none_c Flex5">
  11. <view class="Flex1" v-if="leftIcon">
  12. <view class="flex_row_c_c width100">
  13. <uni-icon :type="leftIcon" :size="iconSize" :color="leftIconColor||'#999'"></uni-icon>
  14. </view>
  15. </view>
  16. <view class="Flex5 position_relative">
  17. <input
  18. :type="inputType||'text'"
  19. :value="value"
  20. @input="inputs_change($event)"
  21. :placeholder="placeholder||('请输入' + title)"
  22. :password="passwordBl"
  23. :placeholder-style="inputSet.placeholder_style"
  24. :placeholder-class="inputSet.placeholder_class"
  25. :maxlength="inputSet.maxlength||140"
  26. :cursor-spacing="inputSet.cursor_spacing"
  27. :confirm-type="inputSet.confirm_type"
  28. :confirm-hold="inputSet.confirm_hold"
  29. :selection-start="inputSet.selection_start"
  30. :selection-end="inputSet.selection_end"
  31. :cursor="inputSet.cursor"
  32. :adjust-position="inputSet.adjust_position"
  33. :disabled="disabled"
  34. :style="{'font-size': fontSize + 'rpx', 'opacity': itemDisabled?0:1}"
  35. :focus="focusBl"
  36. class="fontColor666666 width100"
  37. @focus="focusChange()"
  38. @blur="blurChange()">
  39. </input>
  40. <view class="fontColor666666 inputItemDis flex_row_none_c" :style="{'font-size': fontSize + 'rpx'}" v-if="itemDisabled">
  41. {{value || placeholder || ('请输入' + title)}}
  42. </view>
  43. </view>
  44. </view>
  45. <view class="Flex1_5" v-if="tapClear">
  46. <view class="flex_row_c_c width100" v-if="value" @tap.prevent.stop="inputTap('clear')">
  47. <uni-icon type="clear" :size="iconSize" color="#999999"></uni-icon>
  48. </view>
  49. </view>
  50. <view class="Flex1_5" v-if="password">
  51. <view class="flex_row_c_c width100" @tap.prevent.stop="inputTap('password')">
  52. <uni-icon type="eye" :size="iconSize" :color="passwordBl?'#999999':passwordIconColor||'#33cc33'"></uni-icon>
  53. </view>
  54. </view>
  55. <view class="Flex1_5" v-if="customTapIcon">
  56. <view class="flex_row_c_c width100" @tap.prevent.stop="inputTap('custom')">
  57. <uni-icon :type="customTapIcon" :size="iconSize" :color="customTapIconColor||'#999'"></uni-icon>
  58. </view>
  59. </view>
  60. <view class="Flex2 flex_row_c_c" v-if="rightButtonTex">
  61. <button type="primary" size="mini" class="width100 text_nowrap margin_10rpx" :style="'font-size:' + btnSize + 'rpx;' + rightButtonStyle"
  62. @tap="inputTap('button')">
  63. {{rightButtonTex}}
  64. </button>
  65. </view>
  66. <view class="Flex2 flex_row_c_c" v-if="ifCode">
  67. <button type="primary" size="mini" class="width100 text_nowrap margin_10rpx" :disabled="startCodeBl" :style="'font-size:' + btnSize + 'rpx;' + codeButtonStyle"
  68. @tap="getCode()">
  69. {{startCodeBl?codeCount + 's':'获取验证码'}}
  70. </button>
  71. </view>
  72. </view>
  73. </QStemplate>
  74. </template>
  75. <script>
  76. import _app from '../../js/app.js';
  77. import QStemplate from '../../template/template.vue';
  78. import uniIcon from '../../uniIcons/uni-icons.vue';
  79. import QSInputsMixin from '../../js/QSInputsMixin.js';
  80. export default {
  81. components: {
  82. uniIcon,
  83. QStemplate
  84. },
  85. props: {
  86. inputSet: {
  87. type: Object,
  88. default () {
  89. return {};
  90. }
  91. },
  92. tapClear: {
  93. type: Boolean,
  94. default: true
  95. },
  96. inputType: {
  97. type: String,
  98. default: 'text'
  99. },
  100. focus: {
  101. type: Boolean,
  102. default: false
  103. },
  104. focusBorderColor: {
  105. type: String,
  106. default: '#999'
  107. },
  108. blurBorderColor: {
  109. type: String,
  110. default: '#f2f2f2'
  111. },
  112. password: {
  113. type: Boolean,
  114. default: false
  115. },
  116. passwordIconColor: {
  117. type: String,
  118. default: '#33cc33'
  119. },
  120. leftIcon: {
  121. type: String,
  122. default: ''
  123. },
  124. leftIconColor: {
  125. type: String,
  126. default: '#999'
  127. },
  128. customTapIcon: {
  129. type: String,
  130. default: ''
  131. },
  132. customTapIconColor: {
  133. type: String,
  134. default: '#999'
  135. },
  136. rightButtonTex: {
  137. type: String,
  138. default: ''
  139. },
  140. rightButtonStyle: {
  141. type: String,
  142. default: ''
  143. },
  144. ifCode: {
  145. type: Boolean,
  146. default: false
  147. },
  148. codeCountDown: {
  149. type: [String, Number],
  150. default: 60
  151. },
  152. codeButtonStyle: {
  153. type: String,
  154. default: ''
  155. },
  156. phoneNum: {
  157. type: String,
  158. default: ''
  159. },
  160. checkPhoneNum: {
  161. type: Boolean,
  162. default: false
  163. },
  164. disabled: {
  165. type: Boolean,
  166. default: false
  167. },
  168. placeholder: {
  169. type: String,
  170. default: ''
  171. },
  172. filterFc: {
  173. type: Function,
  174. default: null
  175. },
  176. filterType: {
  177. type: String,
  178. default: ''
  179. },
  180. verifyFc: {
  181. type: Function,
  182. default: null
  183. },
  184. verifyType: {
  185. type: String,
  186. default: ''
  187. },
  188. inputDebounceSet: {
  189. type: Object,
  190. default () {
  191. return {
  192. openInputDebounce: true,
  193. delay: 500
  194. };
  195. }
  196. }
  197. },
  198. computed: {
  199. iconSize() {
  200. return this.fontSize + 8;
  201. },
  202. btnSize() {
  203. return this.fontSize - 8;
  204. }
  205. },
  206. data() {
  207. return {
  208. passwordBl: !!this.password,
  209. focusBl: this.focus,
  210. inputDebounce: {},
  211. userCode: '', //用户输入的验证码
  212. codeCount: this.codeCountDown || 60, //获取验证码后倒计时时间
  213. code: '',
  214. startCodeBl: false //获取验证码状态
  215. }
  216. },
  217. watch: {
  218. itemDisabled(n, o) {
  219. if(n && this.focusBl) {
  220. uni.hideKeyboard();
  221. this.blurChange();
  222. }
  223. }
  224. },
  225. methods: {
  226. inputs_change({
  227. detail: {
  228. value
  229. }
  230. } = {}) { // 用户输入时,根据index赋值
  231. //_app.log(e.detail.value);
  232. // _app.log(index);
  233. const inputDebounce = this.inputDebounce;
  234. if (this.inputDebounceSet.openInputDebounce) {
  235. if (inputDebounce.debounce) clearTimeout(inputDebounce.debounce);
  236. if (inputDebounce.debounceTime && new Date().getTime() - inputDebounce.debounceTime < (
  237. this.inputDebounceSet.delay || 500)) {
  238. _app.log('防抖冲突,立即执行')
  239. this.inputs_changeFc(value, true);
  240. } else {
  241. inputDebounce.debounce = setTimeout(() => {
  242. _app.log('防抖')
  243. this.inputs_changeFc(value);
  244. }, this.inputDebounceSet.delay || 500);
  245. }
  246. } else {
  247. _app.log('无防抖')
  248. this.inputs_changeFc(value);
  249. }
  250. },
  251. inputs_changeFc(value, clash) {
  252. const inputDebounce = this.inputDebounce;
  253. if (this.inputDebounceSet.openInputDebounce) {
  254. if (clash) inputDebounce.debounceTime = 0;
  255. else inputDebounce.debounceTime = new Date().getTime();
  256. }
  257. if (this.filterFc && typeof(this.filterFc) == 'function') { //有filterFc则过滤
  258. this.input_filter_change(value, this.filterFc);
  259. } else if (this.filterType && _app.filterTypeObj[this.filterType] && typeof(_app.filterTypeObj[this.filterType]) ==
  260. 'function') {
  261. this.input_filter_change(value, _app.filterTypeObj[this.filterType]);
  262. } else {
  263. this.setValue(value);
  264. }
  265. },
  266. input_filter_change(value, filterFc) {
  267. const val = filterFc(value);
  268. if(val != value) {
  269. new Promise((reslove,reject)=>{
  270. this.setValue(' ');
  271. reslove();
  272. })
  273. .then(()=>{
  274. // setTimeout(()=>{
  275. this.setValue(val);
  276. // }, 10)
  277. })
  278. }else{
  279. this.setValue(val);
  280. }
  281. },
  282. focusChange() {
  283. if(!this.itemDisabled) this.focusBl = true;
  284. },
  285. blurChange() {
  286. this.focusBl = false;
  287. },
  288. inputTap(type) { //input点击事件
  289. switch (type) {
  290. case 'password': //密码显隐
  291. this.passwordBl = !this.passwordBl
  292. break;
  293. case 'clear': //一键清除
  294. this.setValue('');
  295. break;
  296. case 'custom':
  297. this.inputCustomTapFc();
  298. break;
  299. case 'button':
  300. this.inputCustomTapFc();
  301. break;
  302. default:
  303. _app.showToast('inputTap类型错误');
  304. break;
  305. }
  306. },
  307. async inputCustomTapFc() {
  308. try {
  309. const data = await _app.inputCustomTapFc(this.customId);
  310. if (data !== undefined && data !== null) {
  311. this.setValue(data);
  312. }
  313. } catch (e) {
  314. //TODO handle the exception
  315. const data = await _app.inputCustomTapCatchFc(this.customId, e);
  316. if (data !== undefined && data !== null) {
  317. this.setValue(data);
  318. }
  319. }
  320. },
  321. getCode() { // 判断是否正确输入手机号后发送验证码并倒计时
  322. let _this = this;
  323. if (_this.startCodeBl) return;
  324. if(this.checkPhoneNum) {
  325. const phone = this.phoneNum;
  326. if (_app.regTest('Tel', phone)) { //正则判断
  327. _this.$emit('getCode');
  328. // _this.code = _app.sendSMS(this.customId, phone);
  329. } else {
  330. _app.showToast('请正确输入11位手机号');
  331. return;
  332. }
  333. }else{
  334. _this.$emit('getCode');
  335. }
  336. /* let setInterValFunc = setInterval(() => { //定时器
  337. if (_this.codeCount > 0)
  338. --_this.codeCount;
  339. else {
  340. _this.startCodeBl = false;
  341. clearInterval(setInterValFunc);
  342. _this.code = '';
  343. _this.codeCount = this.codeCountDown;
  344. }
  345. }, 1000)
  346. _this.startCodeBl = true; */
  347. },
  348. startCode() {
  349. let _this = this;
  350. if(_this.startCodeBl) return;
  351. let setInterValFunc = setInterval(() => { //定时器
  352. if (_this.codeCount > 0)
  353. --_this.codeCount;
  354. else {
  355. _this.startCodeBl = false;
  356. clearInterval(setInterValFunc);
  357. _this.code = '';
  358. _this.codeCount = this.codeCountDown;
  359. }
  360. }, 1000)
  361. _this.startCodeBl = true;
  362. },
  363. /* checkCode(cb) {
  364. let result = false;
  365. let msg = '';
  366. if (this.ifCode) {
  367. if (!this.code) {
  368. msg = '请先获取验证码';
  369. } else if (!this.value) {
  370. msg = '请填写验证码';
  371. } else if (this.value !== this.code) {
  372. msg = '验证码不正确';
  373. this.code = '';
  374. this.setValue('');
  375. } else {
  376. result = true;
  377. msg = '验证通过';
  378. }
  379. } else {
  380. result = true;
  381. msg = '未启用验证码功能';
  382. }
  383. const obj = {
  384. result,
  385. msg
  386. };
  387. if (cb && typeof(cb) === 'function') {
  388. cb(obj);
  389. } else {
  390. return obj;
  391. }
  392. } */
  393. },
  394. mixins: [QSInputsMixin({
  395. QSInputsType: _app.typeObj.input
  396. })]
  397. };
  398. </script>
  399. <style scoped>
  400. @import url("../../css/inputs.css");
  401. </style>