@pnt-team/pnt-component-frontend 0.0.36 → 0.0.39
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/lib/cjs/assets/css/tdesign-theme.css +584 -0
- package/lib/cjs/assets/images/uploadImg.png +0 -0
- package/lib/cjs/assets/svg/inputSearch.svg +4 -0
- package/lib/cjs/assets/svg/inputTip.svg +5 -0
- package/lib/cjs/assets/svg/inputWarnTip.svg +5 -0
- package/lib/cjs/components/PntCopyData/index.d.ts +91 -0
- package/lib/cjs/components/PntCopyData/index.js +81 -0
- package/lib/cjs/components/PntCopyData/index.scss +5 -0
- package/lib/cjs/components/PntImagePreview/index.d.ts +75 -0
- package/lib/cjs/components/PntImagePreview/index.js +91 -0
- package/lib/cjs/components/PntImagePreview/index.scss +54 -0
- package/lib/cjs/components/PntSecureBox/index.d.ts +80 -0
- package/lib/cjs/components/PntSecureBox/index.js +74 -0
- package/lib/cjs/components/PntSecureBox/index.scss +19 -0
- package/lib/cjs/global.d.ts +30 -0
- package/lib/cjs/hooks/useBtnPermission.d.ts +67 -0
- package/lib/cjs/hooks/useBtnPermission.js +57 -0
- package/lib/cjs/hooks/useHighSecurity.d.ts +48 -0
- package/lib/cjs/hooks/useHighSecurity.js +64 -0
- package/lib/cjs/hooks/useOsPlatformList.d.ts +66 -0
- package/lib/cjs/hooks/useOsPlatformList.js +88 -0
- package/lib/cjs/hooks/usePagination.d.ts +72 -0
- package/lib/cjs/hooks/usePagination.js +71 -0
- package/lib/cjs/index.d.ts +10 -0
- package/lib/cjs/utils/const.d.ts +13 -0
- package/lib/cjs/utils/const.js +51 -0
- package/lib/cjs/utils/index.d.ts +6 -0
- package/lib/cjs/utils/index.js +43 -0
- package/lib/cjs/utils/request.d.ts +8 -0
- package/lib/cjs/utils/request.js +82 -0
- package/lib/esm/assets/css/tdesign-theme.css +584 -0
- package/lib/esm/assets/images/uploadImg.png +0 -0
- package/lib/esm/assets/svg/inputSearch.svg +4 -0
- package/lib/esm/assets/svg/inputTip.svg +5 -0
- package/lib/esm/assets/svg/inputWarnTip.svg +5 -0
- package/lib/esm/components/PntCopyData/index.d.ts +91 -0
- package/lib/esm/components/PntCopyData/index.js +51 -0
- package/lib/esm/components/PntCopyData/index.scss +5 -0
- package/lib/esm/components/PntImagePreview/index.d.ts +75 -0
- package/lib/esm/components/PntImagePreview/index.js +61 -0
- package/lib/esm/components/PntImagePreview/index.scss +54 -0
- package/lib/esm/components/PntSecureBox/index.d.ts +80 -0
- package/lib/esm/components/PntSecureBox/index.js +46 -0
- package/lib/esm/components/PntSecureBox/index.scss +19 -0
- package/lib/esm/global.d.ts +30 -0
- package/lib/esm/hooks/useBtnPermission.d.ts +67 -0
- package/lib/esm/hooks/useBtnPermission.js +31 -0
- package/lib/esm/hooks/useHighSecurity.d.ts +48 -0
- package/lib/esm/hooks/useHighSecurity.js +40 -0
- package/lib/esm/hooks/useOsPlatformList.d.ts +66 -0
- package/lib/esm/hooks/useOsPlatformList.js +63 -0
- package/lib/esm/hooks/usePagination.d.ts +72 -0
- package/lib/esm/hooks/usePagination.js +47 -0
- package/lib/esm/index.d.ts +10 -0
- package/lib/esm/index.js +17 -0
- package/lib/esm/utils/const.d.ts +13 -0
- package/lib/esm/utils/const.js +26 -0
- package/lib/esm/utils/index.d.ts +6 -0
- package/lib/esm/utils/index.js +19 -0
- package/lib/esm/utils/request.d.ts +8 -0
- package/lib/esm/utils/request.js +52 -0
- package/lib/umd/pnt-component-frontend.min.css +1 -0
- package/lib/umd/pnt-component-frontend.min.js +1 -0
- package/package.json +13 -8
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/components/PntCopyData/index.tsx
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { Popup } from "tdesign-react";
|
|
4
|
+
import "./index.scss";
|
|
5
|
+
var PntCopyData = (props) => {
|
|
6
|
+
const { data, className, contentFn, placement, tips } = props;
|
|
7
|
+
const [isCopy, setIsCopy] = useState(false);
|
|
8
|
+
const [isFail, setIsFail] = useState(false);
|
|
9
|
+
const copyDataToClipboard = async () => {
|
|
10
|
+
const text = typeof data === "string" ? data : await data();
|
|
11
|
+
if (!text) {
|
|
12
|
+
return setIsFail(true);
|
|
13
|
+
}
|
|
14
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
15
|
+
navigator.clipboard.writeText(text);
|
|
16
|
+
setIsCopy(true);
|
|
17
|
+
} else {
|
|
18
|
+
const textArea = document.createElement("textarea");
|
|
19
|
+
textArea.value = text;
|
|
20
|
+
document.body.appendChild(textArea);
|
|
21
|
+
textArea.focus();
|
|
22
|
+
textArea.select();
|
|
23
|
+
document.execCommand("copy") && setIsCopy(true);
|
|
24
|
+
textArea.remove();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
return /* @__PURE__ */ React.createElement(
|
|
28
|
+
Popup,
|
|
29
|
+
{
|
|
30
|
+
overlayClassName: `pnt-copy-data-popup${className ? " " + className : ""}`,
|
|
31
|
+
placement,
|
|
32
|
+
content: tips(isCopy, isFail),
|
|
33
|
+
visible: isCopy || isFail
|
|
34
|
+
},
|
|
35
|
+
contentFn({
|
|
36
|
+
onClick: () => {
|
|
37
|
+
copyDataToClipboard();
|
|
38
|
+
},
|
|
39
|
+
onMouseLeave: () => {
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
setIsCopy(false);
|
|
42
|
+
setIsFail(false);
|
|
43
|
+
}, 200);
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
var PntCopyData_default = PntCopyData;
|
|
49
|
+
export {
|
|
50
|
+
PntCopyData_default as default
|
|
51
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import './index.scss';
|
|
3
|
+
interface PntImagePreviewProps {
|
|
4
|
+
/**
|
|
5
|
+
* 当前图片组件 URL
|
|
6
|
+
* @description 图片的完整 URL 地址,用于显示已上传的图片
|
|
7
|
+
*/
|
|
8
|
+
iconUrl: string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* 上传加载状态
|
|
11
|
+
* @description 当为 true 时显示上传加载状态,阻止其他操作
|
|
12
|
+
*/
|
|
13
|
+
loading: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* 默认图片
|
|
16
|
+
* @description 支持传入默认封面图片,不传入则使用默认的 uploadImg 作为默认图片
|
|
17
|
+
*/
|
|
18
|
+
defaultImg?: string;
|
|
19
|
+
/**
|
|
20
|
+
* 自定义扩展参数
|
|
21
|
+
* @description 用于传递额外的配置选项,如样式等
|
|
22
|
+
*/
|
|
23
|
+
params?: {
|
|
24
|
+
/** 自定义样式 */
|
|
25
|
+
style?: React.CSSProperties;
|
|
26
|
+
/** 其他可扩展配置 */
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* 删除回调函数
|
|
31
|
+
* @description 当点击删除图标时触发的回调函数
|
|
32
|
+
* @param e - 事件对象
|
|
33
|
+
*/
|
|
34
|
+
onRemove?: (e: any) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 上传图片查看器组件
|
|
38
|
+
* @description 用于展示上传的图片,支持预览、删除功能和上传状态显示
|
|
39
|
+
* @param {PntImagePreviewProps} props - 组件属性
|
|
40
|
+
* @param {string | undefined} props.iconUrl - 当前图片组件 URL
|
|
41
|
+
* @param {boolean} props.loading - 上传加载状态
|
|
42
|
+
* @param {string} [props.defaultImg] - 默认图片
|
|
43
|
+
* @param {object} [props.params] - 自定义扩展参数
|
|
44
|
+
* @param {function} [props.onRemove] - 删除回调函数
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* // 基础用法
|
|
49
|
+
* <UploadImageViewer
|
|
50
|
+
* iconUrl={imageUrl}
|
|
51
|
+
* loading={uploading}
|
|
52
|
+
* onRemove={handleRemove}
|
|
53
|
+
* />
|
|
54
|
+
*
|
|
55
|
+
* // 带默认图片
|
|
56
|
+
* <UploadImageViewer
|
|
57
|
+
* iconUrl={imageUrl}
|
|
58
|
+
* loading={false}
|
|
59
|
+
* defaultImg="/path/to/default.png"
|
|
60
|
+
* onRemove={handleRemove}
|
|
61
|
+
* />
|
|
62
|
+
*
|
|
63
|
+
* // 自定义样式
|
|
64
|
+
* <UploadImageViewer
|
|
65
|
+
* iconUrl={imageUrl}
|
|
66
|
+
* loading={uploading}
|
|
67
|
+
* params={{ style: { width: '200px', height: '200px' } }}
|
|
68
|
+
* onRemove={handleRemove}
|
|
69
|
+
* />
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @returns {ReactElement} 上传图片查看器组件
|
|
73
|
+
*/
|
|
74
|
+
declare const PntImagePreview: FC<PntImagePreviewProps>;
|
|
75
|
+
export default PntImagePreview;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/components/PntImagePreview/index.tsx
|
|
2
|
+
import uploadImg from "../../assets/images/uploadImg.png";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { BrowseIcon, DeleteIcon, LoadingIcon } from "tdesign-icons-react";
|
|
5
|
+
import { Image, ImageViewer } from "tdesign-react";
|
|
6
|
+
import "./index.scss";
|
|
7
|
+
var PntImagePreview = ({
|
|
8
|
+
iconUrl,
|
|
9
|
+
loading,
|
|
10
|
+
defaultImg,
|
|
11
|
+
params,
|
|
12
|
+
onRemove
|
|
13
|
+
}) => {
|
|
14
|
+
const src = (iconUrl == null ? void 0 : iconUrl.length) ? iconUrl : defaultImg || uploadImg;
|
|
15
|
+
const LoadingContent = (isImageLoading) => /* @__PURE__ */ React.createElement(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: isImageLoading ? "pnt-image-preview-progress" : "pnt-image-preview-upload-progress",
|
|
19
|
+
style: params == null ? void 0 : params.style
|
|
20
|
+
},
|
|
21
|
+
/* @__PURE__ */ React.createElement("div", { className: "pnt-image-preview-loading" }, /* @__PURE__ */ React.createElement(LoadingIcon, { size: "18px", name: "loading" }), /* @__PURE__ */ React.createElement("p", null, "上传中"))
|
|
22
|
+
);
|
|
23
|
+
return /* @__PURE__ */ React.createElement(
|
|
24
|
+
"div",
|
|
25
|
+
{
|
|
26
|
+
className: "pnt-image-preview-wrapper",
|
|
27
|
+
onClick: (e) => {
|
|
28
|
+
if ((iconUrl == null ? void 0 : iconUrl.length) || loading) {
|
|
29
|
+
e.stopPropagation();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
loading ? LoadingContent(false) : /* @__PURE__ */ React.createElement(
|
|
34
|
+
ImageViewer,
|
|
35
|
+
{
|
|
36
|
+
images: [src],
|
|
37
|
+
closeOnOverlay: true,
|
|
38
|
+
trigger: ({ open }) => {
|
|
39
|
+
const mask = /* @__PURE__ */ React.createElement("div", { className: "pnt-image-preview-mask" }, /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(BrowseIcon, { onClick: open, size: "16px", name: "browse" })), /* @__PURE__ */ React.createElement("span", { className: "pnt-image-preview-divider" }), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(DeleteIcon, { onClick: onRemove, size: "16px", name: "delete" })));
|
|
40
|
+
return /* @__PURE__ */ React.createElement(
|
|
41
|
+
Image,
|
|
42
|
+
{
|
|
43
|
+
alt: "",
|
|
44
|
+
src,
|
|
45
|
+
loading: LoadingContent(true),
|
|
46
|
+
overlayContent: iconUrl ? mask : /* @__PURE__ */ React.createElement(React.Fragment, null),
|
|
47
|
+
overlayTrigger: "hover",
|
|
48
|
+
fit: "contain",
|
|
49
|
+
className: "pnt-image-preview",
|
|
50
|
+
style: params == null ? void 0 : params.style
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
var PntImagePreview_default = PntImagePreview;
|
|
59
|
+
export {
|
|
60
|
+
PntImagePreview_default as default
|
|
61
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
.pnt-image-preview-wrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
|
|
4
|
+
.pnt-image-preview-progress,
|
|
5
|
+
.pnt-image-preview-upload-progress {
|
|
6
|
+
width: 136px;
|
|
7
|
+
height: 136px;
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
|
|
12
|
+
.pnt-image-preview-loading {
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
text-align: center;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
border-radius: 4px;
|
|
21
|
+
background-color: #f7f8fa;
|
|
22
|
+
|
|
23
|
+
svg {
|
|
24
|
+
color: var(--td-brand-color);
|
|
25
|
+
font-size: 24px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
p {
|
|
29
|
+
margin-top: 4px;
|
|
30
|
+
color: #808191;
|
|
31
|
+
font-size: 12px;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.pnt-image-preview {
|
|
37
|
+
width: 136px;
|
|
38
|
+
height: 136px;
|
|
39
|
+
|
|
40
|
+
.pnt-image-preview-mask {
|
|
41
|
+
background: rgba(0, 0, 0, 60%);
|
|
42
|
+
color: #fff;
|
|
43
|
+
height: 100%;
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
.pnt-image-preview-divider {
|
|
48
|
+
margin: 0 var(--td-comp-margin-l);
|
|
49
|
+
border-left: 1px var(--td-text-color-anti) solid;
|
|
50
|
+
height: var(--td-comp-size-xxxs);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type HighSecurityFetcher } from "../../hooks/useHighSecurity";
|
|
2
|
+
import React, { FC } from 'react';
|
|
3
|
+
import './index.scss';
|
|
4
|
+
interface PntSecureBoxProps {
|
|
5
|
+
/**
|
|
6
|
+
* 高敏信息的唯一标识 key
|
|
7
|
+
* @description 用于标识和存储特定的高敏数据项
|
|
8
|
+
*/
|
|
9
|
+
dataKey: string;
|
|
10
|
+
/**
|
|
11
|
+
* 高敏信息的实际值
|
|
12
|
+
* @description 初始显示的值,通常为脱敏后的数据
|
|
13
|
+
*/
|
|
14
|
+
dataValue: string;
|
|
15
|
+
/**
|
|
16
|
+
* 环境标识
|
|
17
|
+
* @description 用于区分不同环境(如:dev, test, production)
|
|
18
|
+
*/
|
|
19
|
+
env: string | number;
|
|
20
|
+
/**
|
|
21
|
+
* 游戏 ID
|
|
22
|
+
* @description 标识具体的游戏项目
|
|
23
|
+
*/
|
|
24
|
+
gameId: string | number;
|
|
25
|
+
/**
|
|
26
|
+
* 自定义渲染函数
|
|
27
|
+
* @description 接收处理后的数据作为参数,返回需要渲染的 React 元素
|
|
28
|
+
* @param content - 处理后的数据内容(真实数据或脱敏数据)
|
|
29
|
+
* @returns React 元素
|
|
30
|
+
*/
|
|
31
|
+
renderDom: (content: string) => React.ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* 自定义查看按钮文案
|
|
34
|
+
* @description 用于适配多语言场景,默认为 'View'
|
|
35
|
+
*/
|
|
36
|
+
viewText?: string;
|
|
37
|
+
/**
|
|
38
|
+
* 页面 ID
|
|
39
|
+
* @description 用于记录操作日志和权限验证
|
|
40
|
+
*/
|
|
41
|
+
pageId?: string;
|
|
42
|
+
/**
|
|
43
|
+
* 高敏数据请求函数
|
|
44
|
+
* @description 通过外部注入请求函数,避免组件库内部依赖敏感配置
|
|
45
|
+
*/
|
|
46
|
+
fetcher: HighSecurityFetcher;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 高敏信息展示统一组件
|
|
50
|
+
* @description 用于统一处理和展示高敏信息,支持脱敏显示和按需获取真实数据
|
|
51
|
+
* @param {PntSecureBoxProps} props - 组件属性
|
|
52
|
+
* @param {string} props.dataKey - 高敏信息的唯一标识 key
|
|
53
|
+
* @param {string} props.dataValue - 高敏信息的实际值
|
|
54
|
+
* @param {string | number} props.env - 环境标识
|
|
55
|
+
* @param {string | number} props.gameId - 游戏 ID
|
|
56
|
+
* @param {(content: string) => React.ReactNode} props.renderDom - 自定义渲染函数
|
|
57
|
+
* @param {string} [props.viewText] - 自定义查看按钮文案
|
|
58
|
+
* @param {string} [props.pageId] - 页面 ID
|
|
59
|
+
* @param {HighSecurityFetcher} props.fetcher - 高敏数据请求函数
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* import http from '@/utils/request';
|
|
64
|
+
* import { PntSecureBox } from '@pnt-team/pnt-component-frontend';
|
|
65
|
+
*
|
|
66
|
+
* <PntSecureBox
|
|
67
|
+
* dataKey="userPhone"
|
|
68
|
+
* dataValue="138****8888"
|
|
69
|
+
* env="production"
|
|
70
|
+
* gameId={12345}
|
|
71
|
+
* fetcher={(params) => http.post('/api/v3/business/game_info/high-security-decrypt', params).then(r => r.data)}
|
|
72
|
+
* renderDom={(content) => <span>{content}</span>}
|
|
73
|
+
* viewText="查看"
|
|
74
|
+
* />
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @returns {ReactElement} 高敏信息展示组件
|
|
78
|
+
*/
|
|
79
|
+
declare const PntSecureBox: FC<PntSecureBoxProps>;
|
|
80
|
+
export default PntSecureBox;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/components/PntSecureBox/index.tsx
|
|
2
|
+
import {
|
|
3
|
+
useHighSecurity
|
|
4
|
+
} from "../../hooks/useHighSecurity";
|
|
5
|
+
import { isSecurityData } from "../../utils";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import "./index.scss";
|
|
8
|
+
var PntSecureBox = (prop) => {
|
|
9
|
+
const {
|
|
10
|
+
dataKey,
|
|
11
|
+
dataValue,
|
|
12
|
+
env,
|
|
13
|
+
gameId,
|
|
14
|
+
renderDom,
|
|
15
|
+
viewText,
|
|
16
|
+
pageId,
|
|
17
|
+
fetcher
|
|
18
|
+
} = prop;
|
|
19
|
+
const { securityData, requestSecurityData } = useHighSecurity(fetcher);
|
|
20
|
+
return /* @__PURE__ */ React.createElement("div", { className: "pnt-secure-box" }, /* @__PURE__ */ React.createElement(React.Fragment, null, renderDom(
|
|
21
|
+
isSecurityData(dataValue) ? securityData[dataKey] || "******" : dataValue
|
|
22
|
+
), isSecurityData(dataValue) && !securityData.hasOwnProperty(dataKey) && /* @__PURE__ */ React.createElement(
|
|
23
|
+
"span",
|
|
24
|
+
{
|
|
25
|
+
className: "view-icon",
|
|
26
|
+
onClick: () => {
|
|
27
|
+
requestSecurityData({
|
|
28
|
+
env,
|
|
29
|
+
gameId,
|
|
30
|
+
pageId,
|
|
31
|
+
param: [
|
|
32
|
+
{
|
|
33
|
+
key: dataKey,
|
|
34
|
+
value: dataValue
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
viewText || "View"
|
|
41
|
+
)));
|
|
42
|
+
};
|
|
43
|
+
var PntSecureBox_default = PntSecureBox;
|
|
44
|
+
export {
|
|
45
|
+
PntSecureBox_default as default
|
|
46
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.pnt-secure-box {
|
|
2
|
+
position: relative;
|
|
3
|
+
color: #333;
|
|
4
|
+
max-width: fit-content;
|
|
5
|
+
|
|
6
|
+
.view-icon {
|
|
7
|
+
position: absolute;
|
|
8
|
+
top: 1px;
|
|
9
|
+
right: -30px;
|
|
10
|
+
color: #3f8cff !important;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
font-size: small;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.security-value {
|
|
16
|
+
position: relative;
|
|
17
|
+
top: 3px;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/global.d.ts
|
|
2
|
+
declare module '*.png' {
|
|
3
|
+
const src: string;
|
|
4
|
+
export default src;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
declare module '*.jpg' {
|
|
8
|
+
const src: string;
|
|
9
|
+
export default src;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare module '*.svg' {
|
|
13
|
+
const src: string;
|
|
14
|
+
export default src;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 字体文件
|
|
18
|
+
declare module '*.woff' {
|
|
19
|
+
const src: string;
|
|
20
|
+
export default src;
|
|
21
|
+
}
|
|
22
|
+
declare module '*.woff2' {
|
|
23
|
+
const src: string;
|
|
24
|
+
export default src;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare module '*.json' {
|
|
28
|
+
const value: any;
|
|
29
|
+
export default value;
|
|
30
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** 按钮权限值:1 有权限,-1 隐藏,-2 禁用 */
|
|
2
|
+
export type BtnPermissionValue = number;
|
|
3
|
+
/** 按钮权限映射:外层 key 为业务类型(全局为 'global' / 演示游戏为 '0' / 业务为具体 gameId / 兜底为 'no_permission_manner'),内层 key 为按钮标识符 */
|
|
4
|
+
export type BtnPermissionMap = Record<string, Record<string, BtnPermissionValue>>;
|
|
5
|
+
/** 演示游戏信息(来自用户信息,用于演示游戏判定) */
|
|
6
|
+
export interface DemoGameInfo {
|
|
7
|
+
id: number | string;
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
/** 当前服务信息(与 demoGame 比对判断是否演示游戏) */
|
|
11
|
+
export interface ServiceInfo {
|
|
12
|
+
serviceType?: number | string;
|
|
13
|
+
serviceName?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface UseBtnPermissionOptions {
|
|
16
|
+
/**
|
|
17
|
+
* 按钮权限映射(原从全局 store 注入,现改为入参注入)。
|
|
18
|
+
* 未传或取不到值时按有权限(1)处理。
|
|
19
|
+
*/
|
|
20
|
+
permissions?: BtnPermissionMap;
|
|
21
|
+
/** 演示游戏信息;与 serviceInfo 同时传入才启用演示游戏判定 */
|
|
22
|
+
demoGame?: DemoGameInfo;
|
|
23
|
+
/** 当前服务信息 */
|
|
24
|
+
serviceInfo?: ServiceInfo;
|
|
25
|
+
}
|
|
26
|
+
/** 演示游戏在权限映射中的业务类型 key */
|
|
27
|
+
export declare const DEMO_GAME_TYPE_KEY = "0";
|
|
28
|
+
/** 无权限兜底配置的业务类型 key */
|
|
29
|
+
export declare const NO_PERMISSION_MANNER_KEY = "no_permission_manner";
|
|
30
|
+
/**
|
|
31
|
+
* 按钮权限 Hook(L3 业务 Hook)
|
|
32
|
+
*
|
|
33
|
+
* 融合 account-business-frontend 与 pnt-internal-tools-frontend 两版实现:
|
|
34
|
+
* - getBtnPermission(type, key):获取按钮处理方式,1 有权限 / -1 隐藏 / -2 禁用,
|
|
35
|
+
* 取不到值时依次回退到 no_permission_manner 兜底配置、defaultValue(默认 1);
|
|
36
|
+
* - 演示游戏(当前服务命中 demoGame)时固定使用 key '0' 的权限配置(account 版行为);
|
|
37
|
+
* - 零业务侵入:权限列表与演示游戏信息均通过入参注入,不再依赖 redux / umi / dva。
|
|
38
|
+
*
|
|
39
|
+
* @param options.permissions 按钮权限映射
|
|
40
|
+
* @param options.demoGame 演示游戏信息
|
|
41
|
+
* @param options.serviceInfo 当前服务信息
|
|
42
|
+
* @returns btnPermission 权限映射原文;isDemoGame 是否为演示游戏;getBtnPermission 获取按钮权限
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* import { useBtnPermission } from '@pnt/business-components';
|
|
47
|
+
*
|
|
48
|
+
* const Demo = ({ btnPermission, userInfo }) => {
|
|
49
|
+
* const { isDemoGame, getBtnPermission } = useBtnPermission({
|
|
50
|
+
* permissions: btnPermission, // 例如 { global: { create: 1 }, no_permission_manner: { create: -2 } }
|
|
51
|
+
* demoGame: userInfo?.demoGame, // 例如 { id: 11, name: 'DemoGame' }
|
|
52
|
+
* serviceInfo: { serviceType: userInfo?.serviceType, serviceName: userInfo?.serviceName },
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* const createPerm = getBtnPermission('global', 'create'); // 1 | -1 | -2
|
|
56
|
+
*
|
|
57
|
+
* if (createPerm === -1) return null; // 隐藏
|
|
58
|
+
* return <Button disabled={createPerm === -2}>新建{isDemoGame ? '(演示)' : ''}</Button>;
|
|
59
|
+
* };
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const useBtnPermission: (options?: UseBtnPermissionOptions) => {
|
|
63
|
+
btnPermission: BtnPermissionMap | undefined;
|
|
64
|
+
isDemoGame: boolean;
|
|
65
|
+
getBtnPermission: (type: string, key: string, defaultValue?: BtnPermissionValue) => BtnPermissionValue;
|
|
66
|
+
};
|
|
67
|
+
export default useBtnPermission;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/hooks/useBtnPermission.ts
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
3
|
+
var DEMO_GAME_TYPE_KEY = "0";
|
|
4
|
+
var NO_PERMISSION_MANNER_KEY = "no_permission_manner";
|
|
5
|
+
var useBtnPermission = (options = {}) => {
|
|
6
|
+
const { permissions, demoGame, serviceInfo } = options;
|
|
7
|
+
const isDemoGame = useMemo(() => {
|
|
8
|
+
if (!demoGame || !serviceInfo)
|
|
9
|
+
return false;
|
|
10
|
+
return serviceInfo.serviceType === demoGame.id && serviceInfo.serviceName === demoGame.name;
|
|
11
|
+
}, [demoGame, serviceInfo]);
|
|
12
|
+
const getBtnPermission = useCallback(
|
|
13
|
+
(type, key, defaultValue = 1) => {
|
|
14
|
+
var _a, _b;
|
|
15
|
+
return ((_a = permissions == null ? void 0 : permissions[isDemoGame ? DEMO_GAME_TYPE_KEY : type]) == null ? void 0 : _a[key]) ?? ((_b = permissions == null ? void 0 : permissions[NO_PERMISSION_MANNER_KEY]) == null ? void 0 : _b[key]) ?? defaultValue ?? 1;
|
|
16
|
+
},
|
|
17
|
+
[permissions, isDemoGame]
|
|
18
|
+
);
|
|
19
|
+
return {
|
|
20
|
+
btnPermission: permissions,
|
|
21
|
+
isDemoGame,
|
|
22
|
+
getBtnPermission
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
var useBtnPermission_default = useBtnPermission;
|
|
26
|
+
export {
|
|
27
|
+
DEMO_GAME_TYPE_KEY,
|
|
28
|
+
NO_PERMISSION_MANNER_KEY,
|
|
29
|
+
useBtnPermission_default as default,
|
|
30
|
+
useBtnPermission
|
|
31
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** 高敏数据请求参数 */
|
|
2
|
+
export interface HighSecurityRequestParams {
|
|
3
|
+
/** 游戏 ID */
|
|
4
|
+
gameId: string | number;
|
|
5
|
+
/** 环境标识 */
|
|
6
|
+
env: string | number;
|
|
7
|
+
/** 页面 ID(不传则默认取 location.pathname) */
|
|
8
|
+
pageId?: string;
|
|
9
|
+
/** 需要解锁的参数列表 */
|
|
10
|
+
param: Array<{
|
|
11
|
+
key: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
/** 高敏数据请求函数:返回 { ret, data } 结构且 ret === 0 视为成功 */
|
|
16
|
+
export type HighSecurityFetcher = (params: HighSecurityRequestParams) => Promise<{
|
|
17
|
+
ret: number;
|
|
18
|
+
data?: Array<{
|
|
19
|
+
key: string;
|
|
20
|
+
value: string;
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* 高敏数据解锁 Hook(L3 业务 Hook)
|
|
25
|
+
*
|
|
26
|
+
* 管理高敏数据的解锁状态。零业务侵入:请求函数通过 fetcher 注入,
|
|
27
|
+
* 不再依赖内部 api/configs,避免将敏感配置打包进发布产物。
|
|
28
|
+
*
|
|
29
|
+
* @param fetcher 自定义高敏数据请求函数,需返回 { ret, data } 结构且 ret === 0 视为成功
|
|
30
|
+
* @returns securityData 已解锁的高敏数据映射;requestSecurityData 请求解锁指定数据
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* import http from '@/utils/request';
|
|
35
|
+
* import { useHighSecurity } from '@pnt-team/pnt-component-frontend';
|
|
36
|
+
*
|
|
37
|
+
* const Demo = () => {
|
|
38
|
+
* const { securityData, requestSecurityData } = useHighSecurity((params) =>
|
|
39
|
+
* http.post('/api/v3/business/game_info/high-security-decrypt', params).then(r => r.data)
|
|
40
|
+
* );
|
|
41
|
+
* // ...
|
|
42
|
+
* };
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare const useHighSecurity: (fetcher: HighSecurityFetcher) => {
|
|
46
|
+
securityData: Record<string, string>;
|
|
47
|
+
requestSecurityData: ({ gameId, param, env, pageId, }: HighSecurityRequestParams) => Promise<void>;
|
|
48
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/hooks/useHighSecurity.ts
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
var securityCache = /* @__PURE__ */ new Map();
|
|
4
|
+
var useHighSecurity = (fetcher) => {
|
|
5
|
+
const [securityData, setSecurityData] = useState(
|
|
6
|
+
() => {
|
|
7
|
+
const cached = {};
|
|
8
|
+
securityCache.forEach((value, key) => {
|
|
9
|
+
cached[key] = value;
|
|
10
|
+
});
|
|
11
|
+
return cached;
|
|
12
|
+
}
|
|
13
|
+
);
|
|
14
|
+
const requestSecurityData = async ({
|
|
15
|
+
gameId,
|
|
16
|
+
param,
|
|
17
|
+
env,
|
|
18
|
+
pageId
|
|
19
|
+
}) => {
|
|
20
|
+
const result = await fetcher({
|
|
21
|
+
gameId,
|
|
22
|
+
env: Number(env),
|
|
23
|
+
pageId: pageId || location.pathname,
|
|
24
|
+
param
|
|
25
|
+
});
|
|
26
|
+
if (result.ret === 0 && result.data) {
|
|
27
|
+
result.data.forEach((item) => {
|
|
28
|
+
securityCache.set(item.key, item.value);
|
|
29
|
+
});
|
|
30
|
+
setSecurityData(Object.fromEntries(securityCache));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
securityData,
|
|
35
|
+
requestSecurityData
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export {
|
|
39
|
+
useHighSecurity
|
|
40
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** OS 平台数据类型定义 */
|
|
2
|
+
export interface OsItem {
|
|
3
|
+
id: number;
|
|
4
|
+
os_name: string;
|
|
5
|
+
sdk_name: string;
|
|
6
|
+
status: number;
|
|
7
|
+
platform_id: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PlatformItem {
|
|
10
|
+
id: number;
|
|
11
|
+
platform_name_zh: string;
|
|
12
|
+
platform_name_en: string;
|
|
13
|
+
status: number;
|
|
14
|
+
}
|
|
15
|
+
export interface OsPlatformData {
|
|
16
|
+
os_list: OsItem[];
|
|
17
|
+
platform_list: PlatformItem[];
|
|
18
|
+
}
|
|
19
|
+
/** OS/平台列表请求函数:返回 { code, msg, data } 结构且 code === 0 视为成功 */
|
|
20
|
+
export type OsPlatformFetcher = () => Promise<{
|
|
21
|
+
code: number;
|
|
22
|
+
msg: string;
|
|
23
|
+
data: OsPlatformData;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* 清除缓存(用于极少数需要强制刷新的场景,如后台更新了平台列表后)。
|
|
27
|
+
* @param fetcher 指定要清除的 fetcher;不传则清除全部缓存
|
|
28
|
+
*/
|
|
29
|
+
export declare const clearOsPlatformListCache: (fetcher?: OsPlatformFetcher) => void;
|
|
30
|
+
/**
|
|
31
|
+
* OS/平台列表 Hook(L3 业务 Hook)
|
|
32
|
+
*
|
|
33
|
+
* 拉取 OS 与平台枚举数据并做模块级缓存,整个会话只请求一次;
|
|
34
|
+
* 并发调用共享同一个进行中的请求。
|
|
35
|
+
*
|
|
36
|
+
* 零业务侵入:数据接口通过 fetcher 注入,不再依赖内部 request/configs,
|
|
37
|
+
* 避免将敏感配置打包进发布产物。
|
|
38
|
+
*
|
|
39
|
+
* @param fetcher 自定义请求函数,需返回 { code, msg, data } 结构且 code === 0 视为成功
|
|
40
|
+
* @returns osPlatformList OS/平台数据,请求完成或命中缓存前为 undefined
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* import http from '@/utils/request';
|
|
45
|
+
* import { useOsPlatformList } from '@pnt-team/pnt-component-frontend';
|
|
46
|
+
*
|
|
47
|
+
* const Demo = () => {
|
|
48
|
+
* const { osPlatformList } = useOsPlatformList(() =>
|
|
49
|
+
* http.get('/api/internal/business/manage/osPlatformList').then(r => r.data)
|
|
50
|
+
* );
|
|
51
|
+
*
|
|
52
|
+
* return (
|
|
53
|
+
* <Select
|
|
54
|
+
* options={osPlatformList?.platform_list.map((p) => ({
|
|
55
|
+
* label: p.platform_name_zh,
|
|
56
|
+
* value: p.id,
|
|
57
|
+
* }))}
|
|
58
|
+
* />
|
|
59
|
+
* );
|
|
60
|
+
* };
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const useOsPlatformList: (fetcher: OsPlatformFetcher) => {
|
|
64
|
+
osPlatformList: OsPlatformData | undefined;
|
|
65
|
+
};
|
|
66
|
+
export default useOsPlatformList;
|