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

This commit is contained in:
dataeaseShu 2024-03-19 17:30:35 +08:00
parent 3baef7ccc4
commit 8b0f5c2426
5 changed files with 435 additions and 148 deletions

View File

@ -67,6 +67,8 @@
<script>
import { ApplicationContext } from '@/utils/ApplicationContext'
import { timeSection } from '@/utils'
import dayjs from "dayjs";
import { getThisStart, getLastStart, getAround } from "@/views/panel/filter/filterMain/time-format-dayjs.js";
import bus from '@/utils/bus'
import customInput from '@/components/widget/deWidget/customInput'
import { dateMap, years, seconds } from '@/components/widget/deWidget/serviceNameFn'
@ -111,6 +113,7 @@ export default {
data() {
return {
showDate: false,
startWindowTime: 0,
minDate: new Date(1980, 0, 1),
maxDate: new Date(2025, 10, 1),
currentDate: new Date(),
@ -209,7 +212,107 @@ export default {
}
})
return {
shortcuts: result
shortcuts: result,
disabledDate: (val) => {
const timeStamp = +new Date(val)
if (!this.element.options.attrs.setTimeRange) {
return false
}
const {
intervalType,
regularOrTrends,
regularOrTrendsValue,
relativeToCurrent,
timeNum,
relativeToCurrentType,
around,
dynamicWindow,
maximumSingleQuery,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange
} = this.element.options.attrs.timeRange || {}
let isDynamicWindowTime = false
if (this.startWindowTime && dynamicWindow) {
isDynamicWindowTime =
dayjs(this.startWindowTime)
.add(maximumSingleQuery, 'day')
.startOf('day')
.valueOf() -
1000 <
timeStamp
}
if (intervalType === 'none') {
if (dynamicWindow) return isDynamicWindowTime
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) || isDynamicWindowTime
}
if (intervalType === 'end') {
return timeStamp > +new Date(startValue) || isDynamicWindowTime
}
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) ||
isDynamicWindowTime
)
}
},
onPick: ({ minDate }) => {
this.startWindowTime = +new Date(minDate)
},
}
}
return null
@ -447,6 +550,7 @@ export default {
}
},
onBlur() {
this.startWindowTime = 0
this.onFocus = false
},
toFocus() {

View File

@ -27,6 +27,7 @@
>
<el-checkbox
v-model="checkAll"
class="is-tree-select"
:indeterminate="isIndeterminate"
@change="handleCheckAllChange"
>
@ -38,6 +39,7 @@
>
<template v-for="item in dataWithEmpty">
<el-checkbox
class="is-tree-select"
:key="item.id"
:label="item.id"
>{{ item.label || item.id }}

View File

@ -501,6 +501,7 @@
</template>
<script>
import dayjs from 'dayjs'
import DeMainContainer from '@/components/dataease/DeMainContainer'
import DeContainer from '@/components/dataease/DeContainer'
import DeAsideContainer from '@/components/dataease/DeAsideContainer'
@ -508,6 +509,7 @@ import { addClass, removeClass } from '@/utils'
import FilterGroup from '../filter'
import SubjectSetting from '../subjectSetting'
import bus from '@/utils/bus'
import { getThisStart, getLastStart, getAround } from '@/views/panel/filter/filterMain/time-format-dayjs.js'
import { deepCopy, getNowCanvasComponentData, imgUrlTrans, matrixBaseChange } from '@/components/canvas/utils/utils'
import componentList, {
BASE_MOBILE_STYLE,
@ -550,6 +552,7 @@ import { userLoginInfo } from '@/api/systemInfo/userLogin'
import { activeWatermark } from '@/components/canvas/tools/watermark'
import PositionAdjust from '@/views/chart/view/PositionAdjust'
import { hexColorToRGBA } from '@/views/chart/chart/util'
import msgCfm from '@/components/msgCfm'
export default {
name: 'PanelEdit',
components: {
@ -575,6 +578,7 @@ export default {
ChartEdit,
CanvasOptBar
},
mixins: [msgCfm],
data() {
return {
userInfo: null,
@ -1260,8 +1264,113 @@ export default {
bus.$emit('onRemoveLastItem')
}
},
isInRange(ele, startWindowTime, timeStamp) {
const {
intervalType,
regularOrTrends,
regularOrTrendsValue,
relativeToCurrent,
timeNum,
relativeToCurrentType,
around,
dynamicWindow,
maximumSingleQuery,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange
} = ele.timeRange || {}
let isDynamicWindowTime = false
if (startWindowTime && dynamicWindow) {
isDynamicWindowTime =
dayjs(startWindowTime)
.add(maximumSingleQuery, 'day')
.startOf('day')
.valueOf() -
1000 <
timeStamp
}
if (intervalType === 'none') {
if (dynamicWindow) return isDynamicWindowTime
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 startWindowTime < +new Date(startValue) || isDynamicWindowTime
}
if (intervalType === 'end') {
return timeStamp > +new Date(startValue) || isDynamicWindowTime
}
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 (
startWindowTime < +new Date(startTime) - 1000 ||
timeStamp > +new Date(endTime) ||
isDynamicWindowTime
)
}
},
sureFilter() {
this.currentFilterCom = this.$refs['filter-setting-' + this.currentFilterCom.id].getElementInfo()
if (this.currentFilterCom.serviceName === 'timeDateRangeWidget') {
const { value, attrs } = this.currentFilterCom.options
if (!!value && attrs.setTimeRange) {
const [startWindowTime, timeStamp] = attrs.default.isDynamic ? ApplicationContext.getService('timeDateRangeWidget').dynamicDateFormNow(this.currentFilterCom) : value.split(',')
if(this.isInRange(attrs, +startWindowTime, dayjs(+timeStamp)
.startOf('day')
.valueOf())) {
this.openMessageSuccess('默认值必须在时间筛选范围!', 'error')
return
}
}
}
if (this.editType !== 'update') {
adaptCurThemeCommonStyle(this.currentFilterCom)
}

View File

@ -8,49 +8,6 @@
:active-text="$t('panel.multiple_choice')"
@change="multipleChange"
/>
<span
v-if="widget.isTimeWidget && widget.isTimeWidget()"
style="padding-left: 10px;"
>
<el-checkbox
v-model="attrs.showTime"
@change="showTimeChange"
>
<span>{{ $t('panel.show_time') }} </span>
</el-checkbox>
<el-popover
v-model="timePopovervisible"
placement="bottom-end"
:disabled="!attrs.showTime"
width="140"
>
<div style="width: 100%;overflow-y: auto;overflow-x: hidden;word-break: break-all;position: relative;">
<ul class="de-ul">
<li
v-for="(node, i) in accuracyOptions"
:key="node.id"
:index="i"
class="de-sort-field-span"
:class="attrs.accuracy === node.id ? 'de-active-li': ''"
@click="attrs.accuracy = node.id"
>
<span>{{ node.name }}</span>
</li>
</ul>
</div>
<i
slot="reference"
:class="{'i-filter-active': attrs.showTime, 'i-filter-inactive': !attrs.showTime}"
class="el-icon-setting i-filter"
/>
</el-popover>
</span>
<span
v-if="widget.isSortWidget && widget.isSortWidget()"
style="padding-left: 10px;"
@ -70,31 +27,7 @@
<el-col :span="16">
<div class="filter-options-right">
<span style="padding-right: 10px;">
<el-popover :visible-arrow="false" placement="bottom-start" :width="180" trigger="click">
<template #reference>
<div class="more-select-btn icon iconfont icon-icon-more">
{{ $t('panel.more') }}
</div>
</template>
<el-checkbox
v-if="widget.name && ['textSelectWidget', 'textSelectGridWidget'].includes(widget.name)"
v-model="attrs.showEmpty"
>{{ $t('panel.show_empty') }}
</el-checkbox>
<el-checkbox
v-if="widget.name && ['timeDateRangeWidget'].includes(widget.name)"
v-model="attrs.showEmpty"
>设置时间筛选范围
</el-checkbox>
<el-popover :visible-arrow="false" :offset="-452" placement="bottom-start" :width="452" trigger="click">
<template #reference>
<svg-icon
icon-class="icon-setting"
/>
</template>
<RangeFilterTime :timeRangeData="attrs.timeRange" />
</el-popover>
</el-popover>
<el-checkbox
v-model="attrs.showTitle"
@ -180,101 +113,171 @@
</el-popover>
</span>
<span
v-if="showParams"
style="padding-left: 10px;"
>
<el-checkbox
v-model="attrs.enableParameters"
@change="enableParametersChange"
><span>
{{ $t('panel.binding_parameters') }} </span> </el-checkbox>
<el-popover
placement="bottom-end"
:disabled="!attrs.enableParameters"
width="420"
>
<div class="view-container-class">
<el-tabs
v-if="isRangeParamWidget"
v-model="activeName"
<el-popover popper-class="popover-more-parent" :visible-arrow="false" placement="bottom-start" :width="182" trigger="click">
<template #reference>
<div class="more-select-btn icon iconfont icon-icon-more">
{{ $t('panel.more') }}
</div>
</template>
<div class="check-item">
<el-checkbox
v-if="widget.name && ['textSelectWidget', 'textSelectGridWidget'].includes(widget.name)"
v-model="attrs.showEmpty"
>{{ $t('panel.show_empty') }}
</el-checkbox>
</div>
<div class="check-item">
<el-checkbox
v-model="attrs.showTime"
v-if="widget.isTimeWidget && widget.isTimeWidget()"
@change="showTimeChange"
>
<el-tab-pane
v-for="(item, index) in tabsOption"
:key="item.name + index"
:label="item.label"
:name="item.name"
>
<span>{{ $t('panel.show_time') }} </span>
</el-checkbox>
<el-popover
v-model="timePopovervisible"
placement="bottom-end"
:disabled="!attrs.showTime"
width="140"
>
<div style="width: 100%;overflow-y: auto;overflow-x: hidden;word-break: break-all;position: relative;">
<ul class="de-ul">
<li
v-for="(node, i) in accuracyOptions"
:key="node.id"
:index="i"
class="de-sort-field-span"
:class="attrs.accuracy === node.id ? 'de-active-li': ''"
@click="attrs.accuracy = node.id"
>
<span>{{ node.name }}</span>
</li>
</ul>
</div>
<i
slot="reference"
:class="{'i-filter-active': attrs.showTime, 'i-filter-inactive': !attrs.showTime}"
v-if="widget.isTimeWidget && widget.isTimeWidget()"
class="el-icon-setting i-filter"
/>
</el-popover>
</div>
<div class="check-item">
<el-checkbox
v-if="widget.name && ['timeDateRangeWidget'].includes(widget.name)"
v-model="attrs.setTimeRange"
>设置时间筛选范围
</el-checkbox>
<el-popover :disabled="!attrs.setTimeRange" popper-class="popover-setting-parent" ref="popoverSetting" :visible-arrow="false" placement="bottom-start" :width="452" trigger="click">
<RangeFilterTime @changeData="changeData" :timeRangeData="attrs.timeRange" />
<i
v-if="widget.name && ['timeDateRangeWidget'].includes(widget.name)"
:class="{'i-filter-active': attrs.setTimeRange, 'i-filter-inactive': !attrs.setTimeRange}"
slot="reference"
class="el-icon-setting i-filter"
/>
</el-popover>
</div>
<div class="check-item">
<el-checkbox
v-if="showParams"
v-model="attrs.enableParameters"
@change="enableParametersChange"
><span>
{{ $t('panel.binding_parameters') }} </span>
</el-checkbox>
<el-popover
placement="bottom-end"
:disabled="!attrs.enableParameters"
width="420"
>
<div class="view-container-class">
<el-tabs
v-if="isRangeParamWidget"
v-model="activeName"
>
<el-tab-pane
v-for="(item, index) in tabsOption"
:key="item.name + index"
:label="item.label"
:name="item.name"
>
<el-checkbox-group
v-model="attrs[item.name + 'Parameters']"
@change="val => {changeDynamicParams(val, item.name)}"
>
<el-checkbox
v-for="(ele ) in allParams"
:key="ele.id"
:label="ele.id"
:disabled="attrs[tabsOption[(index + 1)%2].name + 'Parameters'] && attrs[tabsOption[(index + 1)%2].name + 'Parameters'].includes(ele.id)"
class="de-checkbox"
>
<div class="span-div">
<span
v-if="ele.alias && ele.alias.length <= 7"
style="margin-left: 6px"
>{{ ele.alias }}</span>
<el-tooltip
v-else
class="item"
effect="dark"
:content="ele.alias"
placement="left"
>
<span style="margin-left: 6px">{{ ele.alias }}</span>
</el-tooltip>
</div>
</el-checkbox>
</el-checkbox-group>
</el-tab-pane>
</el-tabs>
<el-checkbox-group
v-model="attrs[item.name + 'Parameters']"
@change="val => {changeDynamicParams(val, item.name)}"
v-else
v-model="attrs.parameters"
>
<el-checkbox
v-for="(ele ) in allParams"
:key="ele.id"
:label="ele.id"
:disabled="attrs[tabsOption[(index + 1)%2].name + 'Parameters'] && attrs[tabsOption[(index + 1)%2].name + 'Parameters'].includes(ele.id)"
v-for="(item ) in allParams"
:key="item.id"
:label="item.id"
class="de-checkbox"
>
<div class="span-div">
<div class="span-div2">
<span
v-if="ele.alias && ele.alias.length <= 7"
v-if="item.alias && item.alias.length <= 7"
style="margin-left: 6px"
>{{ ele.alias }}</span>
>{{ item.alias }}</span>
<el-tooltip
v-else
class="item"
effect="dark"
:content="ele.alias"
:content="item.alias"
placement="left"
>
<span style="margin-left: 6px">{{ ele.alias }}</span>
<span style="margin-left: 6px">{{ item.alias }}</span>
</el-tooltip>
</div>
</el-checkbox>
</el-checkbox-group>
</el-tab-pane>
</el-tabs>
<el-checkbox-group
v-else
v-model="attrs.parameters"
>
<el-checkbox
v-for="(item ) in allParams"
:key="item.id"
:label="item.id"
class="de-checkbox"
>
<div class="span-div2">
<span
v-if="item.alias && item.alias.length <= 7"
style="margin-left: 6px"
>{{ item.alias }}</span>
<el-tooltip
v-else
class="item"
effect="dark"
:content="item.alias"
placement="left"
>
<span style="margin-left: 6px">{{ item.alias }}</span>
</el-tooltip>
</div>
</div>
</el-checkbox>
</el-checkbox-group>
<i
slot="reference"
v-if="showParams"
:class="{'i-filter-active': attrs.enableParameters, 'i-filter-inactive': !attrs.enableParameters}"
class="el-icon-setting i-filter"
/>
</el-popover>
</div>
<i
slot="reference"
:class="{'i-filter-active': attrs.enableParameters, 'i-filter-inactive': !attrs.enableParameters}"
class="el-icon-setting i-filter"
/>
</el-popover>
</span>
</div>
</el-col>
</el-row>
</template>
@ -428,6 +431,12 @@ export default {
}
this.attrs.parameters = [...new Set([...start, ...end])]
},
changeData(val) {
if (val) {
this.attrs.timeRange = val
}
this.$refs.popoverSetting.doClose()
},
sortChange(param) {
this.element.options.attrs.sort = param
},
@ -498,10 +507,15 @@ export default {
justify-content: flex-end;
flex-wrap: nowrap;
height: 50px;
.more-select-btn {
display: inline-flex;
width: 56px;
height: 26px;
cursor: pointer;
margin-right: -4px;
margin-left: 6px;
border-radius: 4px;
color: #3370FF;
font-size: 14px;
@ -595,3 +609,17 @@ export default {
}
</style>
<style lang="scss">
.popover-more-parent {
margin-top: 4px !important;
.check-item {
margin-bottom: 5px;
&:last-of-type {
margin-bottom: 0;
}
}
.el-checkbox {
margin-right: 0;
}
}
</style>

View File

@ -45,6 +45,7 @@
<div class="setting-input">
<el-input-number
v-model="timeRange.timeNum"
size="small"
:min="0"
controls-position="right"
/>
@ -75,6 +76,7 @@
<div class="setting-input range">
<el-input-number
v-model="timeRange.timeNum"
size="small"
:min="0"
controls-position="right"
/>
@ -101,6 +103,7 @@
<div class="setting-input range">
<el-input-number
v-model="timeRange.timeNumRange"
size="small"
:min="0"
controls-position="right"
/>
@ -153,16 +156,30 @@
<el-input-number
v-model="timeRange.maximumSingleQuery"
:min="1"
size="small"
controls-position="right"
/>
{{ relativeToCurrentTypeListTips }}
</div>
</div>
<div class="popover-foot">
<de-btn
secondary
@click="closeFilter"
>{{ $t('chart.cancel') }}
</de-btn>
<de-btn
type="primary"
@click="changeFilter"
>{{ $t('chart.confirm') }}
</de-btn>
</div>
</div>
</template>
<script>
import { getThisStart, getLastStart, getAround } from "./time-format-dayjs";
import { cloneDeep } from 'lodash-es'
const intervalTypeList = [
{
label: "无",
@ -228,11 +245,8 @@ const relativeToCurrentList = [
value: "custom",
},
];
export default {
props: {
timeRangeData: {
type: Object,
defalut: () => ({
const defaultObj = {
intervalType: "none",
dynamicWindow: false,
maximumSingleQuery: 0,
@ -245,7 +259,12 @@ export default {
timeNumRange: 0,
relativeToCurrentTypeRange: "year",
aroundRange: "f",
}),
}
export default {
props: {
timeRangeData: {
type: Object,
defalut: () => (defaultObj),
},
},
data() {
@ -271,7 +290,8 @@ export default {
};
},
created() {
this.timeRange = this.timeRangeData;
this.timeRange = cloneDeep(this.timeRangeData);
this.init()
},
computed: {
timeConfig() {
@ -324,10 +344,17 @@ export default {
around,
relativeToCurrent,
intervalType,
regularOrTrendsValue,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
regularOrTrends,
} = this.timeRange;
if (regularOrTrends === 'fixed') {
if (!!regularOrTrendsValue) return
this.timeRange.regularOrTrendsValue = new Date()
return
}
if (intervalType === "timeInterval") {
const startTime = getAround(
relativeToCurrentType,
@ -380,11 +407,19 @@ export default {
}
}
},
closeFilter() {
this.timeRange = cloneDeep(defaultObj)
this.$emit('changeData', null)
},
changeFilter() {
this.$emit('changeData', cloneDeep(this.timeRange))
}
},
};
</script>
<style lang="less">
.set-time-filtering-range {
color: #1F2329;
.el-radio,
.el-checkbox.el-checkbox--default {
height: 22px;
@ -392,6 +427,14 @@ export default {
--el-radio-input-height: 16px;
--el-radio-input-width: 16px;
}
.popover-foot {
height: 64px;
text-align: right;
padding: 16px;
width: calc(100% + 24px);
margin: 0 0 -12px -12px;
border-top: 1px solid #1F232926;
}
.title {
font-size: 14px;
font-weight: 500;
@ -410,6 +453,7 @@ export default {
&.maximum-single-query {
padding-left: 24px;
display: flex;
margin-top: 8px;
align-items: center;
.el-input-number {
width: 120px;
@ -523,7 +567,7 @@ export default {
.setting-input {
display: flex;
padding-left: 112px;
padding-left: 118px;
justify-content: flex-end;
align-items: center;
&.range {