vueComponent / ant-design-vue

🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
https://antdv.com/
Other
20.27k stars 3.79k forks source link

默认日期选择,切换为月份日期不对。 #7840

Open LOADINGG opened 2 months ago

LOADINGG commented 2 months ago

Version

4.2.3

Environment

Vue

Reproduction link

Edit on CodeSandbox

Steps to reproduce

参考codesandbox代码片段

What is expected?

模式为选择月份时,选择月份后应该返回这样格式,例如选择1月到9月返回值应该是2024-01-01~2024-09-30。

现在是,默认时间为2024-05-12 ~ 2024-09-15,切换为月份选择后返回值是2024-01-12 ~ 2024-09-12。

What is actually happening?

heart-to-the-sea commented 1 month ago

image 这个问题产生的原因是,在你切换picker的时候组建会生成选择的日期弹窗,生成的日期弹窗依赖于你上一次选择的值,而月份只有12个,是无法对应到具体的日期的,所以会出现你描述的这种情况,目前最好的解决方式就是你自己手动缓存天和月份的数据,在你切换picker时动态替换为你自己上一次选择的值,因为从功能的角度上来说你所关注的本应是month,而非day

LOADINGG commented 1 month ago

image 这个问题产生的原因是,在你切换picker的时候组建会生成选择的日期弹窗,生成的日期弹窗依赖于你上一次选择的值,而月份只有12个,是无法对应到具体的日期的,所以会出现你描述的这种情况,目前最好的解决方式就是你自己手动缓存天和月份的数据,在你切换picker时动态替换为你自己上一次选择的值,因为从功能的角度上来说你所关注的本应是month,而非day

自己手动缓存是怎么缓存? 月和天是平等筛选条件两个需要来回切换使用。

heart-to-the-sea commented 1 month ago

image 这个问题产生的原因是,在你切换picker的时候组建会生成选择的日期弹窗,生成的日期弹窗依赖于你上一次选择的值,而月份只有12个,是无法对应到具体的日期的,所以会出现你描述的这种情况,目前最好的解决方式就是你自己手动缓存天和月份的数据,在你切换picker时动态替换为你自己上一次选择的值,因为从功能的角度上来说你所关注的本应是month,而非day

自己手动缓存是怎么缓存? 月和天是平等筛选条件两个需要来回切换使用。

你可以看看这个,我写了一个模拟的 https://codesandbox.io/p/devbox/range-picker-forked-hwgsw7

LOADINGG commented 1 month ago

image 这个问题产生的原因是,在你切换picker的时候组建会生成选择的日期弹窗,生成的日期弹窗依赖于你上一次选择的值,而月份只有12个,是无法对应到具体的日期的,所以会出现你描述的这种情况,目前最好的解决方式就是你自己手动缓存天和月份的数据,在你切换picker时动态替换为你自己上一次选择的值,因为从功能的角度上来说你所关注的本应是month,而非day

自己手动缓存是怎么缓存? 月和天是平等筛选条件两个需要来回切换使用。

你可以看看这个,我写了一个模拟的 https://codesandbox.io/p/devbox/range-picker-forked-hwgsw7

这个demo还是那个问题,默认是12日,切换为月选择后选择日期返回2024-xx-12 ~ 2024-xx-12,我根据picker类型处理了下,这样是可以的。 switch(p) { case !p: case 'date': formState.value[n] = [dayjs(e[0]), dayjs(e[1])] break case 'month': formState.value[n] = [dayjs(e[0]), dayjs(${dayjs(e[1]).format('YYYY-MM')}-${dayjs(e[1]).daysInMonth()})] break case 'quarter': formState.value[n] = [dayjs(e[0]), dayjs(${dayjs(e[1]).add(2, 'month').format('YYYY-MM')}-${dayjs(e[1]).add(2, 'month').daysInMonth()})] break case 'year': formState.value[n] = [dayjs(e[0]), dayjs(${dayjs(e[1]).format('YYYY')}-12-31)] break }

heart-to-the-sea commented 1 month ago

image 这个问题产生的原因是,在你切换picker的时候组建会生成选择的日期弹窗,生成的日期弹窗依赖于你上一次选择的值,而月份只有12个,是无法对应到具体的日期的,所以会出现你描述的这种情况,目前最好的解决方式就是你自己手动缓存天和月份的数据,在你切换picker时动态替换为你自己上一次选择的值,因为从功能的角度上来说你所关注的本应是month,而非day

自己手动缓存是怎么缓存? 月和天是平等筛选条件两个需要来回切换使用。

你可以看看这个,我写了一个模拟的 https://codesandbox.io/p/devbox/range-picker-forked-hwgsw7

这个demo还是那个问题,默认是12日,切换为月选择后选择日期返回2024-xx-12 ~ 2024-xx-12,我根据picker类型处理了下,这样是可以的。 switch(p) { case !p: case 'date': formState.value[n] = [dayjs(e[0]), dayjs(e[1])] break case 'month': formState.value[n] = [dayjs(e[0]), dayjs(${dayjs(e[1]).format('YYYY-MM')}-${dayjs(e[1]).daysInMonth()})] break case 'quarter': formState.value[n] = [dayjs(e[0]), dayjs(${dayjs(e[1]).add(2, 'month').format('YYYY-MM')}-${dayjs(e[1]).add(2, 'month').daysInMonth()})] break case 'year': formState.value[n] = [dayjs(e[0]), dayjs(${dayjs(e[1]).format('YYYY')}-12-31)] break } image valueFormat 你可以利用这个属性实现你想要的功能 案例如下 https://codesandbox.io/p/devbox/range-picker-forked-hwgsw7

heart-to-the-sea commented 1 month ago
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>
LOADINGG commented 1 month ago
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>

日切换月后单纯看月份本来就是对的,我们的后端要的日期格式前端选月(2024-08 ~ 2024-09)给后端要(2024-08-01 ~ 2024-09-30)这样子,组件本身的返回的日期就不对了。

heart-to-the-sea commented 1 month ago
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>

日切换月后单纯看月份本来就是对的,我们的后端要的日期格式前端选月(2024-08 ~ 2024-09)给后端要(2024-08-01 ~ 2024-09-30)这样子,组件本身的返回的日期就不对了。

你可以配合dayjs或moment来实现具体日期的匹配,这个日期也只是在接口发送时的请求体中携带吧,跟页面交互不影响

heart-to-the-sea commented 1 month ago
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>

日切换月后单纯看月份本来就是对的,我们的后端要的日期格式前端选月(2024-08 ~ 2024-09)给后端要(2024-08-01 ~ 2024-09-30)这样子,组件本身的返回的日期就不对了。

你可以配合dayjs或moment来实现具体日期的匹配,这个日期也只是在接口发送时的请求体中携带吧,跟页面交互不影响,不要期待一个开源组件库能满足你的全部需求,有些需求适合你但并不适合其他人,所以组件库不会做的这么精细

heart-to-the-sea commented 1 month ago
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>

日切换月后单纯看月份本来就是对的,我们的后端要的日期格式前端选月(2024-08 ~ 2024-09)给后端要(2024-08-01 ~ 2024-09-30)这样子,组件本身的返回的日期就不对了。

你可以配合dayjs或moment来实现具体日期的匹配,这个日期也只是在接口发送时的请求体中携带吧,跟页面交互不影响

1728704933435

heart-to-the-sea commented 1 month ago
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>

日切换月后单纯看月份本来就是对的,我们的后端要的日期格式前端选月(2024-08 ~ 2024-09)给后端要(2024-08-01 ~ 2024-09-30)这样子,组件本身的返回的日期就不对了。

你可以配合dayjs或moment来实现具体日期的匹配,这个日期也只是在接口发送时的请求体中携带吧,跟页面交互不影响

1728704933435

<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { RangePicker, RadioGroup, RadioButton } from "ant-design-vue";

const FORMAT_YM='YYYY-MM'
const FORMAT_YMD='YYYY-MM-DD'

const format = ref(FORMAT_YMD)

const d = ref("date");
const v = ref([dayjs("2024-09-12").format(FORMAT_YMD), dayjs().format(FORMAT_YMD)]);

const vCache = ref([...v.value]);
const mCache = ref([...v.value.map(item=>dayjs(item).format(FORMAT_YM))]);

function handleChange(e) {
  switch(e.target.value) {
    case 'month':
      format.value=FORMAT_YM
      vCache.value = [...v.value];
      v.value = [...mCache.value];
      break;
    case 'date':
      format.value=FORMAT_YMD
      mCache.value = [...v.value];
      v.value = [...vCache.value];
      break;
  }

  d.value = e.target.value;
}
</script>

<template>
  <RadioGroup :value="d" @change="handleChange">
    <RadioButton value="date">按日</RadioButton>
    <RadioButton value="month">按月</RadioButton>
  </RadioGroup>
  <br /><br />
  {{ v }}
  <br /><br />
  {{ d }} {{format}}
  <p>
    选择日期:{{ v[0] }} ~ {{ v[1] }}
  </p>
  <br />
  <RangePicker v-model:value="v" :picker="d" :valueFormat="format"/>
</template>

<style scoped></style>

日切换月后单纯看月份本来就是对的,我们的后端要的日期格式前端选月(2024-08 ~ 2024-09)给后端要(2024-08-01 ~ 2024-09-30)这样子,组件本身的返回的日期就不对了。

你可以配合dayjs或moment来实现具体日期的匹配,这个日期也只是在接口发送时的请求体中携带吧,跟页面交互不影响

1728704933435

对应这种定制化需求,建议最好二次开发,而不是通过修复的方式解决