app内嵌H5的上传图片的功能




1.上传组件

<!--
  - hasBorder {Boolean} cell底部边框,oneline 为 true 有效
  - inlineBorder {Boolean} cell底部短边框
  - height 
  - titleColor {String} 标题颜色
  - readOnly {Boolean} date/radio/address 类型只读
  - inputData @updateValue传递value 获取 输出String或Number,address类型输出 [provinceId, cityId]
  以下参数只用于 radio 类型
  - radioValues {Array} 单选选项数组,["苹果","橘子"] 或 [{name: "苹果",value: "apple"}](updateValue传递value)
  - labelKey {String} 数组项为对象类型时要显示值的 key
  - emitObject {Boolean} 数组项为对象时决定是否将选中的整个对象上报
  - radio 示例
    <form-cell title="单选"
              :readOnly="false"
              :value="radioValue"
              titleColor="#575fb6"
              inputType="radio"
              :oneLine="true"
              :arrow="true"
              :radio-values="[{name:'苹果', value:'apple'},{name:'桔子', value:'orange'}]"
              @updateValue="val => {radioValue = val}"
              ></form-cell>
  - address 示例
    <form-cell title="省市选择"
              :readOnly="false" // true 不可点击,可返回绑定 value 对应的 name
              :value="addressIdArr" // {Array || ''} 数组前两项必须为[provinceId,cityId],输出第三项为'广东省广州市'
              titleColor="#575fb6"
              inputType="address"
              :oneLine="true"
              :arrow="true"
              @updateValue="val => {addressIdArr = val}"
              ></form-cell>
-->
<template>
  <div>
    <div class="cell-wrapper new-line" v-if="!oneLine">
      <span class="title"
            @click="activeInput"
            :style="{ color: titleColor, lineHeight: height }">{{ title }}</span>
      <span class="value value-single-line"
            v-if="inputType === 'number'">
        <span class="icon-edit" v-if="!disabled"></span>
        <input v-if="!disabled"
               v-model="inputData"
               ref="numberInput"
               :style="{'text-align': textAlign}"
               @change="updateValue"
               type="number"
               :placeholder="placeholder">
        <span v-else>{{ inputData }}</span>
        <span v-show="inputData && !disabled"
              @click="emptyInput"
              class="btn__empty"></span>  
        <!-- <span v-show="inputData" 
              class="icon-empty__inline-text"
              @click="emptyInput"
              ></span> -->
        <span class="input-unit">{{unit}}</span>
      </span>
      <span class="value value-single-line"
            v-if="inputType === 'text'">
        <span class="icon-edit" v-if="!disabled"></span>
        <input v-if="!disabled"
               v-model="inputData"
               ref="textInput"
               :style="{'text-align': textAlign}"
               @change="updateValue"
               @blur="handleInputBlur"
               type="text"
               :placeholder="placeholder">
        <span v-else>{{ inputData }}</span>
        <span v-show="inputData && !disabled"
              @click="emptyInput"
              class="btn__empty"></span> 
        <!-- <span v-show="inputData" 
              class="icon-empty__inline-text"
              @click="emptyInput"
              ></span> -->
      </span>
      <span v-if="inputType === 'textarea'"
            v-show="inputData && !disabled"
            @click="emptyInput"
            class="btn__empty-textarea">清除</span>  
      <span class="value"
            v-if="inputType === 'textarea'">
            <span class="icon-edit"
                  v-if="showIcon && !disabled"></span>
            <!-- <div class="auto-height">
              <pre><br>{{ inputData }}</pre> -->
            <span class="icon-history" v-if="showHistory" @click="selectHistory"></span>  
            <textarea v-if="!disabled" ref="remark" v-autosize="inputData" v-model="inputData" @change="updateValue" :rows="rows" :placeholder="placeholder"
            :style="fixHistory"></textarea>
            <span v-else>{{ inputData }}</span>
            <!-- </div> -->
      </span>
      <div v-if="inlineBorder"
          class="inline-border"></div>
      <slot></slot>
    </div>
    <div class="cell-wrapper one-line" v-else
         :class="{ 'has-border': hasBorder}"
         :style="{ minHeight: height }">
      <span class="title"
            v-if="!multiLine"
            @click="activeInput"
            :style="{ color: titleColor,  titleWidth, lineHeight: height }">{{ title }}</span>
      <span class="title-multiLine"
            v-else
            :style="{ color: titleColor}">{{ title }}</span>
      <span class="value"
            :style="{ lineHeight: height, color: valueColor }"
            v-if="readOnly && !multiLine && !isLabelShowing">{{ value }}</span>
      <span class="value value-multiLine"
            :style="{ color: valueColor }"
            v-if="readOnly && multiLine && !isLabelShowing">{{ value }}</span>
      <span class="value switch-wrapper"
            v-if="inputType === 'switch' && !readOnly">
        <mt-switch v-model="inputData" @change="updateValue"></mt-switch>
      </span>
      <span v-if="inputType === 'date' && !readOnly"
            class="value date">
        <input v-model="inputData"
               @click="selectDate"
               :style="{ lineHeight: height }">
        <mt-datetime-picker
          :value="startDate"
          ref="picker"
          type="date"
          @confirm="updateDate"
          @touchmove.prevent.stop.native>
        </mt-datetime-picker>
      </span>
      <span v-if="inputType === 'time' && !readOnly"
            class="value date">
        <input v-model="inputData"
               @click="selectDate"
               :style="{ lineHeight: height }">
        <mt-datetime-picker
          :value="startDate"
          ref="picker"
          type="dateTime"
          @confirm="updateDate"
          @touchmove.prevent.stop.native>
        </mt-datetime-picker>
      </span>
      <span v-if="inputType === 'radio'"
            class="value date">
        <input v-model="popupLabel"
               @click="showPopup"
               :style="{ lineHeight: height }">
        <popup-picker ref="radio" 
                      :picker-type="inputType" 
                      :radio-values="radioValues" 
                      :label-key="labelKey"
                      :value="value" 
                      :emitObject="emitObject"
                      @updateLabel="setLabelandArrow" 
                      @confirm="confirmPopup">
        </popup-picker>
      </span>
      <span v-if="inputType === 'address'"
            class="value date">
        <input v-model="popupLabel"
               @click="showPopup"
               :style="{ lineHeight: height }">
        <popup-picker ref="address" 
                      :picker-type="inputType"
                      :value="value" 
                      :provinceList="provinceList"
                      :cityList="cityList"
                      :label-key="labelKey"
                      :addressSlotsObject="addressSlotsObject"
                      @updateLabel="setLabelandArrow" 
                      @confirm="confirmPopup">
        </popup-picker>
      </span>
      <span v-if="inputType === 'counties'"
            class="value date">
        <input v-model="popupLabel"
               @click="showPopup"
               :style="{ lineHeight: height }">
        <popup-picker ref="counties" 
                      :picker-type="inputType"
                      :value="value" 
                      :saveCityMap="saveCityMap"
                      :needCounties="needCounties"
                      @updateLabel="setLabelandArrow" 
                      @confirm="confirmPopup">
        </popup-picker>
      </span>
      <span v-if="inputType === 'dateTime'"
            class="value date">
        <input v-model="value"
               @click="showPopup"
               :style="{ lineHeight: height }">
        <popup-picker ref="dateTime" 
                      :picker-type="inputType"
                      :value="value" 
                      @updateLabel="setLabelandArrow" 
                      @confirm="confirmPopup">
        </popup-picker>
      </span>
      <span class="arrow" v-show="arrow"></span>
      <div v-if="inlineBorder"
          class="inline-border"></div>
    </div>
  </div>
</template>

<script>
import PopupPicker from './formCellPicker'
export default {
  name: 'formCell',
  props: {
    disabled: {
      type: Boolean,
      default: false
    },
    hasBorder: {
      type: Boolean,
      default: false
    },
    inlineBorder: {
      type: Boolean,
      default: false
    },
    height: {
      type: String,
      default: '1.333rem'
    },
    titleColor: {
      type: String,
      default: '#999999'
    },
    readOnly: {
      type: Boolean,
      default: true
    },
    unit: {
      type: String,
      default: ''
    },
    title: {
      type: String,
      required: true
    },
    titleWidth: {
      type: String
    },
    value: {
      require: true
    },
    valueColor: {
      type: String,
      default: '#4a4a4a'
    },
    multiLine: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: '请输入'
    },
    arrow: {
      type: Boolean,
      default: false
    },
    inputType: {
      type: String,
      default: 'text'
    },
    oneLine: {
      type: Boolean,
      defalut: false
    },
    showIcon: {
      type: Boolean,
      default: true
    },
    textAlign: {
      type: String,
      default: 'left'
    },
    radioValues: {
      type: Array
    },
    labelKey: {
      type: String
    },
    rows: {
      type: Number,
      default: 1
    },
    reportFocusAndBlur: {
      type: Boolean,
      defalut: false
    },
    showHistory: {
      type: Boolean,
      default: false
    },
    saveCityMap: {
      type: Boolean,
      default: false
    },
    needCounties: {
      type: Boolean,
      default: false
    },
    provinceList: {
      type: Array,
      defalut: () => { return [] }
    },
    cityList: {
      type: Object,
      defalut: () => { return {} }
    },
    emitObject: {
      type: Boolean,
      defalut: false
    },
    addressSlotsObject: {
      type: String,
      default: 'NONE'
    }
  },
  components: {
    PopupPicker
  },
  data () {
    return {
      inputData: '',
      showArrow: false,
      startDate: new Date(),
      popupLabel: '',
      isIos: /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent),
      isAndroid: /(Android)/i.test(navigator.userAgent),
      fixHistory: {
        paddingRight: this.showHistory ? '1rem' : 0
      }
    }
  },
  computed: {
    isLabelShowing () {
      return this.inputType === 'radio' || this.inputType === 'address' || this.inputType === 'counties' || this.inputType === 'dateTime'
    }
  },
  created () {
    this.inputData = this.value
    this.showArrow = this.arrow
  },
  mounted () {
    this.inputData = this.value
    this.showArrow = this.arrow
    if (this.inputData && (this.inputType === 'time' || this.inputType === 'date')) {
      this.startDate = new Date(this.inputData.replace('-', '/'))
    }
    if (this.reportFocusAndBlur) {
      let inputEl = 'textInput'
      if (this.inputType === 'number') {
        inputEl = 'numberInput'
      }
      if (this.inputType === 'textarea') {
        inputEl = 'remark'
      }
      let that = this
      this.$refs[inputEl].addEventListener('focus', () => {
        setTimeout(() => {
          that.$emit('inputFocus')
        }, 100)
      })
      this.$refs[inputEl].addEventListener('blur', () => {
        setTimeout(() => {
          that.$emit('inputBlur')
        }, 100)
      })
    }
    if (this.inputType === 'number') {
      this.$refs['numberInput'].addEventListener('paste', (e) => {
        if (!(e.clipboardData && e.clipboardData.items)) {
          return
        }
        let that = this
        for (let i = 0, len = e.clipboardData.items.length; i < len; i++) {
          let item = e.clipboardData.items[i]
          if (item.kind === 'string') {
            item.getAsString((string) => {
              that.inputData = string ? string.replace(/[^d]/g, '') : ''
            })
          }
        }
      })
    }
  },
  watch: {
    value: function () {
      this.inputData = this.value
    },
    inputData: function () {
      this.$emit('updateValue', this.inputData)
    }
  },
  methods: {
    updateValue () {
      this.$emit('updateValue', this.inputData)
    },
    handleInputBlur () {
      this.$emit('handleBlur')
    },
    selectHistory () {
      this.$emit('history')
    },
    activeInput () {
      if (this.inputType === 'date') {
        this.selectDate()
      }
      if (this.inputType === 'radio' || this.inputType === 'address' || this.inputType === 'counties' || this.inputType === 'dateTime') {
        this.showPopup()
      }
      if (this.inputType === 'textarea') {
        this.$refs.remark.focus()
      }
      if (this.inputType === 'number') {
        this.$refs.numberInput.focus()
      }
      if (this.inputType === 'text') {
        this.$refs.textInput.focus()
      }
    },
    emptyInput () {
      this.inputData = ''
      this.activeInput()
    },
    selectDate () {
      document.activeElement.blur()
      this.$mint.delayWhileInputFocus(() => {
        this.$refs.picker.open()
      })
    },
    updateDate (value) {
      let year = value.getFullYear()
      let month = value.getMonth() + 1
      let day = value.getDate()
      if (this.inputType === 'date') {
        this.inputData = year + '-' + month + '-' + day
      }
      if (this.inputType === 'time') {
        let hour = value.getHours() < 10 ? '0' + value.getHours() : value.getHours()
        let minute = value.getMinutes() < 10 ? '0' + value.getMinutes() : value.getMinutes()
        this.inputData = year + '-' + month + '-' + day + ' ' + hour + ':' + minute
      }
      this.$emit('updateValue', this.inputData)
    },
    showPopup () {
      document.activeElement.blur()
      if (this.readOnly) {
        return
      }
      this.$mint.delayWhileInputFocus(() => {
        if (this.inputType === 'radio') {
          this.$refs.radio.open()
        } else if (this.inputType === 'address') {
          this.$refs.address.open()
        } else if (this.inputType === 'counties') {
          this.$refs.counties.open()
        } else if (this.inputType === 'dateTime') {
          this.$refs.dateTime.open()
        }
      })
    },
    confirmPopup (obj) {
      this.inputData = obj.val
      // this.showArrow = obj.showArrow
      this.$emit('updateValue', this.inputData)
    },
    setLabelandArrow (val) {
      this.popupLabel = val
      this.$emit('updateLabel', val)
      // this.$nextTick(()=>{this.showArrow = !val})
    }
  }
}
</script>

<style lang="stylus" scoped>
@import "~@/assets/mixin.stylus"
.cell-wrapper{
  position relative
  font-dpr(16px)
  padding 0 .5rem
  background-color white
  vertical-align middle
  box-sizing border-box
  .title{
    width 3.5rem
  }
  .title-multiLine{
    display inline-block
    width 3.5rem
    height 1.2rem
    line-height 1.2rem
  }
  .value{
    position relative
    display inline-block
    width 5.5rem
    // color #4A4A4A
    .auto-height{
      position relative
      padding .1rem 0
      pre{
        display block
        visibility hidden
        line-height normal
      }
    }
  }
  .switch-wrapper{
    display flex
    justify-content flex-end
  }
  .btn__empty-textarea {
    position absolute
    top .4rem
    right .5rem
    display inline-block
    width 1.2rem
    height .5rem
    line-height .5rem
    text-align center
    border-radius .3rem
    background-color #D8D8D8
    font-dpr(12px)
    color #4a4a4a
  }
  .value-multiLine{
    padding .32rem 0
    word-wrap break-word
    // line-height .7rem
  }
  .arrow{
    position relative
    top .45rem
    display inline-block
    width .2rem
    height .4rem
    bg-image('~@/assets/img/arrow')
    background-size contain
    margin-left .3rem
  }
  .inline-border{
    position absolute
    bottom 0
    left .4rem
    width 9.6rem
    height 1px
    background-color #ECECEC
  }
}
.new-line{
  .value{
    display flex
    width 100%
    padding-bottom .3rem
    .icon-edit{
      position relative
      top .05rem
      display inline-block
      width .45rem
      height .45rem
      padding-right .3rem
      bg-image('img/pen')
      background-size contain
    }
    .icon-history{
      position absolute
      right 0
      bottom .3rem
      display inline-block
      width .56rem
      height .56rem
      bg-image('img/record')
      background-size contain
      z-index 11
    }
    input{
      height .6rem
      width 100%
      margin-right .2rem
      text-align left
      color #4a4a4a
      &:placeholder {
        font-dpr(16px)
        color #979797
      }
      &::-webkit-input-placeholder {
        font-dpr(16px)
        color #979797
      }
      &:-moz-placeholder {
        font-dpr(16px)
        color #979797
      }
      &::-moz-placeholder {
        font-dpr(16px)
        color #979797
      }
      &:-ms-input-placeholder {
        font-dpr(16px)
        color #979797
      }
    }
    .btn__empty {
      display inline-block
      width .5rem
      height .5rem
      bg-image('./img/close')
      background-size contain
      position relative
      top .08rem
    }
    .icon-empty__inline-text {
      float right 
      position relative
      display inline-block
      height .6rem
      width .6rem
      margin-right .2rem
      bg-image('~@detailComponents/img/delete')
      background-size contain
    }
    textarea{
      font-dpr(16px)
      position relative
      width 100%
      color #4a4a4a
      &:placeholder {
        font-dpr(16px)
        color #979797
      }
      &::-webkit-input-placeholder {
        font-dpr(16px)
        color #979797
      }
      &:-moz-placeholder {
        font-dpr(16px)
        color #979797
      }
      &::-moz-placeholder {
        font-dpr(16px)
        color #979797
      }
      &:-ms-input-placeholder {
        font-dpr(16px)
        color #979797
      }
    }
  }
}
.one-line{
  display flex
  .value{
    text-align right
  }
  .switch-wrapper{
    display flex
    justify-content flex-end
  }
  .date{
    input{
      width 100%
      text-align right
    }
  }
}
.has-border{
  border-bottom 1px solid #ECECEC
}
</style>

<template>
  <div>
    <mt-popup v-if="pickerType === 'radio'"
      v-model="popupVisible"
      class="lx-popup"
      position="bottom">
      <mt-picker @touchmove.prevent.stop.native
        ref="radio"
        :slots="radioSlots"
        :value-key="labelKey"
        show-toolbar>
        <span class="mint-datetime-action mint-datetime-cancel" @click="popupVisible=false">取消</span>
        <span class="mint-datetime-action mint-datetime-confirm" @click="confirmRadio">确认</span>
      </mt-picker>
    </mt-popup>
    <mt-popup v-else-if="pickerType === 'address'"
      v-model="popupVisible"
      class="lx-popup"
      position="bottom">
      <mt-picker @touchmove.prevent.stop.native
        ref="address"
        @change="onAddressChange"
        :slots="addressSlots"
        :value-key="labelKey"
        show-toolbar>
        <span class="mint-datetime-action mint-datetime-cancel" @click="popupVisible=false">取消</span>
        <span class="mint-datetime-action mint-datetime-confirm" @click="confirmAddress">确认</span>
      </mt-picker>
    </mt-popup>
    <mt-popup v-else-if="pickerType === 'counties'"
      v-model="popupVisible"
      class="lx-popup"
      position="bottom">
      <mt-picker @touchmove.prevent.stop.native
        ref="counties"
        @change="onCountiesChange"
        :slots="countiesSlots"
        value-key="name"
        show-toolbar>
        <span class="mint-datetime-action mint-datetime-cancel"
              :class="{'lx-action__with-title': title}" @click="popupVisible=false">取消</span>
        <span class="lx-picker-title" v-if="title">{{title}}</span>
        <span class="mint-datetime-action mint-datetime-confirm"
              :class="{'lx-action__with-title': title}"  @click="confirmCounties">确认</span>
      </mt-picker>
    </mt-popup>
    <mt-popup v-else-if="pickerType === 'dateTime'"
      v-model="popupVisible"
      class="lx-popup"
      position="bottom">
      <mt-picker @touchmove.prevent.stop.native
        ref="dateTime"
        @change="onTimeChange"
        :slots="dateTimeSlots"
        show-toolbar>
        <span class="mint-datetime-action mint-datetime-cancel"
              :class="{'lx-action__with-title': title}" @click="popupVisible=false">取消</span>
        <span class="lx-picker-title" v-if="title">{{title}}</span>
        <span class="mint-datetime-action mint-datetime-confirm"
              :class="{'lx-action__with-title': title}"  @click="confirmTime">确认</span>
      </mt-picker>
    </mt-popup>
  </div>
</template>

<script>
import store from '@/utils/store'
import mapCity from '@/api/mapAsk'
let loadingAddress = false

export default {
  name: 'PopupPicker',
  props: {
    pickerType: {
      type: String
    },
    radioValues: {
      type: Array
    },
    labelKey: {
      type: String,
      default: 'name'
    },
    value: {
      default: ''
    },
    title: {
      default: ''
    },
    saveCityMap: {
      type: Boolean,
      default: false
    },
    needCounties: {
      type: Boolean,
      default: false
    },
    provinceList: {
      type: Array,
      default: () => { return [] }
    },
    cityList: {
      type: Object,
      default: () => { return {} }
    },
    emitObject: {
      type: Boolean,
      default: false
    },
    /**
     *  address picker 组件判断各slot内部选项是否为对象 NONE--都不是  FIRST--第一个slot为对象 LAST--最后一个slot为对象
     *  BOTH--都是对象
     */
    addressSlotsObject: {
      type: String,
      default: 'NONE'
    }
  },
  data () {
    return {
      popupVisible: false,
      selectedRadioIndex: 0,
      selectAddressIndex: [0, 0],
      selectCountiesIndex: [0, 0, 0],
      selectTimeIndex: [0, 0, 0],
      dateForOddMonth: ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日', '29日', '30日', '31日'],
      dateForEvenMonth: ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日', '29日', '30日'],
      addressData: [],
      addressSlots: [
        {
          flex: 1,
          values: [],
          textAlign: 'center'
        }, {
          divider: true,
          content: '-'
        }, {
          flex: 1,
          values: [],
          textAlign: 'center'
        }
      ],
      countiesSlots: [
        {
          flex: 1,
          values: [],
          textAlign: 'center'
        }, {
          flex: 1,
          values: [],
          textAlign: 'center'
        }, {
          flex: 1,
          values: [],
          textAlign: 'center'
        }
      ],
      dateTimeSlots: [
        {
          flex: 0.5,
          values: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
          textAlign: 'right'
        },
        {
          flex: 0.5,
          values: ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日', '29日', '30日', '31日'],
          textAlign: 'left'
        },
        {
          flex: 1,
          values: ['0:00 - 0:30', '0:30 - 1:00', '1:00 - 1:30', '1:30 - 2:00', '2:00 - 2:30', '2:30 - 3:00', '3:00 - 3:30', '3:30 - 4:00', '4:00 - 4:30', '4:30 - 5:00', '5:00 - 5:30', '5:30 - 6:00', '6:00 - 6:30', '6:30 - 7:00', '7:00 - 7:30', '7:30 - 8:00', '8:00 - 8:30', '8:30 - 9:00', '9:00 - 9:30', '9:30 - 10:00', '10:00 - 10:30', '10:30 - 11:00', '11:00 - 11:30', '11:30 - 12:00', '12:00 - 12:30', '12:30 - 13:00', '13:00 - 13:30', '13:30 - 14:00', '14:00 - 14:30', '14:30 - 15:00', '15:00 - 15:30', '15:30 - 16:00', '16:00 - 16:30', '16:30 - 17:00', '17:00 - 17:30', '17:30 - 18:00', '18:00 - 18:30', '18:30 - 19:00', '19:00 - 19:30', '19:30 - 20:00', '20:00 - 20:30', '20:30 - 21:00', '21:00 - 21:30', '21:30 - 22:00', '22:00 - 22:30', '22:30 - 23:00', '23:00 - 23:30', '23:30 - 24:00'],
          textAlign: 'center'
        }
      ]
    }
  },
  computed: {
    dateForFeb () {
      let year = new Date().getFullYear()
      if (year % (year % 100 ? 4 : 400)) {
        return ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日']
      } else {
        return ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日', '29日']
      }
    },
    radioSlots () {
      if (this.pickerType !== 'radio') {
        return []
      }
      const arr = this.radioValues.slice()
      if (arr.length === 0) {
        return []
      }
      if (typeof arr[0] !== 'object') {
        // if (arr[0] !== '请选择') {arr.splice(0,0,'请选择')}
        return [{
          flex: 1,
          values: arr
        }]
      } else {
        // if (arr[0][this.labelKey] !== '请选择') {
        //   const obj ={}
        //   obj[this.labelKey] = '请选择'
        //   obj.value = ''
        //   arr.splice(0,0,obj)
        // }
        return [{
          flex: 1,
          values: arr
        }]
      }
    },
    label () {
      if (this.pickerType === 'radio') {
        if (this.radioValues.length === 0) {
          return ''
        }
        // radioValues 数组元素不是对象直接返回
        if (Object.prototype.toString.call(this.radioValues[0]) !== '[object Object]') {
          this.selectedRadioIndex = this.radioValues.indexOf(this.value)
          return this.value
        }
        // 是对象进行对比
        const values = this.radioValues
        for (let i = 0; i < values.length; i++) {
          const obj = values[i]
          if (obj.value && this.value === obj.value) {
            this.selectedRadioIndex = i
            return obj[this.labelKey]
          } else if (this.value === obj[this.labelKey]) {
            this.selectedRadioIndex = i
            return obj[this.labelKey]
          }
        }
      } else if (this.pickerType === 'counties') {
        if (this.addressData.length === 0 || !this.isArray(this.value)) {
          return ''
        }
        const selectedProvinceId = this.value[0]
        const selectedCityId = this.value[1]
        const selectedCountyId = this.value[2]
        for (var i = 0; i < this.addressData.length; i++) {
          const province = this.addressData[i]
          if (selectedProvinceId === province.id) {
            for (var j = 0; j < province.cities.length; j++) {
              const city = province.cities[j]
              if (selectedCityId === city.id) {
                if (this.pickerType === 'address') {
                  this.selectAddressIndex = [i, j]
                  return `${province.name} ${city.name}`
                } else {
                  for (var k = 0; k < city.counties.length; k++) {
                    const county = city.counties[k]
                    if (selectedCountyId === county.id) {
                      this.selectCountiesIndex = [i, j, k]
                      return `${province.name} ${city.name} ${county.name !== '暂不选择' ? county.name : ''}`
                    }
                  }
                }
              }
            }
          }
        }
      } else if (this.pickerType === 'address') {
        if (this.provinceList.length === 0 || !this.isArray(this.value)) {
          return ''
        }
        const values = this.value
        let label = ''
        switch (this.addressSlotsObject) {
          case 'NONE':
            label = `${values[0]}${values[1]}`
            break
          case 'FIRST':
            label = `${values[0][this.labelKey]}${values[1]}`
            break
          case 'LAST':
            label = `${values[0]}${values[1][this.labelKey]}`
            break
          case 'BOTH':
            label = `${values[0][this.labelKey]}${values[1][this.labelKey]}`
            break
          default:
            label = `${values[0]}${values[1]}`
            break
        }
        return label
      }
      return ''
    }
  },
  watch: {
    label (val) {
      this.$emit('updateLabel', val)
    }
  },
  methods: {
    open () {
      if (this.pickerType === 'radio') {
        this.$nextTick(() => {
          this.$refs.radio.setValues([this.radioValues[this.selectedRadioIndex]])
        })
        this.popupVisible = true
        // if (this.selectedRadioIndex < 0) return
      } else if (this.pickerType === 'address') {
        if (this.provinceList && this.provinceList.length > 0) {
          this.addressSlots[0].values = this.provinceList
          this.addressSlots[2].values = this.cityList[this.provinceList[0]]
          if (this.value[0]) {
            this.addressSlots[2].values = this.cityList[this.value[0]]
          }
          this.popupVisible = true
        }
        const values = this.value.length === 0 ? [this.provinceList[0], this.cityList[this.provinceList[0]][0]] : this.value
        this.$refs.address.setValues(values)
      } else if (this.pickerType === 'counties') {
        if (this.addressData.length === 0) {
          loadingAddress = true
          this.$indicator.open()
          this.getAddressData()
        } else {
          this.popupVisible = true
        }
        if (!this.isArray(this.selectCountiesIndex)) {
          return
        }
        // if (this.selectCountiesIndex[0] < 0&&this.selectCountiesIndex[1] < 0) {return}
        const selectedProvince = this.addressData[this.selectCountiesIndex[0]]
        const selectedCity = selectedProvince.cities[this.selectCountiesIndex[1]]
        const selectCounty = selectedCity.counties[this.selectCountiesIndex[2]]
        this.$refs.counties.setValues([selectedProvince, selectedCity, selectCounty])
      } else if (this.pickerType === 'dateTime') {
        this.popupVisible = true
        if (this.value) {
          const month = this.value.split('月')[0] === this.value ? '1月' : this.value.split('月')[0] + '月'
          let day = '1日'
          if (this.value.split('月')[1]) {
            day = this.value.split('月')[1].split('日')[0] + '日'
          }
          let time = '0:00 - 0:30'
          let values = this.value.split('')
          if (values.length === 4) {
            time = `${values[1]} - ${values[3]}`
          }
          this.$refs.dateTime.setValues([month, day, time])
        } else {
          let month = new Date().getMonth() + 1 + '月'
          let date = new Date().getDate() + '日'
          this.$refs.dateTime.setValues([month, date, '0:00 - 0:30'])
        }
      }
    },
    confirmRadio () {
      let val
      const valArr = this.$refs.radio.getValues()
      const temVal = valArr[0]
      if (typeof temVal === 'undefined') {
        this.popupVisible = false
        return
      }
      if (this.emitObject) {
        val = typeof temVal === 'object' ? temVal : {}
      } else {
        val = typeof temVal === 'object' ? temVal.value : temVal
        val = val === '请选择' ? '' : val
      }
      this.popupVisible = false
      this.$emit('confirm', {
        val
      })
    },
    confirmAddress () {
      const values = this.$refs.address.getValues()
      // const pickerSlots = this.$refs.address.$children
      // this.selectAddressIndex = [pickerSlots[0].valueIndex, pickerSlots[2].valueIndex]
      this.popupVisible = false
      this.$emit('confirm', {
        val: [values[0], values[1]]
        // label: `${values[0].name} ${values[1].name}`,
        // showArrow: false
      })
    },
    onAddressChange (picker, values) {
      for (let i = 0; i < this.provinceList.length; i++) {
        if (values[0] === this.provinceList[i]) {
          picker.setSlotValues(1, this.cityList[values[0]])
          break
        }
      }
    },
    confirmCounties () {
      const values = this.$refs.counties.getValues()
      const label = `${values[0].name}${values[1].name}${values[2].name !== '暂不选择' ? values[2].name : ''}`
      this.popupVisible = false
      this.$emit('confirm', {
        val: [values[0].id, values[1].id, values[2].id, label]
      })
    },
    onCountiesChange (picker, values) {
      for (let i = 0; i < this.addressData.length; i++) {
        if (values[0].id === this.addressData[i].id) {
          const cities = this.addressData[i].cities
          picker.setSlotValues(1, cities)
          for (let j = 0; j < cities.length; j++) {
            if (!values[1]) return
            if (values[1].id === cities[j].id) {
              // 增加区暂不选择选项
              if (cities[j].counties[0].name !== '暂不选择' && !this.needCounties) {
                cities[j].counties.unshift({id: '', name: '暂不选择'})
              }
              picker.setSlotValues(2, cities[j].counties)
              break
            }
          }
        }
      }
    },
    onTimeChange (picker, values) {
      if (values[0] === '2月') {
        picker.setSlotValues(1, this.dateForFeb)
        return
      }
      if (values[0] === '4月' || values[0] === '6月' || values[0] === '9月' || values[0] === '11月') {
        picker.setSlotValues(1, this.dateForEvenMonth)
        return
      }
      picker.setSlotValues(1, this.dateForOddMonth)
    },
    confirmTime () {
      const values = this.$refs.dateTime.getValues()
      const value = `${values[0]}${values[1]} ${values[2]}`
      this.popupVisible = false
      this.$emit('confirm', {
        val: value
      })
    },
    getAddressData () {
      if (!this.pickerType || this.pickerType === 'radio' || this.pickerType === 'dateTime') {
        return
      }
      mapCity().then(res => {
        this.$indicator.close()
        if (res.status === 200) {
          if (loadingAddress) {
            this.popupVisible = true
            loadingAddress = false
          }
          this.addressData = res.data.data
          if (this.saveCityMap) {
            store.set('vehicle-map-city', this.addressData)
          }
          if (this.pickerType === 'address') {
            const slots = this.addressSlots
            slots[0].values = this.addressData
          } else if (this.pickerType === 'counties') {
            const slots = this.countiesSlots
            slots[0].values = this.addressData
          }
        } else {
          if (loadingAddress) {
            this.$toast({
              message: '获取地址列表失败,请稍后重试',
              iconClass: 'icon icon-warning'
            })
            loadingAddress = false
          }
          console.log(res.data.message)
        }
      })
    },
    isArray (item) {
      return Object.prototype.toString.call(item) === '[object Array]'
    }
  },
  created () {
    if (this.pickerType === 'counties') {
      this.getAddressData()
    }
  },
  mounted () {
    this.$emit('updateLabel', this.label)
  }
}
</script>

<style lang="stylus" scoped>
  @import "~@/assets/mixin.stylus"
  .lx-popup {
     100%
    // 取消确定键栏
    >>> .picker-toolbar {
      border-bottom 1px solid #eaeaea
    }
  }
  .lx-picker-title
    display inline-block
    width 60%
    line-height 40px
    text-align center
    font-dpr(16px)
  .lx-action__with-title
    width 20%
</style>
<image-cell @click.native="uploadImage('idCardPics', '身份证正反面')"
                :imageTitle="'身份证正反面'"
                :titleColor="titleColor"
                :image="searchCar.idCardPics"
                :hasBorder="true">
    </image-cell>
   uploadImage (tag, title) {
      const that = this
      let images = that.searchCar[tag] || []
      let data = {
        functionName: 'sendImage',
        data: {
          tag: tag,
          imageUrl: images,
          countLimit: 9,
          title: title,
          compression: 0.8,
          editable: true
        }
      }
      try {
        window.JSBridge.navigationTo('imagePick', JSON.stringify(data))
      } catch (error) {
        console.error(error)
      }
    }
原文地址:https://www.cnblogs.com/antyhouse/p/10475331.html