Skip to content

Commit db67c6b

Browse files
author
lirenhao
committed
服务查看
1 parent e57eae5 commit db67c6b

File tree

8 files changed

+343
-0
lines changed

8 files changed

+343
-0
lines changed

config/config.ts

+6
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ export default {
111111
component: './Admin',
112112
authority: ['admin'],
113113
},
114+
{
115+
name: '服务',
116+
icon: 'smile',
117+
path: '/svc',
118+
component: './svc',
119+
},
114120
{
115121
name: 'permit',
116122
icon: 'smile',

mock/svr.ts

Whitespace-only changes.

src/pages/svc/_mock.ts

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { Request, Response } from 'express';
2+
3+
const data = [
4+
{
5+
id: "service-1",
6+
resources: [
7+
{
8+
uri: "/merchant",
9+
ops: ["READ", "CREATE", "UPDATE", "DELETE"],
10+
},
11+
{
12+
uri: "/terminal",
13+
ops: ["READ", "CREATE", "UPDATE", "DELETE"],
14+
},
15+
{
16+
uri: "/trans",
17+
ops: ["READ"],
18+
},
19+
],
20+
},
21+
{
22+
id: "service-2",
23+
resources: [
24+
{
25+
uri: "/merchant",
26+
ops: ["READ"],
27+
},
28+
{
29+
uri: "/terminal",
30+
ops: ["READ"],
31+
},
32+
{
33+
uri: "/trans",
34+
ops: ["READ"],
35+
},
36+
],
37+
},
38+
{
39+
id: "service-3",
40+
resources: [
41+
{
42+
uri: "/merchant",
43+
ops: ["CREATE"],
44+
},
45+
{
46+
uri: "/terminal",
47+
ops: ["CREATE"],
48+
},
49+
{
50+
uri: "/trans",
51+
ops: ["READ"],
52+
},
53+
],
54+
},
55+
{
56+
id: "service-4",
57+
resources: [
58+
{
59+
uri: "/merchant",
60+
ops: ["UPDATE"],
61+
},
62+
{
63+
uri: "/terminal",
64+
ops: ["UPDATE"],
65+
},
66+
{
67+
uri: "/trans",
68+
ops: ["READ"],
69+
},
70+
],
71+
},
72+
]
73+
74+
export default {
75+
'GET /api/permit/svc': (req: Request, resp: Response) => {
76+
resp.send(data.map(item => item.id));
77+
},
78+
'GET /api/permit/svc/:id': (req: Request, resp: Response) => {
79+
const { id } = req.params;
80+
resp.send(data.filter(item => item.id === decodeURIComponent(id))[0]);
81+
}
82+
}

src/pages/svc/data.d.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export enum Operator {
2+
READ = "READ",
3+
CREATE = "CREATE",
4+
UPDATE = "UPDATE",
5+
DELETE = "DELETE",
6+
}
7+
8+
export interface ResData {
9+
uri: String;
10+
ops: Operator[];
11+
}
12+
13+
export interface SvcData {
14+
id: String;
15+
resources: ResData[];
16+
}

src/pages/svc/index.tsx

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import React from 'react';
2+
import { Dispatch } from 'redux';
3+
import { GridContent } from '@ant-design/pro-layout';
4+
import { PageHeaderWrapper } from '@ant-design/pro-layout';
5+
import { Spin, Menu, List } from 'antd';
6+
import { connect } from 'dva';
7+
import { SvcData, ResData } from './data.d';
8+
import { ModelState } from './model';
9+
10+
import styles from './style.less';
11+
12+
const { Item } = Menu;
13+
14+
interface SvcProps {
15+
dispatch: Dispatch<any>;
16+
ids: string[];
17+
info: SvcData;
18+
loading: boolean;
19+
}
20+
21+
const SvcView: React.FC<SvcProps> = props => {
22+
23+
const [id, setId] = React.useState<string>("");
24+
const [info, setInfo] = React.useState<Partial<SvcData>>({});
25+
26+
React.useEffect(() => {
27+
props.dispatch({ type: 'svc/fetchIds' });
28+
}, []);
29+
30+
const selectKey = (key: string) => {
31+
setId(key);
32+
props.dispatch({
33+
type: 'svc/fetchInfo',
34+
payload: key,
35+
callback: (info: SvcData) => setInfo(info),
36+
});
37+
}
38+
39+
const { ids, loading } = props;
40+
41+
return (
42+
<PageHeaderWrapper>
43+
<Spin spinning={loading}>
44+
<GridContent>
45+
<div className={styles.main} >
46+
<div className={styles.leftMenu}>
47+
<Menu
48+
mode="inline"
49+
selectedKeys={[id]}
50+
onClick={({ key }) => selectKey(key)}
51+
>
52+
{ids.map(id => <Item key={id}>{id}</Item>)}
53+
</Menu>
54+
</div>
55+
<div className={styles.right}>
56+
<div className={styles.title}>{id}</div>
57+
<List
58+
loading={loading}
59+
itemLayout="horizontal"
60+
dataSource={info.resources}
61+
renderItem={(item: ResData) => (
62+
<List.Item>
63+
<List.Item.Meta title={item.uri} description={item.ops.join(' | ')} />
64+
</List.Item>
65+
)}
66+
/>
67+
</div>
68+
</div>
69+
</GridContent>
70+
</Spin>
71+
</PageHeaderWrapper>
72+
)
73+
}
74+
75+
export default connect(
76+
({ svc,
77+
loading,
78+
}: {
79+
svc: ModelState,
80+
loading: { models: { [key: string]: boolean } };
81+
}) => ({
82+
ids: svc.ids,
83+
loading: loading.models.svc,
84+
}),
85+
)(SvcView);

src/pages/svc/model.ts

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Effect } from 'dva';
2+
import { Reducer } from 'redux';
3+
import { getAllIds, getInfo } from './service';
4+
5+
export interface ModelState {
6+
ids: string[];
7+
}
8+
9+
export interface ModelType {
10+
namespace: string;
11+
state: ModelState;
12+
effects: {
13+
fetchIds: Effect;
14+
fetchInfo: Effect;
15+
};
16+
reducers: {
17+
setIds: Reducer<ModelState>;
18+
};
19+
}
20+
21+
const Model: ModelType = {
22+
namespace: 'svc',
23+
state: {
24+
ids: [],
25+
},
26+
effects: {
27+
*fetchIds(_, { call, put }) {
28+
const ids = yield call(getAllIds);
29+
yield put({
30+
type: 'setIds',
31+
payload: ids,
32+
});
33+
},
34+
*fetchInfo({ payload, callback }, { call }) {
35+
const info = yield call(getInfo, payload);
36+
if (callback) callback(info);
37+
},
38+
},
39+
reducers: {
40+
setIds(_, action) {
41+
return {
42+
ids: action.payload,
43+
};
44+
},
45+
}
46+
}
47+
48+
export default Model;

src/pages/svc/service.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import request from '@/utils/request';
2+
3+
export async function getAllIds() {
4+
return request('/api/permit/svc');
5+
}
6+
7+
export async function getInfo(id: string) {
8+
return request(`/api/permit/svc/${encodeURIComponent(id)}`);
9+
}

src/pages/svc/style.less

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
@import '~antd/es/style/themes/default.less';
2+
3+
.main {
4+
display: flex;
5+
width: 100%;
6+
height: 100%;
7+
padding-top: 16px;
8+
padding-bottom: 16px;
9+
overflow: auto;
10+
background-color: @menu-bg;
11+
.leftMenu {
12+
width: 224px;
13+
border-right: @border-width-base @border-style-base @border-color-split;
14+
:global {
15+
.ant-menu-inline {
16+
border: none;
17+
}
18+
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
19+
font-weight: bold;
20+
}
21+
}
22+
}
23+
.right {
24+
flex: 1;
25+
padding-top: 8px;
26+
padding-right: 40px;
27+
padding-bottom: 8px;
28+
padding-left: 40px;
29+
.title {
30+
margin-bottom: 12px;
31+
color: @heading-color;
32+
font-weight: 500;
33+
font-size: 20px;
34+
line-height: 28px;
35+
}
36+
}
37+
:global {
38+
.ant-list-split .ant-list-item:last-child {
39+
border-bottom: 1px solid @border-color-split;
40+
}
41+
.ant-list-item {
42+
padding-top: 14px;
43+
padding-bottom: 14px;
44+
}
45+
}
46+
}
47+
:global {
48+
.ant-list-item-meta {
49+
// 账号绑定图标
50+
.taobao {
51+
display: block;
52+
color: #ff4000;
53+
font-size: 48px;
54+
line-height: 48px;
55+
border-radius: @border-radius-base;
56+
}
57+
.dingding {
58+
margin: 2px;
59+
padding: 6px;
60+
color: #fff;
61+
font-size: 32px;
62+
line-height: 32px;
63+
background-color: #2eabff;
64+
border-radius: @border-radius-base;
65+
}
66+
.alipay {
67+
color: #2eabff;
68+
font-size: 48px;
69+
line-height: 48px;
70+
border-radius: @border-radius-base;
71+
}
72+
}
73+
74+
// 密码强度
75+
font.strong {
76+
color: @success-color;
77+
}
78+
font.medium {
79+
color: @warning-color;
80+
}
81+
font.weak {
82+
color: @error-color;
83+
}
84+
}
85+
86+
@media screen and (max-width: @screen-md) {
87+
.main {
88+
flex-direction: column;
89+
.leftMenu {
90+
width: 100%;
91+
border: none;
92+
}
93+
.right {
94+
padding: 40px;
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)