Skip to content

Commit b05f682

Browse files
authored
Merge pull request #662 from nickcdon/main
✨ 仓库登记页面结构优化调整
2 parents 0d81671 + 3c670c0 commit b05f682

140 files changed

Lines changed: 4195 additions & 2995 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

web/packages/login/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"react-i18next": "^11.17.3",
4040
"react-redux": "^7.2.5",
4141
"react-router-dom": "^5.3.0",
42-
"tdesign-react": "0.36.4",
42+
"tdesign-react": "0.42.3",
4343
"universal-cookie": "^4.0.4"
4444
},
4545
"devDependencies": {

web/packages/shared/component/authority/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ export const AUTH_TYPE_TXT = {
3434
OAUTH: 'OAuth',
3535
};
3636

37+
export const AUTH_TYPE_CHOICES = {
38+
[AUTH_TYPE.HTTP]: AUTH_TYPE_TXT.HTTP,
39+
[AUTH_TYPE.SSH]: AUTH_TYPE_TXT.SSH,
40+
[AUTH_TYPE.OAUTH]: AUTH_TYPE_TXT.OAUTH,
41+
};
42+
3743
// 凭证映射,对应 api 返回的字段名
3844
export const SCM_MAP = {
3945
[AUTH_TYPE.HTTP]: 'scm_account',

web/packages/shared/component/authority/index.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import PlusIcon from 'coding-oa-uikit/lib/icon/Plus';
88
import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh';
99

1010
import { AUTH_TYPE, AUTH_TYPE_TXT, SCM_MAP, SCM_PLATFORM_CHOICES } from './constants';
11+
import { FormInstance } from 'coding-oa-uikit/lib/form';
1112

12-
import { FormInstance } from 'rc-field-form';
1313
const { Option, OptGroup } = Select;
1414

1515
export interface RestfulListAPIParams {
@@ -30,10 +30,14 @@ interface AuthorityProps {
3030
placeholder?: string;
3131
required?: boolean;
3232
allowClear?: boolean;
33+
formLayout?: any;
34+
/** 新增凭证路由 */
35+
addAuthRouter?: string
3336
}
3437

3538
const Authority = (props: AuthorityProps) => {
36-
const { form, name, label, initAuth, getAuthList, selectStyle = {}, placeholder, required, allowClear } = props;
39+
const { form, name, label, initAuth, getAuthList, selectStyle = {},
40+
placeholder, required, allowClear, formLayout, addAuthRouter } = props;
3741
const [sshAuthList, setSshAuthList] = useState<any>([]);
3842
const [httpAuthList, setHttpAuthList] = useState<any>([]);
3943
const [oauthAuthList, setOauthAuthList] = useState<any>([]);
@@ -105,7 +109,7 @@ const Authority = (props: AuthorityProps) => {
105109
}, [initAuth, authLoading]);
106110

107111
return (
108-
<Form.Item label={label} required={required}>
112+
<Form.Item label={label} required={required} {...formLayout}>
109113
<Form.Item name={name} noStyle rules={[{ required, message: '请选择仓库凭证' }]}>
110114
<Select
111115
style={selectStyle}
@@ -120,9 +124,10 @@ const Authority = (props: AuthorityProps) => {
120124
<Option
121125
key={`${AUTH_TYPE.OAUTH}#${auth.id}`}
122126
value={`${AUTH_TYPE.OAUTH}#${auth.id}`}
123-
label={`${get(SCM_PLATFORM_CHOICES, auth.scm_platform)}: ${AUTH_TYPE_TXT.OAUTH}`}
127+
label={`${get(SCM_PLATFORM_CHOICES, auth.scm_platform)}: ${auth.user?.username || auth.user}`}
124128
>
125-
{get(SCM_PLATFORM_CHOICES, auth.scm_platform)}
129+
{get(SCM_PLATFORM_CHOICES, auth.scm_platform)}: {auth.user?.username || auth.user}
130+
<small style={{ marginLeft: 8, color: '#8592a6' }}>(在 {auth.auth_origin} 创建)</small>
126131
</Option>
127132
))}
128133
</OptGroup>
@@ -163,7 +168,7 @@ const Authority = (props: AuthorityProps) => {
163168
right: 10,
164169
}}>
165170
<Tooltip title='新增凭证' placement='top' getPopupContainer={() => document.body}>
166-
<Button type='link' className="ml-12" href='/user/auth' target='_blank'><PlusIcon /></Button>
171+
<Button type='link' className="ml-12" href={addAuthRouter || '/user/auth'} target='_blank'><PlusIcon /></Button>
167172
</Tooltip>
168173
<Tooltip title='刷新凭证' placement='top' getPopupContainer={() => document.body}>
169174
<Button
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as RouteListener } from './listener';
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* 用于父子页面路由监听
3+
*/
4+
import React, { useEffect } from 'react';
5+
import { useHistory, useLocation } from 'react-router-dom';
6+
import { LogMgr } from '../../../util';
7+
/** 跨页面通信消息状态码 */
8+
export enum PostMessageCode {
9+
SUCCESS = 200,
10+
}
11+
12+
/** 跨页面通信消息数据结构 */
13+
export interface PostMessageData {
14+
code: number;
15+
type: string;
16+
data: string;
17+
}
18+
19+
/** route接收消息数据结构 */
20+
export interface RouteReceiveMessage {
21+
/** 接受消息来源 */
22+
eventOrigin?: string;
23+
/** 接收消息类型 */
24+
messageType?: string;
25+
/** history 路由跳转类型 */
26+
jumpType?: 'push' | 'replace';
27+
/** 路由前缀,接收路由时会增加路由前缀再执行跳转发送 */
28+
prefix?: string;
29+
/** 自定义处理 */
30+
customHandler?: (event: MessageEvent<PostMessageData>) => void;
31+
}
32+
33+
/** route发送消息数据结构 */
34+
export interface RoutePostMessage {
35+
/** 自定义操作 */
36+
customHandler?: (urlPath: string) => void
37+
/** 发送消息目标源,不存在customHandler时必传 */
38+
targetOrigin?: string;
39+
/** 发送消息类型,不存在customHandler时必传 */
40+
messageType?: string;
41+
/** 是否处于 iframe 内 */
42+
inIframe?: boolean;
43+
/** 路由前缀,发送路由时会替换路由前缀再发送 */
44+
prefix?: string;
45+
}
46+
47+
interface RouteListenerProps {
48+
postMessage?: RoutePostMessage;
49+
receiveMessage?: RouteReceiveMessage;
50+
children: React.ReactNode;
51+
}
52+
53+
const RouteListener = ({ receiveMessage, postMessage, children }: RouteListenerProps) => {
54+
const history = useHistory();
55+
56+
const { pathname, search, hash } = useLocation();
57+
// 获取url path
58+
const urlPath = `${pathname}${search}${hash}`;
59+
60+
useEffect(() => {
61+
if (postMessage?.customHandler) {
62+
// 存在自定义操作
63+
postMessage.customHandler(urlPath);
64+
} else if (postMessage?.targetOrigin && postMessage.messageType) {
65+
// 存在目标源以及消息类型
66+
// 路由变更时发送消息
67+
const msg: PostMessageData = {
68+
code: PostMessageCode.SUCCESS,
69+
type: postMessage.messageType,
70+
// 存在前缀则先替换前缀
71+
data: postMessage.prefix ? urlPath.replace(postMessage.prefix, '') : urlPath,
72+
};
73+
if (postMessage.inIframe && window.self !== window.top) {
74+
// 在iframe内,对iframe父页面发送路由变更消息
75+
window.top?.postMessage(msg, postMessage.targetOrigin);
76+
} else {
77+
LogMgr.warn('route 路由变更,未发送消息');
78+
}
79+
}
80+
}, [urlPath, postMessage]);
81+
82+
useEffect(() => {
83+
const receiveRouteHandler = (event: MessageEvent<PostMessageData>) => {
84+
if (receiveMessage?.customHandler) {
85+
// 存在自定义操作
86+
receiveMessage.customHandler(event);
87+
} else if (
88+
receiveMessage?.eventOrigin && receiveMessage.messageType
89+
&& receiveMessage.jumpType && event.origin === receiveMessage.eventOrigin) {
90+
// 存在发送源、消息类型、路由调整类型,且来自发送源消息
91+
const { code, type, data } = event.data;
92+
if (code === PostMessageCode.SUCCESS && type === receiveMessage.messageType) {
93+
// 默认匹配
94+
const urlPath = receiveMessage.prefix ? `${receiveMessage.prefix}${data}` : data;
95+
history[receiveMessage.jumpType](urlPath);
96+
} else {
97+
LogMgr.warn('接收到 route 消息,未匹配成功,未进行任何处理');
98+
}
99+
}
100+
};
101+
receiveMessage && window.addEventListener('message', receiveRouteHandler, false);
102+
return () => {
103+
receiveMessage && window.removeEventListener('message', receiveRouteHandler);
104+
};
105+
}, [receiveMessage]);
106+
107+
return <>{children}</>;
108+
};
109+
110+
export default RouteListener;

web/packages/shared/global.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,12 @@ interface WindowMicroHook {
5252
interface Window {
5353
microHook: WindowMicroHook;
5454
}
55+
56+
57+
// drf restful list api
58+
interface RestfulListAPIParams {
59+
results: any[];
60+
count: number;
61+
next: string;
62+
previous: string
63+
}

web/packages/shared/hooks/useFetch.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export interface UseFetchOptions {
6363
/** 失败的回调 */
6464
onFail?: (error: any) => void
6565
/** 最终的回调 */
66-
onFinnaly?: () => void
66+
onFinally?: () => void
6767
}
6868

6969
/**
@@ -78,7 +78,7 @@ const useFetch = <ApiArgs extends any[]>(
7878
apiArgs: ApiArgs,
7979
options: UseFetchOptions = {},
8080
): [State, () => void] => {
81-
const { initData = null, onPreHandler, onSuccess, onFail, onFinnaly } = options;
81+
const { initData = null, onPreHandler, onSuccess, onFail, onFinally } = options;
8282
const [state, dispatch] = useReducer(fetchReducer, {
8383
isLoading: false,
8484
isError: false,
@@ -117,7 +117,7 @@ const useFetch = <ApiArgs extends any[]>(
117117
dispatch({ type: 'FETCH_FAILURE', payload: error });
118118
onFail?.(error);
119119
} finally {
120-
onFinnaly?.();
120+
onFinally?.();
121121
}
122122
};
123123
fetchData();

web/packages/shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"react-router-dom": "^5.3.0",
4646
"react-copy-to-clipboard": "^5.0.4",
4747
"react-i18next": "^11.17.3",
48-
"tdesign-react": "0.36.4",
48+
"tdesign-react": "0.42.3",
4949
"typescript": "^4.5.5"
5050
}
5151
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# 用户个人凭证管理
2+
3+
- index: 用户个人凭证管理页面
4+
5+
- git-oauth: git oauth 授权回调页面
6+
7+
- auth-form-item: 凭证选择组件
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { FetchAPIManager } from '../../util/fetch';
2+
import { AuthTypeEnum, SCM_PLATFORM_NAME_CHOICES } from './constant';
3+
import { OAuthResult, UserAuthAPI } from './types';
4+
5+
export const formatUserAuthAPI = (
6+
/** ssh 凭证接口 */
7+
ssh: FetchAPIManager,
8+
/** account 凭证接口 */
9+
account: FetchAPIManager,
10+
/** oauth 凭证接口 */
11+
oauth: FetchAPIManager,
12+
/** oauth 凭证后台配置项接口 */
13+
oauthSetting: FetchAPIManager,
14+
/** oauth 凭证个人认证项接口 */
15+
oauthStatus: FetchAPIManager,
16+
/** oauth 认证回调接口 */
17+
oauthCallback: FetchAPIManager,
18+
): UserAuthAPI => ({
19+
getAuths: () => Promise.all([
20+
ssh.get({ limit: 200 }),
21+
account.get({ limit: 200 }),
22+
oauthSetting.get(),
23+
oauthStatus.get(),
24+
]).then(([sshInfo, accountInfo, oauthSettings, oauthStatus]) => {
25+
const sshList = (sshInfo as RestfulListAPIParams).results.map(item => ({ ...item, auth_type: AuthTypeEnum.SSH }));
26+
const accountList = (accountInfo as RestfulListAPIParams).results.map(item => ({
27+
...item, auth_type: AuthTypeEnum.HTTP,
28+
}));
29+
const oauthList = Object.keys(SCM_PLATFORM_NAME_CHOICES).filter(scmPlatformName => (
30+
oauthSettings as OAuthResult
31+
)[scmPlatformName])
32+
.map(scmPlatformName => ({
33+
...SCM_PLATFORM_NAME_CHOICES[scmPlatformName],
34+
platform_status: true,
35+
oauth_status: (oauthStatus as OAuthResult)[scmPlatformName] || false,
36+
}));
37+
return [...oauthList, ...sshList, ...accountList];
38+
}),
39+
getAuthInfos: () => Promise.all([
40+
ssh.get({ limit: 200 }),
41+
account.get({ limit: 200 }),
42+
oauth.get(),
43+
oauthStatus.get(),
44+
]).then(([sshInfo, accountInfo, oauthInfo, oauthStatus]) => {
45+
const sshList = (sshInfo as RestfulListAPIParams).results;
46+
const accountList = (accountInfo as RestfulListAPIParams).results;
47+
const oauthList = (oauthInfo as RestfulListAPIParams).results.filter(item => (
48+
oauthStatus as OAuthResult
49+
)[item.scm_platform_name]);
50+
return { oauthList, sshList, accountList };
51+
}),
52+
ssh,
53+
account,
54+
oauth,
55+
oauthSetting,
56+
oauthStatus,
57+
oauthCallback,
58+
});

0 commit comments

Comments
 (0)