@pnt-team/pnt-component-frontend 0.0.73 → 0.0.75

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.
@@ -1,68 +1,120 @@
1
- // src/components/PntImagePreview/index.tsx
2
1
  import uploadImg from "../../assets/images/uploadImg.png";
3
- import { BrowseIcon, DeleteIcon, LoadingIcon } from "tdesign-icons-react";
4
- import { Image, ImageViewer } from "tdesign-react";
2
+ import React from 'react';
3
+ import { BrowseIcon, DeleteIcon, LoadingIcon } from 'tdesign-icons-react';
4
+ import { Image, ImageViewer } from 'tdesign-react';
5
5
  import "./index.scss";
6
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
- var PntImagePreview = ({
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ import { jsxs as _jsxs } from "react/jsx-runtime";
8
+ import { Fragment as _Fragment } from "react/jsx-runtime";
9
+ /**
10
+ * 上传图片查看器组件
11
+ * @description 用于展示上传的图片,支持预览、删除功能和上传状态显示
12
+ * @param {PntImagePreviewProps} props - 组件属性
13
+ * @param {string | undefined} props.iconUrl - 当前图片组件 URL
14
+ * @param {boolean} props.loading - 上传加载状态
15
+ * @param {string} [props.defaultImg] - 默认图片
16
+ * @param {object} [props.params] - 自定义扩展参数
17
+ * @param {function} [props.onRemove] - 删除回调函数
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * // 基础用法
22
+ * <UploadImageViewer
23
+ * iconUrl={imageUrl}
24
+ * loading={uploading}
25
+ * onRemove={handleRemove}
26
+ * />
27
+ *
28
+ * // 带默认图片
29
+ * <UploadImageViewer
30
+ * iconUrl={imageUrl}
31
+ * loading={false}
32
+ * defaultImg="/path/to/default.png"
33
+ * onRemove={handleRemove}
34
+ * />
35
+ *
36
+ * // 自定义样式
37
+ * <UploadImageViewer
38
+ * iconUrl={imageUrl}
39
+ * loading={uploading}
40
+ * params={{ style: { width: '200px', height: '200px' } }}
41
+ * onRemove={handleRemove}
42
+ * />
43
+ * ```
44
+ *
45
+ * @returns {ReactElement} 上传图片查看器组件
46
+ */
47
+ const PntImagePreview = ({
8
48
  iconUrl,
9
49
  loading,
10
50
  defaultImg,
11
51
  params,
12
52
  onRemove
13
53
  }) => {
14
- const src = (iconUrl == null ? void 0 : iconUrl.length) ? iconUrl : defaultImg || uploadImg;
15
- const LoadingContent = (isImageLoading) => /* @__PURE__ */ jsx(
16
- "div",
17
- {
18
- className: isImageLoading ? "pnt-image-preview-progress" : "pnt-image-preview-upload-progress",
19
- style: params == null ? void 0 : params.style,
20
- children: /* @__PURE__ */ jsxs("div", { className: "pnt-image-preview-loading", children: [
21
- /* @__PURE__ */ jsx(LoadingIcon, { size: "18px", name: "loading" }),
22
- /* @__PURE__ */ jsx("p", { children: "上传中" })
23
- ] })
24
- }
25
- );
26
- return /* @__PURE__ */ jsx(
27
- "div",
28
- {
29
- className: "pnt-image-preview-wrapper",
30
- onClick: (e) => {
31
- if ((iconUrl == null ? void 0 : iconUrl.length) || loading) {
32
- e.stopPropagation();
33
- }
34
- },
35
- children: loading ? LoadingContent(false) : /* @__PURE__ */ jsx(
36
- ImageViewer,
37
- {
38
- images: [src],
39
- closeOnOverlay: true,
40
- trigger: ({ open }) => {
41
- const mask = /* @__PURE__ */ jsxs("div", { className: "pnt-image-preview-mask", children: [
42
- /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(BrowseIcon, { onClick: open, size: "16px", name: "browse" }) }),
43
- /* @__PURE__ */ jsx("span", { className: "pnt-image-preview-divider" }),
44
- /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(DeleteIcon, { onClick: onRemove, size: "16px", name: "delete" }) })
45
- ] });
46
- return /* @__PURE__ */ jsx(
47
- Image,
48
- {
49
- alt: "",
50
- src,
51
- loading: LoadingContent(true),
52
- overlayContent: iconUrl ? mask : /* @__PURE__ */ jsx(Fragment, {}),
53
- overlayTrigger: "hover",
54
- fit: "contain",
55
- className: "pnt-image-preview",
56
- style: params == null ? void 0 : params.style
57
- }
58
- );
59
- }
60
- }
61
- )
62
- }
63
- );
64
- };
65
- var PntImagePreview_default = PntImagePreview;
66
- export {
67
- PntImagePreview_default as default
54
+ const src = iconUrl?.length ? iconUrl : defaultImg || uploadImg;
55
+
56
+ /**
57
+ * 加载中组件
58
+ * @param isImageLoading - 是否为图片加载状态
59
+ * @description 统一使用一种loading效果,避免两种加载风格
60
+ * @returns 加载状态的 JSX 元素
61
+ */
62
+ const LoadingContent = isImageLoading => /*#__PURE__*/_jsx("div", {
63
+ className: isImageLoading ? 'pnt-image-preview-progress' : 'pnt-image-preview-upload-progress',
64
+ style: params?.style,
65
+ children: /*#__PURE__*/_jsxs("div", {
66
+ className: "pnt-image-preview-loading",
67
+ children: [/*#__PURE__*/_jsx(LoadingIcon, {
68
+ size: "18px",
69
+ name: 'loading'
70
+ }), /*#__PURE__*/_jsx("p", {
71
+ children: "\u4E0A\u4F20\u4E2D"
72
+ })]
73
+ })
74
+ });
75
+ return /*#__PURE__*/_jsx("div", {
76
+ className: "pnt-image-preview-wrapper",
77
+ onClick: e => {
78
+ if (iconUrl?.length || loading) {
79
+ e.stopPropagation(); // 图片已上传 或 加载中 阻止上传行为
80
+ }
81
+ },
82
+ children: loading ? LoadingContent(false) : /*#__PURE__*/_jsx(ImageViewer, {
83
+ images: [src],
84
+ closeOnOverlay: true,
85
+ trigger: ({
86
+ open
87
+ }) => {
88
+ const mask = /*#__PURE__*/_jsxs("div", {
89
+ className: "pnt-image-preview-mask",
90
+ children: [/*#__PURE__*/_jsx("span", {
91
+ children: /*#__PURE__*/_jsx(BrowseIcon, {
92
+ onClick: open,
93
+ size: "16px",
94
+ name: 'browse'
95
+ })
96
+ }), /*#__PURE__*/_jsx("span", {
97
+ className: "pnt-image-preview-divider"
98
+ }), /*#__PURE__*/_jsx("span", {
99
+ children: /*#__PURE__*/_jsx(DeleteIcon, {
100
+ onClick: onRemove,
101
+ size: "16px",
102
+ name: 'delete'
103
+ })
104
+ })]
105
+ });
106
+ return /*#__PURE__*/_jsx(Image, {
107
+ alt: '',
108
+ src: src,
109
+ loading: LoadingContent(true),
110
+ overlayContent: iconUrl ? mask : /*#__PURE__*/_jsx(_Fragment, {}),
111
+ overlayTrigger: "hover",
112
+ fit: "contain",
113
+ className: "pnt-image-preview",
114
+ style: params?.style
115
+ });
116
+ }
117
+ })
118
+ });
68
119
  };
120
+ export default PntImagePreview;
@@ -1,38 +1,75 @@
1
- // src/components/PntSecureBox/index.tsx
2
1
  import { useHighSecurity } from "../../hooks/useHighSecurity";
3
2
  import { isSecurityData } from "../../utils";
3
+ import React from 'react';
4
4
  import "./index.scss";
5
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
- var PntSecureBox = (prop) => {
7
- const { dataKey, dataValue, env, gameId, renderDom, viewText, pageId } = prop;
8
- const { securityData, requestSecurityData } = useHighSecurity();
9
- return /* @__PURE__ */ jsx("div", { className: "pnt-secure-box", children: /* @__PURE__ */ jsxs(Fragment, { children: [
10
- renderDom(
11
- isSecurityData(dataValue) ? securityData[dataKey] || "******" : dataValue
12
- ),
13
- isSecurityData(dataValue) && !securityData.hasOwnProperty(dataKey) && /* @__PURE__ */ jsx(
14
- "span",
15
- {
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { Fragment as _Fragment } from "react/jsx-runtime";
7
+ import { jsxs as _jsxs } from "react/jsx-runtime";
8
+ /**
9
+ * 高敏信息展示统一组件
10
+ * @description 用于统一处理和展示高敏信息,支持脱敏显示和按需获取真实数据。
11
+ * 通过 PntProvider 注入 http 实例,对接 `/api/v3/business/game_info/high-security-decrypt`。
12
+ *
13
+ * @param {PntSecureBoxProps} props - 组件属性
14
+ * @param {string} props.dataKey - 高敏信息的唯一标识 key
15
+ * @param {string} props.dataValue - 高敏信息的实际值
16
+ * @param {string | number} props.env - 环境标识
17
+ * @param {string | number} props.gameId - 游戏 ID
18
+ * @param {(content: string) => React.ReactNode} props.renderDom - 自定义渲染函数
19
+ * @param {string} [props.viewText] - 自定义查看按钮文案
20
+ * @param {string} [props.pageId] - 页面 ID
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { PntSecureBox } from '@pnt-team/pnt-component-frontend';
25
+ *
26
+ * <PntSecureBox
27
+ * dataKey="userPhone"
28
+ * dataValue="_high_security_:AAAA...:6542"
29
+ * env={2}
30
+ * gameId={12345}
31
+ * renderDom={(content) => <span>{content}</span>}
32
+ * viewText="查看"
33
+ * />
34
+ * ```
35
+ *
36
+ * @returns {ReactElement} 高敏信息展示组件
37
+ */
38
+ const PntSecureBox = prop => {
39
+ const {
40
+ dataKey,
41
+ dataValue,
42
+ env,
43
+ gameId,
44
+ renderDom,
45
+ viewText,
46
+ pageId
47
+ } = prop;
48
+
49
+ // 通过 PntProvider 注入的 http 实例请求高敏数据
50
+ const {
51
+ securityData,
52
+ requestSecurityData
53
+ } = useHighSecurity();
54
+ return /*#__PURE__*/_jsx("div", {
55
+ className: "pnt-secure-box",
56
+ children: /*#__PURE__*/_jsxs(_Fragment, {
57
+ children: [renderDom(isSecurityData(dataValue) ? securityData[dataKey] || '******' : dataValue), isSecurityData(dataValue) && !securityData.hasOwnProperty(dataKey) && /*#__PURE__*/_jsx("span", {
16
58
  className: "view-icon",
17
59
  onClick: () => {
18
60
  requestSecurityData({
19
61
  env,
20
62
  gameId,
21
63
  pageId,
22
- param: [
23
- {
24
- key: dataKey,
25
- value: dataValue
26
- }
27
- ]
64
+ param: [{
65
+ key: dataKey,
66
+ value: dataValue
67
+ }]
28
68
  });
29
69
  },
30
- children: viewText || "View"
31
- }
32
- )
33
- ] }) });
34
- };
35
- var PntSecureBox_default = PntSecureBox;
36
- export {
37
- PntSecureBox_default as default
70
+ children: viewText || 'View'
71
+ })]
72
+ })
73
+ });
38
74
  };
75
+ export default PntSecureBox;
package/lib/esm/config.js CHANGED
@@ -1,17 +1,37 @@
1
- // src/config.tsx
2
- import { createContext, useContext } from "react";
3
- var PntContext = createContext(null);
4
- var PntProvider = PntContext.Provider;
5
- var usePntConfig = () => {
1
+ import { createContext, useContext } from 'react';
2
+
3
+ /**
4
+ * 统一响应结构(与后端 commonEesType 对齐)
5
+ */
6
+
7
+ /**
8
+ * 组件库运行时配置:由消费方通过 PntProvider 注入
9
+ */
10
+
11
+ const PntContext = /*#__PURE__*/createContext(null);
12
+
13
+ /**
14
+ * 配置 Provider:消费方在应用根入口包裹一次即可
15
+ * @example
16
+ * ```tsx
17
+ * import { PntProvider } from '@pnt-team/pnt-component-frontend';
18
+ * import http from './utils/request';
19
+ *
20
+ * <PntProvider value={{ http }}>
21
+ * <App />
22
+ * </PntProvider>
23
+ * ```
24
+ */
25
+ export const PntProvider = PntContext.Provider;
26
+
27
+ /**
28
+ * 获取组件库运行时配置(内部使用)
29
+ * @internal
30
+ */
31
+ export const usePntConfig = () => {
6
32
  const cfg = useContext(PntContext);
7
33
  if (!cfg) {
8
- throw new Error(
9
- "[pnt-component-frontend] 未注入配置:请在应用根入口用 <PntProvider value={{ http }}> 包裹"
10
- );
34
+ throw new Error('[pnt-component-frontend] 未注入配置:请在应用根入口用 <PntProvider value={{ http }}> 包裹');
11
35
  }
12
36
  return cfg;
13
- };
14
- export {
15
- PntProvider,
16
- usePntConfig
17
- };
37
+ };
@@ -1,40 +1,47 @@
1
- // src/hooks/useHighSecurity.ts
2
1
  import { businessGameInfoHighSecurityDecrypt } from "../api";
3
2
  import { usePntConfig } from "../config";
4
- import { useState } from "react";
5
- var securityCache = /* @__PURE__ */ new Map();
6
- var useHighSecurity = () => {
7
- const { http } = usePntConfig();
8
- const [securityData, setSecurityData] = useState(
9
- () => {
10
- const cached = {};
11
- securityCache.forEach((value, key) => {
12
- cached[key] = value;
13
- });
14
- return cached;
15
- }
16
- );
3
+ import { useState } from 'react';
4
+
5
+ /** 高敏数据请求参数(组件层友好命名) */
6
+
7
+ const securityCache = new Map();
8
+
9
+ /**
10
+ * 高敏数据解锁 Hook(PntSecureBox 内部依赖)
11
+ * @internal 不对外导出,归 PntSecureBox 组件内部使用
12
+ */
13
+ export const useHighSecurity = () => {
14
+ const {
15
+ http
16
+ } = usePntConfig();
17
+ const [securityData, setSecurityData] = useState(() => {
18
+ const cached = {};
19
+ securityCache.forEach((value, key) => {
20
+ cached[key] = value;
21
+ });
22
+ return cached;
23
+ });
17
24
  const requestSecurityData = async ({
18
25
  gameId,
19
26
  param,
20
27
  env,
21
28
  pageId
22
29
  }) => {
30
+ // 适配后端 BusinessGameInfoHighSecurityDecryptBody 结构
23
31
  const body = {
24
32
  game_id: Number(gameId),
25
33
  env: Number(env),
26
34
  page_id: pageId || location.pathname,
27
- param: param.map(
28
- (i) => ({
29
- key: i.key,
30
- value: i.value
31
- })
32
- )
35
+ param: param.map(i => ({
36
+ key: i.key,
37
+ value: i.value
38
+ }))
33
39
  };
34
40
  const result = await businessGameInfoHighSecurityDecrypt(http, body);
41
+ // 适配 commonEesType:code === 0 视为成功
35
42
  if (result.code === 0 && result.data) {
36
43
  const data = result.data;
37
- data.forEach((item) => {
44
+ data.forEach(item => {
38
45
  securityCache.set(item.key, item.value);
39
46
  });
40
47
  setSecurityData(Object.fromEntries(securityCache));
@@ -44,7 +51,4 @@ var useHighSecurity = () => {
44
51
  securityData,
45
52
  requestSecurityData
46
53
  };
47
- };
48
- export {
49
- useHighSecurity
50
- };
54
+ };
package/lib/esm/index.js CHANGED
@@ -1,17 +1,18 @@
1
- // src/index.ts
2
- import {
3
- PntProvider,
4
- usePntConfig
5
- } from "./config";
6
- import { default as default2 } from "./components/PntImagePreview";
7
- import { default as default3 } from "./components/PntBusinessSelect";
8
- import { default as default4 } from "./components/PntSecureBox";
9
- import { default as default5 } from "./components/PntGeneralLayout";
10
- export {
11
- default3 as PntBusinessSelect,
12
- default5 as PntGeneralLayout,
13
- default2 as PntImagePreview,
14
- PntProvider,
15
- default4 as PntSecureBox,
16
- usePntConfig
17
- };
1
+ // ==========================================
2
+ // pnt-component-frontend 统一出口
3
+ // 只保留业务语义组件:有视觉、有交互、有业务含义
4
+ // hooks / 纯工具 / API wrapper 归各项目自己维护
5
+ // ==========================================
6
+
7
+ // ---------- 配置 Provider(消费方根入口注入 http 实例) ----------
8
+ export { PntProvider, usePntConfig } from "./config";
9
+
10
+ // ---------- L1 基础展示组件 ----------
11
+ export { default as PntImagePreview } from "./components/PntImagePreview";
12
+
13
+ // ---------- L2 业务复合组件 ----------
14
+ export { default as PntBusinessSelect } from "./components/PntBusinessSelect";
15
+ export { default as PntSecureBox } from "./components/PntSecureBox";
16
+
17
+ // ---------- L3 布局组件 ----------
18
+ export { default as PntGeneralLayout } from "./components/PntGeneralLayout";
@@ -1,16 +1,17 @@
1
- // src/utils/const.ts
2
- var SUB_APP_PATHNAME = {
3
- ACCOUNT: "/laas",
4
- SDK: "/intlsdk",
5
- NOTICE: "/notice",
6
- CONFIGFROM: "/configform",
7
- CONFIGTHEME: "/configtheme",
8
- REVIEWLIST: "/approvalservices",
9
- INTERNALTOOLS: "/internaltools",
10
- REPORTS: "/reports"
1
+ // 子系统页面的路由
2
+ export const SUB_APP_PATHNAME = {
3
+ ACCOUNT: '/laas',
4
+ SDK: '/intlsdk',
5
+ NOTICE: '/notice',
6
+ CONFIGFROM: '/configform',
7
+ CONFIGTHEME: '/configtheme',
8
+ REVIEWLIST: '/approvalservices',
9
+ INTERNALTOOLS: '/internaltools',
10
+ REPORTS: '/reports'
11
11
  };
12
- var audienceSuffix = "-pnt";
13
- var AUDIENCE_MAPPING = {
12
+ const audienceSuffix = '-pnt';
13
+ // 子系统的audienceMapping
14
+ export const AUDIENCE_MAPPING = {
14
15
  [SUB_APP_PATHNAME.ACCOUNT]: `/laas${audienceSuffix}`,
15
16
  [SUB_APP_PATHNAME.SDK]: `/intl-sdk${audienceSuffix}`,
16
17
  [SUB_APP_PATHNAME.NOTICE]: `/notice${audienceSuffix}`,
@@ -19,8 +20,4 @@ var AUDIENCE_MAPPING = {
19
20
  [SUB_APP_PATHNAME.REVIEWLIST]: `/approval-services${audienceSuffix}`,
20
21
  [SUB_APP_PATHNAME.INTERNALTOOLS]: `/internaltools${audienceSuffix}`,
21
22
  [SUB_APP_PATHNAME.REPORTS]: `/reports${audienceSuffix}`
22
- };
23
- export {
24
- AUDIENCE_MAPPING,
25
- SUB_APP_PATHNAME
26
- };
23
+ };
@@ -1,19 +1,22 @@
1
- // src/utils/index.ts
2
- var isSecurityData = (val) => {
1
+ /**
2
+ * 判断是否是高敏信息逻辑
3
+ * @param {*} val
4
+ * @returns
5
+ */
6
+ export const isSecurityData = val => {
3
7
  const str = String(val);
4
- if (!str.includes("_high_security_:"))
5
- return false;
6
- const rsp = str.split(":");
7
- const calcStr = rsp.slice(0, -1).join(":");
8
+ if (!str.includes('_high_security_:')) return false;
9
+
10
+ // 符合加密条件 开始解密
11
+ const rsp = str.split(':');
12
+ const calcStr = rsp.slice(0, -1).join(':');
8
13
  const calcNum = parseInt(rsp[rsp.length - 1], 10);
9
- if (isNaN(calcNum))
10
- return false;
14
+
15
+ // 错误处理
16
+ if (isNaN(calcNum)) return false;
11
17
  let num = 0;
12
18
  for (const item of calcStr) {
13
19
  num += item.charCodeAt(0);
14
20
  }
15
21
  return num === calcNum;
16
- };
17
- export {
18
- isSecurityData
19
- };
22
+ };
@@ -1 +1 @@
1
- .pnt-image-preview-wrapper{position:relative}.pnt-image-preview-wrapper .pnt-image-preview-progress,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress{align-items:center;display:flex;height:8.5rem;justify-content:center;width:8.5rem}.pnt-image-preview-wrapper .pnt-image-preview-progress .pnt-image-preview-loading,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress .pnt-image-preview-loading{align-items:center;background-color:#f7f8fa;border-radius:.25rem;display:flex;flex-direction:column;height:100%;justify-content:center;text-align:center;width:100%}.pnt-image-preview-wrapper .pnt-image-preview-progress .pnt-image-preview-loading svg,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress .pnt-image-preview-loading svg{color:var(--td-brand-color);font-size:1.5rem}.pnt-image-preview-wrapper .pnt-image-preview-progress .pnt-image-preview-loading p,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress .pnt-image-preview-loading p{color:#808191;font-size:.75rem;margin-top:.25rem}.pnt-image-preview-wrapper .pnt-image-preview{height:8.5rem;width:8.5rem}.pnt-image-preview-wrapper .pnt-image-preview .pnt-image-preview-mask{align-items:center;background:rgba(0,0,0,.6);color:#fff;display:flex;height:100%;justify-content:center}.pnt-image-preview-wrapper .pnt-image-preview .pnt-image-preview-mask .pnt-image-preview-divider{border-left:.0625rem solid var(--td-text-color-anti);height:var(--td-comp-size-xxxs);margin:0 var(--td-comp-margin-l)}.pnt-business-select{width:100%}.pnt-business-select-option-label{display:block;width:100%}.pnt-secure-box{color:#333;max-width:-moz-fit-content;max-width:fit-content;position:relative}.pnt-secure-box .view-icon{color:#3f8cff!important;cursor:pointer;font-size:small;position:absolute;right:-1.875rem;top:.0625rem}.pnt-secure-box .security-value{position:relative;top:.1875rem}.pnt-general-layout{background-color:transparent;height:100%}.pnt-general-layout .t-layout__header{border-bottom:.0625rem solid #f0f3f6;display:flex;height:auto;justify-content:space-between}.pnt-general-layout .t-layout__header .header-title{display:inline-block;padding:1.5rem;vertical-align:top}.pnt-general-layout .t-layout__header .header-title .goback-icon{color:#3f8cff;cursor:pointer;margin-right:.75rem;vertical-align:top}.pnt-general-layout .t-layout__header .header-title .title{display:inline-block;font-size:1.25rem;font-weight:600;height:1.5rem;line-height:1.5rem;vertical-align:top}.pnt-general-layout .t-layout__header .header-operation{height:4.5rem;line-height:4.5rem;padding-right:1.5rem}.pnt-general-layout .t-layout__header .header-operation .t-button+.t-button{margin-left:.75rem}.pnt-general-layout .general-layout-sub-header{border-bottom:.0625rem solid #f0f3f6}.pnt-general-layout .general-layout-body{background:#fafafa;height:100%;overflow-y:auto;padding:1.5rem}.pnt-general-layout .general-layout-body>div.t-card,.pnt-general-layout .general-layout-body>div.t-loading__parent>div.t-card,.pnt-general-layout .general-layout-body>div.tea-card,.pnt-general-layout .general-layout-body>div[class*=-block],.pnt-general-layout .general-layout-body>div[class*=-wrapper]{border-radius:.25rem;box-shadow:none;margin-bottom:1.5rem}.pnt-general-layout .general-layout-body>div.t-loading__parent>div:last-child.t-card,.pnt-general-layout .general-layout-body>div:last-child,.pnt-general-layout .general-layout-body>div:last-child.t-card,.pnt-general-layout .general-layout-body>div:last-child.tea-card,.pnt-general-layout .general-layout-body>div:last-child[class*=-block],.pnt-general-layout .general-layout-body>div:last-child[class*=-wrapper]{margin-bottom:0}.pnt-general-layout .t-layout__footer{background:#fff;border-top:.0625rem solid #f0f3f6;padding:1.125rem 1.5rem}.pnt-general-layout .t-layout__footer .t-button{font-size:.875rem;font-weight:600;height:2.25rem;min-width:5.75rem}.pnt-general-layout .t-layout__footer .t-button+.t-button{margin-left:.75rem}
1
+ .pnt-image-preview-wrapper{position:relative}.pnt-image-preview-wrapper .pnt-image-preview-progress,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress{align-items:center;display:flex;height:8.5rem;justify-content:center;width:8.5rem}.pnt-image-preview-wrapper .pnt-image-preview-progress .pnt-image-preview-loading,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress .pnt-image-preview-loading{align-items:center;background-color:#f7f8fa;border-radius:.25rem;display:flex;flex-direction:column;height:100%;justify-content:center;text-align:center;width:100%}.pnt-image-preview-wrapper .pnt-image-preview-progress .pnt-image-preview-loading svg,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress .pnt-image-preview-loading svg{color:var(--td-brand-color);font-size:1.5rem}.pnt-image-preview-wrapper .pnt-image-preview-progress .pnt-image-preview-loading p,.pnt-image-preview-wrapper .pnt-image-preview-upload-progress .pnt-image-preview-loading p{color:#808191;font-size:.75rem;margin-top:.25rem}.pnt-image-preview-wrapper .pnt-image-preview{height:8.5rem;width:8.5rem}.pnt-image-preview-wrapper .pnt-image-preview .pnt-image-preview-mask{align-items:center;background:rgba(0,0,0,.6);color:#fff;display:flex;height:100%;justify-content:center}.pnt-image-preview-wrapper .pnt-image-preview .pnt-image-preview-mask .pnt-image-preview-divider{border-left:.0625rem solid var(--td-text-color-anti);height:var(--td-comp-size-xxxs);margin:0 var(--td-comp-margin-l)}.pnt-business-select{width:100%}.pnt-business-select-option-label{display:block;width:100%}.pnt-business-select-popup .t-popup__content .t-loading,.pnt-business-select-popup .t-popup__content .total-wrapper{align-items:center;display:flex;font-weight:400;height:2.25rem;line-height:1.25rem;padding:0 .875rem}.pnt-business-select-popup .t-popup__content .total-wrapper{color:#808191;font-size:.875rem}.pnt-secure-box{color:#333;max-width:-moz-fit-content;max-width:fit-content;position:relative}.pnt-secure-box .view-icon{color:#3f8cff!important;cursor:pointer;font-size:small;position:absolute;right:-1.875rem;top:.0625rem}.pnt-secure-box .security-value{position:relative;top:.1875rem}.pnt-general-layout{background-color:transparent;height:100%}.pnt-general-layout .t-layout__header{border-bottom:.0625rem solid #f0f3f6;display:flex;height:auto;justify-content:space-between}.pnt-general-layout .t-layout__header .header-title{display:inline-block;padding:1.5rem;vertical-align:top}.pnt-general-layout .t-layout__header .header-title .goback-icon{color:#3f8cff;cursor:pointer;margin-right:.75rem;vertical-align:top}.pnt-general-layout .t-layout__header .header-title .title{display:inline-block;font-size:1.25rem;font-weight:600;height:1.5rem;line-height:1.5rem;vertical-align:top}.pnt-general-layout .t-layout__header .header-operation{height:4.5rem;line-height:4.5rem;padding-right:1.5rem}.pnt-general-layout .t-layout__header .header-operation .t-button+.t-button{margin-left:.75rem}.pnt-general-layout .general-layout-sub-header{border-bottom:.0625rem solid #f0f3f6}.pnt-general-layout .general-layout-body{background:#fafafa;height:100%;overflow-y:auto;padding:1.5rem}.pnt-general-layout .general-layout-body>div.t-card,.pnt-general-layout .general-layout-body>div.t-loading__parent>div.t-card,.pnt-general-layout .general-layout-body>div.tea-card,.pnt-general-layout .general-layout-body>div[class*=-block],.pnt-general-layout .general-layout-body>div[class*=-wrapper]{border-radius:.25rem;box-shadow:none;margin-bottom:1.5rem}.pnt-general-layout .general-layout-body>div.t-loading__parent>div:last-child.t-card,.pnt-general-layout .general-layout-body>div:last-child,.pnt-general-layout .general-layout-body>div:last-child.t-card,.pnt-general-layout .general-layout-body>div:last-child.tea-card,.pnt-general-layout .general-layout-body>div:last-child[class*=-block],.pnt-general-layout .general-layout-body>div:last-child[class*=-wrapper]{margin-bottom:0}.pnt-general-layout .t-layout__footer{background:#fff;border-top:.0625rem solid #f0f3f6;padding:1.125rem 1.5rem}.pnt-general-layout .t-layout__footer .t-button{font-size:.875rem;font-weight:600;height:2.25rem;min-width:5.75rem}.pnt-general-layout .t-layout__footer .t-button+.t-button{margin-left:.75rem}