win-chart 1.0.0

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.
Files changed (185) hide show
  1. package/.eslintrc.json +3 -0
  2. package/.prettierrc.json +5 -0
  3. package/README.md +0 -0
  4. package/localhost-key.pem +28 -0
  5. package/localhost.pem +25 -0
  6. package/package.json +65 -0
  7. package/rsbuild.config.ts +48 -0
  8. package/src/api/README.md +15 -0
  9. package/src/api/index.js +5 -0
  10. package/src/api/layout/index.js +32 -0
  11. package/src/api/request.ts +87 -0
  12. package/src/api/url-map/index.js +10 -0
  13. package/src/api/user/index.js +12 -0
  14. package/src/components/FilterContext.tsx +6 -0
  15. package/src/components/GlobalStyle.tsx +25 -0
  16. package/src/components/HalfScreenBrowser.tsx +95 -0
  17. package/src/components/ImgBox.tsx +19 -0
  18. package/src/components/JumpBtn.tsx +38 -0
  19. package/src/components/MCardWrapper.tsx +33 -0
  20. package/src/components/NoContent/index.tsx +85 -0
  21. package/src/components/ResponsiveReactGridLayout.tsx +218 -0
  22. package/src/components/SliderDecoration.tsx +27 -0
  23. package/src/components/VisionUserConfigContext.ts +6 -0
  24. package/src/components/WinMenu/README.md +11 -0
  25. package/src/components/WinMenu/WinHeader.tsx +5 -0
  26. package/src/components/WinMenu/components/ExtraBox.tsx +61 -0
  27. package/src/components/WinMenu/components/FullMenuBox.tsx +80 -0
  28. package/src/components/WinMenu/components/FullMenuContainer.tsx +50 -0
  29. package/src/components/WinMenu/components/FullMenuItem.tsx +128 -0
  30. package/src/components/WinMenu/components/LangSwitch.tsx +84 -0
  31. package/src/components/WinMenu/components/LogoBox.tsx +29 -0
  32. package/src/components/WinMenu/components/PinDialog.tsx +72 -0
  33. package/src/components/WinMenu/components/PinnedMenuBox.tsx +183 -0
  34. package/src/components/WinMenu/components/UserBox.tsx +83 -0
  35. package/src/components/WinMenu/hooks/useUserInfo.ts +21 -0
  36. package/src/components/WinMenu/hooks/useUserMenu.ts +35 -0
  37. package/src/components/WinMenu/index.tsx +100 -0
  38. package/src/components/WinMenu/services/WinService.ts +79 -0
  39. package/src/components/WinMenu/services/request.ts +53 -0
  40. package/src/components/WinMenu/utils/const.ts +80 -0
  41. package/src/components/WinMenu/utils/enum.ts +19 -0
  42. package/src/components/WinMenu/utils/interface.ts +61 -0
  43. package/src/components/WinMenu/utils/map.ts +39 -0
  44. package/src/components/WinMenu/utils/tool.ts +142 -0
  45. package/src/components/WinMenu/utils/type.ts +1 -0
  46. package/src/components/hover-view.tsx +48 -0
  47. package/src/components/icon.tsx +44 -0
  48. package/src/components/indicator-remark.tsx +25 -0
  49. package/src/components/none-content.tsx +93 -0
  50. package/src/components/panel-tab.tsx +150 -0
  51. package/src/components/panel-title-tab.tsx +60 -0
  52. package/src/components/win-card/components/ChartContent.tsx +47 -0
  53. package/src/components/win-card/components/Indicator.tsx +42 -0
  54. package/src/components/win-card/components/IndicatorArea.tsx +63 -0
  55. package/src/components/win-card/components/IndicatorInfo.tsx +78 -0
  56. package/src/components/win-card/components/MatterContent.tsx +121 -0
  57. package/src/components/win-card/components/MatterList.tsx +141 -0
  58. package/src/components/win-card/components/NoticeContent.tsx +73 -0
  59. package/src/components/win-card/components/NoticeList.tsx +68 -0
  60. package/src/components/win-card/components/SelectDecoration.tsx +34 -0
  61. package/src/components/win-card/components/WinRankContent.tsx +102 -0
  62. package/src/components/win-card/index.tsx +298 -0
  63. package/src/components/win-card/utils/interface.ts +12 -0
  64. package/src/components/win-card/utils/tool.ts +11 -0
  65. package/src/components/win-card-mobile/components/ChartContent.tsx +47 -0
  66. package/src/components/win-card-mobile/components/DualLineBar.tsx +61 -0
  67. package/src/components/win-card-mobile/components/Indicator.tsx +42 -0
  68. package/src/components/win-card-mobile/components/IndicatorArea.tsx +65 -0
  69. package/src/components/win-card-mobile/components/IndicatorInfo.tsx +83 -0
  70. package/src/components/win-card-mobile/components/SelectDecoration.tsx +28 -0
  71. package/src/components/win-card-mobile/index.tsx +235 -0
  72. package/src/components/win-card-mobile/utils/interface.ts +12 -0
  73. package/src/components/win-card-mobile/utils/tool.ts +9 -0
  74. package/src/components/win-chart/components/chart-wrapper.tsx +5 -0
  75. package/src/components/win-chart/index.tsx +59 -0
  76. package/src/components/win-chart/theme/win-dark.json +372 -0
  77. package/src/components/win-chart/theme/win-light.json +372 -0
  78. package/src/components/win-chart/utils/const.ts +37 -0
  79. package/src/components/win-chart/utils/getAreaSpec.ts +150 -0
  80. package/src/components/win-chart/utils/getBarSpec.ts +60 -0
  81. package/src/components/win-chart/utils/getChartOptions.ts +59 -0
  82. package/src/components/win-chart/utils/getColumnSpec.ts +112 -0
  83. package/src/components/win-chart/utils/getDualSpec.ts +79 -0
  84. package/src/components/win-chart/utils/getFunnelSpec.ts +70 -0
  85. package/src/components/win-chart/utils/getLineSpec.ts +53 -0
  86. package/src/components/win-chart/utils/getPieSpec.ts +124 -0
  87. package/src/components/win-chart/utils/getRadarSpec.ts +87 -0
  88. package/src/components/win-chart/utils/tool.ts +163 -0
  89. package/src/components/win-chart/utils/type.ts +96 -0
  90. package/src/components/win-icon/index.tsx +97 -0
  91. package/src/components/win-v/components/EmptyBox.tsx +9 -0
  92. package/src/components/win-v/components/VDialog.tsx +173 -0
  93. package/src/components/win-v/components/VDialogBtn.tsx +119 -0
  94. package/src/components/win-v/components/VDialogMsg.tsx +325 -0
  95. package/src/components/win-v/components/VInput.tsx +15 -0
  96. package/src/components/win-v/components/VRemindMsgList.tsx +303 -0
  97. package/src/components/win-v/components/VRobot.tsx +97 -0
  98. package/src/components/win-v/hooks/useVDialogCore.ts +102 -0
  99. package/src/components/win-v/hooks/useVDialogOperate.ts +132 -0
  100. package/src/components/win-v/hooks/useVDialogState.ts +52 -0
  101. package/src/components/win-v/hooks/useVRemindMsgShow.ts +15 -0
  102. package/src/components/win-v/index.tsx +205 -0
  103. package/src/components/win-wrappers/card-wrapper.tsx +103 -0
  104. package/src/components/win-wrappers/dot-wrapper.tsx +18 -0
  105. package/src/components/win-wrappers/iframe-wrapper.tsx +7 -0
  106. package/src/components/win-wrappers/request-wrapper.tsx +190 -0
  107. package/src/global.d.ts +53 -0
  108. package/src/hooks/useCardOptionList.ts +23 -0
  109. package/src/hooks/useCostFiltersDicList.ts +22 -0
  110. package/src/hooks/useFbiUrl.ts +22 -0
  111. package/src/hooks/useHalfScreenState.ts +50 -0
  112. package/src/hooks/useHasIntersected.ts +36 -0
  113. package/src/hooks/useIndicatorCardInfo.ts +26 -0
  114. package/src/hooks/useIndicatorCardQueryList.ts +22 -0
  115. package/src/hooks/useIndicatorClassifyList.ts +25 -0
  116. package/src/hooks/useIndicatorDetailsDateList.ts +22 -0
  117. package/src/hooks/useIndicatorDetailsInfo.ts +49 -0
  118. package/src/hooks/useIndicatorDetailsTrend.ts +25 -0
  119. package/src/hooks/useIndicatorDicList.ts +22 -0
  120. package/src/hooks/useIndicatorLabelList.ts +20 -0
  121. package/src/hooks/useIndicatorList.ts +24 -0
  122. package/src/hooks/useIndicatorRangeList.ts +20 -0
  123. package/src/hooks/useIndicatorTypeList.ts +20 -0
  124. package/src/hooks/useIndicatorUnitList.ts +21 -0
  125. package/src/hooks/useListenQuery.ts +29 -0
  126. package/src/hooks/useMobile.ts +58 -0
  127. package/src/hooks/useNotice.ts +42 -0
  128. package/src/hooks/useOrgLevelList.ts +23 -0
  129. package/src/hooks/usePageSelection.ts +121 -0
  130. package/src/hooks/usePageState.ts +22 -0
  131. package/src/hooks/usePendingList.ts +27 -0
  132. package/src/hooks/usePortalPageInfo.ts +43 -0
  133. package/src/hooks/useRefreshByLocationChange.ts +16 -0
  134. package/src/hooks/useReportIndicatorList.ts +21 -0
  135. package/src/hooks/useReportInfo.ts +45 -0
  136. package/src/hooks/useReportPersonList.ts +21 -0
  137. package/src/hooks/useScriptLoader.ts +22 -0
  138. package/src/hooks/useUnreadMsgList.ts +26 -0
  139. package/src/hooks/useUserAvatar.ts +23 -0
  140. package/src/hooks/useVReportInfo.ts +50 -0
  141. package/src/hooks/useVisionUserConfig.ts +25 -0
  142. package/src/hooks/useWorkbenchOptions.ts +63 -0
  143. package/src/index.tsx +20 -0
  144. package/src/services/CardService.ts +91 -0
  145. package/src/services/CommonService.ts +23 -0
  146. package/src/services/CostService.ts +56 -0
  147. package/src/services/DialogService.ts +74 -0
  148. package/src/services/IndicatorService.ts +406 -0
  149. package/src/services/PageService.ts +204 -0
  150. package/src/services/ReportService.ts +335 -0
  151. package/src/services/WorkbenchService.ts +411 -0
  152. package/src/styles/README.md +12 -0
  153. package/src/styles/index.scss +9 -0
  154. package/src/styles/mixins/index.scss +25 -0
  155. package/src/styles/next-cover.scss +4 -0
  156. package/src/styles/normalize.scss +27 -0
  157. package/src/styles/utilities/index.scss +5 -0
  158. package/src/styles/vars/index.scss +17 -0
  159. package/src/types/enum-workbench.ts +29 -0
  160. package/src/types/enum.ts +156 -0
  161. package/src/types/index.ts +19 -0
  162. package/src/types/indicator.ts +299 -0
  163. package/src/types/interface.ts +303 -0
  164. package/src/types/portal.ts +211 -0
  165. package/src/types/report.ts +28 -0
  166. package/src/types/type.ts +11 -0
  167. package/src/types/user.ts +28 -0
  168. package/src/utils/README.md +4 -0
  169. package/src/utils/arms.ts +59 -0
  170. package/src/utils/arr.ts +123 -0
  171. package/src/utils/const-workbench.ts +9 -0
  172. package/src/utils/const.ts +18 -0
  173. package/src/utils/index.ts +18 -0
  174. package/src/utils/init.ts +5 -0
  175. package/src/utils/map-workbench.ts +66 -0
  176. package/src/utils/map.ts +377 -0
  177. package/src/utils/number.ts +101 -0
  178. package/src/utils/page.ts +81 -0
  179. package/src/utils/str.ts +26 -0
  180. package/src/utils/tools.ts +44 -0
  181. package/src/utils/tree.ts +145 -0
  182. package/src/utils/url.ts +40 -0
  183. package/src/utils/util.ts +99 -0
  184. package/src/utils/workbench.ts +25 -0
  185. package/tsconfig.json +33 -0
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 当前菜单业务域
3
+ */
4
+ export enum MenuBizType {
5
+ /**
6
+ * 园区
7
+ */
8
+ PARK,
9
+
10
+ /**
11
+ * 幻视
12
+ */
13
+ VISION,
14
+
15
+ /**
16
+ * 招商租赁
17
+ */
18
+ RENT,
19
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 菜单
3
+ */
4
+ export interface IMenuItem {
5
+ menuCode: string;
6
+ menuTitle: string;
7
+ menuUrl?: string;
8
+ menuIcon?: string;
9
+
10
+ /**
11
+ * 关联的管理制度链接
12
+ */
13
+ docUrl?: string;
14
+
15
+ /**
16
+ * 关联的管理制度名
17
+ */
18
+ docName?: string;
19
+ firstMenuCode?: number | string;
20
+ children?: IMenuItem[];
21
+
22
+ /**
23
+ * 是否被钉住
24
+ */
25
+ pinned: boolean;
26
+ }
27
+
28
+ export interface IUserInfo {
29
+ employeeName: string;
30
+ employeeId: string;
31
+ employeeType: string;
32
+ tenantName: string;
33
+ workNo: string;
34
+ registDate: number;
35
+ }
36
+
37
+ export interface IListItem<T = string> {
38
+ label: string;
39
+ value: T;
40
+ children?: IListItem<T>[];
41
+ }
42
+
43
+ export interface IWinHeaderProps {
44
+ data?: IMenuItem[];
45
+ pinnedData?: IMenuItem[];
46
+ title?: string;
47
+ logo?: string;
48
+ userInfo?: Partial<IUserInfo>;
49
+ isMiniOverlay?: boolean;
50
+ onPinned?: (data: IMenuItem) => void;
51
+ downloadCenterUrl?: string;
52
+ }
53
+
54
+ export interface IResponse<T = any> {
55
+ data: T;
56
+ errorCode: string;
57
+ errorMsg: string;
58
+ msg?: string;
59
+ success: boolean;
60
+ code?: string;
61
+ }
@@ -0,0 +1,39 @@
1
+ import { DEFAULT_LOGO } from './const';
2
+ import { MenuBizType } from './enum';
3
+ import { IListItem } from './interface';
4
+ import { WinLanguage } from './type';
5
+
6
+ export const langList: IListItem<WinLanguage>[] = [
7
+ { label: '中文', value: 'zh-CN' },
8
+ { label: 'English', value: 'en-US' },
9
+ ];
10
+
11
+ export const langMap = new Map<WinLanguage, string>()
12
+ .set('zh-CN', '中文')
13
+ .set('en-US', 'English');
14
+
15
+ /**
16
+ * 菜单配置
17
+ */
18
+ export const menuConfigMap = new Map<
19
+ MenuBizType,
20
+ {
21
+ title: string;
22
+ logo: string;
23
+ downloadCenterUrl?: string;
24
+ productCodes: string[];
25
+ }
26
+ >();
27
+
28
+ menuConfigMap.set(MenuBizType.PARK, {
29
+ title: '智慧园区',
30
+ logo: DEFAULT_LOGO,
31
+ productCodes: ['SMART_PARK', 'WAREHOUSE_BUSINESS', 'PLATFORM', 'ASSET'],
32
+ downloadCenterUrl: '/park/pc#/downloadCenter',
33
+ });
34
+
35
+ menuConfigMap.set(MenuBizType.VISION, {
36
+ title: '幻视平台',
37
+ logo: 'https://tianshu.alicdn.com/d380d002-fbbc-47c0-a17f-8fc3ecc368ee.png',
38
+ productCodes: ['VISION', 'PLATFORM'],
39
+ });
@@ -0,0 +1,142 @@
1
+ import { MenuBizType } from './enum';
2
+ import { IListItem, IMenuItem, IResponse } from './interface';
3
+
4
+ /**
5
+ * 处理返回结果
6
+ * @returns
7
+ */
8
+ export function handleCnResult<T>({ data }: IResponse<T>): T {
9
+ return data;
10
+ }
11
+
12
+ /**
13
+ * 当前菜单是否为地址栏链接
14
+ * @param item
15
+ * @returns
16
+ */
17
+ export const checkCurLink = (item: IMenuItem) =>
18
+ !!item.menuUrl &&
19
+ !checkEntityArr(item.children) &&
20
+ location.href.includes(item.menuUrl);
21
+
22
+ /**
23
+ * 获取当前一级 MenuCode
24
+ * @param data
25
+ * @returns
26
+ */
27
+ export const getCurLocationFirstIdByMenuList = (data: IMenuItem[]) => {
28
+ for (const firstMenu of data) {
29
+ if (firstMenu.children) {
30
+ const item = menuTreeFind(firstMenu.children, checkCurLink);
31
+
32
+ if (item) {
33
+ return firstMenu.menuCode;
34
+ }
35
+ }
36
+ }
37
+ };
38
+
39
+ /**
40
+ * 映射一级 MenuCode
41
+ * @param data
42
+ * @returns
43
+ */
44
+ export const initFirstMenuCode = (data: IMenuItem[]) => {
45
+ const mapFirstMenuCode = (
46
+ data: IMenuItem[],
47
+ firstMenuCode: number | string,
48
+ ): IMenuItem[] => {
49
+ return data.map((item) => {
50
+ const newItem = {
51
+ ...item,
52
+ firstParentId: firstMenuCode,
53
+ };
54
+ if (newItem.children) {
55
+ newItem.children = mapFirstMenuCode(newItem.children, firstMenuCode);
56
+ }
57
+
58
+ return newItem;
59
+ });
60
+ };
61
+
62
+ return data.map((item) => {
63
+ const newItem = { ...item };
64
+ if (newItem.children) {
65
+ newItem.children = mapFirstMenuCode(newItem.children, item.menuCode);
66
+ }
67
+
68
+ return newItem;
69
+ });
70
+ };
71
+
72
+ /**
73
+ * 树形递归查找
74
+ * @param tree
75
+ * @param fn
76
+ * @returns
77
+ */
78
+ export const menuTreeFind = (
79
+ tree: IMenuItem[],
80
+ fn: (item: IMenuItem) => boolean,
81
+ ): IMenuItem | undefined => {
82
+ for (const item of tree) {
83
+ if (fn(item)) {
84
+ return item;
85
+ }
86
+
87
+ if (item.children) {
88
+ const res = menuTreeFind(item.children, fn);
89
+ if (res) {
90
+ return res;
91
+ }
92
+ }
93
+ }
94
+ };
95
+
96
+ /**
97
+ * 判断是否为一个有效数组(有值,并且长度大于 0)
98
+ * @param data
99
+ * @returns
100
+ */
101
+ export const checkEntityArr = (data: unknown) =>
102
+ Array.isArray(data) && data.length > 0;
103
+
104
+ /**
105
+ * 处理跳转
106
+ * @param data
107
+ */
108
+ export const getHandleJump = (data: IMenuItem) => () => {
109
+ if (data.menuUrl) {
110
+ location.href = data.menuUrl;
111
+ }
112
+ };
113
+
114
+ /**
115
+ * 根据 value 查询列表项 label
116
+ * @param list
117
+ * @param value
118
+ * @returns
119
+ */
120
+ export const getListLabelByValue = (
121
+ list: Array<IListItem<string | number>>,
122
+ value?: number | string,
123
+ ) => list.find((item) => item.value === value)?.label;
124
+
125
+ /**
126
+ * 获取外部链接跳转处理
127
+ * @param url
128
+ * @returns
129
+ */
130
+ export const getHandleOpenLink = (url?: string | null) => () =>
131
+ !!url && open(url);
132
+
133
+ /**
134
+ * 获取当前菜单业务域类型
135
+ */
136
+ export const getDefaultMenuBizTypeByHref = () => {
137
+ if (location.href.includes('vision')) {
138
+ return MenuBizType.VISION;
139
+ }
140
+
141
+ return MenuBizType.PARK;
142
+ };
@@ -0,0 +1 @@
1
+ export type WinLanguage = 'zh-CN' | 'en-US';
@@ -0,0 +1,48 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ import { Balloon } from '@cainiaofe/cn-ui';
3
+ import { IStyleProps } from '@/types';
4
+
5
+ interface IProps extends IStyleProps {
6
+ content: ReactNode;
7
+ style?: CSSProperties;
8
+ cStyle?: CSSProperties;
9
+ onClick?(): void;
10
+ followTrigger?: boolean;
11
+ }
12
+
13
+ export const HoverView = ({
14
+ followTrigger = false,
15
+ content,
16
+ style,
17
+ cStyle,
18
+ className,
19
+ onClick,
20
+ }: IProps) => {
21
+ const { Tooltip } = Balloon;
22
+ const intro = (
23
+ <div
24
+ onClick={onClick}
25
+ className={className}
26
+ style={{
27
+ overflow: 'hidden',
28
+ textOverflow: 'ellipsis',
29
+ whiteSpace: 'nowrap',
30
+ ...cStyle,
31
+ }}
32
+ >
33
+ {content}
34
+ </div>
35
+ );
36
+
37
+ return (
38
+ <Tooltip
39
+ trigger={intro}
40
+ followTrigger={followTrigger}
41
+ v2
42
+ align='br'
43
+ style={style}
44
+ >
45
+ {content}
46
+ </Tooltip>
47
+ );
48
+ };
@@ -0,0 +1,44 @@
1
+ import { IStyleProps } from 'src/types';
2
+ import { createIconComponent } from './win-icon';
3
+
4
+ export const CustomIcon = createIconComponent(
5
+ '//at.alicdn.com/t/a/font_2948873_rlsy8tmmati.js',
6
+ );
7
+
8
+ interface IProps extends IStyleProps {
9
+ show: boolean;
10
+ src: string;
11
+ size: number | string;
12
+ onClick: () => void;
13
+ }
14
+
15
+ export const IconBox = ({
16
+ src,
17
+ size = 12,
18
+ onClick,
19
+ show = true,
20
+ style,
21
+ ...args
22
+ }: Partial<IProps>) => (
23
+ <img
24
+ alt=""
25
+ src={src}
26
+ onClick={(e) => {
27
+ if (onClick) {
28
+ e.stopPropagation();
29
+ onClick();
30
+ }
31
+ }}
32
+ {...args}
33
+ style={{
34
+ width: size,
35
+ height: size,
36
+ objectFit: 'contain',
37
+ display: show ? 'inline-block' : 'none',
38
+ ...(onClick && {
39
+ cursor: 'pointer',
40
+ }),
41
+ ...style,
42
+ }}
43
+ />
44
+ );
@@ -0,0 +1,25 @@
1
+ import { IStyleProps } from '@/types';
2
+ import { CnBalloon, CnIcon } from '@cainiaofe/cn-ui';
3
+
4
+ interface IProps extends IStyleProps {
5
+ remark: string;
6
+ }
7
+
8
+ export const IndicatorRemark = ({ remark, style }: IProps) => (
9
+ <CnBalloon.Tooltip
10
+ v2
11
+ followTrigger
12
+ align='bl'
13
+ trigger={
14
+ <CnIcon
15
+ type='help-color'
16
+ style={{
17
+ marginLeft: 4,
18
+ ...style,
19
+ }}
20
+ />
21
+ }
22
+ >
23
+ {remark}
24
+ </CnBalloon.Tooltip>
25
+ );
@@ -0,0 +1,93 @@
1
+ import { Box } from '@cainiaofe/cn-ui';
2
+ import { CSSProperties } from 'react';
3
+
4
+ const noContentImg =
5
+ 'https://img.alicdn.com/imgextra/i4/O1CN01g0QafV1rIyRHX6HA9_!!6000000005609-55-tps-190-120.svg';
6
+ const noContentImgDark =
7
+ 'https://img.alicdn.com/imgextra/i1/O1CN01A8j5NM26FVeLRKiQo_!!6000000007632-55-tps-160-104.svg';
8
+ const noAccessImg =
9
+ 'https://img.alicdn.com/imgextra/i4/O1CN01oQNWzR1rY5L7fdHcH_!!6000000005642-55-tps-160-160.svg';
10
+
11
+ interface IProps {
12
+ direction?: 'row' | 'column' | 'row-reverse';
13
+ style: CSSProperties;
14
+ message: string;
15
+ className: string;
16
+ isDark: boolean;
17
+ }
18
+
19
+ export const NoContent = ({
20
+ direction = 'row',
21
+ message = '无内容',
22
+ style,
23
+ className,
24
+ isDark,
25
+ }: Partial<IProps>) => {
26
+ return (
27
+ <Box
28
+ direction={direction}
29
+ justify='center'
30
+ align='center'
31
+ spacing={20}
32
+ className={className}
33
+ style={{
34
+ transform: 'translateY(20px)',
35
+ ...style,
36
+ }}
37
+ >
38
+ <img
39
+ alt=''
40
+ src={isDark ? noContentImgDark : noContentImg}
41
+ style={{
42
+ width: 120,
43
+ height: 120,
44
+ objectFit: 'contain',
45
+ }}
46
+ />
47
+ <span
48
+ style={{
49
+ fontSize: 14,
50
+ fontWeight: 500,
51
+ color: '#6D7A90',
52
+ }}
53
+ >
54
+ {message}
55
+ </span>
56
+ </Box>
57
+ );
58
+ };
59
+
60
+ export const NoAssess = ({
61
+ direction = 'row',
62
+ message = '暂无权限',
63
+ style,
64
+ className,
65
+ }: Partial<IProps>) => {
66
+ return (
67
+ <Box
68
+ direction={direction}
69
+ justify='center'
70
+ align='center'
71
+ spacing={20}
72
+ className={className}
73
+ style={{
74
+ ...style,
75
+ }}
76
+ >
77
+ <img
78
+ alt=''
79
+ src={noAccessImg}
80
+ style={{ width: 120, height: 120, objectFit: 'contain' }}
81
+ />
82
+ <span
83
+ style={{
84
+ fontSize: 14,
85
+ fontWeight: 700,
86
+ color: '#6D7A90',
87
+ }}
88
+ >
89
+ {message}
90
+ </span>
91
+ </Box>
92
+ );
93
+ };
@@ -0,0 +1,150 @@
1
+ import { useSize } from 'ahooks';
2
+ import { rgba } from 'polished';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { IListItem } from 'src/types/interface';
5
+ import { arraySum } from 'src/utils/arr';
6
+ import { css, styled } from 'styled-components';
7
+
8
+ interface IProps<T = string> {
9
+ dataList: IListItem<T>[];
10
+ value: T;
11
+ onChange(value: T): void;
12
+ style?: React.CSSProperties;
13
+ className?: string;
14
+ aroundTab?: boolean;
15
+ }
16
+
17
+ const spacing = 4;
18
+
19
+ function Tab<T>({
20
+ dataList = [],
21
+ value,
22
+ aroundTab = false,
23
+ onChange,
24
+ ...args
25
+ }: IProps<T>) {
26
+ const containerRef = useRef<HTMLDivElement | null>(null);
27
+ const [tagState, setTagState] = useState({ width: 0, left: 0 });
28
+ const { width } = useSize(containerRef) ?? {};
29
+
30
+ useEffect(() => {
31
+ if (containerRef.current) {
32
+ // tab 容器宽度
33
+ const containerWidth = containerRef.current.getBoundingClientRect().width;
34
+ // tab 元素宽度
35
+ const tabWidthList = Array.from(
36
+ containerRef.current.querySelectorAll('[data-tab-item]'),
37
+ ).map((item) => item.getBoundingClientRect().width);
38
+ // 当前 tab 索引
39
+ const index = dataList.findIndex((item) => item.value === value);
40
+ // 当前 tab 宽度
41
+ const width = tabWidthList[index];
42
+ // 当前 tab 左侧元素宽度之和
43
+ const plusWith = arraySum(tabWidthList.slice(0, index));
44
+
45
+ if (aroundTab) {
46
+ const spacingWidth =
47
+ (containerWidth - arraySum(tabWidthList)) / (tabWidthList.length - 1);
48
+ setTagState({
49
+ width,
50
+ left: plusWith + index * spacingWidth,
51
+ });
52
+ } else {
53
+ setTagState({
54
+ width,
55
+ left: plusWith + index * spacing,
56
+ });
57
+ }
58
+ }
59
+ }, [value, width, aroundTab, dataList]);
60
+
61
+ return (
62
+ <div {...args} ref={containerRef}>
63
+ {dataList.map((item, index) => (
64
+ <div
65
+ data-tab-item
66
+ data-tab-last={index === dataList.length - 1}
67
+ data-checked={item.value === value}
68
+ key={index}
69
+ onClick={() => onChange(item.value)}
70
+ >
71
+ {item.label}
72
+ </div>
73
+ ))}
74
+ <CheckedTag style={{ ...tagState }} />
75
+ </div>
76
+ );
77
+ }
78
+
79
+ export const PanelTab = styled(Tab)<{ $darker?: boolean }>`
80
+ display: flex;
81
+ align-items: center;
82
+ position: relative;
83
+ background-color: ${(props) => props.theme.tabBackgroundColor ?? '#e2e5eb'};
84
+ border-radius: 500px;
85
+ line-height: 1;
86
+ color: ${(props) => props.theme.tabColor ?? '#272e3a'};
87
+
88
+ ${(props) =>
89
+ props.theme.type === 'dark' &&
90
+ props.$darker &&
91
+ css`
92
+ background-color: rgba(18, 22, 31, 0.5);
93
+ color: rgba(255, 255, 255, 0.7);
94
+ `}
95
+
96
+ [data-tab-item] {
97
+ padding: 6px 12px;
98
+ white-space: nowrap;
99
+ text-overflow: ellipsis;
100
+ overflow: hidden;
101
+ font-size: 12px;
102
+ cursor: pointer;
103
+ user-select: none;
104
+ transition: all 0.3s;
105
+ position: relative;
106
+ margin-right: ${spacing}px;
107
+ z-index: 1;
108
+ font-weight: 500;
109
+
110
+ &[data-tab-last='true'] {
111
+ margin-right: 0px;
112
+ }
113
+
114
+ &[data-checked='true'] {
115
+ font-weight: 700;
116
+
117
+ ${(props) =>
118
+ props.theme.type === 'dark' &&
119
+ css`
120
+ color: #000;
121
+ `}
122
+ }
123
+ }
124
+
125
+ ${(props) =>
126
+ props.aroundTab &&
127
+ css`
128
+ justify-content: space-between;
129
+
130
+ [data-tab-item] {
131
+ margin-right: 0px;
132
+ }
133
+ `}
134
+ `;
135
+
136
+ const CheckedTag = styled.div`
137
+ height: 100%;
138
+ border-radius: 500px;
139
+ background-color: #fff;
140
+ transition: all 0.3s;
141
+ position: absolute;
142
+ left: 0;
143
+ top: 0;
144
+
145
+ ${(props) =>
146
+ props.theme.type === 'dark' &&
147
+ css`
148
+ background-color: ${rgba('#fff', 0.7)};
149
+ `}
150
+ `;
@@ -0,0 +1,60 @@
1
+ import { IListItem } from '@/types';
2
+ import { styled } from 'styled-components';
3
+
4
+ interface IProps<T> {
5
+ dataList: IListItem<T>[];
6
+ value: T;
7
+ onChange(value: T): void;
8
+ style?: React.CSSProperties;
9
+ className?: string;
10
+ }
11
+
12
+ const spacing = 24;
13
+
14
+ function Tab<T>({ dataList = [], value, onChange, ...args }: IProps<T>) {
15
+ return (
16
+ <div {...args}>
17
+ {dataList.map((item, index) => (
18
+ <div
19
+ data-tab-item
20
+ data-tab-last={index === dataList.length - 1}
21
+ data-checked={item.value === value}
22
+ key={index}
23
+ onClick={() => onChange(item.value)}
24
+ >
25
+ {item.label}
26
+ </div>
27
+ ))}
28
+ </div>
29
+ );
30
+ }
31
+
32
+ export const PanelTitleTab = styled(Tab)`
33
+ display: flex;
34
+ align-items: center;
35
+ position: relative;
36
+ border-radius: 500px;
37
+ line-height: 1;
38
+ color: #5d677a;
39
+ font-size: 14px;
40
+ margin-bottom: 16px;
41
+ [data-tab-item] {
42
+ white-space: nowrap;
43
+ text-overflow: ellipsis;
44
+ overflow: hidden;
45
+ cursor: pointer;
46
+ user-select: none;
47
+ transition: all 0.3s;
48
+ position: relative;
49
+ margin-right: ${spacing}px;
50
+ z-index: 1;
51
+ &[data-tab-last='true'] {
52
+ margin-right: 0px;
53
+ }
54
+
55
+ &[data-checked='true'] {
56
+ font-weight: 700;
57
+ color: #272f3d;
58
+ }
59
+ }
60
+ `;