@ecoding/components.antd 0.0.2 → 0.0.3

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.
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import type { BaseOptionType } from "antd/lib/cascader";
3
+ interface IFace {
4
+ url: string;
5
+ paramKey?: string;
6
+ paramValue?: string;
7
+ method?: string;
8
+ cache?: boolean;
9
+ format?: {
10
+ [props: string]: any;
11
+ isLeaf: boolean;
12
+ };
13
+ params?: any;
14
+ fromKey?: string[] | string;
15
+ }
16
+ interface IProps {
17
+ ifaces: IFace[];
18
+ placeholder?: string;
19
+ onChange?: (value: any, selectedOptions?: BaseOptionType[]) => void;
20
+ className?: string;
21
+ value?: string[] | number[];
22
+ style?: React.CSSProperties;
23
+ disabled?: boolean;
24
+ }
25
+ declare const AsyncCascader: React.FC<IProps>;
26
+ export default AsyncCascader;
@@ -0,0 +1,181 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useCallback, useEffect, useState, memo, useMemo } from "react";
11
+ import { Cascader } from "antd";
12
+ import { LoadingOutlined } from "@ant-design/icons";
13
+ import { r } from "../../helpers/http";
14
+ import { isSomething } from "@ecoding/helper.is";
15
+ import { jsonFormatNewKey } from "@ecoding/helper.json";
16
+ const setSourceChilren = (source, key, res) => {
17
+ const ex = (ary) => {
18
+ for (let i = 0; i < ary.length; i++) {
19
+ // eslint-disable-next-line eqeqeq
20
+ if (ary[i].value == key) {
21
+ ary[i].children = res;
22
+ break;
23
+ }
24
+ if (ary[i].children && ary[i].children.length > 0) {
25
+ ex(ary[i].children);
26
+ }
27
+ }
28
+ };
29
+ ex(source);
30
+ return source;
31
+ };
32
+ const AsyncCascader = memo((props) => {
33
+ const [loading, setLoading] = useState(true);
34
+ const [options, setOptions] = useState([]);
35
+ const interfaceUrls = useMemo(() => props.ifaces || [], []);
36
+ useEffect(() => {
37
+ const ex = () => __awaiter(void 0, void 0, void 0, function* () {
38
+ const innerEx = () => __awaiter(void 0, void 0, void 0, function* () {
39
+ var _a;
40
+ // 获得第一个接口信息
41
+ const firIFace = interfaceUrls[0];
42
+ let firParams = {};
43
+ if (firIFace.paramKey) {
44
+ // 设置接口调用参数
45
+ firParams[firIFace.paramKey] = firIFace.paramValue;
46
+ }
47
+ if (firIFace.params) {
48
+ firParams = Object.assign({}, firParams, firIFace.params);
49
+ }
50
+ let firResOrigin = [];
51
+ const firMapCache = isSomething(firIFace.cache) ? firIFace.cache : false;
52
+ // 获取第一级联数据
53
+ if (((_a = firIFace.method) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === "post") {
54
+ firResOrigin = yield r.post(firIFace.url, firParams, { cache: firMapCache });
55
+ }
56
+ else {
57
+ firResOrigin = yield r.get(firIFace.url, firParams, { cache: firMapCache });
58
+ }
59
+ // 指定数据key
60
+ if (firIFace && firIFace.fromKey) {
61
+ if (Array.isArray(firIFace.fromKey)) {
62
+ firIFace.fromKey.forEach((key) => {
63
+ firResOrigin = firResOrigin[key];
64
+ });
65
+ }
66
+ else {
67
+ firResOrigin = firResOrigin[firIFace.fromKey];
68
+ }
69
+ }
70
+ const res = jsonFormatNewKey(firResOrigin, firIFace.format);
71
+ const opts = res;
72
+ // 踢除第一级联的接口,剩下接口根据value数组遍历请求
73
+ const afterFirFaces = interfaceUrls.slice(1);
74
+ // 踢除级联最后一位的value,最后的级联不需要请求
75
+ const ary = (props.value && props.value.slice(0, props.value.length - 1)) || [];
76
+ // 异步遍历请求开始
77
+ if (ary && ary.length > 0) {
78
+ return new Promise((resolve) => __awaiter(void 0, void 0, void 0, function* () {
79
+ let i = -1;
80
+ let temp = [];
81
+ const exx = () => __awaiter(void 0, void 0, void 0, function* () {
82
+ var _b;
83
+ i++;
84
+ if (i >= ary.length) {
85
+ return;
86
+ }
87
+ const iFace = afterFirFaces[i];
88
+ let params = {};
89
+ if (iFace.paramKey) {
90
+ // 设置接口调用参数
91
+ params[iFace.paramKey] = ary[i];
92
+ }
93
+ if (iFace.params) {
94
+ params = Object.assign({}, params, iFace.params);
95
+ }
96
+ // 获取当前级联数据
97
+ let resOrigin = [];
98
+ const cache = isSomething(iFace.cache) ? iFace.cache : false;
99
+ if (((_b = iFace.method) === null || _b === void 0 ? void 0 : _b.toLocaleLowerCase()) === "post") {
100
+ resOrigin = yield r.post(iFace.url, params, { cache });
101
+ }
102
+ else {
103
+ resOrigin = yield r.get(iFace.url, params, { cache });
104
+ }
105
+ // 指定数据key
106
+ if (iFace && iFace.fromKey) {
107
+ if (Array.isArray(iFace.fromKey)) {
108
+ iFace.fromKey.forEach((key) => {
109
+ resOrigin = resOrigin[key];
110
+ });
111
+ }
112
+ else {
113
+ resOrigin = resOrigin[iFace.fromKey];
114
+ }
115
+ }
116
+ const formatRes = jsonFormatNewKey(resOrigin, iFace.format);
117
+ temp = setSourceChilren(opts, ary[i], formatRes);
118
+ if (i < ary.length) {
119
+ yield exx();
120
+ }
121
+ });
122
+ yield exx();
123
+ resolve(temp);
124
+ }));
125
+ }
126
+ // 异步遍历请求结束
127
+ // ary.lenth < 0 return first res
128
+ return Promise.resolve(res);
129
+ });
130
+ const res = yield innerEx();
131
+ setOptions(res);
132
+ setLoading(false);
133
+ });
134
+ ex();
135
+ }, []);
136
+ const loadData = useCallback((selectedOptions) => __awaiter(void 0, void 0, void 0, function* () {
137
+ var _a;
138
+ const len = selectedOptions.length;
139
+ const targetOption = selectedOptions[len - 1];
140
+ // 获得接口信息
141
+ const iFace = interfaceUrls[len];
142
+ let params = {};
143
+ if (iFace && iFace.paramKey) {
144
+ // 设置接口调用参数
145
+ params[iFace.paramKey] = targetOption.value;
146
+ }
147
+ if (iFace.params) {
148
+ params = Object.assign({}, params, iFace.params);
149
+ }
150
+ targetOption.loading = true;
151
+ // 获取当前级联数据
152
+ let resOrigin = [];
153
+ const cache = isSomething(iFace.cache) ? iFace.cache : false;
154
+ if (((_a = iFace.method) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === "post") {
155
+ resOrigin = yield r.post(iFace.url, params, { cache });
156
+ }
157
+ else {
158
+ resOrigin = yield r.get(iFace.url, params, { cache });
159
+ }
160
+ // 指定数据key
161
+ if (iFace && iFace.fromKey) {
162
+ if (Array.isArray(iFace.fromKey)) {
163
+ iFace.fromKey.forEach((key) => {
164
+ resOrigin = resOrigin[key];
165
+ });
166
+ }
167
+ else {
168
+ resOrigin = resOrigin[iFace.fromKey];
169
+ }
170
+ }
171
+ const res = jsonFormatNewKey(resOrigin, iFace.format);
172
+ targetOption.loading = false;
173
+ targetOption.children = res;
174
+ setOptions([...options]);
175
+ }), [options]);
176
+ if (loading) {
177
+ return React.createElement(LoadingOutlined, { style: { color: "#3E4D5B" } });
178
+ }
179
+ return React.createElement(Cascader, Object.assign({}, props, { options: options, loadData: loadData, changeOnSelect: true }));
180
+ });
181
+ export default AsyncCascader;
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import type { SelectProps } from "antd/lib/select";
3
+ interface IFace {
4
+ url: string;
5
+ paramKey?: string;
6
+ paramValue?: string;
7
+ params?: any;
8
+ cache?: boolean;
9
+ method?: string;
10
+ fromKey?: string[] | string;
11
+ format?: {
12
+ [props: string]: any;
13
+ };
14
+ }
15
+ interface IData {
16
+ datas: any;
17
+ format?: {
18
+ [props: string]: any;
19
+ };
20
+ }
21
+ interface IProps extends SelectProps<any> {
22
+ iface?: IFace;
23
+ data?: IData;
24
+ }
25
+ declare const AsyncSlect: React.FC<IProps>;
26
+ export default AsyncSlect;
@@ -0,0 +1,87 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useEffect, useState, memo, useMemo } from "react";
11
+ import { Select } from "antd";
12
+ import { LoadingOutlined } from "@ant-design/icons";
13
+ import { r } from "../../helpers/http";
14
+ import { isSomething } from "@ecoding/helper.is";
15
+ import { jsonFormatNewKey } from "@ecoding/helper.json";
16
+ const { Option } = Select;
17
+ const AsyncSlect = memo((props) => {
18
+ const [loading, setLoading] = useState(true);
19
+ const [options, setOptions] = useState([]);
20
+ const iface = useMemo(() => props.iface, []);
21
+ const data = useMemo(() => props.data, []);
22
+ useEffect(() => {
23
+ const ex = () => __awaiter(void 0, void 0, void 0, function* () {
24
+ const innerEx = () => __awaiter(void 0, void 0, void 0, function* () {
25
+ var _a;
26
+ // 获得第一个接口信息
27
+ if (data) {
28
+ const res = data.format ? jsonFormatNewKey(data.datas, data.format) : data.datas;
29
+ return Promise.resolve(res);
30
+ }
31
+ let params = {};
32
+ if (iface) {
33
+ if (iface.paramKey) {
34
+ // 设置接口调用参数
35
+ params[iface.paramKey] = iface.paramValue;
36
+ }
37
+ if (iface.params) {
38
+ params = Object.assign({}, params, iface.params);
39
+ }
40
+ let resOrigin = [];
41
+ // 这里支持了外部直接传入列表结果
42
+ const cache = isSomething(iface.cache) ? iface.cache : false;
43
+ if (((_a = iface.method) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === "post") {
44
+ resOrigin = yield r.post(iface.url, params, { cache });
45
+ }
46
+ else {
47
+ resOrigin = yield r.get(iface.url, params, { cache });
48
+ }
49
+ // 指定数据key
50
+ if (iface && iface.fromKey) {
51
+ if (Array.isArray(iface.fromKey)) {
52
+ iface.fromKey.forEach((key) => {
53
+ resOrigin = resOrigin[key];
54
+ });
55
+ }
56
+ else {
57
+ resOrigin = resOrigin[iface.fromKey];
58
+ }
59
+ }
60
+ const res = jsonFormatNewKey(resOrigin, iface.format);
61
+ return Promise.resolve(res);
62
+ }
63
+ return Promise.reject("没有iface或data");
64
+ });
65
+ const res = yield innerEx();
66
+ setOptions(res);
67
+ setLoading(false);
68
+ });
69
+ ex();
70
+ }, []);
71
+ const children = useMemo(() => {
72
+ return (options &&
73
+ options.map((item) => {
74
+ return (React.createElement(Option, { key: item.value, value: item.value }, item.label));
75
+ }));
76
+ }, [options]);
77
+ if (loading) {
78
+ return React.createElement(LoadingOutlined, { style: { color: "#3E4D5B" } });
79
+ }
80
+ return (React.createElement(Select, Object.assign({ filterOption: (input, option) => {
81
+ if (Array.isArray(option.children)) {
82
+ return option.children.join("").toLowerCase().indexOf(input.toLowerCase()) >= 0;
83
+ }
84
+ return option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
85
+ }, allowClear: true, showSearch: true, optionFilterProp: "children" }, props), children));
86
+ });
87
+ export default AsyncSlect;
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import { TransferProps } from "antd/lib/transfer";
3
+ interface IFace {
4
+ url: string;
5
+ paramKey?: string;
6
+ paramValue?: string;
7
+ method?: string;
8
+ cache?: boolean;
9
+ format?: {
10
+ [props: string]: any;
11
+ };
12
+ params?: any;
13
+ fromKey?: string[] | string;
14
+ }
15
+ interface IProps extends TransferProps<any> {
16
+ iface?: IFace;
17
+ onChange?: any;
18
+ width?: number;
19
+ value?: any;
20
+ }
21
+ declare const AsyncTransfer: React.FC<IProps>;
22
+ export default AsyncTransfer;
@@ -0,0 +1,96 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useEffect, useState, memo, useMemo, useCallback } from "react";
11
+ import { Transfer } from "antd";
12
+ import zhCN from "antd/lib/locale/zh_CN";
13
+ import { LoadingOutlined } from "@ant-design/icons";
14
+ import { r } from "../../helpers/http";
15
+ import { isSomething } from "@ecoding/helper.is";
16
+ import { jsonFormatNewKey } from "@ecoding/helper.json";
17
+ const AsyncTransfer = memo((props) => {
18
+ const [loading, setLoading] = useState(true);
19
+ const [dataSource, setDataSource] = useState(props.dataSource || []);
20
+ const [targetKeys, setTargetKeys] = useState([]);
21
+ const [selectedKeys, setSelectedKeys] = useState([]);
22
+ const iface = useMemo(() => props.iface, []);
23
+ useEffect(() => {
24
+ const ex = () => __awaiter(void 0, void 0, void 0, function* () {
25
+ const innerEx = () => __awaiter(void 0, void 0, void 0, function* () {
26
+ var _a;
27
+ // 获得第一个接口信息
28
+ let params = {};
29
+ if (iface.paramKey) {
30
+ // 设置接口调用参数
31
+ params[iface.paramKey] = iface.paramValue;
32
+ }
33
+ if (iface.params) {
34
+ params = Object.assign({}, params, iface.params);
35
+ }
36
+ let resOrigin = [];
37
+ const cache = isSomething(iface.cache) ? iface.cache : false;
38
+ if (((_a = iface.method) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === "post") {
39
+ resOrigin = yield r.post(iface.url, params, { cache });
40
+ }
41
+ else {
42
+ resOrigin = yield r.get(iface.url, params, { cache });
43
+ }
44
+ // 指定数据key
45
+ if (iface && iface.fromKey) {
46
+ if (Array.isArray(iface.fromKey)) {
47
+ iface.fromKey.forEach((key) => {
48
+ resOrigin = resOrigin[key];
49
+ });
50
+ }
51
+ else {
52
+ resOrigin = resOrigin[iface.fromKey];
53
+ }
54
+ }
55
+ const res = jsonFormatNewKey(resOrigin, iface.format);
56
+ return Promise.resolve(res);
57
+ });
58
+ const res = yield innerEx();
59
+ setDataSource(res);
60
+ setTargetKeys(props.value || []);
61
+ setLoading(false);
62
+ });
63
+ if (dataSource && dataSource.length > 0) {
64
+ setTargetKeys(props.value || []);
65
+ setLoading(false);
66
+ return;
67
+ }
68
+ ex();
69
+ }, []);
70
+ const onChange = useCallback((nextTargetKeys, direction, moveKeys) => {
71
+ // console.log('targetKeys:', nextTargetKeys);
72
+ // console.log('moveKeys:', moveKeys);
73
+ setTargetKeys(nextTargetKeys);
74
+ props.onChange(nextTargetKeys);
75
+ }, []);
76
+ const onSelectChange = useCallback((sourceSelectedKeys, targetSelectedKeys) => {
77
+ // console.log('sourceSelectedKeys:', sourceSelectedKeys);
78
+ // console.log('targetSelectedKeys:', targetSelectedKeys);
79
+ setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
80
+ }, []);
81
+ if (loading) {
82
+ return React.createElement(LoadingOutlined, { style: { color: "#3E4D5B" } });
83
+ }
84
+ return (React.createElement(Transfer, Object.assign({ filterOption: (input, option) => {
85
+ if (Array.isArray(option.label)) {
86
+ return option.label.join("").toLowerCase().indexOf(input.toLowerCase()) >= 0;
87
+ }
88
+ return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
89
+ }, oneWay: true, showSearch: true, showSelectAll: true, titles: ["选择源", "已选择"], render: (item) => item.label, locale: zhCN.Transfer, pagination: { pageSize: 10 } }, props, { listStyle: props.listStyle && JSON.stringify(props.listStyle) !== "{}"
90
+ ? props.listStyle
91
+ : {
92
+ width: props.width || 300,
93
+ height: 300
94
+ }, onChange: onChange, onSelectChange: onSelectChange, targetKeys: targetKeys, selectedKeys: selectedKeys, dataSource: dataSource })));
95
+ });
96
+ export default AsyncTransfer;
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ interface IProps {
3
+ placeholder?: string;
4
+ value?: string;
5
+ max?: number;
6
+ onChange?: any;
7
+ className?: string;
8
+ style?: React.CSSProperties;
9
+ disabled?: boolean;
10
+ }
11
+ declare const LengthInput: React.FC<IProps>;
12
+ export default LengthInput;
@@ -0,0 +1,79 @@
1
+ import React, { useCallback, useEffect, useState, useRef } from "react";
2
+ import { Input } from "antd";
3
+ const LengthInput = (props) => {
4
+ const isCompositionStart = useRef(false);
5
+ const [n, setN] = useState(0);
6
+ const [v, setV] = useState(props.value || "");
7
+ const setString = useCallback((str, len) => {
8
+ let strlen = 0;
9
+ let s = "";
10
+ for (let i = 0; i < str.length; i++) {
11
+ // eslint-disable-next-line no-control-regex
12
+ const m = str.charAt(i).match(/[^\x00-\x80]/g); // 利用match方法检索出中文字符并返回一个存放中文的数
13
+ if (m != null && m.length > 0) {
14
+ strlen += 2;
15
+ }
16
+ else {
17
+ strlen++;
18
+ }
19
+ s += str.charAt(i);
20
+ if (strlen >= len) {
21
+ return s;
22
+ }
23
+ }
24
+ return s;
25
+ }, []);
26
+ const getLen = useCallback((str) => {
27
+ // 获取字符串的真实长度(字节长度)
28
+ if (!str) {
29
+ return 0;
30
+ }
31
+ const len = str.length;
32
+ let truelen = 0;
33
+ for (let x = 0; x < len; x++) {
34
+ if (str.charCodeAt(x) > 128) {
35
+ truelen += 2;
36
+ }
37
+ else {
38
+ truelen += 1;
39
+ }
40
+ }
41
+ return truelen;
42
+ }, []);
43
+ const keyUpHandler = useCallback((e) => {
44
+ let vs = e.target.value;
45
+ let len = getLen(vs);
46
+ if (!isCompositionStart.current && len > props.max) {
47
+ vs = setString(vs, props.max);
48
+ len = getLen(vs);
49
+ }
50
+ setV(vs);
51
+ setN(len);
52
+ e.target.value = vs;
53
+ // 估计form表单会默认有onChange事件
54
+ props.onChange(e);
55
+ }, []);
56
+ useEffect(() => {
57
+ setV(props.value || "");
58
+ }, [props]);
59
+ useEffect(() => {
60
+ const vs = props.value || "";
61
+ const len = getLen(vs);
62
+ setN(len);
63
+ }, [props]);
64
+ const compositionStartHandler = useCallback(() => {
65
+ isCompositionStart.current = true;
66
+ }, []);
67
+ const compositionEndHandler = useCallback((e) => {
68
+ isCompositionStart.current = false;
69
+ keyUpHandler(e);
70
+ }, []);
71
+ return (React.createElement(Input, Object.assign({}, props, { value: v, onCompositionStart: compositionStartHandler, onCompositionEnd: compositionEndHandler, onChange: keyUpHandler, suffix: React.createElement("div", { style: { color: "#666" } },
72
+ n,
73
+ React.createElement("span", { style: { padding: "0 2px" } }, "/"),
74
+ props.max) })));
75
+ };
76
+ LengthInput.defaultProps = {
77
+ max: 30
78
+ };
79
+ export default LengthInput;
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ interface IProps {
3
+ action?: string;
4
+ value?: string;
5
+ className?: string;
6
+ style?: any;
7
+ onChange?: any;
8
+ gif?: boolean;
9
+ size?: number;
10
+ disabled?: boolean;
11
+ }
12
+ declare const Quill: React.FC<IProps>;
13
+ export default Quill;
@@ -0,0 +1,136 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useMemo, useCallback, useState, useRef, lazy } from "react";
11
+ import { Upload, message } from "antd";
12
+ import Toast from "../../core/toast";
13
+ import { r } from "../../helpers/http";
14
+ const ReactQuill = lazy(() => import(/* webpackChunkName: "ReactQuill" */ /* webpackPrefetch: true */ "react-quill"));
15
+ const Quill = (props) => {
16
+ const upRef = useRef();
17
+ const quillRef = useRef();
18
+ const [urlParams, setUrlParams] = useState("");
19
+ const modules = useMemo(() => {
20
+ return {
21
+ toolbar: {
22
+ container: [
23
+ ["bold", "italic", "underline", "strike"],
24
+ ["blockquote", "code-block"],
25
+ [{ header: 1 }, { header: 2 }],
26
+ [{ list: "ordered" }, { list: "bullet" }],
27
+ [{ script: "sub" }, { script: "super" }],
28
+ [{ indent: "-1" }, { indent: "+1" }],
29
+ [{ direction: "rtl" }],
30
+ [{ size: ["small", false, "large", "huge"] }],
31
+ [{ header: [1, 2, 3, 4, 5, 6, false] }],
32
+ [{ color: [] }, { background: [] }],
33
+ [{ font: [] }],
34
+ [{ align: [] }],
35
+ ["link", "image"],
36
+ ["clean"]
37
+ ],
38
+ handlers: {
39
+ image: (value) => {
40
+ if (value) {
41
+ // ref.current && upRef.current.upload.uploader.uploadFiles([file]);
42
+ upRef.current && upRef.current.upload.uploader.fileInput.click();
43
+ }
44
+ else {
45
+ quillRef.current.format("image", false);
46
+ }
47
+ }
48
+ }
49
+ }
50
+ };
51
+ }, []);
52
+ const getBase64 = useCallback((imgFile) => {
53
+ return new Promise((resolve) => {
54
+ const reader = new FileReader();
55
+ reader.addEventListener("load", () => resolve(reader.result));
56
+ reader.readAsDataURL(imgFile);
57
+ });
58
+ }, []);
59
+ const getImgwh = useCallback((base64) => {
60
+ return new Promise((resolve, reject) => {
61
+ const img = new Image();
62
+ img.onload = () => {
63
+ // 宽度固定
64
+ resolve({
65
+ w: img.width,
66
+ h: img.height
67
+ });
68
+ };
69
+ img.onerror = () => reject();
70
+ img.src = base64;
71
+ });
72
+ }, []);
73
+ const beforeUpload = useCallback((file) => {
74
+ return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
75
+ const ary = ["jpg", "jpeg", "png"];
76
+ if (props.gif) {
77
+ ary.push("gif");
78
+ }
79
+ const isLt2M = file.size / 1024 / 1024 < (props.size || 1);
80
+ if (!isLt2M) {
81
+ message.error(`图片大小必须小于${props.size} MB!`);
82
+ reject();
83
+ }
84
+ if (ary.indexOf(file.type.toLowerCase().replace(/image\//g, "")) === -1) {
85
+ message.error(`请上传 ${ary.join(",")} 格式的图片!`);
86
+ reject();
87
+ }
88
+ const base64 = yield getBase64(file);
89
+ const wh = yield getImgwh(base64);
90
+ setUrlParams(`height=${wh.h}`);
91
+ resolve();
92
+ }));
93
+ }, []);
94
+ const handleChange = (info) => {
95
+ switch (info.file.status) {
96
+ case "uploading":
97
+ break;
98
+ case "done":
99
+ const url = info.file.response.data && info.file.response.data[0].imageUrl;
100
+ // setImageUrl(url);
101
+ // 获取富文本组件实例
102
+ const quill = quillRef.current.getEditor();
103
+ // 获取光标所在位置
104
+ const length = quill.getSelection().index;
105
+ // 插入图片,res为服务器返回的图片链接地址
106
+ quill.insertEmbed(length, "image", url);
107
+ // 调整光标到最后
108
+ quill.setSelection(length + 1);
109
+ break;
110
+ case "error":
111
+ Toast.error({
112
+ mask: true,
113
+ title: info.file.response
114
+ ? info.file.response.retDesc || info.file.response.desc || info.file.response.message
115
+ : "服务出错,图片上传失败"
116
+ });
117
+ break;
118
+ default:
119
+ break;
120
+ }
121
+ };
122
+ const action = /^http|^\/\//i.test(props.action) ? `${props.action}?${urlParams}` : `${r.domain}${props.action}?${urlParams}`;
123
+ return (React.createElement(React.Suspense, { fallback: null },
124
+ React.createElement(ReactQuill, { onChange: props.onChange, defaultValue: props.value, ref: quillRef, modules: modules, theme: "snow", className: props.className, style: props.style }),
125
+ React.createElement("span", { style: { display: "none" } },
126
+ React.createElement(Upload, { ref: upRef, withCredentials: true, beforeUpload: beforeUpload, name: "file", listType: "picture-card", showUploadList: false, action: action, onChange: handleChange }))));
127
+ };
128
+ Quill.defaultProps = {
129
+ action: "/upload/img",
130
+ value: "",
131
+ gif: false,
132
+ size: 1,
133
+ className: "",
134
+ style: {}
135
+ };
136
+ export default Quill;
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import { UploadFile } from "antd/lib/upload/interface";
3
+ interface IProps {
4
+ action: string;
5
+ buttonText?: string;
6
+ type?: string;
7
+ name?: string;
8
+ uploadRef?: any;
9
+ onChange?: (file: UploadFile) => void;
10
+ onDone?: (file: UploadFile, res: any) => void;
11
+ onRemove?: (file: UploadFile) => void;
12
+ onError?: (file: UploadFile) => void;
13
+ disabled?: boolean;
14
+ icon?: boolean;
15
+ openFileDialogOnClick?: boolean;
16
+ style?: React.CSSProperties;
17
+ }
18
+ declare const SingleFileUpload: React.FC<IProps>;
19
+ export default SingleFileUpload;
@@ -0,0 +1,84 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useCallback, useMemo, useState } from "react";
11
+ import { Upload, message, Button } from "antd";
12
+ import { UploadOutlined } from "@ant-design/icons";
13
+ import { buildURL } from "@ecoding/helper.url";
14
+ import Toast from "../../core/toast";
15
+ import { r } from "../../helpers/http";
16
+ const SingleFileUpload = (props) => {
17
+ const [urlParams, setUrlParams] = useState({});
18
+ const action = useMemo(() => {
19
+ return /^http|^\/\//i.test(props.action) ? buildURL(props.action, urlParams) : buildURL(`${r.domain}${props.action}`, urlParams);
20
+ }, [urlParams]);
21
+ const handleChange = (info) => {
22
+ props.onChange && props.onChange(info.file);
23
+ switch (info.file.status) {
24
+ case "uploading":
25
+ break;
26
+ case "done":
27
+ const response = info.file.response;
28
+ if (response && (response.code === 200 || response.retCode === 200)) {
29
+ props.onDone && props.onDone(info.file, info.file.response.data);
30
+ }
31
+ else {
32
+ Toast.error({
33
+ mask: true,
34
+ title: info.file.response
35
+ ? info.file.response.retDesc || info.file.response.desc || info.file.response.message
36
+ : "服务出错,文件上传失败"
37
+ });
38
+ }
39
+ break;
40
+ case "error":
41
+ Toast.error({
42
+ mask: true,
43
+ title: info.file.response
44
+ ? info.file.response.retDesc || info.file.response.desc || info.file.response.message
45
+ : "服务出错,文件上传失败"
46
+ });
47
+ props.onError && props.onError(info.file);
48
+ break;
49
+ default:
50
+ break;
51
+ }
52
+ };
53
+ const beforeUpload = useCallback((file) => {
54
+ return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
55
+ const ary = ["jpg", "jpeg", "png", "gif"];
56
+ if (ary.indexOf(file.type.toLowerCase().replace(/image\//g, "")) !== -1) {
57
+ message.error("上传图片请使用 SingleImgUpload 组件");
58
+ reject(new Error("上传图片请使用 SingleImgUpload 组件"));
59
+ return;
60
+ }
61
+ const fileExtension = file.name && file.name.split(".").pop().toLowerCase();
62
+ if (fileExtension && props.type.indexOf(fileExtension) === -1) {
63
+ message.error(`请上传 ${props.type} 格式的文件!`);
64
+ reject();
65
+ return;
66
+ }
67
+ resolve();
68
+ }));
69
+ }, []);
70
+ return (React.createElement(Upload, { ref: props.uploadRef, withCredentials: true, openFileDialogOnClick: props.openFileDialogOnClick, beforeUpload: beforeUpload, name: props.name, disabled: props.disabled, action: action, onChange: handleChange, onRemove: (e) => {
71
+ console.log(e);
72
+ props.onRemove && props.onRemove(e);
73
+ }, maxCount: 1 },
74
+ React.createElement(Button, { icon: props.icon ? React.createElement(UploadOutlined, null) : null }, props.buttonText)));
75
+ };
76
+ SingleFileUpload.defaultProps = {
77
+ name: "file",
78
+ openFileDialogOnClick: true,
79
+ icon: true,
80
+ buttonText: "点击上传",
81
+ type: "xls, xlsx, txt",
82
+ style: {}
83
+ };
84
+ export default SingleFileUpload;
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ /**
3
+ * 小知识(这里默认读了Form.Item value,所以不用设置了):Form.Item 设置
4
+ * valuePropName="imgUrl" // imgUpload默认读取的字段名,welFareUrl的值 => imgUrl 的值
5
+ */
6
+ interface IOpts {
7
+ size?: number;
8
+ w?: number;
9
+ h?: number;
10
+ }
11
+ interface IProps {
12
+ action?: string;
13
+ name?: string;
14
+ opts?: IOpts;
15
+ value?: string;
16
+ onChange?: any;
17
+ gif?: boolean;
18
+ disabled?: boolean;
19
+ }
20
+ declare const ImgUpload: React.FC<IProps>;
21
+ export default ImgUpload;
@@ -0,0 +1,165 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
11
+ import { Upload, message, Space } from "antd";
12
+ import { LoadingOutlined, PlusOutlined, DeleteOutlined } from "@ant-design/icons";
13
+ import { buildURL } from "@ecoding/helper.url";
14
+ import Toast from "../../core/toast";
15
+ import { r } from "../../helpers/http";
16
+ const ImgUpload = (props) => {
17
+ const [loading, setLoading] = useState(false);
18
+ const [imageUrl, setImageUrl] = useState(props.value || "");
19
+ const [urlParams, setUrlParams] = useState({});
20
+ useEffect(() => {
21
+ if (props.value) {
22
+ setImageUrl(props.value);
23
+ }
24
+ }, [props.value]);
25
+ const getBase64 = useCallback((imgFile) => {
26
+ return new Promise((resolve) => {
27
+ const reader = new FileReader();
28
+ reader.addEventListener("load", () => resolve(reader.result));
29
+ reader.readAsDataURL(imgFile);
30
+ });
31
+ }, []);
32
+ const getImgwh = useCallback((base64) => {
33
+ return new Promise((resolve, reject) => {
34
+ const img = new Image();
35
+ img.onload = () => {
36
+ // 宽度固定
37
+ resolve({
38
+ w: img.width,
39
+ h: img.height
40
+ });
41
+ };
42
+ img.onerror = () => reject();
43
+ img.src = base64;
44
+ });
45
+ }, []);
46
+ const handleChange = (info) => {
47
+ switch (info.file.status) {
48
+ case "uploading":
49
+ setLoading(true);
50
+ break;
51
+ case "done":
52
+ setLoading(false);
53
+ const response = info.file.response;
54
+ if (response && (response.code == 200 || response.retCode == 200)) {
55
+ const url = info.file.response.data && info.file.response.data[0].imageUrl;
56
+ setImageUrl(url);
57
+ // Form.item 值注入关键
58
+ props.onChange && props.onChange(url);
59
+ }
60
+ else {
61
+ Toast.error({
62
+ mask: true,
63
+ title: info.file.response
64
+ ? info.file.response.retDesc || info.file.response.desc || info.file.response.message
65
+ : "服务出错,图片上传失败"
66
+ });
67
+ }
68
+ break;
69
+ case "error":
70
+ Toast.error({
71
+ mask: true,
72
+ title: info.file.response
73
+ ? info.file.response.retDesc || info.file.response.desc || info.file.response.message
74
+ : "服务出错,图片上传失败"
75
+ });
76
+ setLoading(false);
77
+ break;
78
+ default:
79
+ break;
80
+ }
81
+ };
82
+ const clear = () => {
83
+ setImageUrl("");
84
+ // Form.item 值注入关键
85
+ props.onChange && props.onChange("");
86
+ };
87
+ const beforeUpload = useCallback((file) => {
88
+ return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
89
+ const ary = ["jpg", "jpeg", "png"];
90
+ if (props.gif) {
91
+ ary.push("gif");
92
+ }
93
+ if (ary.indexOf(file.type.toLowerCase().replace(/image\//g, "")) === -1) {
94
+ message.error(`请上传 ${ary.join(",")} 格式的图片!`);
95
+ reject();
96
+ return;
97
+ }
98
+ const isLt2M = file.size / 1024 / 1024 < (props.opts.size || 1);
99
+ if (!isLt2M) {
100
+ message.error(`图片大小必须小于${props.opts.size} MB!`);
101
+ reject();
102
+ return;
103
+ }
104
+ const base64 = yield getBase64(file);
105
+ const wh = yield getImgwh(base64);
106
+ if (props.opts.w && props.opts.w !== wh.w) {
107
+ message.error(`图片宽度不符合 ${props.opts.w}px 约定!`);
108
+ reject();
109
+ return;
110
+ }
111
+ if (props.opts.h && props.opts.h !== wh.h) {
112
+ message.error(`图片高度不符合 ${props.opts.h}px 约定!`);
113
+ reject();
114
+ return;
115
+ }
116
+ setUrlParams({ height: wh.h });
117
+ resolve();
118
+ }));
119
+ }, []);
120
+ const uploadButton = useMemo(() => (React.createElement("div", null,
121
+ loading ? React.createElement(LoadingOutlined, null) : React.createElement(PlusOutlined, null),
122
+ React.createElement("div", { style: { marginTop: 8 } }, "\u4E0A\u4F20\u56FE\u7247"))), [loading]);
123
+ const action = useMemo(() => {
124
+ return /^http|^\/\//i.test(props.action) ? buildURL(props.action, urlParams) : buildURL(`${r.domain}${props.action}`, urlParams);
125
+ }, [urlParams]);
126
+ return (React.createElement(Space, null,
127
+ React.createElement(Upload, { withCredentials: true, beforeUpload: beforeUpload, name: props.name, disabled: props.disabled, listType: "picture-card", showUploadList: false, action: action, onChange: handleChange }, imageUrl ? (React.createElement("div", { style: { position: "relative" } },
128
+ React.createElement("span", { style: {
129
+ position: "absolute",
130
+ background: "#fff",
131
+ bottom: "6px",
132
+ right: "2px",
133
+ width: "18px",
134
+ height: "18px",
135
+ opacity: ".9"
136
+ }, onClick: (e) => {
137
+ e.stopPropagation();
138
+ clear();
139
+ } },
140
+ React.createElement(DeleteOutlined, null)),
141
+ React.createElement("img", { style: { width: "102px", height: "102px", objectFit: "contain" }, src: imageUrl }))) : (uploadButton)),
142
+ React.createElement("div", null,
143
+ React.createElement("p", null,
144
+ "\u5927\u5C0F\uFF1A\u5C0F\u4E8E ",
145
+ props.opts.size || 1,
146
+ "MB"),
147
+ React.createElement("p", null,
148
+ "\u5C3A\u5BF8\uFF1A",
149
+ props.opts.w ? `${props.opts.w}px` : "n",
150
+ " * ",
151
+ props.opts.h ? `${props.opts.h}px` : "n"),
152
+ React.createElement("p", null,
153
+ "\u652F\u6301\uFF1Ajpg\u3001jpeg\u3001png",
154
+ props.gif ? "、gif" : ""))));
155
+ };
156
+ ImgUpload.defaultProps = {
157
+ action: "/upload/img",
158
+ name: "file",
159
+ value: "",
160
+ gif: false,
161
+ opts: {
162
+ size: 1
163
+ }
164
+ };
165
+ export default ImgUpload;
@@ -0,0 +1,2 @@
1
+ import R from "@ecoding/helper.request.hook";
2
+ export declare const r: R;
@@ -0,0 +1,16 @@
1
+ import axios from "axios";
2
+ import Loading from "../core/loading";
3
+ import Toast from "../core/toast";
4
+ import R from "@ecoding/helper.request.hook";
5
+ const request = new R(axios);
6
+ request.setDomain("");
7
+ request.setFinallyHook(() => {
8
+ Loading.hide();
9
+ });
10
+ request.setErrorUiHook((err) => {
11
+ Toast.error({
12
+ duration: 20000,
13
+ title: err.message || err.msg
14
+ });
15
+ });
16
+ export const r = request;
package/lib/index.d.ts CHANGED
@@ -1,3 +1,10 @@
1
1
  export { default as Toast } from "./core/toast";
2
2
  export { default as Loading } from "./core/loading";
3
3
  export { default as Confirm } from "./core/confirm";
4
+ export { default as AsyncCascader } from "./core/async-cascader";
5
+ export { default as LengthInput } from "./core/length-input";
6
+ export { default as SingleImgUpload } from "./core/single-img-upload";
7
+ export { default as SingleFileUpload } from "./core/single-file-upload";
8
+ export { default as AsyncSlect } from "./core/async-select";
9
+ export { default as AsyncTransfer } from "./core/async-transfer";
10
+ export { default as Quill } from "./core/quill";
package/lib/index.js CHANGED
@@ -1,3 +1,10 @@
1
1
  export { default as Toast } from "./core/toast";
2
2
  export { default as Loading } from "./core/loading";
3
3
  export { default as Confirm } from "./core/confirm";
4
+ export { default as AsyncCascader } from "./core/async-cascader";
5
+ export { default as LengthInput } from "./core/length-input";
6
+ export { default as SingleImgUpload } from "./core/single-img-upload";
7
+ export { default as SingleFileUpload } from "./core/single-file-upload";
8
+ export { default as AsyncSlect } from "./core/async-select";
9
+ export { default as AsyncTransfer } from "./core/async-transfer";
10
+ export { default as Quill } from "./core/quill";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecoding/components.antd",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "author": "cxc",
5
5
  "homepage": "",
6
6
  "license": "MIT",
@@ -23,5 +23,22 @@
23
23
  "dev": "tsc -w",
24
24
  "build": "rm -rf lib && tsc"
25
25
  },
26
- "gitHead": "6f1f561a65700696c8d6fc008642fc936f91d3b2"
26
+ "peerDependencies": {
27
+ "@ecoding/helper.is": ">=0.0.4",
28
+ "@ecoding/helper.json": ">=0.0.5",
29
+ "@ecoding/helper.request.hook": ">=0.0.6",
30
+ "@ecoding/helper.url": ">=0.0.5",
31
+ "axios": ">=1.1.2"
32
+ },
33
+ "devDependencies": {
34
+ "@ecoding/helper.is": "^0.0.4",
35
+ "@ecoding/helper.json": "^0.0.5",
36
+ "@ecoding/helper.request.hook": "^0.0.6",
37
+ "@ecoding/helper.url": "^0.0.5",
38
+ "axios": "^1.1.2"
39
+ },
40
+ "dependencies": {
41
+ "react-quill": "^2.0.0"
42
+ },
43
+ "gitHead": "4171cff635b5d61704143157ddb27e6c94553179"
27
44
  }