Browse Source

feat: 用户白名单

lihao
nili 6 months ago
parent
commit
28237304c3
  1. 2
      dist/_umi_route_preload_helper.f0e6a96a.js
  2. 4
      dist/index.html
  3. 1
      dist/p__SuperAdmin.2c1167ac.async.js
  4. 1
      dist/p__SuperAdmin.fe6b99ac.async.js
  5. 4
      dist/umi.b376a3ea.js
  6. 4
      src/pages/SuperAdmin.tsx
  7. 195
      src/pages/SuperAdmin/WhiteUserManagement.tsx
  8. 23
      src/services/matrix/superAdmin.ts
  9. 21
      src/services/matrix/typings.d.ts

2
dist/_umi_route_preload_helper.cfa973da.js → dist/_umi_route_preload_helper.f0e6a96a.js

@ -1 +1 @@
!function(){"use strict";var t="/".replace(/([^/])$/,"$1/"),e=location.pathname,n=e.startsWith(t)&&decodeURI("/".concat(e.slice(t.length)));if(n){var a=document,c=a.head,r=a.createElement.bind(a),i=function(t,e,n){var a,c=e.r[t]||(null===(a=Object.entries(e.r).find((function(e){var n=e[0];return new RegExp("^".concat(n.replace(/\/:[^/]+/g,"/[^/]+").replace("/*","/.+"),"$")).test(t)})))||void 0===a?void 0:a[1]);return null==c?void 0:c.map((function(t){var a=e.f[t][1],c=e.f[t][0];return{type:c.split(".").pop(),url:"".concat(n.publicPath).concat(c),attrs:[["data-".concat(e.b),"".concat(e.p,":").concat(a)]]}}))}(n,{"p":"ant-design-pro","b":"webpack","f":[["51.a2ea1b3b.async.js",51],["134.6fc81d91.async.js",134],["169.57647c7d.async.js",169],["p__Welcome.61596037.async.js",185],["p__MoneyManagement.60ec3db9.async.js",190],["247.3fe8fb10.async.js",247],["t__plugin-layout__Layout.6cae69f5.chunk.css",301],["t__plugin-layout__Layout.4594a64b.async.js",301],["p__User__Login__index.9d3ab92e.async.js",366],["p__DeviceOwnerApp.ec53e5c4.async.js",371],["390.41467286.async.js",390],["393.38316f72.async.js",393],["397.fb5f72c1.async.js",397],["p__SuperAdmin.fe6b99ac.async.js",455],["531.4c68f902.async.js",531],["539.49b7b156.async.js",539],["p__AdvRecordListV2.ced10464.async.js",542],["p__Bind.b6ee068f.async.js",557],["559.016bfdbb.async.js",559],["p__404.0c100574.async.js",571],["635.20e45f05.async.js",635],["p__App__AppManagement.133ceb4c.async.js",731],["p__AdminManagement.5e2368b3.async.js",816],["822.4ba8fa04.async.js",822],["841.614ef4c0.async.js",841],["p__AdvRecordList.8e5ef22c.async.js",857],["p__UserManagement.c0a8d03f.async.js",903],["905.6e225d1b.async.js",905],["930.fca7adbf.async.js",930]],"r":{"/*":[19,27],"/":[1,6,7,18,20,27],"/welcome":[1,2,3,11,18,28,6,7,20,27],"/super":[0,1,2,5,13,14,15,23,27,28,6,7,18,20],"/adminList":[0,2,22,23,1,6,7,18,20,27],"/bind":[1,2,11,12,17,18,28,6,7,20,27],"/appList":[0,1,2,5,12,14,15,21,23,27,28,6,7,18,20],"/advList/:code":[0,1,2,14,15,18,23,24,25,27,28,6,7,20],"/advListV2/:code":[0,1,2,14,15,16,18,23,24,27,28,6,7,20],"/user/:code":[0,1,2,14,15,23,26,27,28,6,7,18,20],"/money/:code":[0,1,2,4,14,15,23,27,28,6,7,18,20],"/app/:code":[0,1,2,9,14,15,18,23,24,27,28,6,7,20],"/user/login":[1,2,8,14,23]}},{publicPath:"/"});null==i||i.forEach((function(t){var e,n=t.type,a=t.url;if("js"===n)(e=r("script")).src=a,e.async=!0;else{if("css"!==n)return;(e=r("link")).href=a,e.rel="preload",e.as="style"}t.attrs.forEach((function(t){e.setAttribute(t[0],t[1]||"")})),c.appendChild(e)}))}}();
!function(){"use strict";var t="/".replace(/([^/])$/,"$1/"),e=location.pathname,n=e.startsWith(t)&&decodeURI("/".concat(e.slice(t.length)));if(n){var a=document,c=a.head,r=a.createElement.bind(a),i=function(t,e,n){var a,c=e.r[t]||(null===(a=Object.entries(e.r).find((function(e){var n=e[0];return new RegExp("^".concat(n.replace(/\/:[^/]+/g,"/[^/]+").replace("/*","/.+"),"$")).test(t)})))||void 0===a?void 0:a[1]);return null==c?void 0:c.map((function(t){var a=e.f[t][1],c=e.f[t][0];return{type:c.split(".").pop(),url:"".concat(n.publicPath).concat(c),attrs:[["data-".concat(e.b),"".concat(e.p,":").concat(a)]]}}))}(n,{"p":"ant-design-pro","b":"webpack","f":[["51.a2ea1b3b.async.js",51],["134.6fc81d91.async.js",134],["169.57647c7d.async.js",169],["p__Welcome.61596037.async.js",185],["p__MoneyManagement.60ec3db9.async.js",190],["247.3fe8fb10.async.js",247],["t__plugin-layout__Layout.6cae69f5.chunk.css",301],["t__plugin-layout__Layout.4594a64b.async.js",301],["p__User__Login__index.9d3ab92e.async.js",366],["p__DeviceOwnerApp.ec53e5c4.async.js",371],["390.41467286.async.js",390],["393.38316f72.async.js",393],["397.fb5f72c1.async.js",397],["p__SuperAdmin.2c1167ac.async.js",455],["531.4c68f902.async.js",531],["539.49b7b156.async.js",539],["p__AdvRecordListV2.ced10464.async.js",542],["p__Bind.b6ee068f.async.js",557],["559.016bfdbb.async.js",559],["p__404.0c100574.async.js",571],["635.20e45f05.async.js",635],["p__App__AppManagement.133ceb4c.async.js",731],["p__AdminManagement.5e2368b3.async.js",816],["822.4ba8fa04.async.js",822],["841.614ef4c0.async.js",841],["p__AdvRecordList.8e5ef22c.async.js",857],["p__UserManagement.c0a8d03f.async.js",903],["905.6e225d1b.async.js",905],["930.fca7adbf.async.js",930]],"r":{"/*":[19,27],"/":[1,6,7,18,20,27],"/welcome":[1,2,3,11,18,28,6,7,20,27],"/super":[0,1,2,5,13,14,15,23,27,28,6,7,18,20],"/adminList":[0,2,22,23,1,6,7,18,20,27],"/bind":[1,2,11,12,17,18,28,6,7,20,27],"/appList":[0,1,2,5,12,14,15,21,23,27,28,6,7,18,20],"/advList/:code":[0,1,2,14,15,18,23,24,25,27,28,6,7,20],"/advListV2/:code":[0,1,2,14,15,16,18,23,24,27,28,6,7,20],"/user/:code":[0,1,2,14,15,23,26,27,28,6,7,18,20],"/money/:code":[0,1,2,4,14,15,23,27,28,6,7,18,20],"/app/:code":[0,1,2,9,14,15,18,23,24,27,28,6,7,20],"/user/login":[1,2,8,14,23]}},{publicPath:"/"});null==i||i.forEach((function(t){var e,n=t.type,a=t.url;if("js"===n)(e=r("script")).src=a,e.async=!0;else{if("css"!==n)return;(e=r("link")).href=a,e.rel="preload",e.as="style"}t.attrs.forEach((function(t){e.setAttribute(t[0],t[1]||"")})),c.appendChild(e)}))}}();

4
dist/index.html

@ -7,10 +7,10 @@
<title>Ant Design Pro</title>
<link rel="stylesheet" href="/umi.1ca9308c.css">
<script async src="/scripts/loading.js"></script>
<script src="/_umi_route_preload_helper.cfa973da.js"></script>
<script src="/_umi_route_preload_helper.f0e6a96a.js"></script>
</head>
<body>
<div id="root"></div>
<script src="/umi.efd43caa.js"></script>
<script src="/umi.b376a3ea.js"></script>
</body>
</html>

1
dist/p__SuperAdmin.2c1167ac.async.js

File diff suppressed because one or more lines are too long

1
dist/p__SuperAdmin.fe6b99ac.async.js

File diff suppressed because one or more lines are too long

4
dist/umi.efd43caa.js → dist/umi.b376a3ea.js

File diff suppressed because one or more lines are too long

4
src/pages/SuperAdmin.tsx

@ -32,6 +32,7 @@ import React, { useEffect, useState } from 'react';
import OSSUploadDragger from './OSSUploadDragger';
import EvilAppManagement from './SuperAdmin/EvilAppManagement';
import WhiteUserManagement from './SuperAdmin/WhiteUserManagement';
// import { RequestOptionsType, ProFieldRequestData } from "@ant-design/pro-utils";
@ -389,6 +390,9 @@ const SuperAdmin: React.FC = () => {
<TabPane tab="非法应用" key="4">
<EvilAppManagement />
</TabPane>
<TabPane tab="用户白名单" key="5">
<WhiteUserManagement />
</TabPane>
</Tabs>
</PageContainer>
);

195
src/pages/SuperAdmin/WhiteUserManagement.tsx

@ -0,0 +1,195 @@
import { saveWhiteUser, whiteUserList } from '@/services/matrix/superAdmin';
import { SearchOutlined } from '@ant-design/icons';
import { ProColumns, ProTable } from '@ant-design/pro-components';
import { Button, Form, Input, InputNumber, Modal, Space, Tag } from 'antd';
import { useEffect, useState } from 'react';
import UserInfo from '../User/UserInfo';
const WhiteUserManagement = () => {
const [visible, setVisible] = useState(false);
const [whiteUserArr, setWhiteUserArr] = useState<API.WhiteUserBo[]>([]);
const [filteredArr, setFilteredArr] = useState<API.WhiteUserBo[]>([]);
const [form] = Form.useForm();
const fetchApp = async () => {
const res = await whiteUserList();
if (res.data) {
setWhiteUserArr(res.data);
setFilteredArr(res.data);
}
};
const columns: ProColumns<API.WhiteUserBo>[] = [
{
title: '应用名',
dataIndex: 'appName',
copyable: true,
hideInSearch: true,
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
<div style={{ padding: 8 }}>
<Input
placeholder="搜索应用"
value={selectedKeys[0]}
onChange={(e) => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => confirm()}
style={{ marginBottom: 8, display: 'block' }}
/>
<Space>
<Button onClick={() => confirm()} type="primary">
</Button>
<Button onClick={() => clearFilters && clearFilters()} type="link">
</Button>
</Space>
</div>
),
onFilter: (value, record) => {
if (typeof value === 'string' && typeof record?.appName === 'string') {
return record.appName.includes(value);
}
return false;
},
filterIcon: (filtered) => (
<SearchOutlined
style={{ color: filtered ? '#1890ff' : undefined }}
onPointerOverCapture={undefined}
onPointerMoveCapture={undefined}
/>
),
},
{
title: '用户',
dataIndex: 'user',
hideInSearch: true,
render: (_, r) => <UserInfo data={r.user || {}} />,
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => {
const selectedUserId = selectedKeys[0] ? String(selectedKeys[0]) : '';
return (
<div style={{ padding: 8 }}>
<InputNumber
placeholder="搜索 userId"
value={selectedUserId}
onChange={(value) => setSelectedKeys(value ? [value] : [])}
onPressEnter={() => confirm()}
style={{ marginBottom: 8, display: 'block', width: 200 }}
/>
<Space>
<Button onClick={() => confirm()} type="primary">
</Button>
<Button onClick={() => clearFilters && clearFilters()} type="link">
</Button>
</Space>
</div>
);
},
onFilter: (value, record) => {
return record.user?.id === value;
},
filterIcon: (filtered) => (
<SearchOutlined
style={{ color: filtered ? '#1890ff' : undefined }}
onPointerOverCapture={undefined}
onPointerMoveCapture={undefined}
/>
),
},
{
title: '状态',
hideInSearch: true,
renderText: (r: API.WhiteUserBo) =>
r.status === 0 ? <Tag color="green"></Tag> : <Tag color="red"></Tag>,
},
{
title: '创建时间',
hideInSearch: true,
dataIndex: 'createdAt',
valueType: 'dateTime',
},
{
title: '修改时间',
hideInSearch: true,
dataIndex: 'updatedAt',
valueType: 'dateTime',
},
{
title: '操作',
width: 80,
hideInSearch: true,
renderText: (r: API.WhiteUserBo) => {
return (
<a
key="edit"
onClick={async () => {
await saveWhiteUser({ userId: r.user?.id || 0, status: r.status === 0 ? -1 : 0 });
fetchApp();
}}
>
{r.status === 0 ? '禁用' : '启用'}
</a>
);
},
},
];
useEffect(() => {
fetchApp();
}, []);
return (
<>
<Button
style={{ marginBottom: '20px' }}
onClick={() => {
setVisible(true);
form.resetFields();
}}
>
</Button>
<ProTable
search={false}
onReset={() => {
setFilteredArr(whiteUserArr);
}}
columns={columns}
dataSource={filteredArr}
/>
<Modal
title="编辑"
visible={visible}
onOk={() => {
form.submit();
setVisible(false);
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
labelCol={{ span: 4 }}
wrapperCol={{ span: 18 }}
form={form}
onFinish={async ({ userId }) => {
if (userId) {
await saveWhiteUser({ userId: userId });
fetchApp();
}
}}
>
<Form.Item label="userId" name="userId">
<InputNumber style={{ width: 200 }} />
</Form.Item>
</Form>
</Modal>
</>
);
};
export default WhiteUserManagement;

23
src/services/matrix/superAdmin.ts

@ -21,3 +21,26 @@ export async function saveEvilApp(body: API.MatrixEvilApp, options?: { [key: str
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /api/superAdmin/saveWhiteUser */
export async function saveWhiteUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.saveWhiteUserParams,
options?: { [key: string]: any },
) {
return request<API.RVoid>('/api/superAdmin/saveWhiteUser', {
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /api/superAdmin/whiteUserList */
export async function whiteUserList(options?: { [key: string]: any }) {
return request<API.RListWhiteUserBo>('/api/superAdmin/whiteUserList', {
method: 'GET',
...(options || {}),
});
}

21
src/services/matrix/typings.d.ts

@ -369,6 +369,12 @@ declare namespace API {
data?: MatrixWhiteDevice[];
};
type RListWhiteUserBo = {
code?: number;
message?: string;
data?: WhiteUserBo[];
};
type RMatrixAdmin = {
code?: number;
message?: string;
@ -441,6 +447,11 @@ declare namespace API {
appCode: string;
};
type saveWhiteUserParams = {
userId: number;
status?: number;
};
type saveWxConfigParams = {
appCode: string;
};
@ -490,6 +501,16 @@ declare namespace API {
userId?: number;
};
type WhiteUserBo = {
id?: number;
appId?: number;
appName?: string;
user?: UserBo;
status?: number;
createdAt?: number;
updatedAt?: number;
};
type WxConfig = {
appId?: string;
appSecret?: string;

Loading…
Cancel
Save