@hzab/form-render-mobile 0.0.9 → 0.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/form-render-mobile",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "formily-form-render-mobile",
5
5
  "main": "lib",
6
6
  "scripts": {
@@ -43,6 +43,7 @@
43
43
  "@formily/antd-mobile": "1.0.0-beta.3",
44
44
  "@formily/core": "2.2.29",
45
45
  "@formily/react": "2.2.29",
46
+ "@hzab/data-model": "^0.0.3",
46
47
  "antd-mobile": "^5.32.0",
47
48
  "antd-mobile-icons": "^0.2.2",
48
49
  "nanoid": "^5.0.3"
@@ -1,11 +1,13 @@
1
1
  import { useState, useEffect } from "react";
2
2
  import { useField, observer } from "@formily/react";
3
3
  import { CascadePicker } from "antd-mobile";
4
- import { RightOutline } from "antd-mobile-icons";
4
+
5
+ import PickerRightOutline from "../PickerRightOutline";
6
+ import Placeholder from "../Placeholder";
5
7
 
6
8
  import "./index.less";
7
9
 
8
- function Cascader(props) {
10
+ export const Cascader = observer((props) => {
9
11
  const { disabled, readOnly, placeholder = "请选择", onChange } = props;
10
12
 
11
13
  const field = useField();
@@ -39,7 +41,7 @@ function Cascader(props) {
39
41
  }
40
42
 
41
43
  return (
42
- <div className="formily-cascader picker-box" onClick={onClick}>
44
+ <PickerRightOutline className="formily-cascader picker-box" onClick={onClick}>
43
45
  <CascadePicker
44
46
  {...props}
45
47
  style={{ pointerEvents: readOnly || disabled ? "none" : undefined }}
@@ -50,7 +52,7 @@ function Cascader(props) {
50
52
  >
51
53
  {(value) => {
52
54
  if (!value || value.length <= 0) {
53
- return <div className="placeholder">{placeholder}</div>;
55
+ return <Placeholder {...props} placeholder={placeholder} isPicker />;
54
56
  }
55
57
  return value?.reduce((pre, cur) => {
56
58
  if (!cur) {
@@ -63,9 +65,8 @@ function Cascader(props) {
63
65
  }, "");
64
66
  }}
65
67
  </CascadePicker>
66
- <RightOutline className="picker-right-icon" />
67
- </div>
68
+ </PickerRightOutline>
68
69
  );
69
- }
70
+ });
70
71
 
71
- export default observer(Cascader);
72
+ export default Cascader;
@@ -1,6 +1,7 @@
1
1
  import { useState, useEffect, useMemo } from "react";
2
2
  import { useField, observer } from "@formily/react";
3
3
  import { DatePicker as ADataPicker } from "antd-mobile";
4
+ import { Precision } from "antd-mobile/2x/es/components/date-picker/date-picker-utils";
4
5
  import { RightOutline } from "antd-mobile-icons";
5
6
  import dayjs from "dayjs";
6
7
 
@@ -9,6 +10,9 @@ import weekOfYear from "dayjs/plugin/weekOfYear";
9
10
 
10
11
  import { handleValue } from "./common/utils";
11
12
 
13
+ import PickerOutline from "../PickerRightOutline";
14
+ import Placeholder from "../Placeholder";
15
+
12
16
  import "./index.less";
13
17
 
14
18
  dayjs.extend(advancedFormat);
@@ -30,7 +34,18 @@ type fieldT = {
30
34
  dataSource: Array<Object>;
31
35
  };
32
36
 
33
- function DatePicker(props) {
37
+ type DatePickerPropsT = {
38
+ value: string | number | Object;
39
+ disabled: boolean;
40
+ readOnly: boolean;
41
+ placeholder: string;
42
+ format: string;
43
+ picker: string;
44
+ precision: Precision;
45
+ showTime: boolean;
46
+ onChange: (date: string | number) => void;
47
+ };
48
+ export const DatePicker = observer((props: DatePickerPropsT) => {
34
49
  const { value, disabled, readOnly, placeholder = "请选择", format, onChange } = props;
35
50
 
36
51
  const field: fieldT = useField();
@@ -40,25 +55,27 @@ function DatePicker(props) {
40
55
 
41
56
  const [visible, setVisible] = useState(false);
42
57
 
43
- const precision = useMemo(() => {
44
- if (props.picker) {
45
- return props.picker;
46
- }
58
+ const precision: Precision = useMemo(() => {
47
59
  if (props.precision) {
48
60
  return props.precision;
49
61
  }
50
62
  const {
51
- // time date month year
63
+ // time date month year decade quarter
52
64
  picker,
53
65
  showTime,
54
66
  } = props;
67
+ // TODO: 处理 季度、财年、时间 quarter decade time
55
68
  // 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'week' | 'week-day'
56
- let _precision = "day";
69
+ // @ts-ignore 兼容 PC 端配置
70
+ let _precision: Precision = picker || "day";
71
+ if (picker === "date") {
72
+ _precision = "day";
73
+ }
57
74
  if ((!picker || picker === "date") && showTime) {
58
75
  _precision = "second";
59
76
  }
60
77
  return _precision;
61
- }, [props.precision, props.picker, props.mode, props.showTime]);
78
+ }, [props.precision, props.picker, props.showTime]);
62
79
 
63
80
  useEffect(() => {
64
81
  if (dataSource) {
@@ -88,7 +105,7 @@ function DatePicker(props) {
88
105
  const _value = handleValue(value, formatStr, precision);
89
106
 
90
107
  return (
91
- <div className="picker-box formily-date-picker" onClick={onClick}>
108
+ <PickerOutline className="picker-box formily-date-picker" onClick={onClick}>
92
109
  <ADataPicker
93
110
  {...props}
94
111
  value={_value}
@@ -98,11 +115,10 @@ function DatePicker(props) {
98
115
  precision={precision}
99
116
  onConfirm={onConfirm}
100
117
  >
101
- {(val) => (val ? dayjs(val).format(formatStr) : <div className="placeholder">{placeholder}</div>)}
118
+ {(val) => (val ? dayjs(val).format(formatStr) : <Placeholder {...props} placeholder={placeholder} isPicker />)}
102
119
  </ADataPicker>
103
- <RightOutline className="picker-right-icon" />
104
- </div>
120
+ </PickerOutline>
105
121
  );
106
- }
122
+ });
107
123
 
108
- export default observer(DatePicker);
124
+ export default DatePicker;
@@ -1,19 +1,13 @@
1
1
  import React from "react";
2
- import { connect, mapProps } from "@formily/react";
3
2
  import { Stepper } from "antd-mobile";
4
3
 
5
4
  import "./index.less";
6
5
 
7
- function NumberPicker({ precision, className, ...props }) {
6
+ export const NumberPicker = ({ precision, className, ...props }) => {
8
7
  if (props.readOnly) {
9
8
  return props.value || "";
10
9
  }
11
10
  return <Stepper className={`number-picker ${className}`} {...props} digits={precision} />;
12
- }
11
+ };
13
12
 
14
- export default connect(
15
- NumberPicker,
16
- mapProps((props, field) => {
17
- return { ...props, form: field.form, field };
18
- }),
19
- );
13
+ export default NumberPicker;
@@ -1,14 +1,8 @@
1
1
  import React from "react";
2
- import { connect, mapProps } from "@formily/react";
3
2
  import { Input } from "antd-mobile";
4
3
 
5
- function Password(props) {
6
- return <Input {...props} type="password" placeholder={props.placeholder || "请输入"} />;
7
- }
4
+ export const Password = (props) => {
5
+ return <Input {...props} type="password" placeholder={!props.readOnly ? props.placeholder || "请输入" : ""} />;
6
+ };
8
7
 
9
- export default connect(
10
- Password,
11
- mapProps((props, field) => {
12
- return { ...props, form: field.form, field };
13
- }),
14
- );
8
+ export default Password;
@@ -0,0 +1,7 @@
1
+ .form-item-picker-right-outline {
2
+ display: flex;
3
+ justify-content: space-between;
4
+ align-items: center;
5
+ .picker-right-icon {
6
+ }
7
+ }
@@ -0,0 +1,14 @@
1
+ import { RightOutline } from "antd-mobile-icons";
2
+
3
+ import "./index.less";
4
+
5
+ export const PickerOutline = (props) => {
6
+ return (
7
+ <div {...props} className={`form-item-picker-right-outline ${props.className}`}>
8
+ {props.children}
9
+ <RightOutline className="picker-right-icon" />
10
+ </div>
11
+ );
12
+ };
13
+
14
+ export default PickerOutline;
@@ -0,0 +1,3 @@
1
+ .form-item-placeholder {
2
+ color: #ccc;
3
+ }
@@ -0,0 +1,18 @@
1
+ import "./index.less";
2
+
3
+ export const Placeholder = (props) => {
4
+ const { value, placeholder, className, isPicker } = props;
5
+ if (value !== null && value !== undefined && value !== "") {
6
+ return value;
7
+ }
8
+ if (props.readOnly) {
9
+ return <span></span>;
10
+ }
11
+ return (
12
+ <div {...props} className={`form-item-placeholder ${className}`}>
13
+ {placeholder || isPicker ? "请选择" : "请输入"}
14
+ </div>
15
+ );
16
+ };
17
+
18
+ export default Placeholder;
@@ -3,13 +3,23 @@ import { useField, observer } from "@formily/react";
3
3
  import { Picker } from "antd-mobile";
4
4
  import { RightOutline } from "antd-mobile-icons";
5
5
 
6
+ import PickerRightOutline from "../PickerRightOutline";
7
+ import Placeholder from "../Placeholder";
8
+
9
+ import { formItemProps } from "../form-item";
10
+
6
11
  import "./index.less";
7
12
 
8
13
  type fieldT = {
9
14
  dataSource: Array<Object>;
10
15
  };
11
16
 
12
- function Select(props) {
17
+ type SelectPropsT = {
18
+ value: number | string;
19
+ onChange: (val: any) => void;
20
+ } & formItemProps;
21
+
22
+ export const Select = observer((props: SelectPropsT) => {
13
23
  const { value, disabled, readOnly, placeholder = "请选择", onChange } = props;
14
24
 
15
25
  const field: fieldT = useField();
@@ -45,11 +55,12 @@ function Select(props) {
45
55
  }
46
56
 
47
57
  return (
48
- <div className="formily-select picker-box" onClick={onClick}>
58
+ <PickerRightOutline className="formily-select picker-box" onClick={onClick}>
49
59
  <Picker
50
60
  {...props}
51
61
  value={Array.isArray(value) ? value : [value]}
52
62
  style={{ pointerEvents: readOnly || disabled ? "none" : undefined }}
63
+ // @ts-ignore
53
64
  columns={_options}
54
65
  visible={visible}
55
66
  onClose={onClose}
@@ -59,13 +70,12 @@ function Select(props) {
59
70
  return items && items.length > 0 && items[0] ? (
60
71
  items[0]?.label
61
72
  ) : (
62
- <div className="placeholder">{placeholder || "请选择"}</div>
73
+ <Placeholder {...props} placeholder={placeholder} isPicker />
63
74
  );
64
75
  }}
65
76
  </Picker>
66
- <RightOutline className="picker-right-icon" />
67
- </div>
77
+ </PickerRightOutline>
68
78
  );
69
- }
79
+ });
70
80
 
71
- export default observer(Select);
81
+ export default Select;
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
- import { connect, mapProps } from "@formily/react";
3
2
 
4
- function Text({ value, mode, content, className, ...props }) {
3
+ export const Text = ({ value, mode, content, className, ...props }) => {
5
4
  const tagName = mode === "normal" || !mode ? "div" : mode;
6
5
  return React.createElement(
7
6
  tagName,
@@ -11,11 +10,6 @@ function Text({ value, mode, content, className, ...props }) {
11
10
  },
12
11
  value || content,
13
12
  );
14
- }
13
+ };
15
14
 
16
- export default connect(
17
- Text,
18
- mapProps((props, field) => {
19
- return { ...props, form: field.form, field };
20
- }),
21
- );
15
+ export default Text;
@@ -0,0 +1,63 @@
1
+ export function getTimeColumns(opt: any = {}) {
2
+ const { use12Hours, isPM } = opt || {};
3
+ const configList = [
4
+ {
5
+ stepKey: "hourStep",
6
+ max: 23,
7
+ },
8
+ {
9
+ stepKey: "minuteStep",
10
+ max: 59,
11
+ },
12
+ {
13
+ stepKey: "secondStep",
14
+ max: 59,
15
+ },
16
+ ];
17
+
18
+ const columns = [[], [], []];
19
+
20
+ if (use12Hours) {
21
+ columns.push([
22
+ {
23
+ label: "AM",
24
+ value: "AM",
25
+ },
26
+ {
27
+ label: "PM",
28
+ value: "PM",
29
+ },
30
+ ]);
31
+ }
32
+
33
+ configList?.forEach((conf, idx) => {
34
+ let i = 0;
35
+ let { max, stepKey } = conf;
36
+ let step = opt[stepKey] || 1;
37
+ if (step <= 0 || step > max) {
38
+ step = 1;
39
+ }
40
+
41
+ if (use12Hours && stepKey === "hourStep") {
42
+ max = 11;
43
+ if (isPM) {
44
+ columns[idx].push({
45
+ label: "12",
46
+ value: "00",
47
+ });
48
+ i = step;
49
+ }
50
+ }
51
+
52
+ while (i <= max) {
53
+ let _val = `${i > 9 ? i : "0" + i}`;
54
+ columns[idx].push({
55
+ label: _val,
56
+ value: _val,
57
+ });
58
+ i += step;
59
+ }
60
+ });
61
+
62
+ return columns;
63
+ }
@@ -0,0 +1,79 @@
1
+ import { useState, useMemo } from "react";
2
+ import { useField, observer } from "@formily/react";
3
+ import { Picker } from "antd-mobile";
4
+ import PickerRightOutline from "../PickerRightOutline";
5
+ import Placeholder from "../Placeholder";
6
+ import { getTimeColumns } from "./common/utils";
7
+ import { formItemProps } from "../form-item";
8
+
9
+ type TimePickerPropsT = {
10
+ use12Hours: boolean;
11
+ } & formItemProps;
12
+
13
+ export const TimePicker = observer((props: TimePickerPropsT) => {
14
+ const { value, disabled, readOnly, placeholder = "请选择", use12Hours, onChange } = props;
15
+ const field: any = useField();
16
+ const {} = field;
17
+ const [visible, setVisible] = useState(false);
18
+ const [columns, setColumns] = useState(getTimeColumns(props));
19
+
20
+ function onConfirm(val) {
21
+ // 数据进行合并
22
+ let resVal = val?.join(":");
23
+ if (use12Hours) {
24
+ if (val[3] === "PM" && val[0] == 0) {
25
+ val[0] = 12;
26
+ }
27
+ resVal = [...val]?.slice(0, 3)?.join(":");
28
+ resVal += ` ${val[3] || ""}`;
29
+ }
30
+ onChange && onChange(resVal);
31
+ }
32
+
33
+ function onSelect(v, ...args) {
34
+ if (use12Hours && v?.[3] == "PM") {
35
+ setColumns(getTimeColumns({ ...props, isPM: true }));
36
+ } else {
37
+ setColumns(getTimeColumns(props));
38
+ }
39
+ }
40
+
41
+ function onClick() {
42
+ if (readOnly || disabled) {
43
+ return;
44
+ }
45
+ setVisible((val) => {
46
+ return !val;
47
+ });
48
+ }
49
+
50
+ // 拆分字符串数据并转为数字格式
51
+ let pickerVal = value?.split(":");
52
+ if (use12Hours && pickerVal && pickerVal.length > 0) {
53
+ const t = pickerVal[2];
54
+ pickerVal.splice(2, 1, t.split(" ")?.[0]);
55
+ pickerVal.push(t.split(" ")?.[1]);
56
+ if (pickerVal[3] === "PM" && pickerVal[0] == 12) {
57
+ pickerVal[0] = "00";
58
+ }
59
+ }
60
+
61
+ return (
62
+ <PickerRightOutline className="picker-box formily-time-picker" onClick={onClick}>
63
+ <Picker
64
+ {...props}
65
+ value={pickerVal}
66
+ visible={visible}
67
+ columns={columns}
68
+ onSelect={onSelect}
69
+ onClose={() => {
70
+ setVisible(false);
71
+ }}
72
+ onConfirm={onConfirm}
73
+ />
74
+ <Placeholder {...props} value={value} placeholder={placeholder} />
75
+ </PickerRightOutline>
76
+ );
77
+ });
78
+
79
+ export default TimePicker;
@@ -1,4 +1,4 @@
1
- import axios from "axios";
1
+ import { axios } from "@hzab/data-model";
2
2
 
3
3
  export function getSignature(opt = {}) {
4
4
  const { serverUrl = "/api/v1/user/oss/getWebOssConfig" } = opt;
@@ -1,8 +1,6 @@
1
- import { connect, mapProps } from "@formily/react";
1
+ import UploaderCom from "./uploader";
2
2
 
3
- import Uploader from "./uploader";
4
-
5
- function UploaderCom(props) {
3
+ export const Uploader = (props) => {
6
4
  const { field = {}, onChange, value } = props;
7
5
  const { name, mode, componentProps = {} } = field;
8
6
  const { multiple } = componentProps;
@@ -29,12 +27,7 @@ function UploaderCom(props) {
29
27
  ...componentProps,
30
28
  };
31
29
 
32
- return <Uploader {..._props} onChange={onUploadChange} />;
33
- }
30
+ return <UploaderCom {..._props} onChange={onUploadChange} />;
31
+ };
34
32
 
35
- export default connect(
36
- UploaderCom,
37
- mapProps((props, field) => {
38
- return { ...props, form: field.form, field };
39
- }),
40
- );
33
+ export default Uploader;
@@ -0,0 +1,7 @@
1
+ export type formItemProps = {
2
+ value: any;
3
+ disabled: boolean;
4
+ readOnly: boolean;
5
+ placeholder: string;
6
+ onChange: (val: any) => void;
7
+ };
@@ -1,13 +1,11 @@
1
- import Text from "./Text";
2
- import Select from "./Select";
3
- import Cascader from "./Cascader";
4
- import NumberPicker from "./NumberPicker";
5
- import DatePicker from "./DatePicker";
6
- import Password from "./Password";
7
- import Uploader from "./Uploader";
8
-
9
1
  export * from "./ArrayCards";
10
2
  export * from "./ArrayTable";
3
+ export * from "./Cascader";
4
+ export * from "./DatePicker";
11
5
  export * from "./FormCollapse";
12
-
13
- export { NumberPicker, Password, Select, Cascader, DatePicker, Text, Uploader };
6
+ export * from "./NumberPicker";
7
+ export * from "./Password";
8
+ export * from "./Select";
9
+ export * from "./Text";
10
+ export * from "./TimePicker";
11
+ export * from "./Uploader";
package/src/index.less CHANGED
@@ -16,4 +16,13 @@
16
16
  align-items: center;
17
17
  }
18
18
  }
19
+
20
+ &.form-render-detail {
21
+ .adm-formily-item-asterisk {
22
+ display: none;
23
+ }
24
+ .adm-selector-item-disabled {
25
+ opacity: 1;
26
+ }
27
+ }
19
28
  }
package/src/index.tsx CHANGED
@@ -30,6 +30,7 @@ import { formPropsI } from "./type.d";
30
30
  import "./index.less";
31
31
 
32
32
  const FormRender = forwardRef((props: formPropsI, parentRef) => {
33
+ const { isDetail, readOnly } = props;
33
34
  const SchemaField = useMemo(
34
35
  () =>
35
36
  createSchemaField({
@@ -64,7 +65,7 @@ const FormRender = forwardRef((props: formPropsI, parentRef) => {
64
65
  createForm({
65
66
  initialValues: props.initialValues,
66
67
  // 禁用状态(注意,自定义组件组件自行获取对应的状态)
67
- readOnly: props.readOnly,
68
+ readOnly: readOnly || isDetail,
68
69
  disabled: props.disabled,
69
70
  ...(props.formOptions || {}),
70
71
  }),
@@ -82,11 +83,11 @@ const FormRender = forwardRef((props: formPropsI, parentRef) => {
82
83
  }, [props.schema]);
83
84
 
84
85
  return (
85
- <div className={`form-render ${props.className}`}>
86
+ <div className={`form-render ${props.className} ${isDetail ? "form-render-detail" : ""}`}>
86
87
  <FormProvider form={formRender}>
87
88
  {/* @ts-ignore */}
88
89
  <SchemaField schema={schema} />
89
- {props.hasSubmit !== false ? (
90
+ {props.hasSubmit !== false && isDetail !== true && readOnly !== true && !props.disabled ? (
90
91
  <FormButtonGroup>
91
92
  <Submit
92
93
  onSubmit={(values) => {
package/src/type.d.ts CHANGED
@@ -13,6 +13,8 @@ export interface formPropsI {
13
13
  schemaScope?: Object;
14
14
  /** formily 自定义组件 */
15
15
  components?: SchemaReactComponents;
16
+ /** 是否详情页面 */
17
+ isDetail?: boolean;
16
18
  /** 是否只读 */
17
19
  readOnly?: boolean;
18
20
  /** 是否禁用 */