feat(查询组件): 日期筛选组件可设置查询的起始日期 #6005

This commit is contained in:
dataeaseShu 2024-03-12 17:43:56 +08:00
parent d78351ddea
commit d6dcaa1b71
9 changed files with 269 additions and 96 deletions

View File

@ -159,6 +159,7 @@ onBeforeMount(() => {
<template>
<el-date-picker
disabled
:key="config.timeGranularity"
v-model="selectValue"
:type="config.timeGranularity"
:prefix-icon="Calendar"

View File

@ -2,27 +2,16 @@
import { toRefs, PropType, onBeforeMount, watch, computed } from 'vue'
import { Calendar } from '@element-plus/icons-vue'
import { type DatePickType } from 'element-plus-secondary'
import {
getThisYear,
getLastYear,
getThisMonth,
getLastMonth,
getToday,
getYesterday,
getMonthBeginning,
getYearBeginning,
getCustomTime
} from './time-format'
import type { ManipulateType } from 'dayjs'
import { getThisStart, getLastStart, getAround } from './time-format-dayjs'
interface SelectConfig {
timeType: string
intervalType: string
regularOrTrendsValue: Date
regularOrTrends: string
relativeToCurrent: string
timeNum: number
relativeToCurrentType: string
relativeToCurrentType: ManipulateType
around: string
timeGranularity: DatePickType
}
const props = defineProps({
@ -51,27 +40,21 @@ const props = defineProps({
const { config } = toRefs(props)
const timeConfig = computed(() => {
const {
relativeToCurrent,
intervalType,
timeNum,
relativeToCurrentType,
around,
timeGranularity
} = config.value
const { relativeToCurrent, intervalType, timeNum, relativeToCurrentType, around } = config.value
return {
relativeToCurrent,
timeNum,
intervalType,
relativeToCurrentType,
around,
timeGranularity
timeGranularityMultiple: props.timeGranularityMultiple
}
})
watch(
() => timeConfig.value,
() => {
console.log(1)
init()
},
{
@ -80,47 +63,45 @@ watch(
)
const timeInterval = computed<DatePickType>(() => {
return config.value.intervalType !== 'timeInterval'
? (props.timeGranularityMultiple.split('range')[0] as DatePickType)
: props.timeGranularityMultiple
const noTime = props.timeGranularityMultiple.split('time').join('')
return config.value.intervalType === 'timeInterval'
? (noTime as DatePickType)
: (noTime.split('range')[0] as DatePickType)
})
const init = () => {
const { relativeToCurrent, timeNum, relativeToCurrentType, around, timeGranularity } =
timeConfig.value
const { relativeToCurrent, timeNum, relativeToCurrentType, around } = timeConfig.value
if (relativeToCurrent === 'custom') {
config.value.regularOrTrendsValue = getCustomTime(
timeNum,
config.value.regularOrTrendsValue = getAround(
relativeToCurrentType,
timeGranularity,
around,
null
around === 'f' ? 'subtract' : 'add',
timeNum
)
} else {
switch (relativeToCurrent) {
case 'thisYear':
config.value.regularOrTrendsValue = getThisYear()
config.value.regularOrTrendsValue = getThisStart('year')
break
case 'lastYear':
config.value.regularOrTrendsValue = getLastYear()
config.value.regularOrTrendsValue = getLastStart('year')
break
case 'thisMonth':
config.value.regularOrTrendsValue = getThisMonth()
config.value.regularOrTrendsValue = getThisStart('month')
break
case 'lastMonth':
config.value.regularOrTrendsValue = getLastMonth()
config.value.regularOrTrendsValue = getLastStart('month')
break
case 'today':
config.value.regularOrTrendsValue = getToday()
config.value.regularOrTrendsValue = getThisStart('day')
break
case 'yesterday':
config.value.regularOrTrendsValue = getYesterday()
config.value.regularOrTrendsValue = getLastStart('day')
break
case 'monthBeginning':
config.value.regularOrTrendsValue = getMonthBeginning()
config.value.regularOrTrendsValue = getThisStart('month')
break
case 'yearBeginning':
config.value.regularOrTrendsValue = getYearBeginning()
config.value.regularOrTrendsValue = getThisStart('year')
break
default:
@ -137,6 +118,7 @@ onBeforeMount(() => {
<template>
<el-date-picker
:disabled="config.regularOrTrends !== 'fixed'"
:key="timeInterval"
v-model="config.regularOrTrendsValue"
:type="timeInterval"
:prefix-icon="Calendar"

View File

@ -155,6 +155,7 @@ const formatDate = computed(() => {
<el-date-picker
disabled
v-model="selectValue"
:key="config.timeGranularityMultiple"
:type="config.timeGranularityMultiple"
:prefix-icon="Calendar"
:format="formatDate"

View File

@ -1,18 +1,19 @@
<script lang="ts" setup>
import { toRefs, PropType, ref, onBeforeMount, watch, computed } from 'vue'
import { toRefs, PropType, onBeforeMount, watch, computed } from 'vue'
import { Calendar } from '@element-plus/icons-vue'
import { type DatePickType } from 'element-plus-secondary'
import { getCustomTime } from './time-format'
import type { ManipulateType } from 'dayjs'
import { getAround } from './time-format-dayjs'
interface SelectConfig {
regularOrTrends: string
regularOrTrendsValue: [Date, Date]
intervalType: string
timeNum: number
relativeToCurrentType: string
relativeToCurrentType: ManipulateType
around: string
timeGranularity: DatePickType
timeNumRange: number
relativeToCurrentTypeRange: string
relativeToCurrentTypeRange: ManipulateType
aroundRange: string
}
@ -21,7 +22,7 @@ const props = defineProps({
type: Object as PropType<SelectConfig>,
default: () => {
return {
timeGranularityMultiple: 'datetimerange',
timeGranularityMultiple: 'daterange',
regularOrTrendsValue: [],
regularOrTrends: 'fixed',
timeNum: 0,
@ -63,13 +64,15 @@ const timeConfig = computed(() => {
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange
aroundRange,
timeGranularityMultiple: props.timeGranularityMultiple
}
})
const timeInterval = computed<DatePickType>(() => {
return config.value.intervalType !== 'timeInterval'
? (props.timeGranularityMultiple.split('range')[0] as DatePickType)
: props.timeGranularityMultiple
const noTime = props.timeGranularityMultiple.split('time').join('')
return config.value.intervalType === 'timeInterval'
? (noTime as DatePickType)
: (noTime.split('range')[0] as DatePickType)
})
watch(
() => timeConfig.value,
@ -86,29 +89,16 @@ const init = () => {
timeNum,
relativeToCurrentType,
around,
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange
} = timeConfig.value
const startTime = getCustomTime(
timeNum,
relativeToCurrentType,
timeGranularity,
around,
null,
timeInterval.value,
'start-config'
)
const endTime = getCustomTime(
timeNumRange,
const startTime = getAround(relativeToCurrentType, around === 'f' ? 'subtract' : 'add', timeNum)
const endTime = getAround(
relativeToCurrentTypeRange,
timeGranularity,
aroundRange,
null,
timeInterval.value,
'end-config'
aroundRange === 'f' ? 'subtract' : 'add',
timeNumRange
)
config.value.regularOrTrendsValue = [startTime, endTime]
@ -127,6 +117,7 @@ const formatDate = computed(() => {
<el-date-picker
:disabled="config.regularOrTrends !== 'fixed'"
v-model="config.regularOrTrendsValue"
:key="timeInterval"
:type="timeInterval"
:prefix-icon="Calendar"
:format="formatDate"

View File

@ -206,7 +206,9 @@ const setTypeChange = () => {
inputCom.value?.displayTypeChange?.()
if (
+curComponent.value.displayType === 7 &&
['yearrange', 'monthrange', 'datetimerange'].includes(curComponent.value.timeGranularity)
['yearrange', 'monthrange', 'daterange', 'datetimerange'].includes(
curComponent.value.timeGranularity
)
) {
curComponent.value.timeGranularityMultiple = curComponent.value.timeGranularity
}
@ -367,6 +369,7 @@ const validate = () => {
const handleBeforeClose = () => {
inputCom.value?.mult?.handleClickOutside?.()
handleDialogClick()
dialogVisible.value = false
}
@ -504,6 +507,7 @@ const parameterCompletion = () => {
relativeToCurrentTypeRange: 'year',
aroundRange: 'f',
arbitraryTimeRange: new Date(),
setTimeRange: false,
timeRange: {
intervalType: 'none',
dynamicWindow: false,
@ -673,7 +677,7 @@ const relativeToCurrentTypeList = computed(() => {
let index = ['year', 'month', 'date', 'datetime'].indexOf(curComponent.value.timeGranularity) + 1
if (+curComponent.value.displayType === 7) {
index =
['yearrange', 'monthrange', 'datetimerange'].indexOf(
['yearrange', 'monthrange', 'daterange', 'datetimerange'].indexOf(
curComponent.value.timeGranularityMultiple
) + 1
}
@ -708,17 +712,32 @@ const timeGranularityChange = (val: string) => {
const timeGranularityMultipleChange = (val: string) => {
handleDialogClick()
if (
['yearrange', 'monthrange', 'datetimerange'].indexOf(val) <
['yearrange', 'monthrange', 'daterange', 'datetimerange'].indexOf(val) <
['year', 'month', 'date'].indexOf(curComponent.value.relativeToCurrentType)
) {
curComponent.value.relativeToCurrentType = 'year'
}
if (
['yearrange', 'monthrange', 'datetimerange'].indexOf(val) <
['yearrange', 'monthrange', 'daterange', 'datetimerange'].indexOf(val) <
['year', 'month', 'date'].indexOf(curComponent.value.relativeToCurrentTypeRange)
) {
curComponent.value.relativeToCurrentTypeRange = 'year'
}
curComponent.value.timeRange = {
intervalType: 'none',
dynamicWindow: false,
maximumSingleQuery: 0,
regularOrTrends: 'fixed',
regularOrTrendsValue: '',
relativeToCurrent: 'custom',
timeNum: 0,
relativeToCurrentType: 'year',
around: 'f',
timeNumRange: 0,
relativeToCurrentTypeRange: 'year',
aroundRange: 'f'
}
}
const aroundList = [
{
@ -928,6 +947,7 @@ defineExpose({
<span class="dataset ellipsis">{{ field.name }}</span>
<el-select
@change="setType"
@focus="handleDialogClick"
style="margin-left: 12px"
v-if="curComponent.checkedFields.includes(field.componentId)"
v-model="curComponent.checkedFieldsMap[field.componentId]"
@ -990,7 +1010,11 @@ defineExpose({
<div class="list-item">
<div class="label">展示类型</div>
<div class="value">
<el-select @change="setTypeChange" v-model="curComponent.displayType">
<el-select
@focus="handleDialogClick"
@change="setTypeChange"
v-model="curComponent.displayType"
>
<el-option
:disabled="curComponent.displayType !== '0'"
label="文本下拉"
@ -1028,10 +1052,12 @@ defineExpose({
<el-select
@change="timeGranularityMultipleChange"
placeholder="请选择时间粒度"
@focus="handleDialogClick"
v-model="curComponent.timeGranularityMultiple"
>
<el-option label="年" value="yearrange" />
<el-option label="年月" value="monthrange" />
<el-option label="年月日" value="daterange" />
<el-option label="年月日时分秒" value="datetimerange" />
</el-select>
</template>
@ -1213,7 +1239,7 @@ defineExpose({
</div>
<div v-if="curComponent.displayType === '7'" class="list-item">
<div class="label">
<el-checkbox v-model="curComponent.parametersCheck" label="设置时间筛选范围" />
<el-checkbox v-model="curComponent.setTimeRange" label="设置时间筛选范围" />
</div>
<div class="setting-content">
<el-popover
@ -1225,7 +1251,12 @@ defineExpose({
:offset="4"
>
<template #reference>
<el-button @click="handleVisiblePopover($event)" text style="margin-left: -4px">
<el-button
:disabled="!curComponent.setTimeRange"
@click="handleVisiblePopover($event)"
text
style="margin-left: -4px"
>
<template #icon>
<Icon name="icon_admin_outlined"></Icon>
</template>
@ -1237,7 +1268,14 @@ defineExpose({
:timeGranularityMultiple="curComponent.timeGranularityMultiple"
/>
</el-popover>
<span class="config-flag range-filter-time-flag">已配置</span>
<span
v-if="
curComponent.timeRange.intervalType !== 'none' ||
curComponent.timeRange.dynamicWindow
"
class="config-flag range-filter-time-flag"
>已配置</span
>
</div>
</div>
<div class="list-item">
@ -1250,6 +1288,7 @@ defineExpose({
popper-class="dataset-parameters"
value-key="id"
multiple
@focus="handleDialogClick"
v-model="curComponent.parameters"
clearable
>
@ -1273,6 +1312,7 @@ defineExpose({
<el-select
popper-class="dataset-parameters"
value-key="id"
@focus="handleDialogClick"
v-model="curComponent.parametersStart"
clearable
>
@ -1293,6 +1333,7 @@ defineExpose({
<el-select
popper-class="dataset-parameters"
value-key="id"
@focus="handleDialogClick"
v-model="curComponent.parametersEnd"
clearable
>
@ -1330,7 +1371,7 @@ defineExpose({
<div class="setting">
<div class="setting-label">相对当前</div>
<div class="setting-value select">
<el-select v-model="curComponent.relativeToCurrent">
<el-select @focus="handleDialogClick" v-model="curComponent.relativeToCurrent">
<el-option
v-for="item in relativeToCurrentList"
:key="item.value"
@ -1350,7 +1391,10 @@ defineExpose({
:min="0"
controls-position="right"
/>
<el-select v-model="curComponent.relativeToCurrentType">
<el-select
@focus="handleDialogClick"
v-model="curComponent.relativeToCurrentType"
>
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
@ -1358,7 +1402,7 @@ defineExpose({
:value="item.value"
/>
</el-select>
<el-select v-model="curComponent.around">
<el-select @focus="handleDialogClick" v-model="curComponent.around">
<el-option
v-for="item in aroundList"
:key="item.value"
@ -1377,8 +1421,9 @@ defineExpose({
<div
class="setting"
:class="
['yearrange', 'monthrange'].includes(curComponent.timeGranularityMultiple) &&
'is-year-month-range'
['yearrange', 'monthrange', 'daterange'].includes(
curComponent.timeGranularityMultiple
) && 'is-year-month-range'
"
>
<div class="setting-label">开始时间</div>
@ -1388,7 +1433,10 @@ defineExpose({
:min="0"
controls-position="right"
/>
<el-select v-model="curComponent.relativeToCurrentType">
<el-select
@focus="handleDialogClick"
v-model="curComponent.relativeToCurrentType"
>
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
@ -1396,7 +1444,7 @@ defineExpose({
:value="item.value"
/>
</el-select>
<el-select v-model="curComponent.around">
<el-select @focus="handleDialogClick" v-model="curComponent.around">
<el-option
v-for="item in aroundList"
:key="item.value"
@ -1410,8 +1458,9 @@ defineExpose({
<div
class="setting"
:class="
['yearrange', 'monthrange'].includes(curComponent.timeGranularityMultiple) &&
'is-year-month-range'
['yearrange', 'monthrange', 'daterange'].includes(
curComponent.timeGranularityMultiple
) && 'is-year-month-range'
"
>
<div class="setting-label">结束时间</div>
@ -1421,7 +1470,10 @@ defineExpose({
:min="0"
controls-position="right"
/>
<el-select v-model="curComponent.relativeToCurrentTypeRange">
<el-select
@focus="handleDialogClick"
v-model="curComponent.relativeToCurrentTypeRange"
>
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
@ -1429,7 +1481,7 @@ defineExpose({
:value="item.value"
/>
</el-select>
<el-select v-model="curComponent.aroundRange">
<el-select @focus="handleDialogClick" v-model="curComponent.aroundRange">
<el-option
v-for="item in aroundList"
:key="item.value"
@ -1653,6 +1705,7 @@ defineExpose({
border-left: 1px solid #dee0e3;
width: 467px;
position: relative;
overflow-y: auto;
.mask {
left: -1px;
width: calc(100% + 2px);
@ -1696,6 +1749,17 @@ defineExpose({
font-style: normal;
font-weight: 500;
line-height: 22px;
position: relative;
&.flex-align-center::after {
content: '';
position: absolute;
width: 100%;
height: 16px;
background: #fff;
top: -16px;
left: 0;
}
}
.configuration-list {

View File

@ -84,7 +84,7 @@ const relativeToCurrentTypeList = computed(() => {
},
{
label: '日',
value: 'date'
value: 'day'
}
].slice(0, index)
})
@ -295,7 +295,12 @@ const relativeToCurrentList = computed(() => {
<div class="parameters" :class="dynamicTime && 'setting'">
<div class="setting-label" v-if="dynamicTime">预览</div>
<div :class="dynamicTime ? 'setting-value' : 'w100'">
<component :config="timeRange" isConfig ref="inputCom" :is="filterTypeCom"></component>
<component
:config="timeRange"
:timeGranularityMultiple="timeGranularityMultiple"
ref="inputCom"
:is="filterTypeCom"
></component>
</div>
</div>
</div>

View File

@ -3,6 +3,8 @@ import { toRefs, PropType, ref, onBeforeMount, watch, nextTick, computed } from
import { Calendar } from '@element-plus/icons-vue'
import { type DatePickType } from 'element-plus-secondary'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { type TimeRange } from './time-format'
import { getThisStart, getLastStart, getAround } from './time-format-dayjs'
import VanPopup from 'vant/es/popup'
import VanDatePicker from 'vant/es/date-picker'
import VanTimePicker from 'vant/es/time-picker'
@ -20,10 +22,8 @@ interface SelectConfig {
displayType: string
timeGranularity: DatePickType
timeGranularityMultiple: DatePickType
options?: Array<{
label: string
value: string
}>
timeRange: TimeRange
setTimeRange: boolean
}
const props = defineProps({
@ -35,7 +35,23 @@ const props = defineProps({
defaultValue: '',
defaultValueCheck: false,
displayType: '1',
timeGranularity: 'date'
timeGranularity: 'date',
setTimeRange: false,
timeGranularityMultiple: 'daterange',
timeRange: {
intervalType: 'none',
dynamicWindow: false,
maximumSingleQuery: 0,
regularOrTrends: 'fixed',
regularOrTrendsValue: '',
relativeToCurrent: 'custom',
timeNum: 0,
relativeToCurrentType: 'year',
around: 'f',
timeNumRange: 0,
relativeToCurrentTypeRange: 'year',
aroundRange: 'f'
}
}
}
},
@ -166,6 +182,87 @@ const getIndex = () => {
return index
}
const disabledDate = val => {
const timeStamp = +new Date(val)
if (!config.value.setTimeRange) {
return false
}
const {
intervalType,
regularOrTrends,
regularOrTrendsValue,
relativeToCurrent,
timeNum,
relativeToCurrentType,
around,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange
} = config.value.timeRange || {}
if (intervalType === 'none') {
return false
}
let startTime
if (relativeToCurrent === 'custom') {
startTime = getAround(relativeToCurrentType, around === 'f' ? 'subtract' : 'add', timeNum)
} else {
switch (relativeToCurrent) {
case 'thisYear':
startTime = getThisStart('year')
break
case 'lastYear':
startTime = getLastStart('year')
break
case 'thisMonth':
startTime = getThisStart('month')
break
case 'lastMonth':
startTime = getLastStart('month')
break
case 'today':
startTime = getThisStart('day')
break
case 'yesterday':
startTime = getLastStart('day')
break
case 'monthBeginning':
startTime = getThisStart('month')
break
case 'yearBeginning':
startTime = getThisStart('year')
break
default:
break
}
}
const startValue = regularOrTrends === 'fixed' ? regularOrTrendsValue : startTime
if (intervalType === 'start') {
return timeStamp < +new Date(startValue)
}
if (intervalType === 'end') {
return timeStamp > +new Date(startValue)
}
if (intervalType === 'timeInterval') {
const startTime =
regularOrTrends === 'fixed'
? regularOrTrendsValue[0]
: getAround(relativeToCurrentType, around === 'f' ? 'subtract' : 'add', timeNum)
const endTime =
regularOrTrends === 'fixed'
? regularOrTrendsValue[1]
: getAround(
relativeToCurrentTypeRange,
aroundRange === 'f' ? 'subtract' : 'add',
timeNumRange
)
return timeStamp < +new Date(startTime) - 1000 || timeStamp > +new Date(endTime)
}
}
const showPopup = () => {
if (isRange.value) {
const [start] = selectValue.value || []
@ -241,8 +338,10 @@ const formatDate = computed(() => {
<template>
<el-date-picker
v-model="selectValue"
:key="config.timeGranularityMultiple"
:type="config.timeGranularityMultiple"
:style="selectStyle"
:disabled-date="disabledDate"
:format="formatDate"
v-if="multiple"
@change="handleValueChange"
@ -254,8 +353,8 @@ const formatDate = computed(() => {
<el-date-picker
v-else
v-model="selectValue"
@change="handleValueChange"
:type="config.timeGranularity"
:disabled-date="disabledDate"
:style="selectStyle"
:prefix-icon="Calendar"
:placeholder="$t('commons.date.select_date_time')"

View File

@ -0,0 +1,23 @@
import dayjs from 'dayjs'
import type { ManipulateType } from 'dayjs'
function getThisStart(val = 'month' as ManipulateType) {
return new Date(dayjs().startOf(val).format('YYYY/MM/DD HH:mm:ss'))
}
function getThisEnd(val = 'month' as ManipulateType) {
return new Date(dayjs().endOf(val).format('YYYY/MM/DD HH:mm:ss'))
}
function getLastStart(val = 'month' as ManipulateType) {
return new Date(dayjs().subtract(1, val).startOf(val).format('YYYY/MM/DD HH:mm:ss'))
}
function getLastEnd(val = 'month' as ManipulateType) {
return new Date(dayjs().subtract(1, val).endOf(val).format('YYYY/MM/DD HH:mm:ss'))
}
function getAround(val = 'month' as ManipulateType, type = 'add', num = 0) {
return new Date(dayjs()[type](num, val).startOf('day').format('YYYY/MM/DD HH:mm:ss'))
}
export { getThisStart, getThisEnd, getLastStart, getLastEnd, getAround }

View File

@ -1,3 +1,4 @@
import type { ManipulateType } from 'dayjs'
function getThisYear() {
return new Date(`${new Date().getFullYear()}/1`)
}
@ -102,6 +103,12 @@ function getCustomTime(
return getYearMonthRange(new Date(`${resultYear}/${resultMonth}/1`), 'monthrange', sort)
case 'yearrange':
return getYearMonthRange(new Date(`${resultYear}/1`), 'yearrange', sort)
case 'daterange':
return getYearMonthRange(
new Date(`${resultYear}/${resultMonth}/${resultDate}`),
'daterange',
sort
)
default:
break
}
@ -227,10 +234,10 @@ interface TimeRange {
regularOrTrendsValue: string
relativeToCurrent: string
timeNum: number
relativeToCurrentType: string
relativeToCurrentType: ManipulateType
around: string
timeNumRange: number
relativeToCurrentTypeRange: string
relativeToCurrentTypeRange: ManipulateType
aroundRange: string
timeGranularityMultiple: string
}