mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-20 06:34:55 +00:00
[improvement][semantic-fe] enhance the analysis of metric trends (#234)
* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab. [improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions. [improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager. * [improvement][semantic-fe] Add time granularity setting in the data source configuration. * [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility * [improvement][semantic-fe] Modification of data source creation prompt wording" * [improvement][semantic-fe] metric market experience optimization * [improvement][semantic-fe] enhance the analysis of metric trends
This commit is contained in:
@@ -0,0 +1,547 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import type { RadioChangeEvent } from 'antd';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { objToList } from '@/utils/utils';
|
||||
// import { LatestDateMap } from '@/services/global/type';
|
||||
import { DateRangeType, DateRangeTypeToPickerMap, DateRangePicker } from './type';
|
||||
import {
|
||||
SHORT_CUT_ITEM_LIST,
|
||||
datePeriodTypeWordingMap,
|
||||
getDynamicDateRangeStringByParams,
|
||||
getDateStrings,
|
||||
datePeriodTypeMap,
|
||||
dateRangeTypeExchangeDatePeriodTypeMap,
|
||||
} from './utils';
|
||||
import {
|
||||
DynamicAdvancedConfigType,
|
||||
DatePeriodType,
|
||||
PerDatePeriodType,
|
||||
DateSettingType,
|
||||
} from './type';
|
||||
|
||||
import {
|
||||
Typography,
|
||||
Space,
|
||||
Collapse,
|
||||
Tag,
|
||||
Row,
|
||||
Col,
|
||||
Radio,
|
||||
InputNumber,
|
||||
Select,
|
||||
Checkbox,
|
||||
Tooltip,
|
||||
DatePicker,
|
||||
} from 'antd';
|
||||
|
||||
import moment from 'moment';
|
||||
import styles from './style.less';
|
||||
|
||||
const { CheckableTag } = Tag;
|
||||
const { Panel } = Collapse;
|
||||
const { Link } = Typography;
|
||||
const { Option } = Select;
|
||||
|
||||
type Props = {
|
||||
initialValues?: any;
|
||||
submitFormDataState?: boolean;
|
||||
dateRangeTypeProps?: DateRangeType;
|
||||
onDateRangeChange: (value: string[], config: any) => void;
|
||||
onAdvanceSettingCollapsedChange?: (collapse: boolean) => void;
|
||||
onShortCutClick?: (shortCutId: string) => void;
|
||||
onDateRangeStringAndDescChange?: ({
|
||||
dateRangeString,
|
||||
dateRangeStringDesc,
|
||||
}: {
|
||||
dateRangeString: string[];
|
||||
dateRangeStringDesc: string;
|
||||
}) => void;
|
||||
disabledAdvanceSetting?: boolean;
|
||||
};
|
||||
|
||||
const DynamicDate: React.FC<Props> = ({
|
||||
initialValues,
|
||||
dateRangeTypeProps,
|
||||
submitFormDataState,
|
||||
onDateRangeChange,
|
||||
onAdvanceSettingCollapsedChange,
|
||||
onShortCutClick,
|
||||
onDateRangeStringAndDescChange,
|
||||
disabledAdvanceSetting = false,
|
||||
}: any) => {
|
||||
const initAdvacedConfigPanelCollapsed = () => {
|
||||
return !initialValues?.dateSettingType || initialValues?.shortCutId ? [] : ['1'];
|
||||
};
|
||||
const [advancedPanelFormResetState, setAdvancedPanelFormResetState] =
|
||||
useState(dateRangeTypeProps);
|
||||
|
||||
useEffect(() => {
|
||||
// 当时间粒度发生变化时重置高级设置面板
|
||||
resetAdvancedPanelForm(dateRangeTypeProps);
|
||||
}, [dateRangeTypeProps]);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialValues?.dateSettingType !== DateSettingType.DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
initShortCutByDateRangeChange(dateRangeTypeProps);
|
||||
}, [advancedPanelFormResetState]);
|
||||
|
||||
const resetAdvancedPanelForm = (dateRangeType: DateRangeType) => {
|
||||
const lastConfigTypeFormData = advancedPanelFormData[DynamicAdvancedConfigType.LAST];
|
||||
const historyConfigTypeFormData = advancedPanelFormData[DynamicAdvancedConfigType.HISTORY];
|
||||
switch (dateRangeType) {
|
||||
case DateRangeType.DAY:
|
||||
setAdvancedPanelFormData({
|
||||
...advancedPanelFormData,
|
||||
[DynamicAdvancedConfigType.LAST]: {
|
||||
...lastConfigTypeFormData,
|
||||
periodType: DatePeriodType.DAY,
|
||||
},
|
||||
[DynamicAdvancedConfigType.HISTORY]: {
|
||||
...historyConfigTypeFormData,
|
||||
periodType: DatePeriodType.DAY,
|
||||
},
|
||||
});
|
||||
break;
|
||||
case DateRangeType.WEEK:
|
||||
setAdvancedPanelFormData({
|
||||
...advancedPanelFormData,
|
||||
[DynamicAdvancedConfigType.LAST]: {
|
||||
...lastConfigTypeFormData,
|
||||
periodType: DatePeriodType.WEEK,
|
||||
},
|
||||
[DynamicAdvancedConfigType.HISTORY]: {
|
||||
...historyConfigTypeFormData,
|
||||
periodType: DatePeriodType.WEEK,
|
||||
},
|
||||
});
|
||||
break;
|
||||
case DateRangeType.MONTH:
|
||||
setAdvancedPanelFormData({
|
||||
...advancedPanelFormData,
|
||||
[DynamicAdvancedConfigType.LAST]: {
|
||||
...lastConfigTypeFormData,
|
||||
periodType: DatePeriodType.MONTH,
|
||||
},
|
||||
[DynamicAdvancedConfigType.HISTORY]: {
|
||||
...historyConfigTypeFormData,
|
||||
periodType: DatePeriodType.MONTH,
|
||||
},
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
setAdvancedPanelFormResetState(dateRangeType);
|
||||
setAdvacedConfigPanelCollapsed([]);
|
||||
};
|
||||
|
||||
const initAdvancedConfigType = () => {
|
||||
return initialValues?.dynamicAdvancedConfigType;
|
||||
};
|
||||
const initAdvancedPanelFormData = () => {
|
||||
let defaultConfig = {
|
||||
[DynamicAdvancedConfigType.LAST]: {
|
||||
number: 1,
|
||||
periodType: dateRangeTypeExchangeDatePeriodTypeMap[dateRangeTypeProps],
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
[DynamicAdvancedConfigType.HISTORY]: {
|
||||
number: 1,
|
||||
periodType: dateRangeTypeExchangeDatePeriodTypeMap[dateRangeTypeProps],
|
||||
},
|
||||
[DynamicAdvancedConfigType.FROM_DATE_PERIOD]: {
|
||||
perPeriodType: PerDatePeriodType.PERDAY,
|
||||
},
|
||||
[DynamicAdvancedConfigType.FROM_DATE]: { date: moment() },
|
||||
};
|
||||
if (advancedPanelFormData) {
|
||||
defaultConfig = { ...advancedPanelFormData };
|
||||
}
|
||||
if (initialValues?.dynamicAdvancedConfigType) {
|
||||
const { dynamicAdvancedConfigType } = initialValues;
|
||||
const targetConfig = defaultConfig[dynamicAdvancedConfigType];
|
||||
if (!targetConfig) {
|
||||
return defaultConfig;
|
||||
}
|
||||
const mergeConfig = Object.keys(targetConfig).reduce((result, key) => {
|
||||
return {
|
||||
...result,
|
||||
[key]: initialValues[key],
|
||||
};
|
||||
}, {});
|
||||
defaultConfig[dynamicAdvancedConfigType] = mergeConfig;
|
||||
}
|
||||
return defaultConfig;
|
||||
};
|
||||
const initShortCutSettingChecked = () => {
|
||||
return initialValues?.shortCutId || '';
|
||||
};
|
||||
const [advacedConfigPanelCollapsed, setAdvacedConfigPanelCollapsed] = useState<string | string[]>(
|
||||
initAdvacedConfigPanelCollapsed(),
|
||||
);
|
||||
const [advancedConfigType, setAdvancedConfigType] = useState<
|
||||
DynamicAdvancedConfigType | undefined
|
||||
>(initAdvancedConfigType());
|
||||
const [advancedPanelFormData, setAdvancedPanelFormData] = useState<any>(
|
||||
initAdvancedPanelFormData(),
|
||||
);
|
||||
const [shortCutSettingChecked, setShortCutSettingChecked] = useState<string>(
|
||||
initShortCutSettingChecked(),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// 外部状态触发表单数据提交
|
||||
if (submitFormDataState && advancedConfigType) {
|
||||
updateAdvancedPanelFormData(
|
||||
advancedPanelFormData[advancedConfigType],
|
||||
advancedConfigType,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}, [submitFormDataState]);
|
||||
|
||||
const init = () => {
|
||||
setAdvacedConfigPanelCollapsed(initAdvacedConfigPanelCollapsed());
|
||||
setAdvancedConfigType(initAdvancedConfigType());
|
||||
setAdvancedPanelFormData(initAdvancedPanelFormData());
|
||||
setShortCutSettingChecked(initShortCutSettingChecked());
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (initialValues?.dateSettingType === DateSettingType.DYNAMIC) {
|
||||
init();
|
||||
}
|
||||
}, [initialValues]);
|
||||
|
||||
const handleDateRangeChange = (dateRange: string[], config: any) => {
|
||||
onDateRangeChange(dateRange, {
|
||||
...config,
|
||||
dateSettingType: DateSettingType.DYNAMIC,
|
||||
});
|
||||
};
|
||||
|
||||
const updateAdvancedPanelFormData = (
|
||||
formData: any,
|
||||
configType: DynamicAdvancedConfigType,
|
||||
emitImmediately = false,
|
||||
) => {
|
||||
const mergeConfigTypeData = {
|
||||
...advancedPanelFormData[configType],
|
||||
...formData,
|
||||
// shortCutId: shortCutSettingChecked,
|
||||
dateRangeType: dateRangeTypeProps,
|
||||
dynamicAdvancedConfigType: configType,
|
||||
};
|
||||
const { dateRangeString, dateRangeStringDesc } = getDynamicDateRangeStringByParams(
|
||||
mergeConfigTypeData,
|
||||
configType,
|
||||
{ maxPartition: moment().format('YYYY-MM-DD') },
|
||||
);
|
||||
mergeConfigTypeData.dateRangeStringDesc = dateRangeStringDesc;
|
||||
onDateRangeStringAndDescChange?.({ dateRangeString, dateRangeStringDesc });
|
||||
if (emitImmediately) {
|
||||
handleDateRangeChange(dateRangeString, mergeConfigTypeData);
|
||||
}
|
||||
setAdvancedPanelFormData({
|
||||
...advancedPanelFormData,
|
||||
[configType]: mergeConfigTypeData,
|
||||
});
|
||||
};
|
||||
|
||||
// 根据当前时间粒度判断高级设置中时间区间选项哪些可用
|
||||
const isDisabledDatePeriodTypeOption = (
|
||||
datePeriodType: DatePeriodType,
|
||||
dateRangeType: DateRangeType,
|
||||
) => {
|
||||
switch (datePeriodType) {
|
||||
case DatePeriodType.DAY:
|
||||
return ![DateRangeType.DAY].includes(dateRangeType);
|
||||
case DatePeriodType.WEEK:
|
||||
return ![DateRangeType.DAY, DateRangeType.WEEK].includes(dateRangeType);
|
||||
case DatePeriodType.MONTH:
|
||||
return false;
|
||||
case DatePeriodType.YEAR:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getDatePeriodTypeOptions = (dateRangeType: DateRangeType) => {
|
||||
const list = objToList(datePeriodTypeMap);
|
||||
const optionList = list.reduce((result: any[], { value, label }: any) => {
|
||||
const isDisabled = isDisabledDatePeriodTypeOption(value, dateRangeType);
|
||||
if (isDisabled) {
|
||||
return result;
|
||||
}
|
||||
result.push(
|
||||
<Option value={value} key={value}>
|
||||
{label}
|
||||
</Option>,
|
||||
);
|
||||
return result;
|
||||
}, []);
|
||||
return optionList;
|
||||
};
|
||||
|
||||
const isAdvancedConfigTypeRadioDisabled = (type: DynamicAdvancedConfigType) => {
|
||||
return type !== advancedConfigType;
|
||||
};
|
||||
|
||||
const initShortCutByDateRangeChange = (dateRangeType: DateRangeType, emitImmediately = false) => {
|
||||
const shortCutList = SHORT_CUT_ITEM_LIST.filter((item) => {
|
||||
return item.dateRangeType === dateRangeType;
|
||||
});
|
||||
const firstItem = shortCutList[0];
|
||||
if (firstItem) {
|
||||
handleShortCutChange(firstItem, emitImmediately);
|
||||
}
|
||||
};
|
||||
|
||||
const handleShortCutChange = (item: any, emitImmediately = true) => {
|
||||
const { id, advancedConfigType, initData } = item;
|
||||
// 设置选中状态
|
||||
setShortCutSettingChecked(id);
|
||||
// 设置快捷选项AdvancedConfigType类型
|
||||
setAdvancedConfigType(advancedConfigType);
|
||||
// 更新数据至表单数据并立即向上层组件传递
|
||||
updateAdvancedPanelFormData(initData, advancedConfigType, emitImmediately);
|
||||
if (emitImmediately) {
|
||||
// 触发快捷选项点击时间,上层组件关闭配置浮窗
|
||||
onShortCutClick?.(id);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAdvancedPanelFormChange = () => {
|
||||
// 当高级面板表单发生变化时,重置快捷选项为空
|
||||
setShortCutSettingChecked('');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.dateShortCutSettingContent}>
|
||||
<Row>
|
||||
{SHORT_CUT_ITEM_LIST.map((item) => {
|
||||
const { id, text, dateRangeType } = item;
|
||||
if (dateRangeType === dateRangeTypeProps) {
|
||||
return (
|
||||
<Col key={`row-col-${id}`}>
|
||||
<CheckableTag
|
||||
className={styles['ant-tag-checkable']}
|
||||
checked={shortCutSettingChecked === id}
|
||||
key={`row-col-tag-${id}`}
|
||||
onChange={() => {
|
||||
handleShortCutChange(item);
|
||||
}}
|
||||
>
|
||||
<div className={styles['tag-value-box']}>{text}</div>
|
||||
</CheckableTag>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
{!disabledAdvanceSetting && (
|
||||
<div className={styles.dateAdvancedSettingContent}>
|
||||
<Collapse
|
||||
// defaultActiveKey={['1']}
|
||||
activeKey={advacedConfigPanelCollapsed}
|
||||
onChange={(key: string | string[]) => {
|
||||
setAdvacedConfigPanelCollapsed(key);
|
||||
if (key.length === 0) {
|
||||
onAdvanceSettingCollapsedChange?.(false);
|
||||
return;
|
||||
}
|
||||
onAdvanceSettingCollapsedChange?.(true);
|
||||
}}
|
||||
bordered={false}
|
||||
ghost={true}
|
||||
expandIconPosition="right"
|
||||
>
|
||||
<Panel
|
||||
header=""
|
||||
// collapsible={'disabled'}
|
||||
key="1"
|
||||
extra={
|
||||
<Space>
|
||||
<Link>高级设置</Link>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<Space>
|
||||
<div style={{ color: 'rgba(0, 0, 0, 0.85)' }}>动态时间</div>
|
||||
<Tooltip
|
||||
title={`日期随着时间推移而更新。 若在1月1日设置查询日期为“今天”, 则第二天的查询日期为1月2日。`}
|
||||
>
|
||||
<QuestionCircleOutlined />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</div>
|
||||
<Radio.Group
|
||||
onChange={(e: RadioChangeEvent) => {
|
||||
const configType = e.target.value;
|
||||
setAdvancedConfigType(configType);
|
||||
updateAdvancedPanelFormData(advancedPanelFormData[configType], configType);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
value={advancedConfigType}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<Radio value={DynamicAdvancedConfigType.LAST}>
|
||||
<Space size={10}>
|
||||
<span className={styles.advancedSettingItemText}>最近</span>
|
||||
<InputNumber
|
||||
style={{ width: 120 }}
|
||||
placeholder="请输入数字"
|
||||
min={1}
|
||||
disabled={isAdvancedConfigTypeRadioDisabled(DynamicAdvancedConfigType.LAST)}
|
||||
value={advancedPanelFormData[DynamicAdvancedConfigType.LAST].number}
|
||||
onChange={(value: number | null) => {
|
||||
updateAdvancedPanelFormData(
|
||||
{ number: value },
|
||||
DynamicAdvancedConfigType.LAST,
|
||||
);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
// defaultValue={DatePeriodType.DAY}
|
||||
style={{ width: 120 }}
|
||||
disabled={isAdvancedConfigTypeRadioDisabled(DynamicAdvancedConfigType.LAST)}
|
||||
value={advancedPanelFormData[DynamicAdvancedConfigType.LAST].periodType}
|
||||
onClick={(e) => {
|
||||
// 禁止冒泡触发Radio点击后续逻辑
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onChange={(value: string) => {
|
||||
updateAdvancedPanelFormData(
|
||||
{ periodType: value },
|
||||
DynamicAdvancedConfigType.LAST,
|
||||
);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
>
|
||||
{getDatePeriodTypeOptions(dateRangeTypeProps)}
|
||||
</Select>
|
||||
<Checkbox
|
||||
disabled={isAdvancedConfigTypeRadioDisabled(DynamicAdvancedConfigType.LAST)}
|
||||
checked={
|
||||
advancedPanelFormData[DynamicAdvancedConfigType.LAST]
|
||||
.includesCurrentPeriod
|
||||
}
|
||||
onChange={(e) => {
|
||||
const isChecked = e.target.checked;
|
||||
updateAdvancedPanelFormData(
|
||||
{ includesCurrentPeriod: isChecked },
|
||||
DynamicAdvancedConfigType.LAST,
|
||||
);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
>
|
||||
包含
|
||||
{
|
||||
datePeriodTypeWordingMap[
|
||||
advancedPanelFormData[DynamicAdvancedConfigType.LAST].periodType
|
||||
]
|
||||
}
|
||||
</Checkbox>
|
||||
</Space>
|
||||
</Radio>
|
||||
<Radio value={DynamicAdvancedConfigType.HISTORY}>
|
||||
<Space size={10}>
|
||||
<span className={styles.advancedSettingItemText}>过去第</span>
|
||||
|
||||
<InputNumber
|
||||
style={{ width: 120 }}
|
||||
placeholder="请输入数字"
|
||||
min={1}
|
||||
disabled={isAdvancedConfigTypeRadioDisabled(
|
||||
DynamicAdvancedConfigType.HISTORY,
|
||||
)}
|
||||
value={advancedPanelFormData[DynamicAdvancedConfigType.HISTORY].number}
|
||||
// defaultValue={3}
|
||||
onChange={(value: number | null) => {
|
||||
updateAdvancedPanelFormData(
|
||||
{ number: value },
|
||||
DynamicAdvancedConfigType.HISTORY,
|
||||
);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
// defaultValue={DatePeriodType.DAY}
|
||||
style={{ width: 120 }}
|
||||
disabled={isAdvancedConfigTypeRadioDisabled(
|
||||
DynamicAdvancedConfigType.HISTORY,
|
||||
)}
|
||||
value={advancedPanelFormData[DynamicAdvancedConfigType.HISTORY].periodType}
|
||||
onClick={(e) => {
|
||||
// 禁止冒泡触发Radio点击后续逻辑
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onChange={(value: string) => {
|
||||
updateAdvancedPanelFormData(
|
||||
{ periodType: value },
|
||||
DynamicAdvancedConfigType.HISTORY,
|
||||
);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
>
|
||||
{getDatePeriodTypeOptions(dateRangeTypeProps)}
|
||||
</Select>
|
||||
</Space>
|
||||
</Radio>
|
||||
<Radio value={DynamicAdvancedConfigType.FROM_DATE}>
|
||||
<Space size={10}>
|
||||
<span className={styles.advancedSettingItemText}>自从</span>
|
||||
<DatePicker
|
||||
disabled={isAdvancedConfigTypeRadioDisabled(
|
||||
DynamicAdvancedConfigType.FROM_DATE,
|
||||
)}
|
||||
value={moment(
|
||||
advancedPanelFormData[DynamicAdvancedConfigType.FROM_DATE].date,
|
||||
)}
|
||||
disabledDate={(current) => {
|
||||
return current && current > moment().endOf('day');
|
||||
}}
|
||||
picker={DateRangeTypeToPickerMap[dateRangeTypeProps]}
|
||||
onChange={(date, dateString) => {
|
||||
if (!date) {
|
||||
return;
|
||||
}
|
||||
const picker = DateRangeTypeToPickerMap[dateRangeTypeProps];
|
||||
|
||||
if (picker === DateRangePicker.WEEK) {
|
||||
date.startOf('week').format('YYYY-MM-DD');
|
||||
}
|
||||
if (picker === DateRangePicker.MONTH) {
|
||||
date.startOf('month').format('YYYY-MM-DD');
|
||||
}
|
||||
updateAdvancedPanelFormData(
|
||||
{ date },
|
||||
DynamicAdvancedConfigType.FROM_DATE,
|
||||
);
|
||||
handleAdvancedPanelFormChange();
|
||||
}}
|
||||
/>
|
||||
至此刻
|
||||
</Space>
|
||||
</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DynamicDate;
|
||||
@@ -0,0 +1,160 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Space, DatePicker } from 'antd';
|
||||
import { DateMode, DateRangeType, DateRangePicker, DateRangeTypeToPickerMap } from './type';
|
||||
import { getDateStrings } from './utils';
|
||||
import { DateSettingType, StaticDateSelectMode } from './type';
|
||||
import moment from 'moment';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
type Props = {
|
||||
initialValues: any;
|
||||
currentDateSettingType?: DateSettingType;
|
||||
selectMode?: StaticDateSelectMode;
|
||||
dateRangeTypeProps?: DateRangeType;
|
||||
onDateRangeChange: (value: string[], config: any) => void;
|
||||
};
|
||||
|
||||
const StaticDate: React.FC<Props> = ({
|
||||
initialValues,
|
||||
dateRangeTypeProps,
|
||||
currentDateSettingType = DateSettingType.STATIC,
|
||||
onDateRangeChange,
|
||||
}: any) => {
|
||||
const [latestDateMap, setLatestDateMap] = useState<any>({
|
||||
maxPartition: moment().format('YYYY-MM-DD'),
|
||||
});
|
||||
|
||||
const [staticFormData, setStaticFormData] = useState<any>(() => {
|
||||
return {
|
||||
dateSettingType: DateSettingType.STATIC,
|
||||
dateMode: initialValues?.dateMode || DateMode.RANGE,
|
||||
dateRangeType: initialValues?.dateRangeType || dateRangeTypeProps || DateRangeType.DAY,
|
||||
dateRange: initialValues?.dateRange || [],
|
||||
dateMultiple: initialValues?.dateMultiple || [],
|
||||
};
|
||||
});
|
||||
const [dateRangeValue, setDateRangeValue] = useState<any>([]);
|
||||
const [pickerType, setPickerType] = useState<PickerType>(() => {
|
||||
if (dateRangeTypeProps) {
|
||||
return DateRangeTypeToPickerMap[dateRangeTypeProps];
|
||||
}
|
||||
if (staticFormData.dateRangeType) {
|
||||
return DateRangeTypeToPickerMap[staticFormData.dateRangeType];
|
||||
}
|
||||
return DateRangePicker.DATE;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
initDateRangeValue();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentDateSettingType === DateSettingType.STATIC) {
|
||||
handleDateRangeTypePropsChange(dateRangeTypeProps);
|
||||
}
|
||||
setPickerType(DateRangeTypeToPickerMap[dateRangeTypeProps]);
|
||||
}, [dateRangeTypeProps, latestDateMap]);
|
||||
|
||||
const handleDateRangeTypePropsChange = async (dateRangeType: DateRangeType) => {
|
||||
if (!dateRangeType) {
|
||||
return;
|
||||
}
|
||||
setStaticFormData({
|
||||
...staticFormData,
|
||||
dateRangeType,
|
||||
});
|
||||
dateRangeChange(dateRangeValue, dateRangeType, staticFormData.dateMode);
|
||||
};
|
||||
const initDateRangeValue = () => {
|
||||
const initDateRange = initialValues?.dateRange || [];
|
||||
const [startDate, endDate] = initDateRange;
|
||||
const { maxPartition } = latestDateMap;
|
||||
let dateRangeMoment = [moment(), moment()];
|
||||
// 如果initialValues时间存在则按initialValues时间初始化
|
||||
if (startDate && endDate) {
|
||||
dateRangeMoment = [moment(startDate), moment(endDate)];
|
||||
}
|
||||
// dateRangeValue未被初始化且maxPartition存在,则按maxPartition初始化
|
||||
if (dateRangeValue.length === 0 && !(startDate && endDate) && maxPartition) {
|
||||
dateRangeMoment = [moment(maxPartition), moment(maxPartition)];
|
||||
}
|
||||
// 否则按当前时间初始化
|
||||
setDateRangeValue(dateRangeMoment);
|
||||
};
|
||||
|
||||
const updateStaticFormData = (formData: any) => {
|
||||
const mergeConfigTypeData = {
|
||||
...staticFormData,
|
||||
...formData,
|
||||
dateRangeStringDesc: '',
|
||||
};
|
||||
const { dateRange, dateMode } = mergeConfigTypeData;
|
||||
if (dateMode === DateMode.RANGE) {
|
||||
const [startDate, endDate] = dateRange;
|
||||
if (startDate && endDate) {
|
||||
mergeConfigTypeData.dateRangeStringDesc = `${startDate}至${endDate}`;
|
||||
mergeConfigTypeData.dateMultiple = [];
|
||||
}
|
||||
}
|
||||
if (dateMode === DateMode.LIST) {
|
||||
mergeConfigTypeData.dateRangeStringDesc = `日期多选`;
|
||||
mergeConfigTypeData.dateRange = [];
|
||||
}
|
||||
setStaticFormData(mergeConfigTypeData);
|
||||
onDateRangeChange(mergeConfigTypeData.dateRange, mergeConfigTypeData);
|
||||
};
|
||||
|
||||
const dateRangeChange = (
|
||||
dates: any,
|
||||
dateRangeType: DateRangeType,
|
||||
dateMode: DateMode,
|
||||
isDateRangeChange?: boolean,
|
||||
) => {
|
||||
if (!dates) {
|
||||
updateStaticFormData({ dateRange: [] });
|
||||
return;
|
||||
}
|
||||
const dateStrings = getDateStrings({
|
||||
dates,
|
||||
dateRangeType,
|
||||
latestDateMap,
|
||||
isDateRangeChange,
|
||||
});
|
||||
if (dateStrings[0] && dateStrings[1]) {
|
||||
setDateRangeValue([moment(dateStrings[0]), moment(dateStrings[1])]);
|
||||
updateStaticFormData({
|
||||
dateMode,
|
||||
dateRangeType,
|
||||
dateRange: dateStrings,
|
||||
});
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Space>
|
||||
<RangePicker
|
||||
style={{ paddingBottom: 5 }}
|
||||
value={dateRangeValue}
|
||||
onChange={(date) => {
|
||||
setDateRangeValue(date);
|
||||
const dateString = getDateStrings({
|
||||
dates: date,
|
||||
latestDateMap,
|
||||
isDateRangeChange: true,
|
||||
dateRangeType: dateRangeTypeProps || staticFormData.dateRangeType,
|
||||
});
|
||||
updateStaticFormData({
|
||||
dateRange: dateString,
|
||||
dateRangeType: dateRangeTypeProps || staticFormData.dateRangeType,
|
||||
});
|
||||
return;
|
||||
}}
|
||||
allowClear={true}
|
||||
picker={pickerType}
|
||||
/>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default StaticDate;
|
||||
@@ -0,0 +1,441 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { InfoCircleOutlined, CalendarOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { Input, Tooltip, Popover, Space, Button, Select, Row, Col, Tag } from 'antd';
|
||||
import styles from './style.less';
|
||||
import { DateMode, DateRangeType } from './type';
|
||||
import {
|
||||
LATEST_TEXT,
|
||||
DATE_RANGE_TYPE_ITEM_LIST,
|
||||
getWeekDateRangeString,
|
||||
getMonthDateRangeString,
|
||||
generatorDateRangesParams,
|
||||
getDynamicDateRangeStringByParams,
|
||||
} from './utils';
|
||||
import { DateSettingType, DateRangeParams, DynamicAdvancedConfigType } from './type';
|
||||
import { LatestDateMap } from './type';
|
||||
import StaticDate from './StaticDate';
|
||||
import DynamicDate from './DynamicDate';
|
||||
import moment from 'moment';
|
||||
import { ProCard } from '@ant-design/pro-card';
|
||||
|
||||
type Props = {
|
||||
disabledAdvanceSetting?: boolean;
|
||||
initialValues?: any;
|
||||
onDateRangeChange: (value: string[], from: any) => void;
|
||||
onDateRangeTypeChange?: (dateRangeType: DateRangeType) => void;
|
||||
};
|
||||
|
||||
const { CheckableTag } = Tag;
|
||||
const MDatePicker: React.FC<Props> = ({
|
||||
disabledAdvanceSetting,
|
||||
initialValues,
|
||||
onDateRangeChange,
|
||||
onDateRangeTypeChange,
|
||||
}: any) => {
|
||||
const getDynamicDefaultConfig = (dateRangeType: DateRangeType) => {
|
||||
const dynamicDefaultConfig = {
|
||||
shortCutId: 'last7Days',
|
||||
dateRangeType: DateRangeType.DAY,
|
||||
dynamicAdvancedConfigType: DynamicAdvancedConfigType.LATEST,
|
||||
dateRangeStringDesc: LATEST_TEXT,
|
||||
number: 7,
|
||||
dateSettingType: DateSettingType.DYNAMIC,
|
||||
};
|
||||
switch (dateRangeType) {
|
||||
case DateRangeType.DAY:
|
||||
return dynamicDefaultConfig;
|
||||
case DateRangeType.WEEK:
|
||||
return {
|
||||
shortCutId: 'last4Weeks',
|
||||
dateRangeType: DateRangeType.WEEK,
|
||||
dynamicAdvancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeStringDesc: '最近4周',
|
||||
dateSettingType: DateSettingType.DYNAMIC,
|
||||
includesCurrentPeriod: false,
|
||||
number: 4,
|
||||
periodType: 'WEEK',
|
||||
};
|
||||
case DateRangeType.MONTH:
|
||||
return {
|
||||
shortCutId: 'last6Months',
|
||||
dateRangeType: DateRangeType.MONTH,
|
||||
dynamicAdvancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeStringDesc: '最近6月',
|
||||
includesCurrentPeriod: false,
|
||||
number: 6,
|
||||
periodType: 'MONTH',
|
||||
dateSettingType: DateSettingType.DYNAMIC,
|
||||
};
|
||||
default:
|
||||
return dynamicDefaultConfig;
|
||||
}
|
||||
};
|
||||
const [dateRangeType, setDateRangeType] = useState<DateRangeType>(
|
||||
initialValues?.dynamicParams?.dateRangeType ||
|
||||
initialValues?.staticParams?.dateRangeType ||
|
||||
DateRangeType.DAY,
|
||||
);
|
||||
// const [pickerType, setPickerType] = useState<PickerType>(() => {
|
||||
// // if (staticFormData.dateRangeType) {
|
||||
// // return DateRangeTypeToPickerMap[staticFormData.dateRangeType];
|
||||
// // }
|
||||
// return DateRangePicker.DATE;
|
||||
// });
|
||||
|
||||
// const [dateRangeValue, setDateRangeValue] = useState<any>([]);
|
||||
|
||||
const staticDefaultConfig = {
|
||||
dateSettingType: DateSettingType.STATIC,
|
||||
dateMode: DateMode.RANGE,
|
||||
dateRangeType: DateRangeType.DAY,
|
||||
dateRange: [],
|
||||
dateMultiple: [],
|
||||
dateRangeStringDesc: '',
|
||||
};
|
||||
// const { getMaxPartitionData } = useModel('useMaxPartitionData');
|
||||
// const { globalViewId } = useModel('useViewsData');
|
||||
const [latestDateMap, setLatestDateMap] = useState<LatestDateMap>({
|
||||
maxPartition: moment().format('YYYY-MM-DD'),
|
||||
});
|
||||
const [dateRangesParams] = useState(() => {
|
||||
return initialValues ? generatorDateRangesParams(initialValues) : {};
|
||||
});
|
||||
const [confirmBtnClickState, setConfirmBtnClickState] = useState(false);
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
const [staticParams, setStaticParams] = useState(() => {
|
||||
return initialValues?.staticParams || {};
|
||||
});
|
||||
const [dynamicParams, setDynamicParams] = useState(() => {
|
||||
return initialValues?.dynamicParams || {};
|
||||
});
|
||||
|
||||
const [currentDateMode, setCurrentDateMode] = useState<DateMode>(
|
||||
initialValues?.staticParams?.dateMode || DateMode.RANGE,
|
||||
);
|
||||
|
||||
const [currentDateSettingType, setCurrentDateSettingType] = useState(
|
||||
initialValues?.dateSettingType || DateSettingType.STATIC,
|
||||
);
|
||||
const [currentDateRange, setCurrentDateRange] = useState<string[]>(() => {
|
||||
return dateRangesParams.dateRange || [];
|
||||
});
|
||||
const [selectedDateRangeString, setSelectedDateRangeString] = useState(() => {
|
||||
return getSelectedDateRangeString();
|
||||
});
|
||||
// const [advanceSettingCollapsed, setAdvanceSettingCollapsed] = useState(false);
|
||||
function getSelectedDateRangeString() {
|
||||
const [startTime, endTime] = currentDateRange;
|
||||
if (currentDateSettingType === DateSettingType.DYNAMIC) {
|
||||
if (startTime && endTime) {
|
||||
if (dateRangeType === DateRangeType.WEEK) {
|
||||
return getWeekDateRangeString(startTime, endTime);
|
||||
}
|
||||
if (dateRangeType === DateRangeType.MONTH) {
|
||||
return getMonthDateRangeString(startTime, endTime);
|
||||
}
|
||||
return `${startTime}至${endTime}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
if (currentDateSettingType === DateSettingType.STATIC) {
|
||||
const { dateMode, dateMultiple } = staticParams;
|
||||
if (dateMode === DateMode.RANGE) {
|
||||
if (startTime && endTime) {
|
||||
if (dateRangeType === DateRangeType.WEEK) {
|
||||
return getWeekDateRangeString(startTime, endTime);
|
||||
}
|
||||
if (dateRangeType === DateRangeType.MONTH) {
|
||||
return getMonthDateRangeString(startTime, endTime);
|
||||
}
|
||||
return `${startTime} 至 ${endTime}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
if (dateMode === DateMode.LIST) {
|
||||
return dateMultiple.join(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
setSelectedDateRangeString(getSelectedDateRangeString());
|
||||
}, [staticParams, dynamicParams, currentDateRange]);
|
||||
|
||||
const handleDateModeChange = (dateMode: DateMode) => {
|
||||
if (!dateMode) {
|
||||
return;
|
||||
}
|
||||
setCurrentDateMode(dateMode);
|
||||
if (dateMode === DateMode.LIST) {
|
||||
setDateRangeType(DateRangeType.DAY);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDateRangeChange = (value: string[] | boolean, config: any) => {
|
||||
const { dateRangeStringDesc, dateSettingType, dateMode } = config;
|
||||
handleDateModeChange(dateMode);
|
||||
setDateRangeStringShow(dateRangeStringDesc);
|
||||
setCurrentDateSettingType(dateSettingType);
|
||||
if (Array.isArray(value)) {
|
||||
setCurrentDateRange(value);
|
||||
}
|
||||
let dateParamsConfig: DateRangeParams = {
|
||||
latestDateMap,
|
||||
dateSettingType,
|
||||
dynamicParams: {},
|
||||
staticParams: {},
|
||||
};
|
||||
if (dateSettingType === DateSettingType.DYNAMIC) {
|
||||
dateParamsConfig = {
|
||||
...dateParamsConfig,
|
||||
dateSettingType,
|
||||
dynamicParams: config,
|
||||
staticParams: {},
|
||||
};
|
||||
}
|
||||
if (dateSettingType === DateSettingType.STATIC) {
|
||||
dateParamsConfig = {
|
||||
...dateParamsConfig,
|
||||
dateSettingType,
|
||||
dynamicParams: {},
|
||||
staticParams: config,
|
||||
};
|
||||
}
|
||||
setDynamicParams({ ...dateParamsConfig.dynamicParams });
|
||||
setStaticParams({ ...dateParamsConfig.staticParams });
|
||||
onDateRangeChange(value, dateParamsConfig);
|
||||
};
|
||||
const getDateRangeStringShow = (dateRange: string[]) => {
|
||||
if (currentDateSettingType === DateSettingType.DYNAMIC) {
|
||||
const { dateRangeStringDesc } = getDynamicDateRangeStringByParams(
|
||||
dynamicParams,
|
||||
dynamicParams.dynamicAdvancedConfigType,
|
||||
latestDateMap,
|
||||
);
|
||||
return dateRangeStringDesc;
|
||||
}
|
||||
if (currentDateSettingType === DateSettingType.STATIC) {
|
||||
const { dateMode } = staticParams;
|
||||
const [startTime, endTime] = currentDateRange || [];
|
||||
if (dateMode === DateMode.RANGE) {
|
||||
if (startTime && endTime) {
|
||||
return `${startTime} 至 ${endTime}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
if (dateMode === DateMode.LIST) {
|
||||
return '日期多选';
|
||||
}
|
||||
}
|
||||
|
||||
const [startTime, endTime] = dateRange || [];
|
||||
if (startTime && endTime) {
|
||||
return `${startTime} 至 ${endTime}`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const [dateRangeStringShow, setDateRangeStringShow] = useState(() => {
|
||||
return getDateRangeStringShow(dateRangesParams.dateRange);
|
||||
});
|
||||
|
||||
const initDefaultDynamicData = ({ latestDateMap }: any) => {
|
||||
if (!initialValues) {
|
||||
const defaultConfig = getDynamicDefaultConfig(dateRangeType);
|
||||
const { maxPartition } = latestDateMap;
|
||||
const dateRange: string[] = [maxPartition, maxPartition];
|
||||
const config = {
|
||||
...defaultConfig,
|
||||
dateRange,
|
||||
};
|
||||
handleDateRangeChange(dateRange, config);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initDefaultDynamicData({ latestDateMap });
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setConfirmBtnClickState(false);
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
useEffect(() => {
|
||||
const { dateRange } = dateRangesParams;
|
||||
setDateRangeStringShow(getDateRangeStringShow(dateRange));
|
||||
}, [dateRangesParams]);
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<ProCard
|
||||
className={styles.dateProCard}
|
||||
title={
|
||||
<Space>
|
||||
时间粒度
|
||||
{/* <Tooltip
|
||||
title={``}
|
||||
>
|
||||
<QuestionCircleOutlined />
|
||||
</Tooltip> */}
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div className={styles.dateShortCutSettingContent}>
|
||||
<Row>
|
||||
{DATE_RANGE_TYPE_ITEM_LIST.map((item: any) => {
|
||||
const { value, label, toolTips } = item;
|
||||
if (currentDateMode === DateMode.LIST && value !== DateRangeType.DAY) {
|
||||
// 在多选模式只允许选择天粒度
|
||||
return undefined;
|
||||
}
|
||||
return (
|
||||
<Col key={`row-col-${value}`}>
|
||||
<Tooltip title={toolTips}>
|
||||
<CheckableTag
|
||||
className={styles['ant-tag-checkable']}
|
||||
checked={dateRangeType === value}
|
||||
key={`row-col-tag-${value}`}
|
||||
onChange={() => {
|
||||
setDateRangeType(value);
|
||||
onDateRangeTypeChange?.(value);
|
||||
}}
|
||||
>
|
||||
<div className={styles['tag-value-box']}>{label}</div>
|
||||
</CheckableTag>
|
||||
</Tooltip>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
</ProCard>
|
||||
|
||||
<ProCard
|
||||
className={styles.dateProCard}
|
||||
title={'快捷选项'}
|
||||
// title={`动态时间${
|
||||
// currentDateSettingType === DateSettingType.DYNAMIC ? '(当前选中)' : ''
|
||||
// }`}
|
||||
// extra="2019年9月28日"
|
||||
>
|
||||
<DynamicDate
|
||||
disabledAdvanceSetting={disabledAdvanceSetting}
|
||||
initialValues={dynamicParams}
|
||||
dateRangeTypeProps={dateRangeType}
|
||||
submitFormDataState={confirmBtnClickState}
|
||||
onDateRangeChange={handleDateRangeChange}
|
||||
onDateRangeStringAndDescChange={({ dateRangeString }) => {
|
||||
setCurrentDateRange(dateRangeString);
|
||||
}}
|
||||
onShortCutClick={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
/>
|
||||
</ProCard>
|
||||
|
||||
<ProCard
|
||||
className={styles.dateProCard}
|
||||
title={
|
||||
<Space>
|
||||
静态时间
|
||||
{/* <Tooltip
|
||||
title={``}
|
||||
>
|
||||
<QuestionCircleOutlined />
|
||||
</Tooltip> */}
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<StaticDate
|
||||
currentDateSettingType={currentDateSettingType}
|
||||
initialValues={staticParams}
|
||||
dateRangeTypeProps={dateRangeType}
|
||||
onDateRangeChange={handleDateRangeChange}
|
||||
/>
|
||||
</ProCard>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
borderTop: '1px solid #eee',
|
||||
paddingTop: '10px',
|
||||
}}
|
||||
>
|
||||
<Space style={{ fontSize: 12, marginRight: 20 }}>
|
||||
<div style={{ width: 60 }}>已选时间:</div>
|
||||
<div>{selectedDateRangeString}</div>
|
||||
</Space>
|
||||
|
||||
<Space style={{ marginLeft: 'auto' }}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
if (currentDateSettingType === DateSettingType.DYNAMIC) {
|
||||
setConfirmBtnClickState(true);
|
||||
}
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
确 认
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
取 消
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<Space direction="vertical">
|
||||
<Popover
|
||||
content={content}
|
||||
// destroyTooltipOnHide={true}
|
||||
// title="Title"
|
||||
open={visible}
|
||||
trigger="click"
|
||||
onOpenChange={(newVisible) => {
|
||||
setVisible(newVisible);
|
||||
if (!newVisible) {
|
||||
// 当界面关闭时,如果是动态模式需检测用户所确认选中数据和当前面板显示数据(切换了时间粒度,但是没有保存配置数据)
|
||||
// 是否为同一时间粒度,如果不是,则需将当前时间粒度调整为动态时间组件所保存的时间粒度
|
||||
if (currentDateSettingType === DateSettingType.DYNAMIC) {
|
||||
const paramsDateRangeType = dynamicParams.dateRangeType;
|
||||
if (paramsDateRangeType && paramsDateRangeType !== dateRangeType) {
|
||||
setDateRangeType(paramsDateRangeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
overlayClassName={styles.popverOverlayContent}
|
||||
placement="left"
|
||||
>
|
||||
<Input
|
||||
className={styles.dateTimeShowInput}
|
||||
value={dateRangeStringShow}
|
||||
placeholder="请选择日期时间"
|
||||
prefix={<CalendarOutlined />}
|
||||
readOnly
|
||||
style={{ width: 280 }}
|
||||
suffix={
|
||||
<Tooltip title={`${selectedDateRangeString}`}>
|
||||
<InfoCircleOutlined style={{}} />
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
</Popover>
|
||||
{!(
|
||||
currentDateSettingType === DateSettingType.STATIC &&
|
||||
currentDateMode === DateMode.RANGE &&
|
||||
dateRangeType === DateRangeType.DAY
|
||||
) && <div style={{ color: '#0e73ff' }}>当前时间: {selectedDateRangeString}</div>}
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default MDatePicker;
|
||||
@@ -0,0 +1,84 @@
|
||||
.popverOverlayContent {
|
||||
padding-top: 0;
|
||||
width: 440px;
|
||||
:global {
|
||||
.ant-popover-content {
|
||||
.ant-popover-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.dateProCard {
|
||||
:global {
|
||||
.ant-pro-card-header {
|
||||
padding: 10px;
|
||||
}
|
||||
.ant-pro-card-body{
|
||||
padding:10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dateTimeShowInput {
|
||||
:global {
|
||||
.ant-input{
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.advancedSettingItemText {
|
||||
width: 40px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dateAdvancedSettingContent {
|
||||
:global {
|
||||
.ant-input{
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dateShortCutSettingContent {
|
||||
:global {
|
||||
.ant-tag-checkable:active, .ant-tag-checkable-checked{
|
||||
background-color: #e6effc;
|
||||
color: #0e73ff;
|
||||
}
|
||||
}
|
||||
.ant-tag-checkable {
|
||||
position: relative;
|
||||
width: 120px;
|
||||
height: 28px;
|
||||
margin-right: 4px;
|
||||
border: none;
|
||||
// margin-right: 0;
|
||||
}
|
||||
|
||||
.tag-value-box {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 3px;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
background-color: #f7f9fc;
|
||||
// background-color: #296df3;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #e6effc;
|
||||
color: #0e73ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
export enum DynamicAdvancedConfigType {
|
||||
LATEST = 'latest',
|
||||
// CUSTOM = 'custom',
|
||||
LAST = 'last',
|
||||
HISTORY = 'history',
|
||||
FROM_DATE_PERIOD = 'fromDatePeriod',
|
||||
FROM_DATE = 'fromDate',
|
||||
}
|
||||
|
||||
export enum DatePeriodType {
|
||||
DAY = 'DAYS',
|
||||
WEEK = 'WEEK',
|
||||
MONTH = 'MONTH',
|
||||
YEAR = 'YEAR',
|
||||
}
|
||||
|
||||
export enum DateSettingType {
|
||||
STATIC = 'STATIC',
|
||||
DYNAMIC = 'DYNAMIC',
|
||||
}
|
||||
|
||||
export enum PerDatePeriodType {
|
||||
PERDAY = 'PERDAY',
|
||||
PERWEEK = 'PERWEEK',
|
||||
PERMONTH = 'PERMONTH',
|
||||
PERYEAR = 'PERYEAR',
|
||||
}
|
||||
|
||||
export type DateRangeParams = {
|
||||
dateSettingType: DateSettingType;
|
||||
dynamicParams: any;
|
||||
staticParams: any;
|
||||
latestDateMap?: { maxPartition: string };
|
||||
};
|
||||
|
||||
export enum StaticDateSelectMode {
|
||||
DATE_RANGE = 'dateRange',
|
||||
DATE_MODE = 'dateMode',
|
||||
}
|
||||
|
||||
export enum DateRangeType {
|
||||
DAY = 'DAY',
|
||||
WEEK = 'WEEK',
|
||||
MONTH = 'MONTH',
|
||||
}
|
||||
|
||||
export enum DateRangePicker {
|
||||
DATE = 'date',
|
||||
WEEK = 'week',
|
||||
MONTH = 'month',
|
||||
}
|
||||
|
||||
export const DateRangeTypeToPickerMap = {
|
||||
[DateRangeType.DAY]: DateRangePicker.DATE,
|
||||
[DateRangeType.WEEK]: DateRangePicker.WEEK,
|
||||
[DateRangeType.MONTH]: DateRangePicker.MONTH,
|
||||
};
|
||||
|
||||
export type LatestDateMap = {
|
||||
maxPartition: string;
|
||||
};
|
||||
|
||||
export enum DateMode {
|
||||
RANGE = 1,
|
||||
LIST = 2,
|
||||
ES = 4,
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
import moment from 'moment';
|
||||
import type { Moment } from 'moment';
|
||||
import { DateMode, DateRangeType, DateRangePicker, DateRangeTypeToPickerMap } from './type';
|
||||
import {
|
||||
DatePeriodType,
|
||||
PerDatePeriodType,
|
||||
DateSettingType,
|
||||
DynamicAdvancedConfigType,
|
||||
DateRangeParams,
|
||||
} from './type';
|
||||
import { LatestDateMap } from './type';
|
||||
|
||||
export const dateRangeTypeExchangeDatePeriodTypeMap = {
|
||||
[DateRangeType.DAY]: DatePeriodType.DAY,
|
||||
[DateRangeType.WEEK]: DatePeriodType.WEEK,
|
||||
[DateRangeType.MONTH]: DatePeriodType.MONTH,
|
||||
};
|
||||
|
||||
export const datePeriodTypeMap = {
|
||||
[DatePeriodType.DAY]: '天',
|
||||
[DatePeriodType.WEEK]: '周',
|
||||
[DatePeriodType.MONTH]: '月',
|
||||
[DatePeriodType.YEAR]: '年',
|
||||
};
|
||||
export const datePeriodTypeWordingMap = {
|
||||
[DatePeriodType.DAY]: '当天',
|
||||
[DatePeriodType.WEEK]: '本周',
|
||||
[DatePeriodType.MONTH]: '本月',
|
||||
[DatePeriodType.YEAR]: '今年',
|
||||
};
|
||||
|
||||
export const perDatePeriodTypeMap = {
|
||||
[PerDatePeriodType.PERDAY]: '每日',
|
||||
[PerDatePeriodType.PERWEEK]: '每周(周一)',
|
||||
[PerDatePeriodType.PERMONTH]: '每月(01日)',
|
||||
[PerDatePeriodType.PERYEAR]: '每年(01月01日)',
|
||||
};
|
||||
|
||||
export const DATE_RANGE_TYPE_ITEM_LIST = [
|
||||
{
|
||||
label: '天',
|
||||
value: DateRangeType.DAY,
|
||||
toolTips: '展示每天数据',
|
||||
},
|
||||
{
|
||||
label: '周',
|
||||
value: DateRangeType.WEEK,
|
||||
toolTips: '仅展示每周日数据',
|
||||
},
|
||||
{
|
||||
label: '月',
|
||||
value: DateRangeType.MONTH,
|
||||
toolTips: '仅展示每月最后一天数据',
|
||||
},
|
||||
];
|
||||
|
||||
export const LATEST_TEXT = '最近1天';
|
||||
|
||||
export const SHORT_CUT_ITEM_LIST = [
|
||||
{
|
||||
id: 'last7Days',
|
||||
text: '最近7天',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.DAY,
|
||||
initData: {
|
||||
shortCutId: 'last7Days',
|
||||
number: 7,
|
||||
periodType: DatePeriodType.DAY,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last15Days',
|
||||
text: '最近15天',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.DAY,
|
||||
initData: {
|
||||
shortCutId: 'last15Days',
|
||||
number: 15,
|
||||
periodType: DatePeriodType.DAY,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last30Days',
|
||||
text: '最近30天',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.DAY,
|
||||
initData: {
|
||||
shortCutId: 'last30Days',
|
||||
number: 30,
|
||||
periodType: DatePeriodType.DAY,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last4Weeks',
|
||||
text: '最近4周',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.WEEK,
|
||||
initData: {
|
||||
shortCutId: 'last4Weeks',
|
||||
number: 4,
|
||||
periodType: DatePeriodType.WEEK,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last8Weeks',
|
||||
text: '最近8周',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.WEEK,
|
||||
initData: {
|
||||
shortCutId: 'last8Weeks',
|
||||
number: 8,
|
||||
periodType: DatePeriodType.WEEK,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last12Weeks',
|
||||
text: '最近12周',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.WEEK,
|
||||
initData: {
|
||||
shortCutId: 'last12Weeks',
|
||||
number: 12,
|
||||
periodType: DatePeriodType.WEEK,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last6Months',
|
||||
text: '最近6个月',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.MONTH,
|
||||
initData: {
|
||||
shortCutId: 'last6Months',
|
||||
number: 6,
|
||||
periodType: DatePeriodType.MONTH,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'last12Months',
|
||||
text: '最近12个月',
|
||||
advancedConfigType: DynamicAdvancedConfigType.LAST,
|
||||
dateRangeType: DateRangeType.MONTH,
|
||||
initData: {
|
||||
shortCutId: 'last12Months',
|
||||
number: 12,
|
||||
periodType: DatePeriodType.MONTH,
|
||||
includesCurrentPeriod: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const computedSubtractDateRange = (number: number, includesCurrentPeriod: boolean) => {
|
||||
const startDateNumber = includesCurrentPeriod ? number - 1 : number;
|
||||
const endDateNumber = includesCurrentPeriod ? 0 : 1;
|
||||
return { startDateNumber, endDateNumber };
|
||||
};
|
||||
|
||||
const getLastTypeDateRange = ({
|
||||
number,
|
||||
periodType,
|
||||
latestDateMap,
|
||||
includesCurrentPeriod = false, // 是否包含当前周期 今天/本周/本月/今年
|
||||
}: {
|
||||
number: number;
|
||||
periodType: DatePeriodType;
|
||||
latestDateMap: LatestDateMap;
|
||||
includesCurrentPeriod?: boolean;
|
||||
}) => {
|
||||
const { startDateNumber, endDateNumber } = computedSubtractDateRange(
|
||||
number,
|
||||
includesCurrentPeriod,
|
||||
);
|
||||
|
||||
switch (periodType) {
|
||||
case DatePeriodType.DAY: {
|
||||
// 如果选取了包含今天,则放弃使用标签最新更新时间;
|
||||
const periodTypeMoment = includesCurrentPeriod
|
||||
? undefined
|
||||
: latestDateMap?.maxPartition || undefined;
|
||||
let subtractData = {
|
||||
startDateNumber,
|
||||
endDateNumber,
|
||||
};
|
||||
if (periodTypeMoment) {
|
||||
// 在使用标签最新更新时间时,需包含最新的时间日期,并重置计算时间区段
|
||||
subtractData = computedSubtractDateRange(number, true);
|
||||
}
|
||||
return [
|
||||
moment(periodTypeMoment).subtract(subtractData.startDateNumber, 'days').startOf('days'),
|
||||
moment(periodTypeMoment).subtract(subtractData.endDateNumber, 'days').endOf('days'),
|
||||
];
|
||||
}
|
||||
case DatePeriodType.WEEK: {
|
||||
// 如果选取了包含今天,则放弃使用标签最新更新时间;
|
||||
const periodTypeMoment = includesCurrentPeriod
|
||||
? undefined
|
||||
: latestDateMap?.maxPartition || undefined;
|
||||
let subtractData = {
|
||||
startDateNumber,
|
||||
endDateNumber,
|
||||
};
|
||||
if (periodTypeMoment) {
|
||||
// 在使用标签最新更新时间时,需包含最新的时间日期,并重置计算时间区段
|
||||
subtractData = computedSubtractDateRange(number, true);
|
||||
}
|
||||
return [
|
||||
moment(periodTypeMoment).subtract(subtractData.startDateNumber, 'week').startOf('week'),
|
||||
moment(periodTypeMoment).subtract(subtractData.endDateNumber, 'week').endOf('week'),
|
||||
];
|
||||
}
|
||||
case DatePeriodType.MONTH: {
|
||||
// 如果选取了包含今天,则放弃使用标签最新更新时间;
|
||||
const periodTypeMoment = includesCurrentPeriod
|
||||
? undefined
|
||||
: latestDateMap?.maxPartition || undefined;
|
||||
let subtractData = {
|
||||
startDateNumber,
|
||||
endDateNumber,
|
||||
};
|
||||
if (periodTypeMoment) {
|
||||
// 在使用标签最新更新时间时,需包含最新的时间日期,并重置计算时间区段
|
||||
subtractData = computedSubtractDateRange(number, true);
|
||||
}
|
||||
return [
|
||||
moment(periodTypeMoment).subtract(subtractData.startDateNumber, 'month').startOf('month'),
|
||||
moment(periodTypeMoment).subtract(subtractData.endDateNumber, 'month').endOf('month'),
|
||||
];
|
||||
}
|
||||
case DatePeriodType.YEAR:
|
||||
return [
|
||||
moment().subtract(startDateNumber, 'year').startOf('year'),
|
||||
moment().subtract(endDateNumber, 'year').endOf('year'),
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const getHistoryTypeDateRange = ({
|
||||
number,
|
||||
periodType,
|
||||
}: {
|
||||
number: number;
|
||||
periodType: DatePeriodType;
|
||||
}) => {
|
||||
const dateNumber = number;
|
||||
switch (periodType) {
|
||||
case DatePeriodType.DAY:
|
||||
return [
|
||||
moment().subtract(dateNumber, 'days').startOf('days'),
|
||||
moment().subtract(dateNumber, 'days').endOf('days'),
|
||||
];
|
||||
case DatePeriodType.WEEK:
|
||||
return [
|
||||
moment().subtract(dateNumber, 'week').startOf('week'),
|
||||
moment().subtract(dateNumber, 'week').endOf('week'),
|
||||
];
|
||||
case DatePeriodType.MONTH:
|
||||
return [
|
||||
moment().subtract(dateNumber, 'month').startOf('month'),
|
||||
moment().subtract(dateNumber, 'month').endOf('month'),
|
||||
];
|
||||
case DatePeriodType.YEAR:
|
||||
return [
|
||||
moment().subtract(dateNumber, 'year').startOf('year'),
|
||||
moment().subtract(dateNumber, 'year').endOf('year'),
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
const getFromDatePeriodTypeDateRange = ({
|
||||
perPeriodType,
|
||||
}: {
|
||||
perPeriodType: PerDatePeriodType;
|
||||
}) => {
|
||||
switch (perPeriodType) {
|
||||
case PerDatePeriodType.PERDAY:
|
||||
return [moment().startOf('days'), moment()];
|
||||
case PerDatePeriodType.PERWEEK:
|
||||
return [moment().startOf('week'), moment()];
|
||||
case PerDatePeriodType.PERMONTH:
|
||||
return [moment().startOf('month'), moment()];
|
||||
case PerDatePeriodType.PERYEAR:
|
||||
return [moment().startOf('year'), moment()];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
const getFromDateTypeDateRange = ({ date }: { date: string }) => {
|
||||
return [moment(date), moment()];
|
||||
};
|
||||
|
||||
export const getLastestTypeDateRange = (latestDate: string) => {
|
||||
if (latestDate) {
|
||||
return [moment(latestDate), moment(latestDate)];
|
||||
}
|
||||
console.warn('最新标签更新日期不存在');
|
||||
return [moment().subtract(1, 'week'), moment().subtract(1, 'week')];
|
||||
};
|
||||
|
||||
export const shortCutDateRangeMap = {
|
||||
// latest: (latestDate?: string) => {
|
||||
// if (latestDate) {
|
||||
// return [moment(latestDate), moment(latestDate)];
|
||||
// }
|
||||
// return [moment(), moment()];
|
||||
// },
|
||||
// yesterday: () => {
|
||||
// return [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
|
||||
// },
|
||||
// last3Days: () => {
|
||||
// return [moment().subtract(3, 'days'), moment()];
|
||||
// },
|
||||
// last7Days: () => {
|
||||
// return [moment().subtract(7, 'days'), moment()];
|
||||
// },
|
||||
// last30Days: () => {
|
||||
// return [moment().subtract(30, 'days'), moment()];
|
||||
// },
|
||||
// today: () => {
|
||||
// return [moment(), moment()];
|
||||
// },
|
||||
// thisWeek: () => {
|
||||
// return [moment().startOf('week'), moment().endOf('week')];
|
||||
// },
|
||||
// thisMonth: () => {
|
||||
// return [moment().startOf('month'), moment().endOf('month')];
|
||||
// },
|
||||
// thisYear: () => {
|
||||
// return [moment().startOf('year'), moment().endOf('year')];
|
||||
// },
|
||||
[DynamicAdvancedConfigType.LATEST]: getLastestTypeDateRange,
|
||||
[DynamicAdvancedConfigType.LAST]: getLastTypeDateRange,
|
||||
[DynamicAdvancedConfigType.HISTORY]: getHistoryTypeDateRange,
|
||||
[DynamicAdvancedConfigType.FROM_DATE_PERIOD]: getFromDatePeriodTypeDateRange,
|
||||
[DynamicAdvancedConfigType.FROM_DATE]: getFromDateTypeDateRange,
|
||||
};
|
||||
|
||||
export const formatDateRangeString = (dateRange: Moment[]) => {
|
||||
if (dateRange && Array.isArray(dateRange)) {
|
||||
return dateRange.map((item) => {
|
||||
return item?.format?.('YYYY-MM-DD') || '';
|
||||
});
|
||||
}
|
||||
return dateRange;
|
||||
};
|
||||
|
||||
// 动态时间配置转换为静态时间参数进行请求
|
||||
export const parseDynamicDateParamsToStaticDateParams = (
|
||||
dateParams: any,
|
||||
latestDateMap: LatestDateMap,
|
||||
) => {
|
||||
const {
|
||||
dynamicAdvancedConfigType,
|
||||
number,
|
||||
periodType,
|
||||
includesCurrentPeriod,
|
||||
perPeriodType,
|
||||
date,
|
||||
dateRangeType,
|
||||
} = dateParams;
|
||||
const staticParams = {
|
||||
dateMode: DateMode.RANGE,
|
||||
dateRangeType: dateRangeType || DateRangeType.DAY,
|
||||
};
|
||||
let dateMomentRange: Moment[] = [];
|
||||
switch (dynamicAdvancedConfigType) {
|
||||
case DynamicAdvancedConfigType.LATEST: {
|
||||
const latestDate = latestDateMap?.maxPartition;
|
||||
dateMomentRange = getLastestTypeDateRange(latestDate);
|
||||
break;
|
||||
}
|
||||
case DynamicAdvancedConfigType.LAST: {
|
||||
dateMomentRange = getLastTypeDateRange({
|
||||
number,
|
||||
periodType,
|
||||
latestDateMap,
|
||||
includesCurrentPeriod,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case DynamicAdvancedConfigType.HISTORY: {
|
||||
dateMomentRange = getHistoryTypeDateRange({ number, periodType });
|
||||
break;
|
||||
}
|
||||
case DynamicAdvancedConfigType.FROM_DATE_PERIOD:
|
||||
dateMomentRange = getFromDatePeriodTypeDateRange({ perPeriodType });
|
||||
break;
|
||||
case DynamicAdvancedConfigType.FROM_DATE:
|
||||
dateMomentRange = getFromDateTypeDateRange({ date });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {
|
||||
...staticParams,
|
||||
dateRange: formatDateRangeString(dateMomentRange),
|
||||
};
|
||||
};
|
||||
|
||||
export const generatorDateRangesParams = (dateRangeParams: DateRangeParams) => {
|
||||
const {
|
||||
dateSettingType,
|
||||
latestDateMap = {},
|
||||
dynamicParams = {},
|
||||
staticParams = {},
|
||||
} = dateRangeParams;
|
||||
if (dateSettingType === DateSettingType.DYNAMIC) {
|
||||
return parseDynamicDateParamsToStaticDateParams(dynamicParams, latestDateMap as any);
|
||||
}
|
||||
return staticParams;
|
||||
};
|
||||
|
||||
export const getDynamicDateRangeStringByParams = (
|
||||
params: any,
|
||||
type: DynamicAdvancedConfigType,
|
||||
latestDateMap: LatestDateMap,
|
||||
) => {
|
||||
const { number, periodType, includesCurrentPeriod, perPeriodType, date } = params;
|
||||
let dateRangeMoment: any[] = [];
|
||||
let dateRangeStringDesc = '';
|
||||
switch (type) {
|
||||
case DynamicAdvancedConfigType.LATEST: {
|
||||
const latestDate = latestDateMap.maxPartition;
|
||||
dateRangeStringDesc = LATEST_TEXT;
|
||||
dateRangeMoment = shortCutDateRangeMap[DynamicAdvancedConfigType.LATEST](latestDate);
|
||||
break;
|
||||
}
|
||||
|
||||
case DynamicAdvancedConfigType.LAST:
|
||||
dateRangeMoment = shortCutDateRangeMap[DynamicAdvancedConfigType.LAST]({
|
||||
number,
|
||||
periodType,
|
||||
latestDateMap,
|
||||
includesCurrentPeriod,
|
||||
});
|
||||
dateRangeStringDesc =
|
||||
`最近${number}${datePeriodTypeMap[periodType]}` +
|
||||
`${includesCurrentPeriod ? `(包含${datePeriodTypeWordingMap[periodType]})` : ''}`;
|
||||
break;
|
||||
case DynamicAdvancedConfigType.HISTORY:
|
||||
dateRangeMoment = shortCutDateRangeMap[DynamicAdvancedConfigType.HISTORY]({
|
||||
number,
|
||||
periodType,
|
||||
});
|
||||
dateRangeStringDesc = `过去第${number}${datePeriodTypeMap[periodType]}`;
|
||||
break;
|
||||
case DynamicAdvancedConfigType.FROM_DATE_PERIOD:
|
||||
dateRangeMoment = shortCutDateRangeMap[DynamicAdvancedConfigType.FROM_DATE_PERIOD]({
|
||||
perPeriodType,
|
||||
});
|
||||
dateRangeStringDesc = `自从${perDatePeriodTypeMap[perPeriodType]}00:00:00至此刻`;
|
||||
break;
|
||||
case DynamicAdvancedConfigType.FROM_DATE:
|
||||
dateRangeMoment = shortCutDateRangeMap[DynamicAdvancedConfigType.FROM_DATE]({
|
||||
date,
|
||||
});
|
||||
dateRangeStringDesc = `${date}至此刻`;
|
||||
break;
|
||||
default:
|
||||
dateRangeMoment = [];
|
||||
dateRangeStringDesc = '';
|
||||
}
|
||||
return {
|
||||
dateRangeString: formatDateRangeString(dateRangeMoment),
|
||||
dateRangeStringDesc,
|
||||
};
|
||||
};
|
||||
|
||||
export function getDateStrings({
|
||||
dates,
|
||||
dateRangeType,
|
||||
latestDateMap,
|
||||
isDateRangeChange,
|
||||
}: {
|
||||
dates: any;
|
||||
dateRangeType: DateRangeType;
|
||||
latestDateMap?: LatestDateMap;
|
||||
isDateRangeChange?: boolean;
|
||||
}) {
|
||||
let dateRange = dates;
|
||||
if (!Array.isArray(dateRange)) {
|
||||
dateRange = [dateRange];
|
||||
}
|
||||
const picker = DateRangeTypeToPickerMap[dateRangeType];
|
||||
const dateStrings = dateRange.map((date: Moment, index: number) => {
|
||||
switch (picker) {
|
||||
case DateRangePicker.DATE:
|
||||
if (latestDateMap?.maxPartition && !isDateRangeChange) {
|
||||
return latestDateMap.maxPartition;
|
||||
}
|
||||
return date.format('YYYY-MM-DD');
|
||||
case DateRangePicker.WEEK:
|
||||
if (index === 0) {
|
||||
// 仅当dateRangeType进行切换时,即天/周/月被转换时对时间进行当前时间周期-1操作
|
||||
return date
|
||||
.startOf('week')
|
||||
.subtract(!isDateRangeChange ? 1 : 0, 'week')
|
||||
.format('YYYY-MM-DD');
|
||||
}
|
||||
return date
|
||||
.endOf('week')
|
||||
.subtract(!isDateRangeChange ? 1 : 0, 'week')
|
||||
.format('YYYY-MM-DD');
|
||||
case DateRangePicker.MONTH:
|
||||
if (index === 0) {
|
||||
return date
|
||||
.startOf('month')
|
||||
.subtract(!isDateRangeChange ? 1 : 0, 'month')
|
||||
.format('YYYY-MM-DD');
|
||||
}
|
||||
return date
|
||||
.endOf('month')
|
||||
.subtract(!isDateRangeChange ? 1 : 0, 'month')
|
||||
.format('YYYY-MM-DD');
|
||||
default:
|
||||
if (latestDateMap?.maxPartition && !isDateRangeChange) {
|
||||
return latestDateMap?.maxPartition;
|
||||
}
|
||||
return date.format('YYYY-MM-DD');
|
||||
}
|
||||
});
|
||||
return dateStrings;
|
||||
}
|
||||
|
||||
export const getWeekDateRangeString = (startTime: string, endTime: string) => {
|
||||
const startTimeWeekNumber = moment(startTime).format('w');
|
||||
const endTimeWeekNumber = moment(endTime).format('w');
|
||||
return `${startTime}(${startTimeWeekNumber}周)至${endTime}(${endTimeWeekNumber}周)`;
|
||||
};
|
||||
|
||||
export const getMonthDateRangeString = (startTime: string, endTime: string) => {
|
||||
const startTimeMonth = moment(startTime).format('YYYY-MM');
|
||||
const endTimeMonth = moment(endTime).format('YYYY-MM');
|
||||
return `${startTimeMonth}至${endTimeMonth}`;
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
.standardFormRow {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 24px;
|
||||
// padding-bottom: 16px;
|
||||
// border-bottom: 1px dashed @border-color-split;
|
||||
:global {
|
||||
@@ -28,14 +28,14 @@
|
||||
}
|
||||
.label {
|
||||
flex: 0 0 auto;
|
||||
margin-right: 24px;
|
||||
margin-right: 12px;
|
||||
color: @heading-color;
|
||||
font-size: @font-size-base;
|
||||
text-align: left;
|
||||
& > span {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
// width: 80px;
|
||||
height: 32px;
|
||||
// height: 20px;
|
||||
color: #999;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.tagSelect {
|
||||
position: relative;
|
||||
max-height: 32px;
|
||||
margin-left: -8px;
|
||||
// margin-left: -8px;
|
||||
overflow: hidden;
|
||||
line-height: 32px;
|
||||
transition: all 0.3s;
|
||||
|
||||
Reference in New Issue
Block a user