@mpxjs/webpack-plugin 2.10.16-beta.7 → 2.10.17
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/LICENSE +433 -0
- package/lib/config.js +0 -60
- package/lib/file-loader.js +3 -13
- package/lib/json-compiler/index.js +2 -2
- package/lib/platform/json/wx/index.js +0 -6
- package/lib/platform/template/wx/component-config/ad.js +0 -5
- package/lib/platform/template/wx/component-config/button.js +2 -9
- package/lib/platform/template/wx/component-config/camera.js +3 -25
- package/lib/platform/template/wx/component-config/canvas.js +1 -8
- package/lib/platform/template/wx/component-config/cover-image.js +2 -7
- package/lib/platform/template/wx/component-config/cover-view.js +1 -3
- package/lib/platform/template/wx/component-config/form.js +2 -27
- package/lib/platform/template/wx/component-config/image.js +0 -5
- package/lib/platform/template/wx/component-config/input.js +0 -10
- package/lib/platform/template/wx/component-config/label.js +2 -10
- package/lib/platform/template/wx/component-config/map.js +0 -11
- package/lib/platform/template/wx/component-config/movable-area.js +1 -4
- package/lib/platform/template/wx/component-config/movable-view.js +2 -17
- package/lib/platform/template/wx/component-config/navigator.js +0 -26
- package/lib/platform/template/wx/component-config/picker-view.js +0 -12
- package/lib/platform/template/wx/component-config/picker.js +1 -3
- package/lib/platform/template/wx/component-config/progress.js +1 -11
- package/lib/platform/template/wx/component-config/rich-text.js +0 -5
- package/lib/platform/template/wx/component-config/scroll-view.js +1 -12
- package/lib/platform/template/wx/component-config/slider.js +0 -8
- package/lib/platform/template/wx/component-config/swiper-item.js +2 -5
- package/lib/platform/template/wx/component-config/swiper.js +0 -10
- package/lib/platform/template/wx/component-config/text.js +0 -5
- package/lib/platform/template/wx/component-config/textarea.js +2 -19
- package/lib/platform/template/wx/component-config/unsupported.js +1 -10
- package/lib/platform/template/wx/component-config/video.js +0 -10
- package/lib/platform/template/wx/index.js +1 -21
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-image.d.ts.map +1 -1
- package/lib/runtime/components/react/dist/mpx-image.jsx +26 -20
- package/lib/runtime/components/react/dist/mpx-input.d.ts.map +1 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +1 -3
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-web-view.d.ts.map +1 -1
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +11 -3
- package/lib/runtime/components/react/mpx-canvas/index.tsx +1 -1
- package/lib/runtime/components/react/mpx-image.tsx +41 -35
- package/lib/runtime/components/react/mpx-input.tsx +1 -3
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +1 -1
- package/lib/runtime/components/react/mpx-web-view.tsx +14 -5
- package/lib/runtime/stringify.wxs +2 -2
- package/lib/style-compiler/strip-conditional-loader.js +4 -5
- package/lib/template-compiler/bind-this.js +2 -2
- package/lib/template-compiler/compiler.js +3 -3
- package/lib/template-compiler/index.js +6 -6
- package/lib/utils/dom-tag-config.js +1 -1
- package/lib/utils/merge-visitors.js +55 -0
- package/lib/wxs/pre-loader.js +8 -5
- package/package.json +7 -8
- package/lib/runtime/components/react/dist/mpx-camera.d.ts +0 -28
- package/lib/runtime/components/react/dist/mpx-camera.d.ts.map +0 -1
- package/lib/runtime/components/react/dist/mpx-camera.jsx +0 -102
- package/lib/runtime/components/react/mpx-camera.tsx +0 -167
- package/lib/utils/chain-assign.js +0 -47
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 链式合并方法的工具函数
|
|
3
|
+
*
|
|
4
|
+
* 在多条件分支下使用 Object.assign 会导致同名方法被覆盖,
|
|
5
|
+
* 这个函数通过创建组合函数来确保所有方法都能按顺序执行。
|
|
6
|
+
*
|
|
7
|
+
* @param {Object} target - 目标 visitor 对象
|
|
8
|
+
* @param {Object} source - 要链式分配的 visitor 方法对象
|
|
9
|
+
**/
|
|
10
|
+
|
|
11
|
+
// 辅助函数:将 visitor 的所有钩子添加到结果中
|
|
12
|
+
function mergeVisitorHooks (result, visitor) {
|
|
13
|
+
result.enter = result.enter.concat(visitor.enter)
|
|
14
|
+
result.exit = result.exit.concat(visitor.exit)
|
|
15
|
+
return result
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function normalizeVisitor(visitor) {
|
|
19
|
+
if (Array.isArray(visitor.enter) && Array.isArray(visitor.exit)) {
|
|
20
|
+
return visitor
|
|
21
|
+
}
|
|
22
|
+
if (typeof visitor === 'function') {
|
|
23
|
+
return { enter: [visitor], exit: [] }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (visitor.enter) {
|
|
27
|
+
if (!Array.isArray(visitor.enter)) {
|
|
28
|
+
visitor.enter = [visitor.enter]
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
visitor.enter = []
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (visitor.exit) {
|
|
35
|
+
if (!Array.isArray(visitor.exit)) {
|
|
36
|
+
visitor.exit = [visitor.exit]
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
visitor.exit = []
|
|
40
|
+
}
|
|
41
|
+
return visitor
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = function mergeVisitors (target, source) {
|
|
45
|
+
for (const [key, value] of Object.entries(source)) {
|
|
46
|
+
if (!target[key]) {
|
|
47
|
+
target[key] = normalizeVisitor(value)
|
|
48
|
+
} else {
|
|
49
|
+
// 合并现有值和新值
|
|
50
|
+
target[key] = mergeVisitorHooks(normalizeVisitor(target[key]), normalizeVisitor(value))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return target
|
|
55
|
+
}
|
package/lib/wxs/pre-loader.js
CHANGED
|
@@ -4,7 +4,7 @@ const t = require('@babel/types')
|
|
|
4
4
|
const generate = require('@babel/generator').default
|
|
5
5
|
const parseRequest = require('../utils/parse-request')
|
|
6
6
|
const isEmptyObject = require('../utils/is-empty-object')
|
|
7
|
-
const
|
|
7
|
+
const mergeVisitors = require('../utils/merge-visitors')
|
|
8
8
|
const parseQuery = require('loader-utils').parseQuery
|
|
9
9
|
|
|
10
10
|
module.exports = function (content) {
|
|
@@ -31,7 +31,7 @@ module.exports = function (content) {
|
|
|
31
31
|
' __mpx_args__[i] = arguments[i];\n' +
|
|
32
32
|
'}'
|
|
33
33
|
).program.body
|
|
34
|
-
|
|
34
|
+
mergeVisitors(visitor, {
|
|
35
35
|
Identifier (path) {
|
|
36
36
|
if (path.node.name === 'arguments') {
|
|
37
37
|
path.node.name = '__mpx_args__'
|
|
@@ -66,7 +66,7 @@ module.exports = function (content) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
if (mode !== 'wx') {
|
|
69
|
-
|
|
69
|
+
mergeVisitors(visitor, {
|
|
70
70
|
CallExpression (path) {
|
|
71
71
|
const callee = path.node.callee
|
|
72
72
|
if (t.isIdentifier(callee) && callee.name === 'getRegExp') {
|
|
@@ -81,7 +81,7 @@ module.exports = function (content) {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
if (mode === 'dd') {
|
|
84
|
-
|
|
84
|
+
mergeVisitors(visitor, {
|
|
85
85
|
MemberExpression (path) {
|
|
86
86
|
const property = path.node.property
|
|
87
87
|
if (
|
|
@@ -96,8 +96,11 @@ module.exports = function (content) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
if (!module.wxs) {
|
|
99
|
-
|
|
99
|
+
mergeVisitors(visitor, {
|
|
100
100
|
MemberExpression (path) {
|
|
101
|
+
if (!t.isMemberExpression(path.node)) {
|
|
102
|
+
return
|
|
103
|
+
}
|
|
101
104
|
const property = path.node.property
|
|
102
105
|
if (
|
|
103
106
|
property && (property.name === 'constructor' || property.value === 'constructor') &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/webpack-plugin",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.17",
|
|
4
4
|
"description": "mpx compile core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mpx"
|
|
@@ -29,10 +29,7 @@
|
|
|
29
29
|
"@better-scroll/wheel": "^2.5.1",
|
|
30
30
|
"@better-scroll/zoom": "^2.5.1",
|
|
31
31
|
"@mpxjs/template-engine": "^2.8.7",
|
|
32
|
-
"@mpxjs/utils": "^2.10.
|
|
33
|
-
"postcss-less": "^6.0.0",
|
|
34
|
-
"postcss-scss": "^4.0.9",
|
|
35
|
-
"postcss-styl": "^0.12.3",
|
|
32
|
+
"@mpxjs/utils": "^2.10.17",
|
|
36
33
|
"acorn": "^8.11.3",
|
|
37
34
|
"acorn-walk": "^7.2.0",
|
|
38
35
|
"async": "^2.6.0",
|
|
@@ -55,12 +52,15 @@
|
|
|
55
52
|
"object-assign": "^4.1.1",
|
|
56
53
|
"postcss": "^8.4.5",
|
|
57
54
|
"postcss-import": "^16.1.1",
|
|
55
|
+
"postcss-less": "^6.0.0",
|
|
58
56
|
"postcss-load-config": "^3.1.1",
|
|
59
57
|
"postcss-modules-extract-imports": "^3.0.0",
|
|
60
58
|
"postcss-modules-local-by-default": "^4.0.0",
|
|
61
59
|
"postcss-modules-scope": "^3.0.0",
|
|
62
60
|
"postcss-modules-values": "^4.0.0",
|
|
61
|
+
"postcss-scss": "^4.0.9",
|
|
63
62
|
"postcss-selector-parser": "^6.0.8",
|
|
63
|
+
"postcss-styl": "^0.12.3",
|
|
64
64
|
"postcss-value-parser": "^4.0.2",
|
|
65
65
|
"semver": "^7.5.4",
|
|
66
66
|
"source-list-map": "^2.0.0",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@d11/react-native-fast-image": "^8.6.12",
|
|
94
|
-
"@mpxjs/api-proxy": "^2.10.
|
|
94
|
+
"@mpxjs/api-proxy": "^2.10.17",
|
|
95
95
|
"@types/babel-traverse": "^6.25.4",
|
|
96
96
|
"@types/babel-types": "^7.0.4",
|
|
97
97
|
"@types/glob": "^8.1.0",
|
|
@@ -105,12 +105,11 @@
|
|
|
105
105
|
"react-native-safe-area-context": "^4.12.0",
|
|
106
106
|
"react-native-svg": "^15.8.0",
|
|
107
107
|
"react-native-video": "^6.9.0",
|
|
108
|
-
"react-native-vision-camera": "^4.7.2",
|
|
109
108
|
"react-native-webview": "^13.12.2",
|
|
110
109
|
"rimraf": "^6.0.1"
|
|
111
110
|
},
|
|
112
111
|
"engines": {
|
|
113
112
|
"node": ">=14.14.0"
|
|
114
113
|
},
|
|
115
|
-
"gitHead": "
|
|
114
|
+
"gitHead": "33fbd0bb8d4b83555239a8931fabb23022af0866"
|
|
116
115
|
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Camera } from 'react-native-vision-camera';
|
|
3
|
-
interface CameraProps {
|
|
4
|
-
mode?: 'normal' | 'scanCode';
|
|
5
|
-
resolution?: 'low' | 'medium' | 'high';
|
|
6
|
-
devicePosition?: 'front' | 'back';
|
|
7
|
-
flash?: 'auto' | 'on' | 'off';
|
|
8
|
-
frameSize?: 'small' | 'medium' | 'large';
|
|
9
|
-
style?: Record<string, any>;
|
|
10
|
-
bindstop?: () => void;
|
|
11
|
-
binderror?: (error: {
|
|
12
|
-
message: string;
|
|
13
|
-
}) => void;
|
|
14
|
-
bindinitdone?: (result: {
|
|
15
|
-
type: string;
|
|
16
|
-
data: string;
|
|
17
|
-
}) => void;
|
|
18
|
-
bindscancode?: (result: {
|
|
19
|
-
type: string;
|
|
20
|
-
data: string;
|
|
21
|
-
}) => void;
|
|
22
|
-
}
|
|
23
|
-
type HandlerRef<T, P> = {
|
|
24
|
-
current: T | null;
|
|
25
|
-
};
|
|
26
|
-
declare const _camera: React.ForwardRefExoticComponent<CameraProps & React.RefAttributes<HandlerRef<Camera, CameraProps>>>;
|
|
27
|
-
export default _camera;
|
|
28
|
-
//# sourceMappingURL=mpx-camera.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mpx-camera.d.ts","sourceRoot":"","sources":["../mpx-camera.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2E,MAAM,OAAO,CAAA;AAC/F,OAAO,EAAE,MAAM,EAAuE,MAAM,4BAA4B,CAAA;AAIxH,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAA;IAC5B,UAAU,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IACtC,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;IAChD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;IAC/D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CAChE;AASD,KAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI;IAEtB,OAAO,EAAE,CAAC,GAAG,IAAI,CAAA;CAClB,CAAA;AAED,QAAA,MAAM,OAAO,qGAoIX,CAAA;AAIF,eAAe,OAAO,CAAA"}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef, useRef, useCallback, useContext, useState, useEffect } from 'react';
|
|
2
|
-
import { Camera, useCameraDevice, useCodeScanner, useCameraFormat } from 'react-native-vision-camera';
|
|
3
|
-
import { getCustomEvent } from './getInnerListeners';
|
|
4
|
-
import { RouteContext } from './context';
|
|
5
|
-
const _camera = forwardRef((props, ref) => {
|
|
6
|
-
const cameraRef = useRef(null);
|
|
7
|
-
const { mode = 'normal', resolution = 'medium', devicePosition = 'back', flash = 'auto', frameSize = 'medium', bindinitdone, bindstop, bindscancode } = props;
|
|
8
|
-
const isPhoto = mode === 'normal';
|
|
9
|
-
const device = useCameraDevice(devicePosition || 'back');
|
|
10
|
-
const { navigation } = useContext(RouteContext) || {};
|
|
11
|
-
const [zoomValue, setZoomValue] = useState(1);
|
|
12
|
-
const [hasPermission, setHasPermission] = useState(null);
|
|
13
|
-
// 先定义常量,避免在条件判断后使用
|
|
14
|
-
const maxZoom = device?.maxZoom || 1;
|
|
15
|
-
const RESOLUTION_MAPPING = {
|
|
16
|
-
low: { width: 640, height: 480 },
|
|
17
|
-
medium: { width: 1280, height: 720 },
|
|
18
|
-
high: { width: 1920, height: 1080 }
|
|
19
|
-
};
|
|
20
|
-
const FRAME_SIZE_MAPPING = {
|
|
21
|
-
small: { width: 480, height: 360 },
|
|
22
|
-
medium: { width: 720, height: 540 },
|
|
23
|
-
large: { width: 1080, height: 810 }
|
|
24
|
-
};
|
|
25
|
-
// 所有 Hooks 必须在条件判断之前调用
|
|
26
|
-
const format = useCameraFormat(device, [
|
|
27
|
-
{
|
|
28
|
-
photoResolution: RESOLUTION_MAPPING[resolution],
|
|
29
|
-
videoResolution: FRAME_SIZE_MAPPING[frameSize] || RESOLUTION_MAPPING[resolution]
|
|
30
|
-
}
|
|
31
|
-
]);
|
|
32
|
-
const codeScanner = useCodeScanner({
|
|
33
|
-
codeTypes: ['qr', 'ean-13'],
|
|
34
|
-
onCodeScanned: (codes) => {
|
|
35
|
-
const result = codes.map(code => code.value).join(',');
|
|
36
|
-
bindscancode && bindscancode(getCustomEvent('scancode', {}, {
|
|
37
|
-
detail: {
|
|
38
|
-
result: codes.map(code => code.value).join(',')
|
|
39
|
-
}
|
|
40
|
-
}));
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
const onInitialized = useCallback(() => {
|
|
44
|
-
bindinitdone && bindinitdone(getCustomEvent('initdone', {}, {
|
|
45
|
-
detail: {
|
|
46
|
-
maxZoom
|
|
47
|
-
}
|
|
48
|
-
}));
|
|
49
|
-
}, [bindinitdone, maxZoom]);
|
|
50
|
-
const onStopped = useCallback(() => {
|
|
51
|
-
bindstop && bindstop();
|
|
52
|
-
}, [bindstop]);
|
|
53
|
-
// 检查相机权限
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
const checkCameraPermission = async () => {
|
|
56
|
-
try {
|
|
57
|
-
const cameraPermission = global?.__mpx?.config?.rnConfig?.cameraPermission;
|
|
58
|
-
if (typeof cameraPermission === 'function') {
|
|
59
|
-
const permissionResult = await cameraPermission();
|
|
60
|
-
setHasPermission(permissionResult === true);
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
setHasPermission(true);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
setHasPermission(false);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
checkCameraPermission();
|
|
71
|
-
}, []);
|
|
72
|
-
const camera = {
|
|
73
|
-
setZoom: (zoom) => {
|
|
74
|
-
setZoomValue(zoom);
|
|
75
|
-
},
|
|
76
|
-
getTakePhoto: () => {
|
|
77
|
-
return cameraRef.current?.takePhoto;
|
|
78
|
-
},
|
|
79
|
-
getStartRecord: () => {
|
|
80
|
-
return cameraRef.current?.startRecording;
|
|
81
|
-
},
|
|
82
|
-
getStopRecord: () => {
|
|
83
|
-
return cameraRef.current?.stopRecording;
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
if (navigation) {
|
|
87
|
-
navigation.camera = camera;
|
|
88
|
-
}
|
|
89
|
-
// 所有 Hooks 调用完成后再进行条件判断
|
|
90
|
-
if (hasPermission === null) {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
if (!hasPermission) {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
if (!device) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
return (<Camera ref={cameraRef} isActive={true} photo={isPhoto} video={true} onInitialized={onInitialized} onStopped={onStopped} device={device} flash={flash} format={format} codeScanner={!isPhoto ? codeScanner : undefined} style={{ flex: 1 }} zoom={zoomValue} {...props}/>);
|
|
100
|
-
});
|
|
101
|
-
_camera.displayName = 'MpxCamera';
|
|
102
|
-
export default _camera;
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef, useRef, useCallback, useContext, useState, useEffect } from 'react'
|
|
2
|
-
import { Camera, useCameraDevice, useCodeScanner, useCameraFormat, useFrameProcessor } from 'react-native-vision-camera'
|
|
3
|
-
import { getCustomEvent } from './getInnerListeners'
|
|
4
|
-
import { RouteContext } from './context'
|
|
5
|
-
|
|
6
|
-
interface CameraProps {
|
|
7
|
-
mode?: 'normal' | 'scanCode'
|
|
8
|
-
resolution?: 'low' | 'medium' | 'high'
|
|
9
|
-
devicePosition?: 'front' | 'back'
|
|
10
|
-
flash?: 'auto' | 'on' | 'off'
|
|
11
|
-
frameSize?: 'small' | 'medium' | 'large'
|
|
12
|
-
style?: Record<string, any>
|
|
13
|
-
bindstop?: () => void
|
|
14
|
-
binderror?: (error: { message: string }) => void
|
|
15
|
-
bindinitdone?: (result: { type: string, data: string }) => void
|
|
16
|
-
bindscancode?: (result: { type: string, data: string }) => void
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface CameraRef {
|
|
20
|
-
setZoom: (zoom: number) => void
|
|
21
|
-
getTakePhoto: () => (() => Promise<any>) | undefined
|
|
22
|
-
getStartRecord: () => ((options: any) => void) | undefined
|
|
23
|
-
getStopRecord: () => (() => void) | undefined
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type HandlerRef<T, P> = {
|
|
27
|
-
// 根据实际的 HandlerRef 类型定义调整
|
|
28
|
-
current: T | null
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const _camera = forwardRef<HandlerRef<Camera, CameraProps>, CameraProps>((props: CameraProps, ref): JSX.Element | null => {
|
|
32
|
-
const cameraRef = useRef<Camera>(null)
|
|
33
|
-
const {
|
|
34
|
-
mode = 'normal',
|
|
35
|
-
resolution = 'medium',
|
|
36
|
-
devicePosition = 'back',
|
|
37
|
-
flash = 'auto',
|
|
38
|
-
frameSize = 'medium',
|
|
39
|
-
bindinitdone,
|
|
40
|
-
bindstop,
|
|
41
|
-
bindscancode
|
|
42
|
-
} = props
|
|
43
|
-
|
|
44
|
-
const isPhoto = mode === 'normal'
|
|
45
|
-
const device = useCameraDevice(devicePosition || 'back')
|
|
46
|
-
const { navigation } = useContext(RouteContext) || {}
|
|
47
|
-
const [zoomValue, setZoomValue] = useState<number>(1)
|
|
48
|
-
const [hasPermission, setHasPermission] = useState<boolean | null>(null)
|
|
49
|
-
|
|
50
|
-
// 先定义常量,避免在条件判断后使用
|
|
51
|
-
const maxZoom = device?.maxZoom || 1
|
|
52
|
-
const RESOLUTION_MAPPING: Record<string, { width: number, height: number }> = {
|
|
53
|
-
low: { width: 640, height: 480 },
|
|
54
|
-
medium: { width: 1280, height: 720 },
|
|
55
|
-
high: { width: 1920, height: 1080 }
|
|
56
|
-
}
|
|
57
|
-
const FRAME_SIZE_MAPPING: Record<string, { width: number, height: number }> = {
|
|
58
|
-
small: { width: 480, height: 360 },
|
|
59
|
-
medium: { width: 720, height: 540 },
|
|
60
|
-
large: { width: 1080, height: 810 }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// 所有 Hooks 必须在条件判断之前调用
|
|
64
|
-
const format = useCameraFormat(device, [
|
|
65
|
-
{
|
|
66
|
-
photoResolution: RESOLUTION_MAPPING[resolution],
|
|
67
|
-
videoResolution: FRAME_SIZE_MAPPING[frameSize] || RESOLUTION_MAPPING[resolution]
|
|
68
|
-
}
|
|
69
|
-
])
|
|
70
|
-
|
|
71
|
-
const codeScanner = useCodeScanner({
|
|
72
|
-
codeTypes: ['qr', 'ean-13'],
|
|
73
|
-
onCodeScanned: (codes) => {
|
|
74
|
-
const result = codes.map(code => code.value).join(',')
|
|
75
|
-
bindscancode && bindscancode(getCustomEvent('scancode', {}, {
|
|
76
|
-
detail: {
|
|
77
|
-
result: codes.map(code => code.value).join(',')
|
|
78
|
-
}
|
|
79
|
-
}))
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
const onInitialized = useCallback(() => {
|
|
84
|
-
bindinitdone && bindinitdone(getCustomEvent('initdone', {}, {
|
|
85
|
-
detail: {
|
|
86
|
-
maxZoom
|
|
87
|
-
}
|
|
88
|
-
}))
|
|
89
|
-
}, [bindinitdone, maxZoom])
|
|
90
|
-
|
|
91
|
-
const onStopped = useCallback(() => {
|
|
92
|
-
bindstop && bindstop()
|
|
93
|
-
}, [bindstop])
|
|
94
|
-
|
|
95
|
-
// 检查相机权限
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
const checkCameraPermission = async () => {
|
|
98
|
-
try {
|
|
99
|
-
const cameraPermission = global?.__mpx?.config?.rnConfig?.cameraPermission
|
|
100
|
-
if (typeof cameraPermission === 'function') {
|
|
101
|
-
const permissionResult = await cameraPermission()
|
|
102
|
-
setHasPermission(permissionResult === true)
|
|
103
|
-
} else {
|
|
104
|
-
setHasPermission(true)
|
|
105
|
-
}
|
|
106
|
-
} catch (error) {
|
|
107
|
-
setHasPermission(false)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
checkCameraPermission()
|
|
112
|
-
}, [])
|
|
113
|
-
|
|
114
|
-
const camera: CameraRef = {
|
|
115
|
-
setZoom: (zoom: number) => {
|
|
116
|
-
setZoomValue(zoom)
|
|
117
|
-
},
|
|
118
|
-
getTakePhoto: () => {
|
|
119
|
-
return cameraRef.current?.takePhoto
|
|
120
|
-
},
|
|
121
|
-
getStartRecord: () => {
|
|
122
|
-
return cameraRef.current?.startRecording
|
|
123
|
-
},
|
|
124
|
-
getStopRecord: () => {
|
|
125
|
-
return cameraRef.current?.stopRecording
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (navigation) {
|
|
130
|
-
navigation.camera = camera
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// 所有 Hooks 调用完成后再进行条件判断
|
|
134
|
-
if (hasPermission === null) {
|
|
135
|
-
return null
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (!hasPermission) {
|
|
139
|
-
return null
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (!device) {
|
|
143
|
-
return null
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<Camera
|
|
148
|
-
ref={cameraRef}
|
|
149
|
-
isActive={true}
|
|
150
|
-
photo={isPhoto}
|
|
151
|
-
video={true}
|
|
152
|
-
onInitialized={onInitialized}
|
|
153
|
-
onStopped={onStopped}
|
|
154
|
-
device={device}
|
|
155
|
-
flash={flash}
|
|
156
|
-
format={format}
|
|
157
|
-
codeScanner={!isPhoto ? codeScanner : undefined}
|
|
158
|
-
style={{ flex: 1 }}
|
|
159
|
-
zoom={zoomValue}
|
|
160
|
-
{...props}
|
|
161
|
-
/>
|
|
162
|
-
)
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
_camera.displayName = 'MpxCamera'
|
|
166
|
-
|
|
167
|
-
export default _camera
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 链式合并方法的工具函数
|
|
3
|
-
*
|
|
4
|
-
* 在多条件分支下使用 Object.assign 会导致同名方法被覆盖,
|
|
5
|
-
* 这个函数通过创建组合函数来确保所有方法都能按顺序执行。
|
|
6
|
-
*
|
|
7
|
-
* @param {Object} target - 目标 visitor 对象
|
|
8
|
-
* @param {Object} source - 要链式分配的 visitor 方法对象
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const visitor = {}
|
|
12
|
-
*
|
|
13
|
-
* // 第一次合并
|
|
14
|
-
* chainAssign(visitor, {
|
|
15
|
-
* CallExpression(path) {
|
|
16
|
-
* console.log('第一个处理器')
|
|
17
|
-
* }
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* // 第二次合并 - 不会覆盖,而是组合执行
|
|
21
|
-
* chainAssign(visitor, {
|
|
22
|
-
* CallExpression(path) {
|
|
23
|
-
* console.log('第二个处理器')
|
|
24
|
-
* }
|
|
25
|
-
* })
|
|
26
|
-
*
|
|
27
|
-
* // 执行时会依次输出:
|
|
28
|
-
* // 第一个处理器
|
|
29
|
-
* // 第二个处理器
|
|
30
|
-
*/
|
|
31
|
-
module.exports = function chainAssign (target, source) {
|
|
32
|
-
for (const [key, value] of Object.entries(source)) {
|
|
33
|
-
if (target[key]) {
|
|
34
|
-
// 如果已存在同名方法,创建组合函数依次执行
|
|
35
|
-
const originalMethod = target[key]
|
|
36
|
-
target[key] = function (path) {
|
|
37
|
-
originalMethod.call(this, path)
|
|
38
|
-
// 只有当节点没有停止遍历或被移除时才继续执行
|
|
39
|
-
if (!path.removed && !path.shouldStop) {
|
|
40
|
-
value.call(this, path)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
target[key] = value
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|