Browse Source

fix: input 迁移

guoxiaoxiao8 4 years ago
parent
commit
f6658e27fd

+ 3 - 0
src/config.json

@@ -516,6 +516,7 @@
         },
         {
           "name": "Input",
+          "taro": true,
           "sort": 2,
           "cName": "输入框",
           "type": "component",
@@ -546,6 +547,7 @@
         },
         {
           "version": "3.0.0",
+          "taro": true,
           "name": "Calendar",
           "type": "component",
           "cName": "日历",
@@ -576,6 +578,7 @@
         },
         {
           "version": "3.0.0",
+          "taro": true,
           "name": "TextArea",
           "type": "component",
           "cName": "文本域",

+ 3 - 0
src/packages/__VUE/calendar/index.scss

@@ -186,3 +186,6 @@
     }
   }
 }
+.nut-calendar-taro {
+  height: 65vh;
+}

+ 129 - 0
src/packages/__VUE/calendar/index.taro.vue

@@ -0,0 +1,129 @@
+<template>
+  <nut-popup
+    v-if="poppable"
+    v-model:visible="visible"
+    position="bottom"
+    round
+    :closeable="true"
+    @click-overlay="closePopup"
+    @click-close-icon="closePopup"
+  >
+    <nut-calendar-item
+      props
+      ref="calendarRef"
+      :type="type"
+      :is-auto-back-fill="isAutoBackFill"
+      :poppable="poppable"
+      :title="title"
+      :default-value="defaultValue"
+      :start-date="startDate"
+      :end-date="endDate"
+      @update="update"
+      @close="close"
+      @choose="choose"
+    >
+    </nut-calendar-item>
+  </nut-popup>
+
+  <nut-calendar-item
+    v-else
+    :type="type"
+    :is-auto-back-fill="isAutoBackFill"
+    :poppable="poppable"
+    :title="title"
+    :default-value="defaultValue"
+    :start-date="startDate"
+    :end-date="endDate"
+    @close="close"
+    @choose="choose"
+  >
+  </nut-calendar-item>
+</template>
+<script lang="ts">
+import { PropType, ref } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+const { create } = createComponent('calendar');
+import Popup from './../popup/index.taro.vue';
+import CalendarItem from '@/packages/__VUE/calendaritem/index.vue';
+// import CalendarItem from './../calendaritem/index.taro.vue';
+import Utils from '@/packages/utils/date';
+type InputDate = string | string[];
+export default create({
+  children: [CalendarItem, Popup],
+  components: {
+    'nut-calendar-item': CalendarItem,
+    'nut-popup': Popup
+  },
+  props: {
+    type: {
+      type: String,
+      default: 'one'
+    },
+    isAutoBackFill: {
+      type: Boolean,
+      default: false
+    },
+    poppable: {
+      type: Boolean,
+      default: true
+    },
+    visible: {
+      type: Boolean,
+      default: true
+    },
+    title: {
+      type: String,
+      default: '日历选择'
+    },
+    defaultValue: {
+      type: String as PropType<InputDate>
+    },
+    startDate: {
+      type: String,
+      default: Utils.getDay(0)
+    },
+    endDate: {
+      type: String,
+      default: Utils.getDay(365)
+    }
+  },
+  emits: ['choose', 'close', 'update:visible'],
+  setup(props, { emit }) {
+    // element refs
+    const calendarRef = ref<null | HTMLElement>(null);
+
+    // methods
+    const update = () => {
+      emit('update:visible', false);
+    };
+
+    const close = () => {
+      emit('close');
+      emit('update:visible', false);
+    };
+
+    const choose = (param: string) => {
+      close();
+      emit('choose', param);
+    };
+
+    const closePopup = () => {
+      close();
+    };
+
+    return {
+      closePopup,
+      update,
+      close,
+      choose,
+      calendarRef
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+.popup-box {
+  height: 518px;
+}
+</style>

+ 3 - 0
src/packages/__VUE/calendaritem/index.scss

@@ -190,3 +190,6 @@
     }
   }
 }
+.nut-calendar-taro {
+  height: 65vh;
+}

+ 1 - 1
src/packages/__VUE/calendaritem/index.vue

@@ -1,6 +1,6 @@
 <template>
   <view
-    class="nut-calendar"
+    class="nut-calendar .nut-calendar-taro"
     :class="{
       'nut-calendar-tile': !poppable,
       'nut-calendar-nofooter': isAutoBackFill

+ 3 - 0
src/packages/__VUE/input/index.scss

@@ -17,6 +17,7 @@
     overflow: hidden;
     display: inline-block;
     text-align: left;
+    display: flex;
     .label-string {
       overflow: hidden;
       white-space: nowrap;
@@ -41,5 +42,7 @@
   }
   &-require {
     color: $primary-color;
+    display: inline-block;
+    margin-right: 5px;
   }
 }

+ 193 - 0
src/packages/__VUE/input/index.taro.vue

@@ -0,0 +1,193 @@
+<template>
+  <view :class="classes">
+    <view class="nut-input-label">
+      <view class="nut-input-require" v-if="requireShow">*</view>
+      <view v-if="label" class="label-string">{{ label }}</view>
+    </view>
+    <view v-if="readonly">
+      {{ modelValue }}
+    </view>
+    <input
+      v-else
+      class="input-text"
+      :style="styles"
+      :type="type"
+      :maxlength="maxLength"
+      :placeholder="placeholder"
+      :disabled="disabled"
+      :readonly="readonly"
+      :value="modelValue"
+      @input="valueChange"
+      @focus="valueFocus"
+      @blur="valueBlur"
+    />
+    <view
+      @click="handleClear"
+      class="nut-textinput-clear"
+      v-if="clearable && !readonly"
+      v-show="active && modelValue.length > 0"
+    >
+      <nut-icon name="close-little" size="12px"></nut-icon>
+    </view>
+  </view>
+</template>
+<script lang="ts">
+import { ref, computed } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+
+console.log('aaaa');
+function trimExtraChar(value: string, char: string, regExp: RegExp) {
+  const index = value.indexOf(char);
+
+  if (index === -1) {
+    return value;
+  }
+
+  if (char === '-' && index !== 0) {
+    return value.slice(0, index);
+  }
+
+  return value.slice(0, index + 1) + value.slice(index).replace(regExp, '');
+}
+
+function formatNumber(value: string, allowDot = true, allowMinus = true) {
+  if (allowDot) {
+    value = trimExtraChar(value, '.', /\./g);
+  } else {
+    value = value.replace(/\./g, '');
+  }
+
+  if (allowMinus) {
+    value = trimExtraChar(value, '-', /-/g);
+  } else {
+    value = value.replace(/-/, '');
+  }
+
+  const regExp = allowDot ? /[^-0-9.]/g : /[^-0-9]/g;
+
+  return value.replace(regExp, '');
+}
+
+const { componentName, create } = createComponent('input');
+interface Events {
+  eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
+  params: (string | number | Event)[];
+}
+export default create({
+  props: {
+    type: {
+      type: String,
+      default: 'text'
+    },
+    modelValue: {
+      type: [String, Number],
+      default: ''
+    },
+    placeholder: {
+      type: String,
+      default: '请输入信息'
+    },
+    label: {
+      type: String,
+      default: ''
+    },
+    requireShow: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    textAlign: {
+      type: String,
+      default: 'left'
+    },
+    maxLength: {
+      type: [String, Number],
+      default: '99999999'
+    },
+    clearable: {
+      type: Boolean,
+      default: true
+    }
+  },
+
+  emits: ['change', 'update:modelValue', 'blur', 'focus', 'clear'],
+
+  setup(props, { emit }) {
+    const active = ref(false);
+
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true,
+        [`${prefixCls}-disabled`]: props.disabled
+      };
+    });
+
+    const styles = computed(() => {
+      return {
+        textAlign: props.textAlign
+      };
+    });
+
+    const valueChange = (event: Event) => {
+      const input = event.target as HTMLInputElement;
+      let val = input.value;
+
+      if (props.maxLength && val.length > Number(props.maxLength)) {
+        val = val.slice(0, Number(props.maxLength));
+      }
+      if (props.type === 'digit') {
+        val = formatNumber(val, true);
+      }
+      if (props.type === 'number') {
+        val = formatNumber(val, false);
+      }
+      emit('change', val, event);
+      emit('update:modelValue', val, event);
+    };
+
+    const valueFocus = (event: Event) => {
+      const input = event.target as HTMLInputElement;
+      let value = input.value;
+      active.value = true;
+      emit('focus', value, event);
+    };
+
+    const valueBlur = (event: Event) => {
+      setTimeout(() => {
+        active.value = false;
+      }, 0);
+
+      const input = event.target as HTMLInputElement;
+      let value = input.value;
+      emit('blur', value, event);
+    };
+
+    const handleClear = (event: Event) => {
+      emit('change', '', event);
+      emit('update:modelValue', '', event);
+    };
+
+    return {
+      active,
+      classes,
+      styles,
+      valueChange,
+      valueFocus,
+      valueBlur,
+      handleClear
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 1 - 0
src/packages/__VUE/textarea/index.scss

@@ -1,6 +1,7 @@
 .nut-textarea {
   position: relative;
   width: 100%;
+  box-sizing: border-box;
   display: flex;
   background: $white;
   font-size: $textarea-font;

+ 132 - 0
src/packages/__VUE/textarea/index.taro.vue

@@ -0,0 +1,132 @@
+<template>
+  <view :class="classes">
+    <view v-if="readonly" class="nut-textarea__textarea">
+      {{ modelValue }}
+    </view>
+    <textarea
+      v-else
+      class="nut-textarea__textarea"
+      :style="styles"
+      :rows="rows"
+      :disabled="disabled"
+      :readonly="readonly"
+      :value="modelValue"
+      @input="change"
+      @blur="blur"
+      @focus="focus"
+      :maxlength="maxLength"
+      :placeholder="placeholder"
+    />
+    <view class="nut-textarea__limit" v-if="limitShow">
+      {{ modelValue.length }}/{{ maxLength }}</view
+    >
+  </view>
+</template>
+<script lang="ts">
+import { computed } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+
+const { componentName, create } = createComponent('textarea');
+
+export default create({
+  props: {
+    modelValue: {
+      type: [String, Number],
+      default: ''
+    },
+    textAlign: {
+      type: String,
+      default: 'left'
+    },
+    limitShow: {
+      type: Boolean,
+      default: false
+    },
+    maxLength: {
+      type: [String, Number],
+      default: ''
+    },
+    rows: {
+      type: [String, Number],
+      default: ''
+    },
+    placeholder: {
+      type: String,
+      default: '请输入内容'
+    },
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    autosize: {
+      type: Boolean,
+      default: false
+    }
+  },
+
+  emits: ['update:modelValue', 'change', 'blur', 'focus'],
+
+  setup(props, { emit }) {
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true,
+        [`${prefixCls}--disabled`]: props.disabled
+      };
+    });
+
+    const styles = computed(() => {
+      return {
+        textAlign: props.textAlign,
+        resize: props.autosize ? 'vertical' : 'none'
+      };
+    });
+
+    const emitChange = (value: string, event: Event) => {
+      if (props.maxLength && value.length > Number(props.maxLength)) {
+        value = value.substring(0, Number(props.maxLength));
+      }
+      emit('change', value, event);
+      emit('update:modelValue', value, event);
+    };
+
+    const change = (event: Event) => {
+      const input = event.target as HTMLInputElement;
+      emitChange(input.value, event);
+    };
+
+    const focus = (event: Event) => {
+      if (props.disabled) return;
+      if (props.readonly) return;
+      emit('focus', event);
+    };
+
+    const blur = (event: Event) => {
+      if (props.disabled) return;
+      if (props.readonly) return;
+      const input = event.target as HTMLInputElement;
+
+      let value = input.value;
+
+      emitChange(value, event);
+      emit('blur', event);
+    };
+
+    return {
+      classes,
+      styles,
+      change,
+      focus,
+      blur
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import './index.scss';
+</style>

+ 3 - 0
src/sites/mobile-taro/vue/src/app.config.ts

@@ -1,5 +1,8 @@
 export default {
   pages: [
+    'pages/textarea/index',
+    'pages/calendar/index',
+    'pages/input/index',
     'pages/popup/index',
     'pages/icon/index',
     'pages/inputnumber/index',

+ 154 - 0
src/sites/mobile-taro/vue/src/pages/calendar/index.vue

@@ -0,0 +1,154 @@
+<template>
+  <div class="demo">
+    <h2>基础用法</h2>
+    <div>
+      <nut-cell
+        :show-icon="true"
+        title="选择单个日期"
+        :desc="date ? `${date} ${dateWeek}` : '请选择'"
+        @click="openSwitch('isVisible')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible"
+        :default-value="date"
+        @close="closeSwitch('isVisible')"
+        @choose="setChooseValue"
+        :start-date="`2019-10-11`"
+        :end-date="`2022-11-11`"
+      >
+      </nut-calendar>
+    </div>
+
+    <div>
+      <nut-cell
+        :show-icon="true"
+        title="选择日期区间"
+        :desc="date1 ? `${date1[0]}至${date1[1]}` : '请选择'"
+        @click="openSwitch('isVisible1')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible1"
+        :default-value="date1"
+        type="range"
+        :start-date="`2019-12-22`"
+        :end-date="`2021-01-08`"
+        @close="closeSwitch('isVisible1')"
+        @choose="setChooseValue1"
+      >
+      </nut-calendar>
+    </div>
+
+    <h2>自定义日历-自动回填</h2>
+    <div>
+      <nut-cell
+        :show-icon="true"
+        title="选择日期"
+        :desc="date3 ? date3 : '请选择'"
+        @click="openSwitch('isVisible3')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible3"
+        @close="closeSwitch('isVisible3')"
+        @choose="setChooseValue3"
+        :default-value="date3"
+        :start-date="null"
+        :end-date="null"
+        :is-auto-back-fill="true"
+      >
+      </nut-calendar>
+    </div>
+
+    <h2>平铺展示</h2>
+    <div class="test-calendar-wrapper">
+      <nut-calendar
+        :poppable="false"
+        :default-value="date2"
+        :is-auto-back-fill="true"
+        @choose="setChooseValue2"
+      >
+      </nut-calendar>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs } from 'vue';
+
+interface TestCalendarState {
+  isVisible: boolean;
+  date: string;
+  dateWeek: string;
+  isVisible1: boolean;
+  date1: string[];
+  date2: string;
+  isVisible3: boolean;
+  date3: string;
+}
+export default {
+  props: {},
+  setup() {
+    const state: TestCalendarState = reactive({
+      isVisible: false,
+      date: '',
+      dateWeek: '',
+
+      isVisible1: false,
+      date1: ['2019-12-23', '2019-12-26'],
+
+      date2: '2020-07-08',
+
+      isVisible3: false,
+      date3: ''
+    });
+    const openSwitch = (param: string) => {
+      state[`${param}`] = true;
+      //state.isVisible = true;
+    };
+
+    const closeSwitch = (param: string) => {
+      state[`${param}`] = false;
+      //state.isVisible = false;
+    };
+
+    const setChooseValue = (param: string) => {
+      state.date = param[3];
+      state.dateWeek = param[4];
+    };
+
+    const setChooseValue1 = (param: string) => {
+      state.date1 = [...[param[0][3], param[1][3]]];
+    };
+
+    const setChooseValue2 = (param: string) => {
+      state.date2 = param[3];
+      console.log(state.date2);
+    };
+
+    const setChooseValue3 = (param: string) => {
+      state.date3 = param[3];
+    };
+
+    return {
+      ...toRefs(state),
+      openSwitch,
+      closeSwitch,
+      setChooseValue,
+      setChooseValue1,
+      setChooseValue2,
+      setChooseValue3
+    };
+  }
+};
+</script>
+
+<style lang="scss">
+.test-calendar-wrapper {
+  display: flex;
+  width: 100%;
+  height: 613px;
+  overflow: hidden;
+}
+</style>

+ 107 - 0
src/sites/mobile-taro/vue/src/pages/input/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="demo full">
+    <h2>基础用法</h2>
+    <nut-input
+      v-model="state.val1"
+      @change="change"
+      @focus="focus"
+      @blur="blur"
+      label="文本(异步)"
+    />
+    <nut-input
+      placeholder="请输入文本"
+      @change="change"
+      v-model="state.val0"
+      :require-show="true"
+      label="文本"
+      @clear="clear"
+    />
+    <h2>禁用输入框</h2>
+    <nut-input
+      v-model="state.val2"
+      @change="change"
+      :disabled="true"
+      label="文本"
+    />
+    <nut-input
+      v-model="state.val3"
+      @change="change"
+      :readonly="true"
+      label="文本"
+    />
+    <h2>限制输入长度</h2>
+    <nut-input
+      v-model="state.val4"
+      @change="change"
+      max-length="7"
+      label="限制7"
+    />
+    <h2>自定义类型</h2>
+    <nut-input
+      v-model="state.val7"
+      @change="change"
+      type="password"
+      label="密码"
+    />
+    <nut-input
+      v-model="state.val5"
+      @change="change"
+      type="number"
+      label="整数"
+    />
+    <nut-input
+      v-model="state.val6"
+      @change="change"
+      type="digit"
+      placeholder="支持小数点的输入"
+      label="数字"
+    />
+  </div>
+</template>
+
+<script lang="ts">
+import { reactive } from 'vue';
+
+export default {
+  props: {},
+
+  setup() {
+    const state = reactive({
+      val0: '',
+      val1: '初始数据',
+      val2: '禁止修改',
+      val3: 'readonly 只读',
+      val4: '',
+      val5: '',
+      val6: '',
+      val7: '',
+      val8: '文案'
+    });
+    setTimeout(function() {
+      state.val1 = '异步数据';
+    }, 2000);
+    const change = (value: string | number, event: Event) => {
+      console.log('change: ', value, event);
+    };
+    const focus = (value: string | number, event: Event) => {
+      console.log('focus:', value, event);
+    };
+    const blur = (value: string | number, event: Event) => {
+      console.log('blur:', value, event);
+    };
+    const clear = (value: string | number) => {
+      console.log('clear:', value);
+    };
+
+    return {
+      state,
+      change,
+      blur,
+      clear,
+      focus
+    };
+  }
+};
+</script>
+
+<style lang="scss"></style>

+ 41 - 0
src/sites/mobile-taro/vue/src/pages/textarea/index.vue

@@ -0,0 +1,41 @@
+<template>
+  <div class="demo full">
+    <h2>基础用法</h2>
+    <nut-textarea v-model="value" />
+    <h2>显示字数统计</h2>
+    <nut-textarea v-model="value2" limit-show max-length="20" />
+    <h2>高度自定义,拉伸</h2>
+    <nut-textarea v-model="value3" rows="10" autosize />
+    <h2>只读</h2>
+    <nut-textarea readonly model-value="textarea只读状态" />
+    <h2>禁用</h2>
+    <nut-textarea
+      disabled
+      model-value="textarea禁用状态"
+      limit-show
+      max-length="20"
+    />
+  </div>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+
+export default {
+  props: {},
+
+  setup() {
+    const value = ref('');
+    const value2 = ref('');
+    const value3 = ref('');
+
+    return {
+      value,
+      value2,
+      value3
+    };
+  }
+};
+</script>
+
+<style lang="scss"></style>