DateRange.vue 6.48 KB
<script lang="ts" setup>
import { onMounted, ref, reactive, computed } from 'vue';
// import { date } from 'quasar';
import { isEmpty } from 'src/common/utils';

interface Props {
  modelValue: any;
  dense?: boolean;
  disable?: boolean;
  readonly?: boolean;
  config?: any;
}
const props = withDefaults(defineProps<Props>(), {
  // modelValue: date.formatDate(Date.now(), 'YYYY/MM/DD HH:mm'),
  modelValue: null,
  dense: false,
  disable: false,
  readonly: false,
  config: () => {
    return {};
  },
});

const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void;
}>();

const myDateRange = ref<any>(null);

const dates = computed({
  set(value: any) {
    // console.log('set', value);

    emit('update:modelValue', value);
  },
  get() {
    // console.log('get', props.modelValue);

    let res = null;
    // 多选
    if (props.config?.multiple) {
      if (isEmpty(props.modelValue)) {
        res = null;
      } else {
        const typeofs = Object.prototype.toString.call(props.modelValue);
        if (typeofs === '[object Array]') {
          const rangeList = props.modelValue.map((item: any) => {
            const str = `${item.from}~${item.to}`;
            return str;
          });
          res = rangeList.join(',');
        } else {
          res = null;
        }
      }
    }
    // 单选
    else {
      if (isEmpty(props.modelValue)) {
        res = null;
      } else {
        const typeofs = Object.prototype.toString.call(props.modelValue);
        if (typeofs === '[object Object]') {
          const from = props.modelValue.from;
          const to = props.modelValue.to;
          if (!from || !to) {
            console.warn('无效时间范围');
            res = null;
          } else {
            const fromDate = new Date(from);
            const toDate = new Date(to);

            if (toDate <= fromDate) {
              console.warn('结束时间不能大于开始时间');
              res = null;
            } else {
              res = `${from}~${to}`;
            }
          }
        } else if (typeofs === '[object String]') {
          res = props.modelValue;
        } else {
          res = null;
        }
      }
    }
    return res;
  },
});

const dateMask = computed(() => {
  let obj = {
    date: 'YYYY/MM/DD',
  };
  if (!isEmpty(props.config) && props.config.dateMask) {
    const maskList = props.config.dateMask.split(' ');
    obj.date = maskList[0];
  }
  return obj;
});

const dateProxyDate = ref<any>(null);
const dateLocale = reactive({
  daysShort: '六_日_一_二_三_四_五'.split('_'),
  months:
    '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
      '_'
    ),
  monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
  firstDayOfWeek: 1,
  format24h: true,
  pluralDay: 'dias',
});

const toolTipData = computed(() => {
  let str = '';
  // 多选
  if (props.config?.multiple) {
    if (!isEmpty(dates.value)) {
      str = dates.value.replace(new RegExp(',', 'g'), '<br />');
    }
  }
  // 单选
  else {
  }

  return str;
});

onMounted(() => {
  const inputElement =
    myDateRange.value.$el.firstElementChild.firstElementChild.firstElementChild
      .firstElementChild;
  inputElement.setAttribute('unselectable', 'on');
  inputElement.setAttribute('readonly', true);
});

function updateProxy() {
  const _dates = dates.value;
  if (!isEmpty(_dates)) {
    // 多选
    if (props.config?.multiple) {
      console.log('updateProxy', _dates);
      const list1 = _dates.split(',');
      const rangeList = list1.map((item: any) => {
        const rangeArr = item.split('~');
        return {
          from: rangeArr[0],
          to: rangeArr[1],
        };
      });
      dateProxyDate.value = rangeList;
    }
    // 单选
    else {
      const dateList = _dates.split('~');
      if (dateList.length === 2) {
        dateProxyDate.value = {
          from: dateList[0],
          to: dateList[1],
        };
      } else if (dateList.length === 1) {
        dateProxyDate.value = dateList[0];
      } else {
        dateProxyDate.value = null;
      }
    }
  } else {
    dateProxyDate.value = null;
  }
}

function onClickDate() {
  // console.log('点击确定', dateProxyDate.value);
  // 多选
  if (props.config?.multiple) {
    if (isEmpty(dateProxyDate.value)) {
      dates.value = null;
    } else {
      dates.value = dateProxyDate.value;
    }
  }
  // 单选
  else {
    if (isEmpty(dateProxyDate.value)) {
      dates.value = null;
    } else {
      dates.value = dateProxyDate.value;
    }
  }
}
</script>
<template>
  <div class="hcy-datetime-pick">
    <q-input
      v-model="dates"
      v-bind="config"
      ref="myDateRange"
      :dense="config.dense === undefined ? props.dense : config.dense"
      :disable="config.disable === undefined ? props.disable : config.disable"
      :readonly="
        config.readonly === undefined ? props.readonly : config.readonly
      "
    >
      <q-tooltip v-if="!isEmpty(dates) && toolTipData">
        <span v-html="toolTipData"></span
      ></q-tooltip>
      <template v-slot:append>
        <q-icon name="event" class="cursor-pointer">
          <q-popup-proxy
            v-if="!props.readonly"
            @before-show="updateProxy"
            transition-show="scale"
            transition-hide="scale"
            class="row"
          >
            <q-date
              flat
              square
              minimal
              range
              :multiple="config.multiple"
              v-model="dateProxyDate"
              :locale="dateLocale"
              :mask="dateMask.date"
              class="my-date"
            >
              <div class="row items-center justify-end q-gutter-sm">
                <q-btn
                  unelevated
                  label="确定"
                  size="sm"
                  color="primary"
                  @click="onClickDate"
                  v-close-popup
                />
              </div>
            </q-date>
          </q-popup-proxy>
        </q-icon>
      </template>
    </q-input>
  </div>
</template>

<style lang="scss" scoped>
.my-date {
  :deep(.q-date__main .q-date__content .q-date__view .q-date__navigation) {
    > .relative-position {
      color: $primary;
    }
  }
}
.my-time {
  :deep(.q-time__header) {
    background-color: white;
  }
  :deep(.q-time__main
      .q-time__content
      .q-time__container-child
      .q-time__clock
      .q-time__clock-circle
      .q-time__clock-position--active) {
    color: white !important;
  }
}
</style>