form-driver 0.4.25 → 0.4.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/m3.js +1 -1
- package/es/m3.js +158 -74
- package/lib/m3.js +158 -75
- package/package.json +1 -1
- package/src/ui/editor/basic/ARangePicker.tsx +323 -124
- package/types/ui/editor/basic/ARangePicker.d.ts +4 -3
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import React, { Component, RefObject } from "react";
|
|
2
2
|
import { DatePicker } from "antd";
|
|
3
|
-
import zhCN from
|
|
3
|
+
import zhCN from "antd/lib/date-picker/locale/zh_CN";
|
|
4
4
|
import moment from "moment";
|
|
5
5
|
import { DatePicker as DatePickerM } from "antd-mobile";
|
|
6
6
|
import { Button as AntButton } from "antd";
|
|
7
|
-
import ReactDOM from "react-dom";
|
|
8
7
|
import { RangePickerProps } from "antd/lib/date-picker";
|
|
9
8
|
import _ from "lodash";
|
|
10
|
-
import { Viewer, ViewerState } from
|
|
11
|
-
import { MUtil } from
|
|
9
|
+
import { Viewer, ViewerState } from "../../BaseViewer";
|
|
10
|
+
import { MUtil } from "../../../framework/MUtil";
|
|
12
11
|
import { MProp } from "../../../framework/Schema";
|
|
13
|
-
import { MDateRangeType } from
|
|
14
|
-
import { assembly } from
|
|
12
|
+
import { MDateRangeType } from "../../../types/MDateRangeType";
|
|
13
|
+
import { assembly } from "../../../framework/Assembly";
|
|
15
14
|
|
|
16
15
|
export type ARangePickerData = [
|
|
17
16
|
// 开始时间
|
|
@@ -19,25 +18,31 @@ export type ARangePickerData = [
|
|
|
19
18
|
// 结束时间
|
|
20
19
|
string | null | undefined,
|
|
21
20
|
// 是否至今,如果true,结束时间是无效的
|
|
22
|
-
boolean | null | undefined
|
|
21
|
+
boolean | null | undefined,
|
|
23
22
|
];
|
|
24
23
|
|
|
25
24
|
type AntData = [moment.Moment | null, moment.Moment | null];
|
|
26
25
|
|
|
27
26
|
interface State extends ViewerState {
|
|
28
27
|
mobileDlg: boolean;
|
|
29
|
-
mobileStep:
|
|
28
|
+
mobileStep: "start" | "end";
|
|
30
29
|
mobileStartDate?: Date;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
export class ARangePicker extends Viewer<State> {
|
|
34
|
-
_pickerRef: RefObject<
|
|
33
|
+
_pickerRef: RefObject<HTMLDivElement> = React.createRef();
|
|
35
34
|
_onCalendarChangeValue?: AntData | null;
|
|
35
|
+
_panelClickedDate?: moment.Moment | null; // showTime 模式下通过面板点击事件捕获的日期
|
|
36
36
|
_startConfirmed = false; // 标记开始日期是否已确认,用于区分 onClose 是取消还是确认后的自动触发
|
|
37
37
|
|
|
38
38
|
constructor(p: MProp) {
|
|
39
39
|
super(p);
|
|
40
|
-
this.state = {
|
|
40
|
+
this.state = {
|
|
41
|
+
ctrlVersion: 1,
|
|
42
|
+
noValidate: false,
|
|
43
|
+
mobileDlg: false,
|
|
44
|
+
mobileStep: "start",
|
|
45
|
+
};
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
componentDidUpdate() {
|
|
@@ -50,21 +55,27 @@ export class ARangePicker extends Viewer<State> {
|
|
|
50
55
|
|
|
51
56
|
_patchTillnow() {
|
|
52
57
|
const v = super.getValue();
|
|
53
|
-
if (_.get(v, "[2]")) {
|
|
54
|
-
|
|
58
|
+
if (_.get(v, "[2]")) {
|
|
59
|
+
// tillnow
|
|
60
|
+
const dom = this._pickerRef.current;
|
|
55
61
|
if (dom) {
|
|
56
|
-
// @ts-ignore
|
|
57
62
|
let r = dom.querySelector(":nth-child(3)");
|
|
58
|
-
r
|
|
63
|
+
if (r) {
|
|
64
|
+
r.innerHTML =
|
|
65
|
+
"<input readonly disabled size='12' autocomplete='off' value='至今' style='color: black'>";
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
68
|
}
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
/**
|
|
64
72
|
* RangePicker的数据转换成json上的数据类型
|
|
65
|
-
* @param r
|
|
73
|
+
* @param r
|
|
66
74
|
*/
|
|
67
|
-
_rangePicker2Data(
|
|
75
|
+
_rangePicker2Data(
|
|
76
|
+
v: AntData | null | undefined,
|
|
77
|
+
tillNow: boolean,
|
|
78
|
+
): ARangePickerData | undefined {
|
|
68
79
|
if (!v) {
|
|
69
80
|
return undefined;
|
|
70
81
|
}
|
|
@@ -74,12 +85,13 @@ export class ARangePicker extends Viewer<State> {
|
|
|
74
85
|
|
|
75
86
|
/**
|
|
76
87
|
* json上的数据转换成RangePicker的数据
|
|
77
|
-
* @param d
|
|
88
|
+
* @param d
|
|
78
89
|
*/
|
|
79
90
|
_data2rangePicker(d: ARangePickerData): AntData {
|
|
80
91
|
const dataFormat = this.props.schema.dataFormat ?? "x";
|
|
81
92
|
// 若 tillNow=true,结束时间传 null,避免 RangePicker 缓存旧结束时间
|
|
82
|
-
const endTime =
|
|
93
|
+
const endTime =
|
|
94
|
+
d[2] === true ? null : d[1] ? moment(d[1], dataFormat) : null;
|
|
83
95
|
return [d[0] ? moment(d[0], dataFormat) : null, endTime];
|
|
84
96
|
}
|
|
85
97
|
|
|
@@ -87,45 +99,76 @@ export class ARangePicker extends Viewer<State> {
|
|
|
87
99
|
const p = this.props.schema.props ?? {};
|
|
88
100
|
let rangePickerData = this._data2rangePicker(this.getValue() ?? []);
|
|
89
101
|
if (MUtil.phoneLike()) {
|
|
90
|
-
let show = MDateRangeType.toReadableN(
|
|
102
|
+
let show = MDateRangeType.toReadableN(
|
|
103
|
+
assembly,
|
|
104
|
+
this.props.schema,
|
|
105
|
+
super.getValue(),
|
|
106
|
+
);
|
|
91
107
|
|
|
92
108
|
// 根据 precision 配置确定移动端 DatePicker 精度(使用扁平化属性 dateRangePrecision)
|
|
93
|
-
const mobilePrecision = (this.props.schema.dateRangePrecision ||
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
const mobilePrecision = (this.props.schema.dateRangePrecision ||
|
|
110
|
+
"day") as "year" | "month" | "day" | "hour" | "minute" | "second";
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<>
|
|
114
|
+
<div
|
|
115
|
+
className="backfill"
|
|
116
|
+
onClick={() =>
|
|
117
|
+
this.setState({ mobileDlg: true, mobileStep: "start" })
|
|
118
|
+
}
|
|
119
|
+
>
|
|
120
|
+
{" "}
|
|
121
|
+
{show ?? "请点击选择"}{" "}
|
|
122
|
+
</div>
|
|
123
|
+
{/* 移动端:使用两步 DatePickerM 选择开始和结束日期 */}
|
|
124
|
+
<DatePickerM
|
|
125
|
+
key={`start_${mobilePrecision}`}
|
|
126
|
+
visible={this.state.mobileDlg && this.state.mobileStep === "start"}
|
|
127
|
+
precision={mobilePrecision}
|
|
128
|
+
title="选择开始日期"
|
|
129
|
+
min={
|
|
130
|
+
this.props.schema.min
|
|
131
|
+
? new Date(this.props.schema.min)
|
|
132
|
+
: undefined
|
|
133
|
+
}
|
|
134
|
+
max={
|
|
135
|
+
this.props.schema.max
|
|
136
|
+
? new Date(this.props.schema.max)
|
|
137
|
+
: undefined
|
|
115
138
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
139
|
+
onConfirm={(val) => {
|
|
140
|
+
this._startConfirmed = true;
|
|
141
|
+
this.setState({ mobileStartDate: val, mobileStep: "end" });
|
|
142
|
+
}}
|
|
143
|
+
onClose={() => {
|
|
144
|
+
// antd-mobile v5 确认时会同时触发 onConfirm 和 onClose
|
|
145
|
+
// 用实例变量同步判断:确认后的 onClose 应忽略,仅用户主动取消时才关闭
|
|
146
|
+
if (this._startConfirmed) {
|
|
147
|
+
this._startConfirmed = false;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.setState({ mobileDlg: false });
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
<DatePickerM
|
|
154
|
+
key={`end_${mobilePrecision}`}
|
|
155
|
+
visible={this.state.mobileDlg && this.state.mobileStep === "end"}
|
|
156
|
+
precision={mobilePrecision}
|
|
157
|
+
title={
|
|
158
|
+
// 如果允许"至今"且开始时间不在未来,在标题区域展示"至今"按钮
|
|
159
|
+
!this.props.schema.dateRange?.hideTillNow &&
|
|
160
|
+
!(
|
|
161
|
+
this.state.mobileStartDate &&
|
|
162
|
+
this.state.mobileStartDate > new Date()
|
|
163
|
+
) ? (
|
|
164
|
+
<div
|
|
165
|
+
style={{
|
|
166
|
+
display: "flex",
|
|
167
|
+
alignItems: "center",
|
|
168
|
+
justifyContent: "center",
|
|
169
|
+
gap: 12,
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
129
172
|
<span>选择结束日期</span>
|
|
130
173
|
<AntButton
|
|
131
174
|
size="small"
|
|
@@ -134,96 +177,252 @@ export class ARangePicker extends Viewer<State> {
|
|
|
134
177
|
const startDate = this.state.mobileStartDate;
|
|
135
178
|
if (startDate) {
|
|
136
179
|
super.changeValueEx(
|
|
137
|
-
this._rangePicker2Data(
|
|
138
|
-
|
|
180
|
+
this._rangePicker2Data(
|
|
181
|
+
[moment(startDate), moment()],
|
|
182
|
+
true,
|
|
183
|
+
),
|
|
184
|
+
true,
|
|
185
|
+
true,
|
|
139
186
|
);
|
|
140
187
|
}
|
|
141
188
|
this.setState({ mobileDlg: false });
|
|
142
189
|
}}
|
|
143
|
-
|
|
190
|
+
>
|
|
191
|
+
至今
|
|
192
|
+
</AntButton>
|
|
144
193
|
</div>
|
|
145
|
-
:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
max={this.props.schema.max ? new Date(this.props.schema.max) : undefined}
|
|
149
|
-
onConfirm={(val: any) => {
|
|
150
|
-
const startDate = this.state.mobileStartDate;
|
|
151
|
-
if (startDate) {
|
|
152
|
-
// 防御:结束日期不能早于开始日期
|
|
153
|
-
const finalEnd = val < startDate ? startDate : val;
|
|
154
|
-
super.changeValueEx(this._rangePicker2Data([moment(startDate), moment(finalEnd)], false), true, true);
|
|
194
|
+
) : (
|
|
195
|
+
"选择结束日期"
|
|
196
|
+
)
|
|
155
197
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
198
|
+
min={
|
|
199
|
+
this.state.mobileStartDate ||
|
|
200
|
+
(this.props.schema.min
|
|
201
|
+
? new Date(this.props.schema.min)
|
|
202
|
+
: undefined)
|
|
203
|
+
}
|
|
204
|
+
max={
|
|
205
|
+
this.props.schema.max
|
|
206
|
+
? new Date(this.props.schema.max)
|
|
207
|
+
: undefined
|
|
208
|
+
}
|
|
209
|
+
onConfirm={(val: any) => {
|
|
210
|
+
const startDate = this.state.mobileStartDate;
|
|
211
|
+
if (startDate) {
|
|
212
|
+
// 防御:结束日期不能早于开始日期
|
|
213
|
+
const finalEnd = val < startDate ? startDate : val;
|
|
214
|
+
super.changeValueEx(
|
|
215
|
+
this._rangePicker2Data(
|
|
216
|
+
[moment(startDate), moment(finalEnd)],
|
|
217
|
+
false,
|
|
218
|
+
),
|
|
219
|
+
true,
|
|
220
|
+
true,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
this.setState({ mobileDlg: false });
|
|
224
|
+
}}
|
|
225
|
+
onClose={() => {
|
|
226
|
+
// 回退到第一步,让用户可以重新选择开始日期
|
|
227
|
+
this.setState({ mobileStep: "start" });
|
|
228
|
+
}}
|
|
229
|
+
/>
|
|
230
|
+
</>
|
|
231
|
+
);
|
|
164
232
|
} else {
|
|
165
233
|
// 根据 precision 配置确定 PC 端 picker 模式和 showTime(使用扁平化属性 dateRangePrecision)
|
|
166
234
|
const precision = this.props.schema.dateRangePrecision;
|
|
167
|
-
const pcShowTime =
|
|
168
|
-
|
|
235
|
+
const pcShowTime =
|
|
236
|
+
precision === "minute" || this.props.schema.dateRange?.showTime;
|
|
237
|
+
const hideFooter = this.props.schema.dateRange?.hideTillNow;
|
|
169
238
|
|
|
170
239
|
// 动态构建额外属性,避免 showTime 和 picker 同时传入导致类型冲突
|
|
171
240
|
const extraProps: any = {};
|
|
172
|
-
if (precision ===
|
|
173
|
-
extraProps.picker =
|
|
174
|
-
} else if (precision ===
|
|
175
|
-
extraProps.picker =
|
|
241
|
+
if (precision === "year") {
|
|
242
|
+
extraProps.picker = "year";
|
|
243
|
+
} else if (precision === "month") {
|
|
244
|
+
extraProps.picker = "month";
|
|
176
245
|
} else if (pcShowTime) {
|
|
177
246
|
// precision 为 minute 时只展示时分,不展示秒
|
|
178
|
-
extraProps.showTime =
|
|
247
|
+
extraProps.showTime =
|
|
248
|
+
precision === "minute" ? { format: "HH:mm" } : true;
|
|
179
249
|
// 同步设置输入框的显示格式,避免 showTime.format 只影响面板列而输入框仍显示秒
|
|
180
|
-
if (precision ===
|
|
181
|
-
extraProps.format =
|
|
250
|
+
if (precision === "minute") {
|
|
251
|
+
extraProps.format = "YYYY-MM-DD HH:mm";
|
|
182
252
|
}
|
|
183
253
|
}
|
|
184
254
|
|
|
255
|
+
// "至今"按钮的点击处理函数
|
|
256
|
+
const handleTillNow = () => {
|
|
257
|
+
// 优先级:onCalendarChange 记录的值 > 面板点击捕获的日期 > 已有默认值 > 当前时间
|
|
258
|
+
const fromCalendarChange = this._onCalendarChangeValue?.[0];
|
|
259
|
+
const fromPanelClick = this._panelClickedDate;
|
|
260
|
+
let startMoment =
|
|
261
|
+
fromCalendarChange ??
|
|
262
|
+
fromPanelClick ??
|
|
263
|
+
rangePickerData?.[0] ??
|
|
264
|
+
moment();
|
|
265
|
+
|
|
266
|
+
// 如果开始时间来自面板点击(只有日期没有时间),将当前时刻的时分附加上去
|
|
267
|
+
if (!fromCalendarChange && fromPanelClick) {
|
|
268
|
+
const now = moment();
|
|
269
|
+
startMoment = startMoment
|
|
270
|
+
.clone()
|
|
271
|
+
.hour(now.hour())
|
|
272
|
+
.minute(now.minute())
|
|
273
|
+
.second(0);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
super.changeValueEx(
|
|
277
|
+
this._rangePicker2Data([startMoment, moment()], true),
|
|
278
|
+
true,
|
|
279
|
+
true,
|
|
280
|
+
);
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// 判断是否应展示"至今"按钮
|
|
284
|
+
const showTillNow = !hideFooter;
|
|
285
|
+
|
|
185
286
|
// 构造元素
|
|
186
|
-
return
|
|
187
|
-
ref={this._pickerRef}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
287
|
+
return (
|
|
288
|
+
<div ref={this._pickerRef}>
|
|
289
|
+
<DatePicker.RangePicker
|
|
290
|
+
key={`${this.state.ctrlVersion}_${
|
|
291
|
+
this.props.schema.dateRangePrecision ?? "day"
|
|
292
|
+
}`}
|
|
293
|
+
panelRender={
|
|
294
|
+
pcShowTime && showTillNow
|
|
295
|
+
? (panelNode) => {
|
|
296
|
+
// showTime 模式下:通过事件委托捕获面板上日期单元格的点击
|
|
297
|
+
// 同时在 footer 的"确定"按钮同一行注入"至今"按钮
|
|
298
|
+
return (
|
|
299
|
+
<div
|
|
300
|
+
onClick={(e) => {
|
|
301
|
+
const target = e.target as HTMLElement;
|
|
302
|
+
const cell = target.closest?.(".ant-picker-cell");
|
|
303
|
+
if (cell) {
|
|
304
|
+
// 排除 disabled 状态的日期单元格
|
|
305
|
+
if (
|
|
306
|
+
cell.classList.contains(
|
|
307
|
+
"ant-picker-cell-disabled",
|
|
308
|
+
)
|
|
309
|
+
)
|
|
310
|
+
return;
|
|
311
|
+
const title = cell.getAttribute("title");
|
|
312
|
+
if (title) {
|
|
313
|
+
const parsed = moment(title, "YYYY-MM-DD");
|
|
314
|
+
// 校验 moment 解析有效性,无效日期不记录
|
|
315
|
+
if (parsed.isValid()) {
|
|
316
|
+
this._panelClickedDate = parsed;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}}
|
|
321
|
+
ref={(el) => {
|
|
322
|
+
// 面板渲染后,将"至今"按钮注入到 .ant-picker-ok 内部,确定按钮之后
|
|
323
|
+
// 这样两者在同一个 flex item 中,确定在左、至今在右
|
|
324
|
+
if (!el) return;
|
|
325
|
+
const okLi = el.querySelector(".ant-picker-ok");
|
|
326
|
+
if (!okLi) return;
|
|
327
|
+
|
|
328
|
+
// 开始时间在未来时,移除已有的至今按钮并不再注入
|
|
329
|
+
const previewStart =
|
|
330
|
+
this._onCalendarChangeValue?.[0] ??
|
|
331
|
+
this._panelClickedDate ??
|
|
332
|
+
rangePickerData?.[0];
|
|
333
|
+
if (previewStart && previewStart.isAfter(moment())) {
|
|
334
|
+
const existingBtn =
|
|
335
|
+
okLi.querySelector(".till-now-btn");
|
|
336
|
+
if (existingBtn) existingBtn.remove();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (!okLi.querySelector(".till-now-btn")) {
|
|
341
|
+
const tillNowBtn = document.createElement("button");
|
|
342
|
+
tillNowBtn.className =
|
|
343
|
+
"ant-btn ant-btn-sm till-now-btn";
|
|
344
|
+
tillNowBtn.textContent = "至今";
|
|
345
|
+
tillNowBtn.style.cssText = "margin-left: 8px;";
|
|
346
|
+
// 使用具名函数以便于清理;先移除可能的旧监听再添加,防止重复绑定
|
|
347
|
+
const onTillNowClick = (e: Event) => {
|
|
348
|
+
e.stopPropagation();
|
|
349
|
+
handleTillNow();
|
|
350
|
+
};
|
|
351
|
+
tillNowBtn.addEventListener(
|
|
352
|
+
"click",
|
|
353
|
+
onTillNowClick,
|
|
354
|
+
);
|
|
355
|
+
okLi.appendChild(tillNowBtn);
|
|
356
|
+
}
|
|
357
|
+
}}
|
|
358
|
+
>
|
|
359
|
+
{panelNode}
|
|
360
|
+
</div>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
: undefined
|
|
196
364
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
365
|
+
renderExtraFooter={
|
|
366
|
+
!pcShowTime && showTillNow
|
|
367
|
+
? (mode) => {
|
|
368
|
+
// 非 showTime 模式:使用 renderExtraFooter 展示"至今"按钮
|
|
369
|
+
const previewStart =
|
|
370
|
+
this._onCalendarChangeValue?.[0] ?? rangePickerData?.[0];
|
|
371
|
+
if (previewStart && previewStart.isAfter(moment())) {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
return (
|
|
375
|
+
<div style={{ textAlign: "right" }}>
|
|
376
|
+
<AntButton
|
|
377
|
+
size="small"
|
|
378
|
+
style={{
|
|
379
|
+
width: "100px",
|
|
380
|
+
display: "inline-block",
|
|
381
|
+
marginTop: "5px",
|
|
382
|
+
}}
|
|
383
|
+
onClick={handleTillNow}
|
|
384
|
+
>
|
|
385
|
+
至今
|
|
386
|
+
</AntButton>
|
|
387
|
+
</div>
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
: undefined
|
|
391
|
+
}
|
|
392
|
+
bordered={this.props.hideBorder ? false : true}
|
|
393
|
+
style={{ width: "360px" }}
|
|
394
|
+
locale={zhCN}
|
|
395
|
+
defaultValue={rangePickerData}
|
|
396
|
+
onCalendarChange={(d) => {
|
|
397
|
+
this._onCalendarChangeValue = d;
|
|
398
|
+
// 用户开始新一轮选择时清理面板点击缓存,避免上一轮过时数据污染
|
|
399
|
+
this._panelClickedDate = null;
|
|
400
|
+
}}
|
|
401
|
+
onOpenChange={(open) => {
|
|
402
|
+
if (!open) {
|
|
403
|
+
this._panelClickedDate = null;
|
|
404
|
+
}
|
|
405
|
+
}}
|
|
406
|
+
onChange={(vv) => {
|
|
407
|
+
// 用户清空日期范围时,直接置空
|
|
408
|
+
if (!vv) {
|
|
409
|
+
super.changeValueEx(undefined, true, true);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const currentData = super.getValue();
|
|
413
|
+
const isTillNow = _.get(currentData, "[2]") === true;
|
|
414
|
+
// 若当前是"至今"且用户只改了开始时间(结束时间仍为 null),保留 tillNow
|
|
415
|
+
const newTillNow = isTillNow && vv[1] == null;
|
|
416
|
+
super.changeValueEx(
|
|
417
|
+
this._rangePicker2Data(vv, newTillNow),
|
|
418
|
+
true,
|
|
419
|
+
true,
|
|
420
|
+
);
|
|
421
|
+
}}
|
|
422
|
+
{...extraProps}
|
|
423
|
+
/>
|
|
424
|
+
</div>
|
|
425
|
+
);
|
|
227
426
|
}
|
|
228
427
|
}
|
|
229
428
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RefObject } from "react";
|
|
2
2
|
import moment from "moment";
|
|
3
|
-
import { Viewer, ViewerState } from
|
|
3
|
+
import { Viewer, ViewerState } from "../../BaseViewer";
|
|
4
4
|
import { MProp } from "../../../framework/Schema";
|
|
5
5
|
export type ARangePickerData = [
|
|
6
6
|
string | null | undefined,
|
|
@@ -10,12 +10,13 @@ export type ARangePickerData = [
|
|
|
10
10
|
type AntData = [moment.Moment | null, moment.Moment | null];
|
|
11
11
|
interface State extends ViewerState {
|
|
12
12
|
mobileDlg: boolean;
|
|
13
|
-
mobileStep:
|
|
13
|
+
mobileStep: "start" | "end";
|
|
14
14
|
mobileStartDate?: Date;
|
|
15
15
|
}
|
|
16
16
|
export declare class ARangePicker extends Viewer<State> {
|
|
17
|
-
_pickerRef: RefObject<
|
|
17
|
+
_pickerRef: RefObject<HTMLDivElement>;
|
|
18
18
|
_onCalendarChangeValue?: AntData | null;
|
|
19
|
+
_panelClickedDate?: moment.Moment | null;
|
|
19
20
|
_startConfirmed: boolean;
|
|
20
21
|
constructor(p: MProp);
|
|
21
22
|
componentDidUpdate(): void;
|