Merge pull request #8571 from dataease/pr@dev_time_filter
feat(过滤组件): 日期筛选组件可设置查询的起始日期 #6005
This commit is contained in:
commit
25936258d3
@ -41,6 +41,7 @@
|
||||
"@tinymce/tinymce-vue": "^3.2.8",
|
||||
"axios": "^1.6.1",
|
||||
"core-js": "^2.6.5",
|
||||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.0.1",
|
||||
"element-resize-detector": "^1.2.3",
|
||||
"element-ui": "2.15.7",
|
||||
|
||||
@ -70,12 +70,32 @@
|
||||
<el-col :span="16">
|
||||
<div class="filter-options-right">
|
||||
<span style="padding-right: 10px;">
|
||||
<span v-if="widget.name && ['textSelectWidget', 'textSelectGridWidget'].includes(widget.name)" 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>
|
||||
</span>
|
||||
<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"
|
||||
@change="showTitleChange"
|
||||
@ -261,9 +281,10 @@
|
||||
|
||||
<script>
|
||||
import FilterSort from './FilterSort'
|
||||
import RangeFilterTime from '@/views/panel/filter/filterMain/RangeFilterTime.vue'
|
||||
export default {
|
||||
name: 'FilterControl',
|
||||
components: { FilterSort },
|
||||
components: { FilterSort, RangeFilterTime },
|
||||
props: {
|
||||
widget: {
|
||||
type: Object,
|
||||
@ -370,6 +391,22 @@ export default {
|
||||
|
||||
created() {
|
||||
this.attrs = this.controlAttrs
|
||||
if (!this.attrs.timeRange) {
|
||||
this.$set(this.attrs, 'timeRange', {
|
||||
intervalType: "none",
|
||||
dynamicWindow: false,
|
||||
maximumSingleQuery: 0,
|
||||
regularOrTrends: "fixed",
|
||||
regularOrTrendsValue: "",
|
||||
relativeToCurrent: "custom",
|
||||
timeNum: 0,
|
||||
relativeToCurrentType: "year",
|
||||
around: "f",
|
||||
timeNumRange: 0,
|
||||
relativeToCurrentTypeRange: "year",
|
||||
aroundRange: "f",
|
||||
})
|
||||
}
|
||||
if (this.widget.isTimeWidget) {
|
||||
this.showParams = true
|
||||
this.isRangeParamWidget = this.widget.isRangeParamWidget && this.widget.isRangeParamWidget()
|
||||
@ -461,6 +498,25 @@ export default {
|
||||
justify-content: flex-end;
|
||||
flex-wrap: nowrap;
|
||||
height: 50px;
|
||||
.more-select-btn {
|
||||
display: inline-flex;
|
||||
width: 56px;
|
||||
height: 26px;
|
||||
border-radius: 4px;
|
||||
color: #3370FF;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
&:hover {
|
||||
background: #3370FF1A;
|
||||
}
|
||||
|
||||
&.icon-icon-more::before {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.i-filter {
|
||||
|
||||
@ -0,0 +1,553 @@
|
||||
<template>
|
||||
<div class="set-time-filtering-range">
|
||||
<div class="title">设置时间筛选范围</div>
|
||||
<div class="list-item">
|
||||
<div class="label">区间类型</div>
|
||||
<div class="setting-content">
|
||||
<div class="setting">
|
||||
<el-radio-group v-model="timeRange.intervalType">
|
||||
<el-radio
|
||||
v-for="ele in intervalTypeList"
|
||||
:key="ele.value"
|
||||
:label="ele.value"
|
||||
>{{ ele.label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item" v-if="timeRange.intervalType !== 'none'">
|
||||
<div class="label">{{ regularOrTrendsTitle }}</div>
|
||||
<div class="setting-content">
|
||||
<div class="setting">
|
||||
<el-radio-group v-model="timeRange.regularOrTrends">
|
||||
<el-radio label="fixed">固定时间</el-radio>
|
||||
<el-radio label="dynamic">动态时间</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<template
|
||||
v-if="dynamicTime && timeRange.intervalType !== 'timeInterval'"
|
||||
>
|
||||
<div class="setting">
|
||||
<div class="setting-label">相对当前</div>
|
||||
<div class="setting-value select">
|
||||
<el-select v-model="timeRange.relativeToCurrent">
|
||||
<el-option
|
||||
v-for="item in relativeToCurrentList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting" v-if="timeRange.relativeToCurrent === 'custom'">
|
||||
<div class="setting-input">
|
||||
<el-input-number
|
||||
v-model="timeRange.timeNum"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
<el-select v-model="timeRange.relativeToCurrentType">
|
||||
<el-option
|
||||
v-for="item in relativeToCurrentTypeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="timeRange.around">
|
||||
<el-option
|
||||
v-for="item in aroundList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
v-else-if="dynamicTime && timeRange.intervalType === 'timeInterval'"
|
||||
>
|
||||
<div class="setting">
|
||||
<div class="setting-label">开始时间</div>
|
||||
<div class="setting-input range">
|
||||
<el-input-number
|
||||
v-model="timeRange.timeNum"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
<el-select v-model="timeRange.relativeToCurrentType">
|
||||
<el-option
|
||||
v-for="item in relativeToCurrentTypeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="timeRange.around">
|
||||
<el-option
|
||||
v-for="item in aroundList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-label">结束时间</div>
|
||||
<div class="setting-input range">
|
||||
<el-input-number
|
||||
v-model="timeRange.timeNumRange"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
<el-select v-model="timeRange.relativeToCurrentTypeRange">
|
||||
<el-option
|
||||
v-for="item in relativeToCurrentTypeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="timeRange.aroundRange">
|
||||
<el-option
|
||||
v-for="item in aroundList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="parameters" :class="dynamicTime && 'setting'">
|
||||
<div class="setting-label" v-if="dynamicTime">预览</div>
|
||||
<div :class="dynamicTime ? 'setting-value' : 'w100'">
|
||||
<el-date-picker
|
||||
:disabled="timeRange.regularOrTrends !== 'fixed'"
|
||||
v-model="timeRange.regularOrTrendsValue"
|
||||
:key="timeInterval"
|
||||
:type="timeInterval"
|
||||
:start-placeholder="$t('dataset.start_time')"
|
||||
:end-placeholder="$t('dataset.end_time')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item">
|
||||
<div class="label">
|
||||
<el-checkbox
|
||||
v-model="timeRange.dynamicWindow"
|
||||
label="动态查询时间窗口"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="timeRange.dynamicWindow"
|
||||
class="setting-content maximum-single-query"
|
||||
>
|
||||
单次查询最多
|
||||
<el-input-number
|
||||
v-model="timeRange.maximumSingleQuery"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
{{ relativeToCurrentTypeListTips }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getThisStart, getLastStart, getAround } from "./time-format-dayjs";
|
||||
const intervalTypeList = [
|
||||
{
|
||||
label: "无",
|
||||
value: "none",
|
||||
},
|
||||
{
|
||||
label: "开始于",
|
||||
value: "start",
|
||||
},
|
||||
{
|
||||
label: "结束于",
|
||||
value: "end",
|
||||
},
|
||||
{
|
||||
label: "时间区间",
|
||||
value: "timeInterval",
|
||||
},
|
||||
];
|
||||
const aroundList = [
|
||||
{
|
||||
label: "前",
|
||||
value: "f",
|
||||
},
|
||||
{
|
||||
label: "后",
|
||||
value: "b",
|
||||
},
|
||||
];
|
||||
const relativeToCurrentTypeList = [
|
||||
{
|
||||
label: "年",
|
||||
value: "year",
|
||||
},
|
||||
{
|
||||
label: "月",
|
||||
value: "month",
|
||||
},
|
||||
{
|
||||
label: "日",
|
||||
value: "day",
|
||||
},
|
||||
];
|
||||
|
||||
const relativeToCurrentList = [
|
||||
{
|
||||
label: "今天",
|
||||
value: "today",
|
||||
},
|
||||
{
|
||||
label: "昨天",
|
||||
value: "yesterday",
|
||||
},
|
||||
{
|
||||
label: "月初",
|
||||
value: "monthBeginning",
|
||||
},
|
||||
{
|
||||
label: "年初",
|
||||
value: "yearBeginning",
|
||||
},
|
||||
{
|
||||
label: "自定义",
|
||||
value: "custom",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
props: {
|
||||
timeRangeData: {
|
||||
type: Object,
|
||||
defalut: () => ({
|
||||
intervalType: "none",
|
||||
dynamicWindow: false,
|
||||
maximumSingleQuery: 0,
|
||||
regularOrTrends: "fixed",
|
||||
regularOrTrendsValue: "",
|
||||
relativeToCurrent: "custom",
|
||||
timeNum: 0,
|
||||
relativeToCurrentType: "year",
|
||||
around: "f",
|
||||
timeNumRange: 0,
|
||||
relativeToCurrentTypeRange: "year",
|
||||
aroundRange: "f",
|
||||
}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
intervalTypeList,
|
||||
relativeToCurrentTypeList,
|
||||
aroundList,
|
||||
relativeToCurrentList,
|
||||
timeRange: {
|
||||
intervalType: "none",
|
||||
dynamicWindow: false,
|
||||
maximumSingleQuery: 0,
|
||||
regularOrTrends: "fixed",
|
||||
regularOrTrendsValue: "",
|
||||
relativeToCurrent: "custom",
|
||||
timeNum: 0,
|
||||
relativeToCurrentType: "year",
|
||||
around: "f",
|
||||
timeNumRange: 0,
|
||||
relativeToCurrentTypeRange: "year",
|
||||
aroundRange: "f",
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.timeRange = this.timeRangeData;
|
||||
},
|
||||
computed: {
|
||||
timeConfig() {
|
||||
const {
|
||||
timeNum,
|
||||
relativeToCurrentType,
|
||||
around,
|
||||
intervalType,
|
||||
timeNumRange,
|
||||
relativeToCurrentTypeRange,
|
||||
aroundRange,
|
||||
} = this.timeRange;
|
||||
return {
|
||||
timeNum,
|
||||
relativeToCurrentType,
|
||||
around,
|
||||
intervalType,
|
||||
timeNumRange,
|
||||
relativeToCurrentTypeRange,
|
||||
aroundRange,
|
||||
};
|
||||
},
|
||||
regularOrTrendsTitle() {
|
||||
return intervalTypeList.find(
|
||||
(ele) => ele.value === this.timeRange.intervalType,
|
||||
).label;
|
||||
},
|
||||
dynamicTime() {
|
||||
return this.timeRange.regularOrTrends !== "fixed";
|
||||
},
|
||||
timeInterval() {
|
||||
return this.timeRange.intervalType === "timeInterval"
|
||||
? "daterange"
|
||||
: "date";
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
timeConfig: {
|
||||
handler() {
|
||||
this.init();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
const {
|
||||
timeNum,
|
||||
relativeToCurrentType,
|
||||
around,
|
||||
relativeToCurrent,
|
||||
intervalType,
|
||||
timeNumRange,
|
||||
relativeToCurrentTypeRange,
|
||||
aroundRange,
|
||||
} = this.timeRange;
|
||||
if (intervalType === "timeInterval") {
|
||||
const startTime = getAround(
|
||||
relativeToCurrentType,
|
||||
around === "f" ? "subtract" : "add",
|
||||
timeNum,
|
||||
);
|
||||
const endTime = getAround(
|
||||
relativeToCurrentTypeRange,
|
||||
aroundRange === "f" ? "subtract" : "add",
|
||||
timeNumRange,
|
||||
);
|
||||
this.timeRange.regularOrTrendsValue = [startTime, endTime];
|
||||
return;
|
||||
}
|
||||
if (relativeToCurrent === "custom") {
|
||||
this.timeRange.regularOrTrendsValue = getAround(
|
||||
relativeToCurrentType,
|
||||
around === "f" ? "subtract" : "add",
|
||||
timeNum,
|
||||
);
|
||||
} else {
|
||||
switch (relativeToCurrent) {
|
||||
case "thisYear":
|
||||
this.timeRange.regularOrTrendsValue = getThisStart("year");
|
||||
break;
|
||||
case "lastYear":
|
||||
this.timeRange.regularOrTrendsValue = getLastStart("year");
|
||||
break;
|
||||
case "thisMonth":
|
||||
this.timeRange.regularOrTrendsValue = getThisStart("month");
|
||||
break;
|
||||
case "lastMonth":
|
||||
this.timeRange.regularOrTrendsValue = getLastStart("month");
|
||||
break;
|
||||
case "today":
|
||||
this.timeRange.regularOrTrendsValue = getThisStart("day");
|
||||
break;
|
||||
case "yesterday":
|
||||
this.timeRange.regularOrTrendsValue = getLastStart("day");
|
||||
break;
|
||||
case "monthBeginning":
|
||||
this.timeRange.regularOrTrendsValue = getThisStart("month");
|
||||
break;
|
||||
case "yearBeginning":
|
||||
this.timeRange.regularOrTrendsValue = getThisStart("year");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less">
|
||||
.set-time-filtering-range {
|
||||
.el-radio,
|
||||
.el-checkbox.el-checkbox--default {
|
||||
height: 22px;
|
||||
margin-right: 24px;
|
||||
--el-radio-input-height: 16px;
|
||||
--el-radio-input-width: 16px;
|
||||
}
|
||||
.title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.setting-content {
|
||||
width: 100%;
|
||||
&.maximum-single-query {
|
||||
padding-left: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.el-input-number {
|
||||
width: 120px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.top-item {
|
||||
.label {
|
||||
margin-bottom: auto;
|
||||
padding-top: 5.5px;
|
||||
}
|
||||
}
|
||||
.label {
|
||||
width: 100px;
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
.value {
|
||||
width: 321px;
|
||||
.value {
|
||||
margin-top: 8px;
|
||||
&:first-child {
|
||||
margin-top: -0.5px;
|
||||
}
|
||||
}
|
||||
.el-select {
|
||||
width: 321px;
|
||||
}
|
||||
}
|
||||
|
||||
.parameters {
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
.w100 {
|
||||
width: 100%;
|
||||
}
|
||||
.el-date-editor,
|
||||
.el-date-editor--datetime .el-input__wrapper,
|
||||
.el-select-v2 {
|
||||
width: 415px;
|
||||
}
|
||||
|
||||
.el-date-editor {
|
||||
.el-input__wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.parameters-range {
|
||||
width: 100%;
|
||||
padding-left: 24px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.range-title,
|
||||
.params-start,
|
||||
.params-end {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.params-start,
|
||||
.params-end {
|
||||
margin-top: 8px;
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.params-end {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.params-start {
|
||||
padding-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.setting {
|
||||
&.setting {
|
||||
margin-top: 8px;
|
||||
}
|
||||
&.parameters {
|
||||
width: 100%;
|
||||
padding-left: 24px;
|
||||
|
||||
.setting-label {
|
||||
margin-left: 0;
|
||||
}
|
||||
.el-date-editor {
|
||||
width: 308px !important;
|
||||
}
|
||||
}
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.setting-label {
|
||||
width: 80px;
|
||||
margin: 0 8px 0 24px;
|
||||
}
|
||||
|
||||
.setting-value {
|
||||
&.select {
|
||||
.el-select {
|
||||
width: 308px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setting-input {
|
||||
display: flex;
|
||||
padding-left: 112px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
&.range {
|
||||
padding-left: 0px;
|
||||
width: 308px;
|
||||
}
|
||||
& > div + div {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-year-month-range {
|
||||
.setting-input {
|
||||
.el-date-editor.el-input {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.range-filter-time {
|
||||
padding: 15px !important;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,22 @@
|
||||
import dayjs from 'dayjs'
|
||||
function getThisStart(val = 'month') {
|
||||
return new Date(dayjs().startOf(val).format('YYYY/MM/DD HH:mm:ss'))
|
||||
}
|
||||
|
||||
function getThisEnd(val = 'month') {
|
||||
return new Date(dayjs().endOf(val).format('YYYY/MM/DD HH:mm:ss'))
|
||||
}
|
||||
|
||||
function getLastStart(val = 'month') {
|
||||
return new Date(dayjs().subtract(1, val).startOf(val).format('YYYY/MM/DD HH:mm:ss'))
|
||||
}
|
||||
|
||||
function getLastEnd(val = 'month') {
|
||||
return new Date(dayjs().subtract(1, val).endOf(val).format('YYYY/MM/DD HH:mm:ss'))
|
||||
}
|
||||
|
||||
function getAround(val = 'month', 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 }
|
||||
Loading…
Reference in New Issue
Block a user