cfel-base-components 2.6.5 → 2.6.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cfel-base-components",
3
- "version": "2.6.5",
3
+ "version": "2.6.7",
4
4
  "description": "cfel-base-components",
5
5
  "main": "/src/index.tsx",
6
6
  "types": "src/index.d.ts",
@@ -10,36 +10,57 @@ instance.interceptors.request.use(
10
10
  (config: any) => {
11
11
  config.headers = {
12
12
  ...config.headers,
13
- 'Accept-Language': currentLanguage,
13
+ 'Accept-Language': currentLanguage
14
14
  } as AxiosRequestHeaders
15
15
 
16
16
  config.params = {
17
17
  ...config.params,
18
- productCode: (window as any)?.g_config?.productCode,
18
+ productCode: (window as any)?.g_config?.productCode
19
19
  }
20
20
 
21
21
  return config
22
22
  },
23
- (error: any) => Promise.reject(error),
23
+ (error: any) => Promise.reject(error)
24
24
  )
25
25
 
26
26
  instance.interceptors.response.use(
27
27
  //状态码为2xx的时候执行
28
28
  (response: any) => {
29
+ //如果返回值是blob,则直接返回
30
+ if (response.data instanceof Blob) {
31
+ return response
32
+ }
33
+
29
34
  const { data = {} } = response
30
35
  const { success, content, errorCode, errorMsg } = data
31
36
 
32
37
  if (!success) {
33
38
  notification.error({
34
- message: errorMsg,
39
+ message: errorMsg
35
40
  })
36
- return Promise.reject(data)
41
+ return Promise.reject(response)
37
42
  }
38
43
 
39
44
  return content
40
45
  },
41
46
  //状态码不为2xx的时候执行
42
47
  (error: any) => {
48
+ // 如果是业务错误(在响应拦截器中已处理),直接返回
49
+ // 检查是否是业务错误:reject 的是 response 对象,且 success === false
50
+ if (error.data && error.data.success === false) {
51
+ // 业务错误已经在响应拦截器中显示了 errorMsg,这里直接返回
52
+ return Promise.reject(error)
53
+ }
54
+ // 兼容旧的判断方式
55
+ if (
56
+ error.data &&
57
+ error.response &&
58
+ error.response.status >= 200 &&
59
+ error.response.status < 300
60
+ ) {
61
+ return Promise.reject(error)
62
+ }
63
+
43
64
  const { response = {} } = error
44
65
  const { status } = response
45
66
 
@@ -58,18 +79,21 @@ instance.interceptors.response.use(
58
79
  '服务器发生错误,请检查服务器。' = 500,
59
80
  '网关错误。' = 502,
60
81
  '服务不可用,服务器暂时过载或维护。' = 503,
61
- '网关超时。' = 504,
82
+ '网关超时。' = 504
62
83
  }
63
84
 
64
85
  notification.error({
65
- message: response?.data?.errorMsg || CodeMessage[status] || '服务暂不可用,请检查网络',
86
+ message: response?.data?.errorMsg || CodeMessage[status] || '服务暂不可用,请检查网络'
66
87
  })
67
88
  // 如果后端在非2xx响应中也返回了业务 errorCode,处理 PRODUCT_NOT_REGISTRY
68
89
  const respData = response?.data || {}
69
- if ((respData && respData.errorCode === 'PRODUCT_NOT_REGISTRY') || respData.errorCode === 'ACCESS_DENIED') {
90
+ if (
91
+ (respData && respData.errorCode === 'PRODUCT_NOT_REGISTRY') ||
92
+ respData.errorCode === 'ACCESS_DENIED'
93
+ ) {
70
94
  if (typeof (window as any).showProductNotRegisteredOverlay === 'function') {
71
95
  ;(window as any).showProductNotRegisteredOverlay({
72
- onAction: () => {},
96
+ onAction: () => {}
73
97
  })
74
98
  } else {
75
99
  if (!(window as any).__PRODUCT_NOT_REGISTRY_SHOWN__) {
@@ -77,7 +101,7 @@ instance.interceptors.response.use(
77
101
  Modal.warning({
78
102
  title: '产品未开通',
79
103
  content: '当前产品未开通或产品编码错误,请联系管理员或检查产品编码。',
80
- okText: '知道了',
104
+ okText: '知道了'
81
105
  })
82
106
  }
83
107
  }
@@ -86,7 +110,7 @@ instance.interceptors.response.use(
86
110
  }
87
111
 
88
112
  return Promise.reject(error)
89
- },
113
+ }
90
114
  )
91
115
 
92
116
  export default instance
@@ -101,13 +125,20 @@ export function request<T = any>(config: Parameters<typeof instance.request>[0])
101
125
  /**
102
126
  * GET 请求,支持类型推断
103
127
  */
104
- export function get<T = any>(url: string, config?: Omit<Parameters<typeof instance.get>[1], 'url'>) {
128
+ export function get<T = any>(
129
+ url: string,
130
+ config?: Omit<Parameters<typeof instance.get>[1], 'url'>
131
+ ) {
105
132
  return instance.get<T, T>(url, config)
106
133
  }
107
134
 
108
135
  /**
109
136
  * POST 请求,支持类型推断
110
137
  */
111
- export function post<T = any>(url: string, data?: any, config?: Omit<Parameters<typeof instance.post>[2], 'url' | 'data'>) {
138
+ export function post<T = any>(
139
+ url: string,
140
+ data?: any,
141
+ config?: Omit<Parameters<typeof instance.post>[2], 'url' | 'data'>
142
+ ) {
112
143
  return instance.post<T, T>(url, data, config)
113
144
  }
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from 'react'
1
+ import React, { useEffect, useState, ReactNode } from 'react'
2
2
  import { Layout, List, Menu, MenuProps, Popover } from 'antd'
3
3
  import UserCard from './user-card'
4
4
  import RcMenu, { SubMenu, MenuItem } from 'rc-menu'
@@ -41,6 +41,12 @@ export interface LiosLayoutlProps {
41
41
  logoutUrl?: string
42
42
  switchTenantUrl?: string
43
43
  defaultOpenKeys?: string[]
44
+ /** 自定义用户信息卡片内容(将完全替换内置的 UserCard) */
45
+ userCard?: ReactNode
46
+ /** 自定义搜索输入占位文案,默认“搜索菜单...” */
47
+ searchPlaceholder?: string
48
+ /** 自定义“最近访问”标题文案,默认“最近访问” */
49
+ searchHistoryTitle?: string
44
50
  isHideHeader?: boolean //是否隐藏header
45
51
  onCollapse?: (value: boolean) => void
46
52
  type?: string
@@ -64,6 +70,9 @@ export default function LiosLayout(props: LiosLayoutlProps) {
64
70
  amountInfo,
65
71
  myWalletInfoAction,
66
72
  myLoginInfoAction,
73
+ userCard,
74
+ searchPlaceholder,
75
+ searchHistoryTitle,
67
76
  isHideHeader,
68
77
  onCollapse,
69
78
  type,
@@ -273,7 +282,16 @@ export default function LiosLayout(props: LiosLayoutlProps) {
273
282
  {!collapsed && <div style={{ height: 24 }}></div>}
274
283
 
275
284
  <div style={{ width: '100%', padding: '0 16px' }}>
276
- <Search menuList={menuList} collapsed={collapsed} type={type || ''} umiHistory={umiHistory} setSelectKey={setSelectKey} findKeyPath={findKeyPath} />
285
+ <Search
286
+ menuList={menuList}
287
+ collapsed={collapsed}
288
+ type={type || ''}
289
+ umiHistory={umiHistory}
290
+ setSelectKey={setSelectKey}
291
+ findKeyPath={findKeyPath}
292
+ searchPlaceholder={searchPlaceholder}
293
+ searchHistoryTitle={searchHistoryTitle}
294
+ />
277
295
  </div>
278
296
 
279
297
  {!collapsed && <div style={{ height: 12 }}></div>}
@@ -500,7 +518,16 @@ export default function LiosLayout(props: LiosLayoutlProps) {
500
518
  <Popover
501
519
  placement="bottom"
502
520
  content={
503
- <UserCard myWalletInfo={myWalletInfo} MyLoginInfo={MyLoginInfo} amountInfo={amountInfo} customAction={customAction} isCopied={isCopied} copyTextToClipboard={copyTextToClipboard} />
521
+ userCard ?? (
522
+ <UserCard
523
+ myWalletInfo={myWalletInfo}
524
+ MyLoginInfo={MyLoginInfo}
525
+ amountInfo={amountInfo}
526
+ customAction={customAction}
527
+ isCopied={isCopied}
528
+ copyTextToClipboard={copyTextToClipboard}
529
+ />
530
+ )
504
531
  }
505
532
  arrow={false}
506
533
  trigger="click"
@@ -556,8 +583,19 @@ type SearchProps = {
556
583
  umiHistory: any
557
584
  setSelectKey: any
558
585
  findKeyPath: (pathname: string) => string[]
586
+ searchPlaceholder?: string
587
+ searchHistoryTitle?: string
559
588
  }
560
- function Search({ menuList, collapsed, type, umiHistory, setSelectKey, findKeyPath }: SearchProps) {
589
+ function Search({
590
+ menuList,
591
+ collapsed,
592
+ type,
593
+ umiHistory,
594
+ setSelectKey,
595
+ findKeyPath,
596
+ searchPlaceholder,
597
+ searchHistoryTitle,
598
+ }: SearchProps) {
561
599
  useEffect(() => {
562
600
  const handleKeyDown = (event: KeyboardEvent) => {
563
601
  if ((navigator.platform.toLowerCase().includes('mac') ? event.metaKey : event.ctrlKey) && event.key.toLowerCase() === 'k') {
@@ -676,7 +714,7 @@ function Search({ menuList, collapsed, type, umiHistory, setSelectKey, findKeyPa
676
714
  value={searchTerm}
677
715
  onChange={(e) => handleSearch(e.target.value)}
678
716
  className="search-input"
679
- placeholder="搜索菜单..."
717
+ placeholder={searchPlaceholder ?? '搜索菜单...'}
680
718
  onFocus={() => setIsFocused(true)}
681
719
  />
682
720
  <div className="search-icon">
@@ -700,7 +738,7 @@ function Search({ menuList, collapsed, type, umiHistory, setSelectKey, findKeyPa
700
738
  <List
701
739
  split={false}
702
740
  className="lists"
703
- header="最近访问"
741
+ header={searchHistoryTitle ?? '最近访问'}
704
742
  size="small"
705
743
  bordered
706
744
  dataSource={searchHistory}
@@ -1,162 +1,133 @@
1
- import React from "react";
2
- import {
3
- SwapOutlined,
4
- FormOutlined,
5
- CopyOutlined,
6
- LogoutOutlined,
7
- } from "@ant-design/icons";
8
- import "./index.scss";
1
+ import React from 'react'
2
+ import { SwapOutlined, CopyOutlined, LogoutOutlined } from '@ant-design/icons'
3
+ import './index.scss'
9
4
 
10
5
  interface UserType {
11
- name: string;
12
- avatar: string;
13
- roleInfo: any[];
14
- id: string;
15
- account: string;
16
- isMaster: boolean;
6
+ name: string
7
+ avatar: string
8
+ roleInfo: any[]
9
+ id: string
10
+ account: string
11
+ isMaster: boolean
17
12
  }
18
- interface CustomType {
19
- type: string;
20
- isCompleted: number;
21
- isAudited: number;
22
- hrefUrl: string;
23
- historyAction?: any;
24
- }
25
- interface MyWalletInfoType {
26
- availableCashAmount: string;
27
- availableAmount: string;
28
- currency: string;
29
- }
30
- interface MyLoginInfoType {
31
- isAdmin: any;
13
+
14
+ export interface MyWalletInfoType {
15
+ availableCashAmount: string
16
+ availableAmount: string
17
+ currency: string
32
18
  }
33
- interface AmountInfoType {
34
- residueNum: string;
35
- currencyCode: string;
19
+ export interface MyLoginInfoType {
20
+ isAdmin: any
36
21
  }
37
22
 
38
- const renderCurrency = (currency: string) => {
39
- switch (currency) {
40
- case "CNY":
41
- return ";
42
- case "USD":
43
- return "$ ";
44
- case "JPY":
45
- return "JP¥ ";
46
- default:
47
- return "¥ ";
48
- }
49
- };
50
-
51
- export default function UserCard({
52
- myWalletInfo,
53
- MyLoginInfo,
54
- amountInfo,
55
- customAction,
56
- isCopied,
57
- copyTextToClipboard,
58
- }: any) {
59
- const { user, tenant, custom, switchTenantUrl, logoutUrl } = (window as any)
60
- ?.g_config;
23
+ export interface UserCardProps {
24
+ myWalletInfo?: MyWalletInfoType
25
+ MyLoginInfo?: MyLoginInfoType
26
+ isCopied?: Record<string, boolean>
27
+ copyTextToClipboard?: (value: string, key: string) => void
28
+ }
61
29
 
62
- const { name, avatar, roleInfo, id, account, isMaster }: UserType =
63
- user || {};
30
+ export default function UserCard({ MyLoginInfo, isCopied, copyTextToClipboard }: UserCardProps) {
31
+ const { user, tenant, switchTenantUrl, logoutUrl } = (window as any)?.g_config
64
32
 
65
- const { isCompleted, isAudited }: CustomType = custom || {};
33
+ const { name, avatar, roleInfo, id, account }: UserType = user || {}
66
34
 
67
- const { isAdmin }: MyLoginInfoType = MyLoginInfo || {};
68
-
69
- const { residueNum, currencyCode }: AmountInfoType = amountInfo || {};
35
+ const { isAdmin }: MyLoginInfoType = (MyLoginInfo || {}) as MyLoginInfoType
70
36
 
71
37
  const UserCard = () => {
72
38
  return (
73
- <div className="layout-user-card">
74
- <div className="user-info">
75
- <div className="user-avatarBox">
76
- <img className="user-avatar" src={avatar}/>
77
- <div className="user-mater">{isAdmin ? "主账号" : "子账号"}</div>
78
- </div>
79
- <div className="user-info-right">
80
- <span className="name">{name}</span>
81
- <div className="role-list">
82
- {roleInfo?.map((i) => (
83
- <span className="role-item" key={i}>
39
+ <div className="layout-user-card">
40
+ <div className="user-info">
41
+ <div className="user-avatarBox">
42
+ <img className="user-avatar" src={avatar} />
43
+ <div className="user-mater">{isAdmin ? '主账号' : '子账号'}</div>
44
+ </div>
45
+ <div className="user-info-right">
46
+ <span className="name">{name}</span>
47
+ <div className="role-list">
48
+ {roleInfo?.map((i) => (
49
+ <span className="role-item" key={i}>
84
50
  {i}
85
51
  </span>
86
- ))}
87
- </div>
52
+ ))}
88
53
  </div>
89
54
  </div>
90
- <div className="lios-userInfo">
91
- <div className="lios-li li-flex">
92
- <div className="lios-keyMare">账号ID</div>
93
- <div className="lios-valueMare" title={id}>{id}</div>
94
- <div
95
- className={isCopied?.['id'] ? "lios-iconDone" : "lios-icon"}
96
- onClick={() => {
97
- copyTextToClipboard(id, 'id');
98
- }}
99
- >
100
- {isCopied?.['id'] ? "已复制" : <CopyOutlined/>}
101
- </div>
55
+ </div>
56
+ <div className="lios-userInfo">
57
+ <div className="lios-li li-flex">
58
+ <div className="lios-keyMare">账号ID</div>
59
+ <div className="lios-valueMare" title={id}>
60
+ {id}
102
61
  </div>
103
- <div className="lios-li li-flex">
104
- <div className="lios-keyMare">账号</div>
105
- <div className="lios-valueMare" title={account}>
106
- {account}
107
- </div>
108
- <div
109
- className={isCopied?.['account'] ? "lios-iconDone" : "lios-icon"}
110
- onClick={() => {
111
- copyTextToClipboard(account, 'account');
112
- }}
113
- >
114
- {isCopied?.['account'] ? "已复制" : <CopyOutlined/>}
115
- </div>
62
+ <div
63
+ className={isCopied?.['id'] ? 'lios-iconDone' : 'lios-icon'}
64
+ onClick={() => {
65
+ copyTextToClipboard && copyTextToClipboard(id, 'id')
66
+ }}
67
+ >
68
+ {isCopied?.['id'] ? '已复制' : <CopyOutlined />}
116
69
  </div>
117
-
118
- <div className="lios-li li-flex">
119
- <div className="lios-keyMare">租户ID</div>
120
- <div className="lios-valueMare" title={tenant?.id}>{tenant?.id}</div>
121
- <div
122
- className={isCopied?.['tenantId'] ? "lios-iconDone" : "lios-icon"}
123
- onClick={() => {
124
- copyTextToClipboard(tenant?.id, 'tenantId');
125
- }}
126
- >
127
- {isCopied?.['tenantId'] ? "已复制" : <CopyOutlined/>}
128
- </div>
70
+ </div>
71
+ <div className="lios-li li-flex">
72
+ <div className="lios-keyMare">账号</div>
73
+ <div className="lios-valueMare" title={account}>
74
+ {account}
129
75
  </div>
130
- <div className="lios-li li-flex">
131
- <div className="lios-keyMare">租户</div>
132
- <div className="lios-valueMare" title={tenant?.name}>{tenant?.name}</div>
76
+ <div
77
+ className={isCopied?.['account'] ? 'lios-iconDone' : 'lios-icon'}
78
+ onClick={() => {
79
+ copyTextToClipboard && copyTextToClipboard(account, 'account')
80
+ }}
81
+ >
82
+ {isCopied?.['account'] ? '已复制' : <CopyOutlined />}
133
83
  </div>
134
84
  </div>
135
85
 
136
-
137
- <div className="lios-logoutBox">
138
- <div
139
- className="lios-logout"
140
- onClick={() => {
141
- location.href = switchTenantUrl;
142
- }}
143
- >
144
- <SwapOutlined className="logout-icon"/>
145
- 切换租户
86
+ <div className="lios-li li-flex">
87
+ <div className="lios-keyMare">租户ID</div>
88
+ <div className="lios-valueMare" title={tenant?.id}>
89
+ {tenant?.id}
146
90
  </div>
147
91
  <div
148
- className="lios-logout"
149
- onClick={() => {
150
- location.href = logoutUrl;
151
- }}
92
+ className={isCopied?.['tenantId'] ? 'lios-iconDone' : 'lios-icon'}
93
+ onClick={() => {
94
+ copyTextToClipboard && copyTextToClipboard(tenant?.id, 'tenantId')
95
+ }}
152
96
  >
153
- <LogoutOutlined className="logout-icon"/>
154
- 退出登录
97
+ {isCopied?.['tenantId'] ? '已复制' : <CopyOutlined />}
98
+ </div>
99
+ </div>
100
+ <div className="lios-li li-flex">
101
+ <div className="lios-keyMare">租户</div>
102
+ <div className="lios-valueMare" title={tenant?.name}>
103
+ {tenant?.name}
155
104
  </div>
156
105
  </div>
157
106
  </div>
158
- );
159
- };
160
107
 
161
- return UserCard();
108
+ <div className="lios-logoutBox">
109
+ <div
110
+ className="lios-logout"
111
+ onClick={() => {
112
+ location.href = switchTenantUrl
113
+ }}
114
+ >
115
+ <SwapOutlined className="logout-icon" />
116
+ 切换租户
117
+ </div>
118
+ <div
119
+ className="lios-logout"
120
+ onClick={() => {
121
+ location.href = logoutUrl
122
+ }}
123
+ >
124
+ <LogoutOutlined className="logout-icon" />
125
+ 退出登录
126
+ </div>
127
+ </div>
128
+ </div>
129
+ )
130
+ }
131
+
132
+ return UserCard()
162
133
  }