form-driver 0.4.19 → 0.4.21
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/README.md +15 -0
- package/dist/m3.js +1 -1
- package/es/m3.js +1734 -1289
- package/lib/m3.js +1733 -1287
- package/package.json +2 -2
- package/src/framework/Init.tsx +6 -0
- package/src/framework/MUtil.tsx +145 -0
- package/src/framework/Schema.ts +16 -2
- package/src/index.ts +0 -1
- package/src/types/MDateRangeType.ts +65 -24
- package/src/types/MDateTimeType.ts +73 -29
- package/src/ui/editor/basic/ACascadePicker.tsx +23 -15
- package/src/ui/editor/basic/ADatetimePicker.tsx +103 -39
- package/src/ui/editor/basic/AGB2260.tsx +25 -14
- package/src/ui/editor/basic/ARangePicker.tsx +110 -26
- package/src/ui/widget/SelectBox.tsx +35 -15
- package/types/framework/Init.d.ts +1 -0
- package/types/framework/MUtil.d.ts +14 -0
- package/types/framework/Schema.d.ts +11 -0
- package/types/index.d.ts +0 -1
- package/types/types/MDateRangeType.d.ts +2 -0
- package/types/types/MDateTimeType.d.ts +2 -2
- package/types/ui/editor/basic/ADatetimePicker.d.ts +2 -1
- package/types/ui/editor/basic/AGB2260.d.ts +1 -0
- package/types/ui/editor/basic/ARangePicker.d.ts +5 -3
- package/types/ui/widget/SelectBox.d.ts +10 -3
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { DatePicker } from "antd";
|
|
3
|
-
import { DatePicker as DatePickerM } from
|
|
2
|
+
import { DatePicker, ConfigProvider } from "antd";
|
|
3
|
+
import { DatePicker as DatePickerM } from "antd-mobile";
|
|
4
4
|
import moment from "moment";
|
|
5
|
-
import zhCN from
|
|
5
|
+
import zhCN from "antd/es/locale/zh_CN";
|
|
6
6
|
import _ from "lodash";
|
|
7
7
|
import { MDateTimeType } from "../../../types/MDateTimeType";
|
|
8
8
|
import { MUtil } from "../../../framework/MUtil";
|
|
9
|
-
import { BaseViewer } from
|
|
9
|
+
import { BaseViewer } from "../../BaseViewer";
|
|
10
|
+
|
|
11
|
+
// antd-mobile v5 DatePicker precision 映射
|
|
12
|
+
function toPrecision(
|
|
13
|
+
mode: string | undefined,
|
|
14
|
+
): "year" | "month" | "day" | "hour" | "minute" | "second" {
|
|
15
|
+
switch (mode) {
|
|
16
|
+
case "year":
|
|
17
|
+
return "year";
|
|
18
|
+
case "month":
|
|
19
|
+
return "month";
|
|
20
|
+
case "date":
|
|
21
|
+
return "day";
|
|
22
|
+
default:
|
|
23
|
+
return "minute"; // datetime 场景
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
10
27
|
/**
|
|
11
28
|
* 日期选择框
|
|
12
29
|
* 配置示例:
|
|
@@ -18,10 +35,18 @@ import { BaseViewer } from '../../BaseViewer';
|
|
|
18
35
|
* 类型是dateTime时,dataFormat默认是x,例如1608897466955
|
|
19
36
|
*/
|
|
20
37
|
export class ADatetimePicker extends BaseViewer {
|
|
38
|
+
constructor(props: any) {
|
|
39
|
+
super(props);
|
|
40
|
+
(this.state as any).pickerVisible = false;
|
|
41
|
+
}
|
|
42
|
+
|
|
21
43
|
element() {
|
|
22
44
|
const antConf = MDateTimeType.antConf(this.props.schema);
|
|
23
45
|
if (!antConf) {
|
|
24
|
-
return MUtil.error(
|
|
46
|
+
return MUtil.error(
|
|
47
|
+
`无效的类型${this.props.schema.type}`,
|
|
48
|
+
this.props.schema,
|
|
49
|
+
);
|
|
25
50
|
}
|
|
26
51
|
|
|
27
52
|
let data = this.getValue();
|
|
@@ -31,46 +56,85 @@ export class ADatetimePicker extends BaseViewer {
|
|
|
31
56
|
const onChange = (vv: Date | moment.Moment | null) => {
|
|
32
57
|
if (vv) {
|
|
33
58
|
const vvAsM = _.isDate(vv) ? moment(vv) : vv;
|
|
34
|
-
super.changeValue(vvAsM.format(antConf.dataFormat))
|
|
59
|
+
super.changeValue(vvAsM.format(antConf.dataFormat));
|
|
35
60
|
} else {
|
|
36
61
|
super.changeValue(undefined);
|
|
37
62
|
}
|
|
38
63
|
};
|
|
39
64
|
const p = this.props.schema.props ?? {};
|
|
40
65
|
// 构造元素
|
|
41
|
-
if (MUtil.phoneLike()) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
if (MUtil.phoneLike()) {
|
|
67
|
+
// 手机
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<div
|
|
71
|
+
className="backfill"
|
|
72
|
+
onClick={() => {
|
|
73
|
+
if (!this.props.disable)
|
|
74
|
+
this.setState({ pickerVisible: true } as any);
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
{dataAsDate
|
|
78
|
+
? moment(dataAsDate).format(antConf.readableFormat)
|
|
79
|
+
: "请点击选择"}
|
|
80
|
+
</div>
|
|
81
|
+
<DatePickerM
|
|
82
|
+
visible={(this.state as any).pickerVisible}
|
|
83
|
+
value={dataAsDate}
|
|
84
|
+
min={
|
|
85
|
+
this.props.schema.min
|
|
86
|
+
? moment(this.props.schema.min, antConf.dataFormat).toDate()
|
|
87
|
+
: undefined
|
|
88
|
+
}
|
|
89
|
+
max={
|
|
90
|
+
this.props.schema.max
|
|
91
|
+
? moment(this.props.schema.max, antConf.dataFormat).toDate()
|
|
92
|
+
: undefined
|
|
93
|
+
}
|
|
94
|
+
precision={toPrecision(antConf.mode)}
|
|
95
|
+
onConfirm={(val) => {
|
|
96
|
+
onChange(val);
|
|
97
|
+
this.setState({ pickerVisible: false } as any);
|
|
98
|
+
}}
|
|
99
|
+
onClose={() => {
|
|
100
|
+
this.setState({ pickerVisible: false } as any);
|
|
101
|
+
}}
|
|
102
|
+
{...p}
|
|
103
|
+
/>
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
// 大屏
|
|
108
|
+
// key 中加入 mode 信息,确保精度切换时组件重新挂载
|
|
109
|
+
const pickerKey = `${this.props.path}_${antConf.mode ?? "datetime"}`;
|
|
110
|
+
return (
|
|
111
|
+
<ConfigProvider locale={zhCN}>
|
|
112
|
+
<DatePicker
|
|
113
|
+
key={pickerKey}
|
|
114
|
+
disabled={this.props.disable}
|
|
115
|
+
bordered={this.props.hideBorder ? false : true}
|
|
116
|
+
disabledDate={(m) => {
|
|
117
|
+
const d =
|
|
118
|
+
(this.props.schema.min &&
|
|
119
|
+
moment(this.props.schema.min, antConf.dataFormat).isAfter(
|
|
120
|
+
m,
|
|
121
|
+
)) ||
|
|
122
|
+
(this.props.schema.max &&
|
|
123
|
+
moment(this.props.schema.max, antConf.dataFormat).isBefore(
|
|
124
|
+
m,
|
|
125
|
+
));
|
|
126
|
+
return !!d;
|
|
127
|
+
}}
|
|
128
|
+
format={antConf.readableFormat}
|
|
129
|
+
style={{ width: "300px" }}
|
|
130
|
+
defaultValue={dataAsMoment}
|
|
131
|
+
showTime={antConf.showTime}
|
|
132
|
+
picker={antConf.mode}
|
|
133
|
+
onChange={onChange}
|
|
134
|
+
{...p}
|
|
135
|
+
/>
|
|
136
|
+
</ConfigProvider>
|
|
137
|
+
);
|
|
74
138
|
}
|
|
75
139
|
}
|
|
76
140
|
}
|
|
@@ -5,12 +5,18 @@ import { Picker } from 'antd-mobile';
|
|
|
5
5
|
import { MUtil } from "../../../framework/MUtil";
|
|
6
6
|
import { BaseViewer } from '../../BaseViewer';
|
|
7
7
|
import { MGB2260Type } from '../../../types/MGB2260Type';
|
|
8
|
+
|
|
8
9
|
/**
|
|
9
10
|
* 选择中国的省市县
|
|
10
11
|
* 示例:{label:"1.5 您目前的居住地",name:"reside", type:"gb2260"},
|
|
11
12
|
* 数据是gb2260的地区代码
|
|
12
13
|
*/
|
|
13
14
|
export class AGB2260 extends BaseViewer {
|
|
15
|
+
constructor(props: any) {
|
|
16
|
+
super(props);
|
|
17
|
+
(this.state as any).pickerVisible = false;
|
|
18
|
+
}
|
|
19
|
+
|
|
14
20
|
element() {
|
|
15
21
|
const v = super.getValue();
|
|
16
22
|
const empty = { label: ["请选择"], code: undefined };
|
|
@@ -18,20 +24,25 @@ export class AGB2260 extends BaseViewer {
|
|
|
18
24
|
const p = this.props.schema.props ?? {};
|
|
19
25
|
|
|
20
26
|
if (MUtil.phoneLike()) { // 手机
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
return <>
|
|
28
|
+
<div className="backfill" style={this.props.style}
|
|
29
|
+
onClick={() => { if (!this.props.disable) this.setState({ pickerVisible: true } as any) }}>
|
|
30
|
+
{looked?.label?.join("/")}
|
|
31
|
+
</div>
|
|
32
|
+
<Picker
|
|
33
|
+
columns={MGB2260Type.gb2260}
|
|
34
|
+
value={looked.code}
|
|
35
|
+
visible={(this.state as any).pickerVisible}
|
|
36
|
+
onConfirm={e => {
|
|
37
|
+
super.changeValue(_.last(e));
|
|
38
|
+
this.setState({ pickerVisible: false } as any);
|
|
39
|
+
}}
|
|
40
|
+
onClose={() => {
|
|
41
|
+
this.setState({ pickerVisible: false } as any);
|
|
42
|
+
}}
|
|
43
|
+
{...p}
|
|
44
|
+
/>
|
|
45
|
+
</>
|
|
35
46
|
} else { // PC
|
|
36
47
|
return <Cascader
|
|
37
48
|
options={MGB2260Type.gb2260}
|
|
@@ -2,7 +2,8 @@ import React, { Component, RefObject } from "react";
|
|
|
2
2
|
import { DatePicker } from "antd";
|
|
3
3
|
import zhCN from 'antd/lib/date-picker/locale/zh_CN';
|
|
4
4
|
import moment from "moment";
|
|
5
|
-
import {
|
|
5
|
+
import { DatePicker as DatePickerM } from "antd-mobile";
|
|
6
|
+
import { Button as AntButton } from "antd";
|
|
6
7
|
import ReactDOM from "react-dom";
|
|
7
8
|
import { RangePickerProps } from "antd/lib/date-picker";
|
|
8
9
|
import _ from "lodash";
|
|
@@ -25,15 +26,18 @@ type AntData = [moment.Moment | null, moment.Moment | null];
|
|
|
25
26
|
|
|
26
27
|
interface State extends ViewerState {
|
|
27
28
|
mobileDlg: boolean;
|
|
29
|
+
mobileStep: 'start' | 'end';
|
|
30
|
+
mobileStartDate?: Date;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export class ARangePicker extends Viewer<State> {
|
|
31
|
-
_pickerRef: RefObject<
|
|
34
|
+
_pickerRef: RefObject<any> = React.createRef();
|
|
32
35
|
_onCalendarChangeValue?: AntData | null;
|
|
36
|
+
_startConfirmed = false; // 标记开始日期是否已确认,用于区分 onClose 是取消还是确认后的自动触发
|
|
33
37
|
|
|
34
38
|
constructor(p: MProp) {
|
|
35
39
|
super(p);
|
|
36
|
-
this.state = { ctrlVersion: 1, noValidate: false, mobileDlg: false };
|
|
40
|
+
this.state = { ctrlVersion: 1, noValidate: false, mobileDlg: false, mobileStep: 'start' };
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
componentDidUpdate() {
|
|
@@ -83,39 +87,117 @@ export class ARangePicker extends Viewer<State> {
|
|
|
83
87
|
if (MUtil.phoneLike()) {
|
|
84
88
|
let show = MDateRangeType.toReadableN(assembly, this.props.schema, super.getValue());
|
|
85
89
|
|
|
90
|
+
// 根据 precision 配置确定移动端 DatePicker 精度(使用扁平化属性 dateRangePrecision)
|
|
91
|
+
const mobilePrecision = (this.props.schema.dateRangePrecision || 'day') as 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second';
|
|
92
|
+
|
|
86
93
|
return <>
|
|
87
|
-
<div className="backfill" onClick={() => this.setState({ mobileDlg: true })}> {show ?? '请点击选择'} </div>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
<div className="backfill" onClick={() => this.setState({ mobileDlg: true, mobileStep: 'start' })}> {show ?? '请点击选择'} </div>
|
|
95
|
+
{/* 移动端:使用两步 DatePickerM 选择开始和结束日期 */}
|
|
96
|
+
<DatePickerM
|
|
97
|
+
key={`start_${mobilePrecision}`}
|
|
98
|
+
visible={this.state.mobileDlg && this.state.mobileStep === 'start'}
|
|
99
|
+
precision={mobilePrecision}
|
|
100
|
+
title="选择开始日期"
|
|
101
|
+
min={this.props.schema.min ? new Date(this.props.schema.min) : undefined}
|
|
102
|
+
max={this.props.schema.max ? new Date(this.props.schema.max) : undefined}
|
|
103
|
+
onConfirm={(val) => {
|
|
104
|
+
this._startConfirmed = true;
|
|
105
|
+
this.setState({ mobileStartDate: val, mobileStep: 'end' });
|
|
106
|
+
}}
|
|
107
|
+
onClose={() => {
|
|
108
|
+
// antd-mobile v5 确认时会同时触发 onConfirm 和 onClose
|
|
109
|
+
// 用实例变量同步判断:确认后的 onClose 应忽略,仅用户主动取消时才关闭
|
|
110
|
+
if (this._startConfirmed) {
|
|
111
|
+
this._startConfirmed = false;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this.setState({ mobileDlg: false });
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
<DatePickerM
|
|
118
|
+
key={`end_${mobilePrecision}`}
|
|
119
|
+
visible={this.state.mobileDlg && this.state.mobileStep === 'end'}
|
|
120
|
+
precision={mobilePrecision}
|
|
121
|
+
title={
|
|
122
|
+
// 如果允许"至今"且开始时间不在未来,在标题区域展示"至今"按钮
|
|
123
|
+
!this.props.schema.dateRange?.hideTillNow
|
|
124
|
+
&& !this.props.schema.dateRange?.showTime
|
|
125
|
+
&& !(this.state.mobileStartDate && this.state.mobileStartDate > new Date())
|
|
126
|
+
? <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
|
|
127
|
+
<span>选择结束日期</span>
|
|
128
|
+
<AntButton
|
|
129
|
+
size="small"
|
|
130
|
+
type="primary"
|
|
131
|
+
onClick={() => {
|
|
132
|
+
const startDate = this.state.mobileStartDate;
|
|
133
|
+
if (startDate) {
|
|
134
|
+
super.changeValueEx(
|
|
135
|
+
this._rangePicker2Data([moment(startDate), moment()], true),
|
|
136
|
+
true, true
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
this.setState({ mobileDlg: false });
|
|
140
|
+
}}
|
|
141
|
+
>至今</AntButton>
|
|
142
|
+
</div>
|
|
143
|
+
: "选择结束日期"
|
|
144
|
+
}
|
|
145
|
+
min={this.state.mobileStartDate || (this.props.schema.min ? new Date(this.props.schema.min) : undefined)}
|
|
146
|
+
max={this.props.schema.max ? new Date(this.props.schema.max) : undefined}
|
|
147
|
+
onConfirm={(val: any) => {
|
|
148
|
+
const startDate = this.state.mobileStartDate;
|
|
149
|
+
if (startDate) {
|
|
150
|
+
// 防御:结束日期不能早于开始日期
|
|
151
|
+
const finalEnd = val < startDate ? startDate : val;
|
|
152
|
+
super.changeValueEx(this._rangePicker2Data([moment(startDate), moment(finalEnd)], false), true, true);
|
|
153
|
+
}
|
|
154
|
+
this.setState({ mobileDlg: false });
|
|
155
|
+
}}
|
|
156
|
+
onClose={() => {
|
|
157
|
+
// 回退到第一步,让用户可以重新选择开始日期
|
|
158
|
+
this.setState({ mobileStep: 'start' });
|
|
97
159
|
}}
|
|
98
|
-
{...p}
|
|
99
160
|
/>
|
|
100
161
|
</>
|
|
101
162
|
} else {
|
|
163
|
+
// 根据 precision 配置确定 PC 端 picker 模式和 showTime(使用扁平化属性 dateRangePrecision)
|
|
164
|
+
const precision = this.props.schema.dateRangePrecision;
|
|
165
|
+
const pcShowTime = precision === 'minute' || this.props.schema.dateRange?.showTime;
|
|
166
|
+
const hideFooter = this.props.schema.dateRange?.hideTillNow || pcShowTime;
|
|
167
|
+
|
|
168
|
+
// 动态构建额外属性,避免 showTime 和 picker 同时传入导致类型冲突
|
|
169
|
+
const extraProps: any = {};
|
|
170
|
+
if (precision === 'year') {
|
|
171
|
+
extraProps.picker = 'year';
|
|
172
|
+
} else if (precision === 'month') {
|
|
173
|
+
extraProps.picker = 'month';
|
|
174
|
+
} else if (pcShowTime) {
|
|
175
|
+
extraProps.showTime = true;
|
|
176
|
+
}
|
|
177
|
+
|
|
102
178
|
// 构造元素
|
|
103
179
|
return <DatePicker.RangePicker
|
|
104
180
|
ref={this._pickerRef}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
renderExtraFooter={this.props.schema.dateRange?.hideTillNow || this.props.schema.dateRange?.showTime // TODO 显示时间时,“至今”无法支持
|
|
181
|
+
key={`${this.state.ctrlVersion}_${this.props.schema.dateRangePrecision ?? 'day'}`}
|
|
182
|
+
renderExtraFooter={hideFooter
|
|
108
183
|
? undefined
|
|
109
|
-
: (mode) =>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
184
|
+
: (mode) => {
|
|
185
|
+
// 如果开始时间超过当前时间(未来时间),不展示"至今"按钮
|
|
186
|
+
const startMoment = this._onCalendarChangeValue?.[0];
|
|
187
|
+
if (startMoment && startMoment.isAfter(moment())) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
return <div style={{ textAlign: "right" }}>
|
|
191
|
+
<AntButton
|
|
192
|
+
size="small" style={{ width: "100px", display: "inline-block", marginTop: "5px" }}
|
|
193
|
+
onClick={() => {
|
|
194
|
+
super.changeValueEx(this._rangePicker2Data(this._onCalendarChangeValue, true), true, true);
|
|
195
|
+
}}>至今</AntButton>
|
|
196
|
+
</div>;
|
|
197
|
+
}
|
|
116
198
|
}
|
|
117
199
|
bordered={this.props.hideBorder ? false : true}
|
|
118
|
-
style={{
|
|
200
|
+
style={{ width: "300px" }}
|
|
119
201
|
locale={zhCN}
|
|
120
202
|
defaultValue={rangePickerData}
|
|
121
203
|
onCalendarChange={(d) => {
|
|
@@ -123,7 +205,9 @@ export class ARangePicker extends Viewer<State> {
|
|
|
123
205
|
}}
|
|
124
206
|
onChange={(vv) => {
|
|
125
207
|
super.changeValueEx(this._rangePicker2Data(vv, false), true, true)
|
|
126
|
-
}}
|
|
208
|
+
}}
|
|
209
|
+
{...extraProps}
|
|
210
|
+
/>;
|
|
127
211
|
}
|
|
128
212
|
}
|
|
129
213
|
}
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import { Select } from "antd";
|
|
4
4
|
import { Picker } from "antd-mobile";
|
|
5
|
-
import { PickerData } from "antd-mobile/lib/picker/PropsType";
|
|
6
5
|
import _ from "lodash";
|
|
7
6
|
import React from "react";
|
|
8
|
-
//import { InputHTMLAttributes } from "react";
|
|
9
7
|
import { MUtil } from '../../framework/MUtil';
|
|
10
8
|
|
|
11
|
-
interface
|
|
9
|
+
interface PickerOption {
|
|
10
|
+
label: string | React.ReactNode;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Prop {
|
|
12
15
|
data: string;
|
|
13
|
-
options:
|
|
16
|
+
options: PickerOption[],
|
|
14
17
|
onChange: (newValue?:string)=>void;
|
|
15
18
|
onBlur?:()=>void;
|
|
16
19
|
|
|
@@ -18,22 +21,39 @@ interface Prop { // extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
18
21
|
openLabel?: string;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
interface SelectBoxState {
|
|
25
|
+
pickerVisible: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class SelectBox extends React.Component<Prop, SelectBoxState> {
|
|
29
|
+
constructor(props: Prop) {
|
|
30
|
+
super(props);
|
|
31
|
+
this.state = { pickerVisible: false };
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
render(){
|
|
23
35
|
if(MUtil.phoneLike()) {
|
|
24
36
|
const looked = this.props.options.find(o=>o.value === this.props.data);
|
|
25
37
|
const backfillClass = looked ? "backfill" : "backfill_empty";
|
|
26
38
|
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
return <>
|
|
40
|
+
<div className={backfillClass} onClick={() => this.setState({ pickerVisible: true })}>
|
|
41
|
+
{looked?.label ?? "点击选择"}
|
|
42
|
+
</div>
|
|
43
|
+
<Picker
|
|
44
|
+
columns={[this.props.options]}
|
|
45
|
+
value={[this.props.data]}
|
|
46
|
+
visible={this.state.pickerVisible}
|
|
47
|
+
onConfirm={e => {
|
|
48
|
+
this.props.onChange(_.last(e) as string);
|
|
49
|
+
this.setState({ pickerVisible: false });
|
|
50
|
+
}}
|
|
51
|
+
onClose={() => {
|
|
52
|
+
this.setState({ pickerVisible: false });
|
|
53
|
+
if(this.props.onBlur) { this.props.onBlur() }
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
</>
|
|
37
57
|
} else {
|
|
38
58
|
return <Select defaultValue={this.props.data}>
|
|
39
59
|
{this.props.options.map(o=><Select.Option value={o.value}>{o.label ?? o.value}</Select.Option>)}
|
|
@@ -115,6 +115,20 @@ export declare let MUtil: {
|
|
|
115
115
|
renameKey: (object: any, renameTo: {
|
|
116
116
|
[oldKey: string]: string;
|
|
117
117
|
}, removeNotExistKey?: boolean) => any;
|
|
118
|
+
/**
|
|
119
|
+
* 提交时将时间字段转换为可读格式
|
|
120
|
+
* @param schema 表单 schema(type 为 object 的根 schema)
|
|
121
|
+
* @param database 表单数据
|
|
122
|
+
* @returns 深拷贝后转换过的数据
|
|
123
|
+
*/
|
|
124
|
+
formatForExport: (schema: MFieldSchemaAnonymity, database: any) => any;
|
|
125
|
+
/**
|
|
126
|
+
* 回填时将可读格式的时间字段反解析为内部格式
|
|
127
|
+
* @param schema 表单 schema(type 为 object 的根 schema)
|
|
128
|
+
* @param database 可读格式的数据
|
|
129
|
+
* @returns 深拷贝后反解析过的数据
|
|
130
|
+
*/
|
|
131
|
+
parseFromExport: (schema: MFieldSchemaAnonymity, database: any) => any;
|
|
118
132
|
/** 啥也不干的空回调 */
|
|
119
133
|
doNothing: () => void;
|
|
120
134
|
/**
|
|
@@ -132,13 +132,24 @@ export interface MFieldSchema {
|
|
|
132
132
|
/** 允许时间段重叠,默认是不能重叠 */
|
|
133
133
|
overlap?: boolean;
|
|
134
134
|
};
|
|
135
|
+
/** date 类型配置 */
|
|
136
|
+
date?: {
|
|
137
|
+
/** 日期精度:month=年月, day=年月日(默认), minute=年月日时分 */
|
|
138
|
+
precision?: "month" | "day" | "minute";
|
|
139
|
+
};
|
|
140
|
+
/** 日期精度(扁平化属性):year=年, month=年月, day=年月日(默认), minute=年月日时分 */
|
|
141
|
+
datePrecision?: string;
|
|
135
142
|
/** dateRange 类型配置 */
|
|
136
143
|
dateRange?: {
|
|
137
144
|
/** 是否隐藏至今按钮 */
|
|
138
145
|
hideTillNow?: boolean;
|
|
139
146
|
/** 是否能选择时间 */
|
|
140
147
|
showTime?: boolean;
|
|
148
|
+
/** 日期精度:month=年月, day=年月日(默认), minute=年月日时分 */
|
|
149
|
+
precision?: "month" | "day" | "minute";
|
|
141
150
|
};
|
|
151
|
+
/** 日期范围精度(扁平化属性) */
|
|
152
|
+
dateRangePrecision?: string;
|
|
142
153
|
/** 数据格式 */
|
|
143
154
|
dataFormat?: "x" | "YYYYMMDD" /** 用于时间日期类型字段的数据格式,参考moment,例如x表示数据是时间戳,YYYYMMDD表示数据是形如19990130的字符串 */ | string;
|
|
144
155
|
/**
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import 'antd/dist/antd.css';
|
|
2
|
-
import 'antd-mobile/dist/antd-mobile.css';
|
|
3
2
|
import { Ajax } from './framework/Ajax';
|
|
4
3
|
import { M3UISpecSegmentItem, MFieldSchema, M3UISpec, MFieldSchemaAnonymity } from './framework/Schema';
|
|
5
4
|
import { MViewerDebug } from './framework/MViewerDebug';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { MFieldSchemaAnonymity } from "../framework/Schema";
|
|
2
2
|
import { MType } from "./MType";
|
|
3
3
|
import { Assembly } from "../framework/Assembly";
|
|
4
|
+
/** 根据 precision 获取可读格式 */
|
|
5
|
+
export declare function getReadableFormat(precision?: string, showTime?: boolean): string;
|
|
4
6
|
export declare function timeRangeExpr(assembly: Assembly, from: number | string, to: number | string, tillNow: boolean, readableFormat?: string): string;
|
|
5
7
|
export declare const MDateRangeType: MType & {
|
|
6
8
|
toReadableN: (assembly: Assembly, s: MFieldSchemaAnonymity, vs: any) => string | undefined;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { MFieldSchemaAnonymity } from
|
|
1
|
+
import { MFieldSchemaAnonymity } from "../framework/Schema";
|
|
2
2
|
import { MType } from "./MType";
|
|
3
3
|
export interface MDateTimeAntConf {
|
|
4
4
|
dataFormat: string;
|
|
5
5
|
readableFormat: string;
|
|
6
|
-
mode: undefined |
|
|
6
|
+
mode: undefined | "date" | "year" | "month" | "time";
|
|
7
7
|
showTime: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare const MDateTimeType: MType & {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { BaseViewer } from
|
|
2
|
+
import { BaseViewer } from "../../BaseViewer";
|
|
3
3
|
/**
|
|
4
4
|
* 日期选择框
|
|
5
5
|
* 配置示例:
|
|
@@ -11,5 +11,6 @@ import { BaseViewer } from '../../BaseViewer';
|
|
|
11
11
|
* 类型是dateTime时,dataFormat默认是x,例如1608897466955
|
|
12
12
|
*/
|
|
13
13
|
export declare class ADatetimePicker extends BaseViewer {
|
|
14
|
+
constructor(props: any);
|
|
14
15
|
element(): JSX.Element;
|
|
15
16
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RefObject } from "react";
|
|
2
2
|
import moment from "moment";
|
|
3
|
-
import { RangePickerProps } from "antd/lib/date-picker";
|
|
4
3
|
import { Viewer, ViewerState } from '../../BaseViewer';
|
|
5
4
|
import { MProp } from "../../../framework/Schema";
|
|
6
5
|
export type ARangePickerData = [
|
|
@@ -11,10 +10,13 @@ export type ARangePickerData = [
|
|
|
11
10
|
type AntData = [moment.Moment | null, moment.Moment | null];
|
|
12
11
|
interface State extends ViewerState {
|
|
13
12
|
mobileDlg: boolean;
|
|
13
|
+
mobileStep: 'start' | 'end';
|
|
14
|
+
mobileStartDate?: Date;
|
|
14
15
|
}
|
|
15
16
|
export declare class ARangePicker extends Viewer<State> {
|
|
16
|
-
_pickerRef: RefObject<
|
|
17
|
+
_pickerRef: RefObject<any>;
|
|
17
18
|
_onCalendarChangeValue?: AntData | null;
|
|
19
|
+
_startConfirmed: boolean;
|
|
18
20
|
constructor(p: MProp);
|
|
19
21
|
componentDidUpdate(): void;
|
|
20
22
|
componentDidMount(): void;
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { PickerData } from "antd-mobile/lib/picker/PropsType";
|
|
2
1
|
import React from "react";
|
|
2
|
+
interface PickerOption {
|
|
3
|
+
label: string | React.ReactNode;
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
3
6
|
interface Prop {
|
|
4
7
|
data: string;
|
|
5
|
-
options:
|
|
8
|
+
options: PickerOption[];
|
|
6
9
|
onChange: (newValue?: string) => void;
|
|
7
10
|
onBlur?: () => void;
|
|
8
11
|
openLabel?: string;
|
|
9
12
|
}
|
|
10
|
-
|
|
13
|
+
interface SelectBoxState {
|
|
14
|
+
pickerVisible: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class SelectBox extends React.Component<Prop, SelectBoxState> {
|
|
17
|
+
constructor(props: Prop);
|
|
11
18
|
render(): JSX.Element;
|
|
12
19
|
}
|
|
13
20
|
export {};
|