@wzyjs/hooks 0.3.3 → 0.3.4
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/antd/index.d.ts +8 -0
- package/dist/antd/index.js +8 -0
- package/dist/antd/useDateRange.d.ts +22 -0
- package/dist/antd/useDateRange.js +101 -122
- package/dist/antd/{useModalFooter.d.ts → useModalConfirmFooter.d.ts} +1 -1
- package/dist/antd/{useModalFooter.js → useModalConfirmFooter.js} +2 -1
- package/dist/antd/usePaginationState.js +6 -4
- package/dist/common/index.d.ts +7 -0
- package/dist/common/index.js +7 -0
- package/dist/common/useClick.d.ts +8 -0
- package/dist/{base → common}/useClick.js +3 -3
- package/dist/dom/index.d.ts +2 -0
- package/dist/dom/index.js +2 -0
- package/dist/rn.d.ts +1 -0
- package/dist/rn.js +1 -0
- package/dist/web.d.ts +6 -0
- package/dist/web.js +6 -0
- package/package.json +24 -2
- package/dist/antd/useOptions.d.ts +0 -0
- package/dist/antd/useOptions.js +0 -46
- package/dist/base/useClick.d.ts +0 -10
- package/dist/index.d.ts +0 -16
- package/dist/index.js +0 -21
- package/dist/other/useCRUD.d.ts +0 -63
- package/dist/other/useCRUD.js +0 -90
- package/dist/other/useRequestPro.d.ts +0 -0
- package/dist/other/useRequestPro.js +0 -73
- package/dist/other/useSetting.d.ts +0 -0
- package/dist/other/useSetting.js +0 -69
- package/dist/other/useUserInfo.d.ts +0 -0
- package/dist/other/useUserInfo.js +0 -97
- package/dist/other/useWechatLogin.d.ts +0 -11
- package/dist/other/useWechatLogin.js +0 -46
- /package/dist/{base → common}/useControlValue.d.ts +0 -0
- /package/dist/{base → common}/useControlValue.js +0 -0
- /package/dist/{base → common}/useDebouncedEffect.d.ts +0 -0
- /package/dist/{base → common}/useDebouncedEffect.js +0 -0
- /package/dist/{base → common}/useEffectValue.d.ts +0 -0
- /package/dist/{base → common}/useEffectValue.js +0 -0
- /package/dist/{base → common}/useMergeState.d.ts +0 -0
- /package/dist/{base → common}/useMergeState.js +0 -0
- /package/dist/{base → common}/useOnceEffect.d.ts +0 -0
- /package/dist/{base → common}/useOnceEffect.js +0 -0
- /package/dist/{base → common}/useVisibleInfo.d.ts +0 -0
- /package/dist/{base → common}/useVisibleInfo.js +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './useForm';
|
|
2
|
+
export * from './useImperativeHandleForm';
|
|
3
|
+
export * from './useModalConfirmFooter';
|
|
4
|
+
export * from './usePaginationState';
|
|
5
|
+
export * from './useHideFooter';
|
|
6
|
+
export * from './useHovered';
|
|
7
|
+
export * from './useStep';
|
|
8
|
+
export * from './useDateRange';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './useForm';
|
|
2
|
+
export * from './useImperativeHandleForm';
|
|
3
|
+
export * from './useModalConfirmFooter';
|
|
4
|
+
export * from './usePaginationState';
|
|
5
|
+
export * from './useHideFooter';
|
|
6
|
+
export * from './useHovered';
|
|
7
|
+
export * from './useStep';
|
|
8
|
+
export * from './useDateRange';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import dayjs, { Dayjs } from 'dayjs';
|
|
2
|
+
export declare enum PresetType {
|
|
3
|
+
TODAY = "\u4ECA\u5929",
|
|
4
|
+
THIS_WEEK = "\u672C\u5468",
|
|
5
|
+
LAST_WEEK = "\u4E0A\u5468",
|
|
6
|
+
THIS_MONTH = "\u672C\u6708",
|
|
7
|
+
LAST_MONTH = "\u4E0A\u6708"
|
|
8
|
+
}
|
|
9
|
+
export declare const rangePresets: {
|
|
10
|
+
label: string;
|
|
11
|
+
value: [Dayjs, Dayjs];
|
|
12
|
+
}[];
|
|
13
|
+
interface Config {
|
|
14
|
+
defaultDateRange?: PresetType | [Dayjs, Dayjs];
|
|
15
|
+
}
|
|
16
|
+
export declare const useDateRange: (config: Config) => {
|
|
17
|
+
dateRange: [dayjs.Dayjs, dayjs.Dayjs];
|
|
18
|
+
onChange: (dateRange?: any) => void;
|
|
19
|
+
onClickPrev: () => void;
|
|
20
|
+
onClickNext: () => void;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -1,122 +1,101 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// }
|
|
103
|
-
// },
|
|
104
|
-
//
|
|
105
|
-
// onClickNext: () => {
|
|
106
|
-
// switch (rangeType) {
|
|
107
|
-
// case 1:
|
|
108
|
-
// setDateRange([dateRange[0].add(1, 'day'), dateRange[1].add(1, 'day')])
|
|
109
|
-
// break
|
|
110
|
-
// case 2:
|
|
111
|
-
// setDateRange([dateRange[0].add(1, 'week'), dateRange[1].add(1, 'week')])
|
|
112
|
-
// break
|
|
113
|
-
// case 3:
|
|
114
|
-
// setDateRange([dateRange[0].add(1, 'month').startOf('month'), dateRange[1].add(1, 'month').endOf('month')])
|
|
115
|
-
// break
|
|
116
|
-
// default:
|
|
117
|
-
// setDateRange([dateRange[0], dateRange[1].add(1, 'day')])
|
|
118
|
-
// break
|
|
119
|
-
// }
|
|
120
|
-
// },
|
|
121
|
-
// }
|
|
122
|
-
// }
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
export var PresetType;
|
|
4
|
+
(function (PresetType) {
|
|
5
|
+
PresetType["TODAY"] = "\u4ECA\u5929";
|
|
6
|
+
PresetType["THIS_WEEK"] = "\u672C\u5468";
|
|
7
|
+
PresetType["LAST_WEEK"] = "\u4E0A\u5468";
|
|
8
|
+
PresetType["THIS_MONTH"] = "\u672C\u6708";
|
|
9
|
+
PresetType["LAST_MONTH"] = "\u4E0A\u6708";
|
|
10
|
+
})(PresetType || (PresetType = {}));
|
|
11
|
+
export const rangePresets = [
|
|
12
|
+
{
|
|
13
|
+
label: PresetType.TODAY,
|
|
14
|
+
value: [dayjs().startOf('day'), dayjs().endOf('day')],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: PresetType.THIS_WEEK,
|
|
18
|
+
value: [dayjs().startOf('week'), dayjs().endOf('week')],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: PresetType.LAST_WEEK,
|
|
22
|
+
value: [dayjs().subtract(1, 'week').startOf('week'), dayjs().subtract(1, 'week').endOf('week')],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: PresetType.THIS_MONTH,
|
|
26
|
+
value: [dayjs().startOf('month'), dayjs().endOf('month')],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: PresetType.LAST_MONTH,
|
|
30
|
+
value: [dayjs().subtract(1, 'month').startOf('month'), dayjs().subtract(1, 'month').endOf('month')],
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
const isStartOrEndOfMonth = (date) => {
|
|
34
|
+
return date.date() === 1 || date.date() === date.daysInMonth();
|
|
35
|
+
};
|
|
36
|
+
const checkDateRules = (dateRange) => {
|
|
37
|
+
const [date1, date2] = dateRange;
|
|
38
|
+
// 规则1: 判断是否为同一天
|
|
39
|
+
if (date1.isSame(date2, 'day')) {
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
// 规则2: 判断是否为周一和周日
|
|
43
|
+
if ((date1.day() === 1 && date2.day() === 0) || (date1.day() === 0 && date2.day() === 1)) {
|
|
44
|
+
return 2;
|
|
45
|
+
}
|
|
46
|
+
// 规则3: 判断是否为月初和月末
|
|
47
|
+
if (isStartOrEndOfMonth(date1) && isStartOrEndOfMonth(date2)) {
|
|
48
|
+
return 3;
|
|
49
|
+
}
|
|
50
|
+
// 如果没有匹配到任何规则,可以根据需要返回默认值,这里假设返回 0
|
|
51
|
+
return 0;
|
|
52
|
+
};
|
|
53
|
+
export const useDateRange = (config) => {
|
|
54
|
+
const { defaultDateRange = PresetType.TODAY } = config;
|
|
55
|
+
const [dateRange, setDateRange] = useState(Array.isArray(defaultDateRange)
|
|
56
|
+
? defaultDateRange
|
|
57
|
+
: rangePresets.find((item) => item.label === defaultDateRange)?.value || [dayjs().startOf('day'), dayjs().endOf('day')]);
|
|
58
|
+
const rangeType = checkDateRules(dateRange);
|
|
59
|
+
return {
|
|
60
|
+
dateRange,
|
|
61
|
+
// 这里的 any 实际应该是 antd 的 RangeValue<Dayjs> 类型,但是这个类型不好获取,所以这里先用 any 代替
|
|
62
|
+
onChange: (dateRange) => {
|
|
63
|
+
if (!dateRange) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
setDateRange(dateRange);
|
|
67
|
+
},
|
|
68
|
+
onClickPrev: () => {
|
|
69
|
+
switch (rangeType) {
|
|
70
|
+
case 1:
|
|
71
|
+
setDateRange([dateRange[0].subtract(1, 'day'), dateRange[1].subtract(1, 'day')]);
|
|
72
|
+
break;
|
|
73
|
+
case 2:
|
|
74
|
+
setDateRange([dateRange[0].subtract(1, 'week'), dateRange[1].subtract(1, 'week')]);
|
|
75
|
+
break;
|
|
76
|
+
case 3:
|
|
77
|
+
setDateRange([dateRange[0].subtract(1, 'month').startOf('month'), dateRange[1].subtract(1, 'month').endOf('month')]);
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
setDateRange([dateRange[0].subtract(1, 'day'), dateRange[1]]);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
onClickNext: () => {
|
|
85
|
+
switch (rangeType) {
|
|
86
|
+
case 1:
|
|
87
|
+
setDateRange([dateRange[0].add(1, 'day'), dateRange[1].add(1, 'day')]);
|
|
88
|
+
break;
|
|
89
|
+
case 2:
|
|
90
|
+
setDateRange([dateRange[0].add(1, 'week'), dateRange[1].add(1, 'week')]);
|
|
91
|
+
break;
|
|
92
|
+
case 3:
|
|
93
|
+
setDateRange([dateRange[0].add(1, 'month').startOf('month'), dateRange[1].add(1, 'month').endOf('month')]);
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
setDateRange([dateRange[0], dateRange[1].add(1, 'day')]);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
};
|
|
@@ -2,7 +2,7 @@ interface Option {
|
|
|
2
2
|
onOk?: () => Promise<void>;
|
|
3
3
|
onConfirm?: () => void;
|
|
4
4
|
}
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const useModalConfirmFooter: (option: Option) => {
|
|
6
6
|
footer: (_: unknown, extra: any) => import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
};
|
|
8
8
|
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { Space, Popconfirm, Button } from 'antd';
|
|
4
|
-
export const
|
|
4
|
+
export const useModalConfirmFooter = (option) => {
|
|
5
|
+
const { onOk, onConfirm } = option;
|
|
5
6
|
const [open, setOpen] = useState(false);
|
|
6
7
|
const onCancel = () => {
|
|
7
8
|
setOpen(false);
|
|
@@ -24,10 +24,12 @@ export const usePaginationState = (paginationProps) => {
|
|
|
24
24
|
pageSize,
|
|
25
25
|
onChange,
|
|
26
26
|
};
|
|
27
|
-
const pageParams = useMemo(() =>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
const pageParams = useMemo(() => {
|
|
28
|
+
return {
|
|
29
|
+
pageNum: current,
|
|
30
|
+
pageSize,
|
|
31
|
+
};
|
|
32
|
+
}, [current, pageSize]);
|
|
31
33
|
return {
|
|
32
34
|
// 重置到第一页
|
|
33
35
|
resetPage,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useRef } from 'react';
|
|
2
2
|
export const useClick = (option) => {
|
|
3
3
|
const { onClick, onDoubleClick, delay = 300 } = option;
|
|
4
|
-
const clickCount =
|
|
5
|
-
const timer =
|
|
4
|
+
const clickCount = useRef(0);
|
|
5
|
+
const timer = useRef(null);
|
|
6
6
|
return (ev) => {
|
|
7
7
|
clickCount.current += 1;
|
|
8
8
|
if (clickCount.current === 1) {
|
package/dist/rn.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './common';
|
package/dist/rn.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './common';
|
package/dist/web.d.ts
ADDED
package/dist/web.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wzyjs/hooks",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "description",
|
|
5
5
|
"author": "wzy",
|
|
6
6
|
"type": "module",
|
|
@@ -13,11 +13,33 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
|
+
"exports": {
|
|
17
|
+
"./web": {
|
|
18
|
+
"import": "./dist/web.js",
|
|
19
|
+
"types": "./dist/web.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./rn": {
|
|
22
|
+
"import": "./dist/rn.js",
|
|
23
|
+
"types": "./dist/rn.d.ts"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"typesVersions": {
|
|
27
|
+
"*": {
|
|
28
|
+
"./web": [
|
|
29
|
+
"./dist/web.d.ts"
|
|
30
|
+
],
|
|
31
|
+
"./rn": [
|
|
32
|
+
"./dist/rn.d.ts"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
16
36
|
"dependencies": {
|
|
37
|
+
"@ahooksjs/use-url-state": "^3.5.1",
|
|
17
38
|
"ahooks": "^3.8.4",
|
|
18
39
|
"antd": "^5.24.3",
|
|
40
|
+
"dayjs": "^1.11.12",
|
|
19
41
|
"react": "^19.1.0",
|
|
20
42
|
"react-use": "^17.4.0"
|
|
21
43
|
},
|
|
22
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "759abaadc6f778c5a1b4ddb5b16f7753d45f37f9"
|
|
23
45
|
}
|
|
File without changes
|
package/dist/antd/useOptions.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// import { useEffect, useMemo, useState } from 'react'
|
|
2
|
-
// import { useRequestPro } from './useRequestPro'
|
|
3
|
-
//
|
|
4
|
-
// interface Option {
|
|
5
|
-
// apis: any
|
|
6
|
-
// onChange?: (data?: any) => void
|
|
7
|
-
// }
|
|
8
|
-
//
|
|
9
|
-
// export const useOptions = (option: Option) => {
|
|
10
|
-
// const { apis } = option
|
|
11
|
-
//
|
|
12
|
-
// const [value, setValue] = useState<string>()
|
|
13
|
-
//
|
|
14
|
-
// // 发请求获取列表数据
|
|
15
|
-
// const { data, loading } = useRequestPro(apis.list, {
|
|
16
|
-
// onSuccess: res => {
|
|
17
|
-
// const [first] = res.data?.data || []
|
|
18
|
-
// if (first) {
|
|
19
|
-
// setValue(first?.id)
|
|
20
|
-
// }
|
|
21
|
-
// },
|
|
22
|
-
// })
|
|
23
|
-
//
|
|
24
|
-
// // 将列表数据转换成 enableOptions
|
|
25
|
-
// const enableOptions = useMemo(() => {
|
|
26
|
-
// return data?.data.map((item: any) => ({ label: item.name, value: item.id })) || []
|
|
27
|
-
// }, [data])
|
|
28
|
-
//
|
|
29
|
-
// // 根据 value 获取当前详细数据
|
|
30
|
-
// const currentData = useMemo(() => {
|
|
31
|
-
// return data?.data.find((item: any) => item.id === value)
|
|
32
|
-
// }, [data, value])
|
|
33
|
-
//
|
|
34
|
-
// // value 变化时触发 onChange
|
|
35
|
-
// useEffect(() => {
|
|
36
|
-
// option.onChange?.(currentData)
|
|
37
|
-
// }, [currentData])
|
|
38
|
-
//
|
|
39
|
-
// return {
|
|
40
|
-
// loading,
|
|
41
|
-
// enableOptions,
|
|
42
|
-
// value,
|
|
43
|
-
// onChange: setValue,
|
|
44
|
-
// currentData,
|
|
45
|
-
// }
|
|
46
|
-
// }
|
package/dist/base/useClick.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
type MouseEventType = React.MouseEvent<HTMLElement> | MouseEvent;
|
|
3
|
-
type ClickHandler<P> = (event: P) => void;
|
|
4
|
-
interface Option<P> {
|
|
5
|
-
onClick: ClickHandler<P>;
|
|
6
|
-
onDoubleClick: ClickHandler<P>;
|
|
7
|
-
delay?: number;
|
|
8
|
-
}
|
|
9
|
-
export declare const useClick: <P = MouseEventType>(option: Option<P>) => ClickHandler<P>;
|
|
10
|
-
export {};
|
package/dist/index.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export * from 'ahooks';
|
|
2
|
-
export { useCopyToClipboard, useCookie, useUpdate } from 'react-use';
|
|
3
|
-
export * from './base/useEffectValue';
|
|
4
|
-
export * from './base/useVisibleInfo';
|
|
5
|
-
export * from './base/useClick';
|
|
6
|
-
export * from './base/useDebouncedEffect';
|
|
7
|
-
export * from './base/useMergeState';
|
|
8
|
-
export * from './base/useControlValue';
|
|
9
|
-
export * from './antd/useForm';
|
|
10
|
-
export * from './antd/useImperativeHandleForm';
|
|
11
|
-
export * from './antd/useModalFooter';
|
|
12
|
-
export * from './antd/usePaginationState';
|
|
13
|
-
export * from './antd/useHideFooter';
|
|
14
|
-
export * from './antd/useHovered';
|
|
15
|
-
export * from './dom/useElement';
|
|
16
|
-
export * from './dom/useElementScrollVisible';
|
package/dist/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export * from 'ahooks';
|
|
2
|
-
// export { default as useUrlState } from '@ahooksjs/use-url-state'
|
|
3
|
-
export { useCopyToClipboard, useCookie, useUpdate } from 'react-use';
|
|
4
|
-
export * from './base/useEffectValue';
|
|
5
|
-
export * from './base/useVisibleInfo';
|
|
6
|
-
export * from './base/useClick';
|
|
7
|
-
export * from './base/useDebouncedEffect';
|
|
8
|
-
export * from './base/useMergeState';
|
|
9
|
-
export * from './base/useControlValue';
|
|
10
|
-
export * from './antd/useForm';
|
|
11
|
-
export * from './antd/useImperativeHandleForm';
|
|
12
|
-
export * from './antd/useModalFooter';
|
|
13
|
-
export * from './antd/usePaginationState';
|
|
14
|
-
export * from './antd/useHideFooter';
|
|
15
|
-
export * from './antd/useHovered';
|
|
16
|
-
export * from './dom/useElement';
|
|
17
|
-
export * from './dom/useElementScrollVisible';
|
|
18
|
-
// export * from './other/useSetting'
|
|
19
|
-
// export * from './useRequestPro'
|
|
20
|
-
// export * from './useDateRange'
|
|
21
|
-
// export * from './useOptions'
|
package/dist/other/useCRUD.d.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export interface ApiResult<D = any> {
|
|
2
|
-
status?: string;
|
|
3
|
-
message?: string;
|
|
4
|
-
success?: boolean;
|
|
5
|
-
data?: D;
|
|
6
|
-
meta?: {
|
|
7
|
-
total_count?: number;
|
|
8
|
-
filter_count?: number;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export declare enum CRUDAction {
|
|
12
|
-
Info = "info",
|
|
13
|
-
List = "list",
|
|
14
|
-
Create = "create",
|
|
15
|
-
Update = "update",
|
|
16
|
-
Delete = "delete"
|
|
17
|
-
}
|
|
18
|
-
type InfoAPI<I> = (id: string) => Promise<ApiResult<I>>;
|
|
19
|
-
type ListAPI<I> = (params?: any) => Promise<ApiResult<I[]>>;
|
|
20
|
-
type CreateAPI<I> = (data: any) => Promise<ApiResult<I>>;
|
|
21
|
-
type UpdateAPI<I> = (id: string, data: any) => Promise<ApiResult<I>>;
|
|
22
|
-
type DeleteAPI<I> = (id: string) => Promise<ApiResult<I>>;
|
|
23
|
-
interface Apis<I> {
|
|
24
|
-
[CRUDAction.Info]?: InfoAPI<I>;
|
|
25
|
-
[CRUDAction.List]?: ListAPI<I>;
|
|
26
|
-
[CRUDAction.Create]?: CreateAPI<I>;
|
|
27
|
-
[CRUDAction.Update]?: UpdateAPI<I>;
|
|
28
|
-
[CRUDAction.Delete]?: DeleteAPI<I>;
|
|
29
|
-
}
|
|
30
|
-
interface AutoRefreshList {
|
|
31
|
-
[CRUDAction.Info]?: boolean;
|
|
32
|
-
[CRUDAction.List]?: boolean;
|
|
33
|
-
[CRUDAction.Create]?: boolean;
|
|
34
|
-
[CRUDAction.Update]?: boolean;
|
|
35
|
-
[CRUDAction.Delete]?: boolean;
|
|
36
|
-
}
|
|
37
|
-
interface CRUDOptions<I> {
|
|
38
|
-
id?: string;
|
|
39
|
-
apis: Apis<I>;
|
|
40
|
-
autoRefreshList?: boolean | AutoRefreshList;
|
|
41
|
-
convertInfo?: (data?: I) => any;
|
|
42
|
-
replaceLocation?: boolean;
|
|
43
|
-
autoFetchList?: boolean;
|
|
44
|
-
debounceWait?: number;
|
|
45
|
-
onSuccess?: (action: CRUDAction, data?: any) => void;
|
|
46
|
-
}
|
|
47
|
-
export declare function useCRUD<I extends {
|
|
48
|
-
id: string;
|
|
49
|
-
}>(options: CRUDOptions<I>): {
|
|
50
|
-
info: I;
|
|
51
|
-
list: I[];
|
|
52
|
-
infoState: import("ahooks/lib/useRequest/src/types").Result<ApiResult<I>, string[]>;
|
|
53
|
-
listState: import("ahooks/lib/useRequest/src/types").Result<ApiResult<I[]>, [params?: any]>;
|
|
54
|
-
createState: import("ahooks/lib/useRequest/src/types").Result<ApiResult<I>, [data: any]>;
|
|
55
|
-
updateState: import("ahooks/lib/useRequest/src/types").Result<ApiResult<I>, [id: string, data: any]>;
|
|
56
|
-
deleteState: import("ahooks/lib/useRequest/src/types").Result<ApiResult<I>, [id: string]>;
|
|
57
|
-
onSave: (data: I & {
|
|
58
|
-
id?: string;
|
|
59
|
-
}) => Promise<void>;
|
|
60
|
-
apis: Apis<I>;
|
|
61
|
-
loading: boolean;
|
|
62
|
-
};
|
|
63
|
-
export {};
|
package/dist/other/useCRUD.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
import { useRequest } from 'ahooks';
|
|
3
|
-
export var CRUDAction;
|
|
4
|
-
(function (CRUDAction) {
|
|
5
|
-
CRUDAction["Info"] = "info";
|
|
6
|
-
CRUDAction["List"] = "list";
|
|
7
|
-
CRUDAction["Create"] = "create";
|
|
8
|
-
CRUDAction["Update"] = "update";
|
|
9
|
-
CRUDAction["Delete"] = "delete";
|
|
10
|
-
})(CRUDAction || (CRUDAction = {}));
|
|
11
|
-
export function useCRUD(options) {
|
|
12
|
-
const { id, apis, autoRefreshList = true, autoFetchList = false, replaceLocation = false, convertInfo = (data) => data, onSuccess = () => undefined, debounceWait = 300, } = options;
|
|
13
|
-
const [list, setList] = useState([]);
|
|
14
|
-
const [info, setInfo] = useState();
|
|
15
|
-
const shouldRefresh = (action, autoRefreshList) => {
|
|
16
|
-
if (typeof autoRefreshList === 'boolean') {
|
|
17
|
-
return autoRefreshList;
|
|
18
|
-
}
|
|
19
|
-
return autoRefreshList[action];
|
|
20
|
-
};
|
|
21
|
-
const infoState = useRequest(apis.info, {
|
|
22
|
-
ready: !!id,
|
|
23
|
-
defaultParams: [id],
|
|
24
|
-
debounceWait,
|
|
25
|
-
onSuccess: (res) => {
|
|
26
|
-
const convertedInfo = convertInfo(res.data);
|
|
27
|
-
setInfo(convertedInfo);
|
|
28
|
-
onSuccess(CRUDAction.Info, convertedInfo);
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
const listState = useRequest(apis.list, {
|
|
32
|
-
manual: !autoFetchList,
|
|
33
|
-
debounceWait,
|
|
34
|
-
onSuccess: (res) => {
|
|
35
|
-
const convertedList = res.data?.map(convertInfo);
|
|
36
|
-
setList(convertedList || []);
|
|
37
|
-
onSuccess(CRUDAction.List, convertedList);
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
const createState = useRequest(apis.create, {
|
|
41
|
-
manual: true,
|
|
42
|
-
debounceWait,
|
|
43
|
-
onSuccess: (res) => {
|
|
44
|
-
if (shouldRefresh(CRUDAction.Create, autoRefreshList)) {
|
|
45
|
-
listState.run();
|
|
46
|
-
}
|
|
47
|
-
onSuccess(CRUDAction.Create, res.data);
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
const updateState = useRequest(apis.update, {
|
|
51
|
-
manual: true,
|
|
52
|
-
debounceWait,
|
|
53
|
-
onSuccess: (res) => {
|
|
54
|
-
if (shouldRefresh(CRUDAction.Update, autoRefreshList)) {
|
|
55
|
-
listState.run();
|
|
56
|
-
}
|
|
57
|
-
onSuccess(CRUDAction.Update, res.data);
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
const deleteState = useRequest(apis.delete, {
|
|
61
|
-
manual: true,
|
|
62
|
-
debounceWait,
|
|
63
|
-
onSuccess: (res) => {
|
|
64
|
-
if (shouldRefresh(CRUDAction.Delete, autoRefreshList)) {
|
|
65
|
-
listState.run();
|
|
66
|
-
}
|
|
67
|
-
onSuccess(CRUDAction.Delete, res.data);
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
const onSave = async (data) => {
|
|
71
|
-
if (data.id) {
|
|
72
|
-
updateState.run(data.id, data);
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
createState.run(data);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
return {
|
|
79
|
-
info,
|
|
80
|
-
list,
|
|
81
|
-
infoState,
|
|
82
|
-
listState,
|
|
83
|
-
createState,
|
|
84
|
-
updateState,
|
|
85
|
-
deleteState,
|
|
86
|
-
onSave,
|
|
87
|
-
apis,
|
|
88
|
-
loading: infoState.loading || listState.loading || createState.loading || updateState.loading || deleteState.loading,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
File without changes
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// import { message } from 'antd'
|
|
2
|
-
// import { useRequest } from 'ahooks'
|
|
3
|
-
// import { noop, omit } from '@wzyjs/utils'
|
|
4
|
-
// import { RequestRes } from '@wzyjs/types'
|
|
5
|
-
// import { Options, Result, Service } from 'ahooks/lib/useRequest/src/types'
|
|
6
|
-
//
|
|
7
|
-
// // 在 useRequest 的基础上扩展的功能
|
|
8
|
-
// interface UserOptions<P extends any[], R> extends Options<R, P> {
|
|
9
|
-
// alertErrorMessage?: false | string,
|
|
10
|
-
// alertSuccessMessage?: true | string,
|
|
11
|
-
// }
|
|
12
|
-
//
|
|
13
|
-
// // 取出 data 里的 data
|
|
14
|
-
// interface IResult<R extends RequestRes, P extends any[]> extends Omit<Result<R, P>, 'data'> {
|
|
15
|
-
// data?: R['data'],
|
|
16
|
-
// }
|
|
17
|
-
//
|
|
18
|
-
// const defaultResult = {
|
|
19
|
-
// loading: false,
|
|
20
|
-
// data: undefined,
|
|
21
|
-
// error: undefined,
|
|
22
|
-
// params: [],
|
|
23
|
-
// cancel: noop,
|
|
24
|
-
// refresh: noop,
|
|
25
|
-
// refreshAsync: noop,
|
|
26
|
-
// run: noop,
|
|
27
|
-
// runAsync: noop,
|
|
28
|
-
// mutate: noop,
|
|
29
|
-
// }
|
|
30
|
-
//
|
|
31
|
-
// export const useRequestPro = <P extends any[], R extends RequestRes>(
|
|
32
|
-
// reqPromise?: Service<R, P>,
|
|
33
|
-
// userOptions?: UserOptions<P, R>,
|
|
34
|
-
// ): IResult<R, P> => {
|
|
35
|
-
// if (!reqPromise) {
|
|
36
|
-
// return defaultResult as IResult<R, P>
|
|
37
|
-
// }
|
|
38
|
-
//
|
|
39
|
-
// const { alertErrorMessage = true, alertSuccessMessage = false } = userOptions || {}
|
|
40
|
-
//
|
|
41
|
-
// const defaultOptions = {
|
|
42
|
-
// debounceWait: 300,
|
|
43
|
-
// throttleWait: 300,
|
|
44
|
-
// onError: (err: Error, params: P) => {
|
|
45
|
-
// if (alertErrorMessage) {
|
|
46
|
-
// message.error(typeof alertErrorMessage === 'string' ? alertErrorMessage : err.message || '请求失败')
|
|
47
|
-
// }
|
|
48
|
-
// userOptions?.onError?.(err, params)
|
|
49
|
-
// },
|
|
50
|
-
// onSuccess: (res: R, params: P) => {
|
|
51
|
-
// // 如果失败,则还是调用 onError
|
|
52
|
-
// if (!res?.success) {
|
|
53
|
-
// defaultOptions.onError(new Error(res?.message), params)
|
|
54
|
-
// return
|
|
55
|
-
// }
|
|
56
|
-
//
|
|
57
|
-
// // 如果成功,并且需要自动弹出提示
|
|
58
|
-
// if (alertSuccessMessage) {
|
|
59
|
-
// message.success(typeof alertSuccessMessage === 'string' ? alertSuccessMessage : res.message || '请求成功')
|
|
60
|
-
// }
|
|
61
|
-
// userOptions?.onSuccess?.(res, params)
|
|
62
|
-
// },
|
|
63
|
-
// }
|
|
64
|
-
//
|
|
65
|
-
// // 用户配置与默认配置合并
|
|
66
|
-
// const enableOptions = Object.assign(defaultOptions, omit(userOptions, ['onSuccess', 'onError']))
|
|
67
|
-
//
|
|
68
|
-
// // 取出 data 里的 data
|
|
69
|
-
// const state = useRequest(reqPromise, enableOptions)
|
|
70
|
-
// state.data = state.data?.data
|
|
71
|
-
//
|
|
72
|
-
// return state
|
|
73
|
-
// }
|
|
File without changes
|
package/dist/other/useSetting.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// import { useCallback, useEffect, useState } from 'react'
|
|
2
|
-
//
|
|
3
|
-
// export const useSetting = (key: string, defaultValue: any = {}) => {
|
|
4
|
-
// // 分割 key 以支持嵌套结构
|
|
5
|
-
// const keys = key.split('.')
|
|
6
|
-
//
|
|
7
|
-
// // 获取初始值
|
|
8
|
-
// const getInitialSetting = useCallback(() => {
|
|
9
|
-
// if (typeof window === 'undefined') return defaultValue
|
|
10
|
-
// try {
|
|
11
|
-
// const stored = localStorage.getItem('settings')
|
|
12
|
-
// if (!stored) return defaultValue
|
|
13
|
-
// let result = JSON.parse(stored)
|
|
14
|
-
// for (let k of keys) {
|
|
15
|
-
// if (result[k] === undefined) {
|
|
16
|
-
// return defaultValue
|
|
17
|
-
// }
|
|
18
|
-
// result = result[k]
|
|
19
|
-
// }
|
|
20
|
-
// return result
|
|
21
|
-
// } catch (error) {
|
|
22
|
-
// console.error('从 localStorage 读取设置失败:', error)
|
|
23
|
-
// return defaultValue
|
|
24
|
-
// }
|
|
25
|
-
// }, [keys])
|
|
26
|
-
//
|
|
27
|
-
// const [setting, setSettingState] = useState(getInitialSetting)
|
|
28
|
-
//
|
|
29
|
-
// // 更新 localStorage
|
|
30
|
-
// const setSetting = useCallback(
|
|
31
|
-
// (newSetting: any) => {
|
|
32
|
-
// setSettingState(newSetting)
|
|
33
|
-
// if (typeof window === 'undefined') return
|
|
34
|
-
// try {
|
|
35
|
-
// const stored = localStorage.getItem('settings')
|
|
36
|
-
// const parsed = stored ? JSON.parse(stored) : {}
|
|
37
|
-
//
|
|
38
|
-
// let current = parsed
|
|
39
|
-
// for (let i = 0; i < keys.length - 1; i++) {
|
|
40
|
-
// if (current[keys[i]] === undefined || typeof current[keys[i]] !== 'object') {
|
|
41
|
-
// current[keys[i]] = {}
|
|
42
|
-
// }
|
|
43
|
-
// current = current[keys[i]]
|
|
44
|
-
// }
|
|
45
|
-
// current[keys[keys.length - 1]] = newSetting
|
|
46
|
-
//
|
|
47
|
-
// localStorage.setItem('settings', JSON.stringify(parsed))
|
|
48
|
-
// } catch (error) {
|
|
49
|
-
// console.error('向 localStorage 写入设置失败:', error)
|
|
50
|
-
// }
|
|
51
|
-
// },
|
|
52
|
-
// [keys],
|
|
53
|
-
// )
|
|
54
|
-
//
|
|
55
|
-
// // 监听 localStorage 中 settings 的变化
|
|
56
|
-
// useEffect(() => {
|
|
57
|
-
// const handleStorageChange = (event: any) => {
|
|
58
|
-
// if (event.key === 'settings') {
|
|
59
|
-
// setSettingState(getInitialSetting())
|
|
60
|
-
// }
|
|
61
|
-
// }
|
|
62
|
-
// window.addEventListener('storage', handleStorageChange)
|
|
63
|
-
// return () => {
|
|
64
|
-
// window.removeEventListener('storage', handleStorageChange)
|
|
65
|
-
// }
|
|
66
|
-
// }, [getInitialSetting])
|
|
67
|
-
//
|
|
68
|
-
// return [setting, setSetting]
|
|
69
|
-
// }
|
|
File without changes
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// import { useEffect, useState } from 'react'
|
|
2
|
-
//
|
|
3
|
-
// import { pick } from 'lodash'
|
|
4
|
-
// import { useLocalStorageState, useRequest } from 'ahooks'
|
|
5
|
-
//
|
|
6
|
-
// import { user } from '@/services'
|
|
7
|
-
// import { User, PageKey } from '@/types'
|
|
8
|
-
//
|
|
9
|
-
// export const useUserInfo = () => {
|
|
10
|
-
// const [token, setToken] = useLocalStorageState<user.LoginResult>('token')
|
|
11
|
-
//
|
|
12
|
-
// const [userInfo, setUserInfo] = useState<User>()
|
|
13
|
-
//
|
|
14
|
-
// const loginState = useRequest(user.login, {
|
|
15
|
-
// manual: true,
|
|
16
|
-
// })
|
|
17
|
-
//
|
|
18
|
-
// const refreshState = useRequest(user.refresh, {
|
|
19
|
-
// manual: true,
|
|
20
|
-
// })
|
|
21
|
-
//
|
|
22
|
-
// const userInfoState = useRequest(user.info, {
|
|
23
|
-
// refreshDeps: [token?.access_token],
|
|
24
|
-
// ready: !!token?.access_token,
|
|
25
|
-
// debounceWait: 300,
|
|
26
|
-
// onSuccess: res => {
|
|
27
|
-
// setUserInfo(res.data)
|
|
28
|
-
// },
|
|
29
|
-
// onError: () => {
|
|
30
|
-
// refreshToken()
|
|
31
|
-
// },
|
|
32
|
-
// })
|
|
33
|
-
//
|
|
34
|
-
// const cacheToken = (data?: user.LoginResult) => {
|
|
35
|
-
// if (!data) {
|
|
36
|
-
// throw new Error('token failed')
|
|
37
|
-
// }
|
|
38
|
-
// data.expires_at = Date.now() + data.expires
|
|
39
|
-
// setToken(data)
|
|
40
|
-
// }
|
|
41
|
-
//
|
|
42
|
-
// const refreshToken = async () => {
|
|
43
|
-
// const token = JSON.parse(localStorage.getItem('token') || '{}')
|
|
44
|
-
//
|
|
45
|
-
// if (token?.expires_at && ((token.expires_at - Date.now()) < (30 * 1000))) {
|
|
46
|
-
// const res = await refreshState.runAsync(pick(token, 'refresh_token'))
|
|
47
|
-
// cacheToken(res.data)
|
|
48
|
-
// }
|
|
49
|
-
// }
|
|
50
|
-
//
|
|
51
|
-
// const login = async (data: user.LoginData) => {
|
|
52
|
-
// if (!data) {
|
|
53
|
-
// throw new Error('data is required')
|
|
54
|
-
// }
|
|
55
|
-
//
|
|
56
|
-
// const res = await loginState.runAsync(data)
|
|
57
|
-
// cacheToken(res.data)
|
|
58
|
-
// }
|
|
59
|
-
//
|
|
60
|
-
// const logout = async () => {
|
|
61
|
-
// if (!token) {
|
|
62
|
-
// return
|
|
63
|
-
// }
|
|
64
|
-
// await user.logout({ refresh_token: token.refresh_token })
|
|
65
|
-
// setToken(undefined)
|
|
66
|
-
// setUserInfo(undefined)
|
|
67
|
-
// location.reload()
|
|
68
|
-
// }
|
|
69
|
-
//
|
|
70
|
-
// useEffect(() => {
|
|
71
|
-
// const timer = setInterval(async () => {
|
|
72
|
-
// try {
|
|
73
|
-
// await refreshToken()
|
|
74
|
-
//
|
|
75
|
-
// } catch (err) {
|
|
76
|
-
// clearInterval(timer)
|
|
77
|
-
// if (location.pathname !== PageKey.Login) {
|
|
78
|
-
// location.reload()
|
|
79
|
-
// }
|
|
80
|
-
// }
|
|
81
|
-
// }, 10 * 1000)
|
|
82
|
-
//
|
|
83
|
-
// return () => {
|
|
84
|
-
// clearInterval(timer)
|
|
85
|
-
// }
|
|
86
|
-
// }, [])
|
|
87
|
-
//
|
|
88
|
-
// return {
|
|
89
|
-
// login,
|
|
90
|
-
// loginLoading: loginState.loading,
|
|
91
|
-
//
|
|
92
|
-
// userInfo,
|
|
93
|
-
// userInfoLoading: userInfoState.loading,
|
|
94
|
-
//
|
|
95
|
-
// logout,
|
|
96
|
-
// }
|
|
97
|
-
// }
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export interface WeChatLoginResult {
|
|
2
|
-
token: string;
|
|
3
|
-
}
|
|
4
|
-
interface wechatLoginOption {
|
|
5
|
-
onSuccess?: (loginResult: WeChatLoginResult) => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function insertWxLoginScript(): void;
|
|
8
|
-
export declare const useWechatLogin: (option: wechatLoginOption) => {
|
|
9
|
-
renderLoginView: () => void;
|
|
10
|
-
};
|
|
11
|
-
export {};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
// import { user } from '@/services'
|
|
3
|
-
import { useAsyncEffect } from 'ahooks';
|
|
4
|
-
export function insertWxLoginScript() {
|
|
5
|
-
const scriptSrc = 'http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js';
|
|
6
|
-
const head = document.head || document.getElementsByTagName('head')[0];
|
|
7
|
-
const script = document.createElement('script');
|
|
8
|
-
script.src = scriptSrc;
|
|
9
|
-
head.appendChild(script);
|
|
10
|
-
}
|
|
11
|
-
// 需要先执行
|
|
12
|
-
// insertWxLoginScript()
|
|
13
|
-
export const useWechatLogin = (option) => {
|
|
14
|
-
const { onSuccess } = option;
|
|
15
|
-
// 显示二维码
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
// @ts-ignore
|
|
18
|
-
new window.WxLogin({
|
|
19
|
-
id: 'qrcode',
|
|
20
|
-
appid: 'wx3802f7d1c135b5e4',
|
|
21
|
-
scope: 'snsapi_login',
|
|
22
|
-
redirect_uri: 'http://localhost:8001/login',
|
|
23
|
-
});
|
|
24
|
-
}, []);
|
|
25
|
-
// 拿到 code,获取微信登录信息
|
|
26
|
-
useAsyncEffect(async () => {
|
|
27
|
-
const code = (new URL(location.href)).searchParams.get('code') || '';
|
|
28
|
-
if (!code) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
// const { data } = await user.loginByWeChat({ code: Array.isArray(code) ? code[code.length - 1] : code })
|
|
32
|
-
// if (!data?.token) {
|
|
33
|
-
// return
|
|
34
|
-
// }
|
|
35
|
-
// onSuccess?.(data)
|
|
36
|
-
}, []);
|
|
37
|
-
// 没有登录时的视图
|
|
38
|
-
const renderLoginView = () => {
|
|
39
|
-
// return (
|
|
40
|
-
// <div id='qrcode' />
|
|
41
|
-
// )
|
|
42
|
-
};
|
|
43
|
-
return {
|
|
44
|
-
renderLoginView,
|
|
45
|
-
};
|
|
46
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|