Browse Source

设备主及相关功能

master
nili 9 months ago
parent
commit
bcc61acc03
  1. 17
      config/routes.ts
  2. 284
      dist/140.1458bf51.async.js
  3. 164
      dist/270.514d6aaa.async.js
  4. 10
      dist/393.2a09f5b6.async.js
  5. 8
      dist/559.683b9a7b.async.js
  6. 96
      dist/601.976fca1c.async.js
  7. 8
      dist/630.1e884d8b.async.js
  8. 18
      dist/635.09454aea.async.js
  9. 30
      dist/706.1c4598f2.async.js
  10. 42
      dist/858.8af04f5f.async.js
  11. 58
      dist/930.05171fe3.async.js
  12. 58
      dist/930.8352590c.async.js
  13. 259
      dist/983.53a1b6a8.async.js
  14. 272
      dist/991.963f9c47.async.js
  15. 2
      dist/index.html
  16. 1
      dist/p__AdminManagement.15a9dbd5.async.js
  17. 1
      dist/p__AdminManagement.c8a5c155.async.js
  18. 2
      dist/p__AdvRecordList.340683d2.async.js
  19. 1
      dist/p__Bind.49c22a98.async.js
  20. 1
      dist/p__DeviceOwnerApp.67a5dc65.async.js
  21. 1
      dist/p__User__Login__index.b793c4e2.async.js
  22. 1
      dist/p__User__Login__index.b7ec804e.async.js
  23. 1
      dist/p__Welcome.61596037.async.js
  24. 10
      dist/p__Welcome.845d8956.async.js
  25. 112
      dist/umi.622a7616.js
  26. 4
      src/access.ts
  27. 80
      src/app.tsx
  28. 104
      src/pages/AdminManagement.tsx
  29. 19
      src/pages/Bind.tsx
  30. 248
      src/pages/DeviceOwnerApp.tsx
  31. 33
      src/services/matrix/device.ts
  32. 2
      src/services/matrix/index.ts
  33. 30
      src/services/matrix/matrixController.ts
  34. 41
      src/services/matrix/typings.d.ts

17
config/routes.ts

@ -1,4 +1,5 @@
/** 
/**
* @name umi * @name umi
* @description path,component,routes,redirect,wrappers,name,icon * @description path,component,routes,redirect,wrappers,name,icon
* @param path path 第一种是动态参数 :id * * @param path path 第一种是动态参数 :id *
@ -32,14 +33,28 @@ export default [
path: '/advList/:code', path: '/advList/:code',
name: '广告列表', name: '广告列表',
icon: 'smile', icon: 'smile',
access: 'canAdmin',
component: './AdvRecordList', component: './AdvRecordList',
}, },
{
path: '/app/:code',
name: '应用列表',
icon: 'smile',
access: 'canDeviceOwner',
component: './DeviceOwnerApp',
},
{ {
path: '/adminList', path: '/adminList',
name: '人员管理', name: '人员管理',
access: 'canAdmin', access: 'canAdmin',
component: './AdminManagement' component: './AdminManagement'
}, },
{
path: '/bind',
name: '绑定设备',
access: 'canDeviceOwner',
component: './Bind'
},
{ {
path: '/', path: '/',
redirect: '/welcome', redirect: '/welcome',

284
dist/140.1458bf51.async.js

File diff suppressed because one or more lines are too long

164
dist/270.514d6aaa.async.js

File diff suppressed because one or more lines are too long

10
dist/393.2a09f5b6.async.js

File diff suppressed because one or more lines are too long

8
dist/559.683b9a7b.async.js

File diff suppressed because one or more lines are too long

96
dist/601.976fca1c.async.js

File diff suppressed because one or more lines are too long

8
dist/630.1e884d8b.async.js

File diff suppressed because one or more lines are too long

18
dist/635.4de81965.async.js → dist/635.09454aea.async.js

File diff suppressed because one or more lines are too long

30
dist/706.1c4598f2.async.js

File diff suppressed because one or more lines are too long

42
dist/858.8af04f5f.async.js

File diff suppressed because one or more lines are too long

58
dist/930.05171fe3.async.js

File diff suppressed because one or more lines are too long

58
dist/930.8352590c.async.js

File diff suppressed because one or more lines are too long

259
dist/983.53a1b6a8.async.js

File diff suppressed because one or more lines are too long

272
dist/991.963f9c47.async.js

File diff suppressed because one or more lines are too long

2
dist/index.html

@ -8,6 +8,6 @@
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script src="/umi.685e7ce1.js"></script> <script src="/umi.622a7616.js"></script>
</body></html> </body></html>

1
dist/p__AdminManagement.15a9dbd5.async.js

File diff suppressed because one or more lines are too long

1
dist/p__AdminManagement.c8a5c155.async.js

File diff suppressed because one or more lines are too long

2
dist/p__AdvRecordList.009dffec.async.js → dist/p__AdvRecordList.340683d2.async.js

@ -1 +1 @@
"use strict";(self.webpackChunkant_design_pro=self.webpackChunkant_design_pro||[]).push([[857],{46701:function(ne,h,t){t.r(h);var b=t(5574),f=t.n(b),C=t(15009),d=t.n(C),U=t(97857),u=t.n(U),y=t(99289),p=t.n(y),D=t(48357),B=t(92296),c=t(31847),g=t(90930),K=t(57470),x=t(64317),L=t(34540),W=t(50624),S=t(35312),Z=t(13169),O=t(16250),F=t(27484),z=t.n(F),$=t(9220),m=t(67294),G=t(96974),r=t(85893),N=function(){var M=(0,m.useRef)(),H=(0,S.useIntl)(),J=[{title:"\u8BBE\u5907id",dataIndex:"deviceId",valueType:"textarea",ellipsis:!0,copyable:!0},{title:"\u5E94\u7528\u540D\u79F0",hideInSearch:!0,dataIndex:"appName",valueType:"textarea"},{title:"\u5E73\u53F0",dataIndex:"platform",valueEnum:{1:{text:"\u7A7F\u5C71\u7532"},2:{text:"\u817E\u8BAF"},3:{text:"\u767E\u5EA6\u8054\u76DF"},4:{text:"Mintegral"},5:{text:"\u5FEB\u624B"},6:{text:"\u6E38\u53EF\u8D62"},7:{text:"Sigmob"},8:{text:"Admob"}}},{title:"\u5E7F\u544A\u7C7B\u578B",dataIndex:"advType",valueEnum:{1:{text:"\u6A2A\u5E45",status:"Default"},2:{text:"\u63D2\u9875",status:"Processing"},3:{text:"\u6FC0\u52B1\u89C6\u9891",status:"Success"}}},{title:"ecpm(\u5143)",dataIndex:"ecpm",hideInSearch:!0,renderText:function(e){return e/100}},{title:"\u8BBE\u5907\u54C1\u724C",dataIndex:"deviceBrand",hideInSearch:!0,valueType:"textarea"},{title:"\u8BBE\u5907\u540D",dataIndex:"deviceName",hideInSearch:!0,valueType:"textarea"},{title:"ip",dataIndex:"ip",hideInSearch:!0,valueType:"textarea"},{title:"\u65F6\u95F4",hideInSearch:!0,dataIndex:"createdAt",valueType:"dateTime"},{title:"\u65F6\u95F4",hideInTable:!0,dataIndex:"createdAt",valueType:"dateRange"}],Q=(0,G.UO)(),v=Q.code,V=function(){var a=p()(d()().mark(function e(s){var n,i,_;return d()().wrap(function(o){for(;;)switch(o.prev=o.next){case 0:return o.next=2,(0,D._5)(u()(u()({},s),{},{code:v}));case 2:return _=o.sent,o.abrupt("return",{data:(n=_.data)===null||n===void 0?void 0:n.data,total:(i=_.data)===null||i===void 0?void 0:i.total,success:!0});case 4:case"end":return o.stop()}},e)}));return function(s){return a.apply(this,arguments)}}(),X=(0,m.useState)(),P=f()(X,2),l=P[0],Y=P[1],w=(0,m.useState)([]),I=f()(w,2),T=I[0],k=I[1],q=c.Z.Divider,ee=(0,m.useState)(!1),j=f()(ee,2),R=j[0],te=j[1],ae=function(){var a=p()(d()().mark(function e(s){var n;return d()().wrap(function(_){for(;;)switch(_.prev=_.next){case 0:return _.next=2,(0,D.d1)({appCode:s});case 2:n=_.sent,n.data&&Y(n.data);case 4:case"end":return _.stop()}},e)}));return function(s){return a.apply(this,arguments)}}(),A=function(){var a=p()(d()().mark(function e(s){var n;return d()().wrap(function(_){for(;;)switch(_.prev=_.next){case 0:return _.next=2,(0,D.Zb)(u()(u()({},s),{},{code:v}));case 2:n=_.sent,n.data&&k(n.data);case 4:case"end":return _.stop()}},e)}));return function(s){return a.apply(this,arguments)}}();(0,m.useEffect)(function(){var a;(a=M.current)===null||a===void 0||a.reload(),ae(v),A({code:v})},[v]);var E=function(e){return e?parseFloat((e/1e5).toFixed(2)):0},re=T.map(function(a){return{date:function(){var e=a.date+"",s=e.slice(0,4),n=e.slice(4,6),i=e.slice(6,8);return"".concat(s,"-").concat(n,"-").concat(i)}(),income:E(a.income)}}),_e={data:re,xField:"date",yField:"income",tooltip:{name:"\u6536\u5165",field:"income"},axis:{date:{title:"\u65E5\u671F"}},title:"\u7D2F\u8BA1"+E(T.reduce(function(a,e){return a+(e.income?e.income:0)},0))+"\u5143",height:400,label:{text:function(e){return e.income>0?e.income:""},textBaseline:"bottom"}};return(0,r.jsx)(g._z,{children:(0,r.jsxs)(Z.Z,{defaultActiveKey:"1",centered:!0,style:{backgroundColor:"white",padding:"20px"},children:[(0,r.jsxs)(O.Z,{tab:"\u6570\u636E\u603B\u89C8",children:[(0,r.jsx)($.Z,{onResize:function(e){te(e.width<596)},children:(0,r.jsx)(c.Z,{children:(0,r.jsxs)(c.Z.Group,{direction:R?"column":"row",children:[(0,r.jsx)(c.Z,{statistic:{title:"\u7D2F\u8BA1\u6536\u5165\uFF08\u5143\uFF09",value:E(l==null?void 0:l.totalIncome)}}),(0,r.jsx)(q,{type:R?"horizontal":"vertical"}),(0,r.jsx)(c.Z,{statistic:{title:"\u4ECA\u65E5\u6536\u5165\uFF08\u5143\uFF09",value:E(l==null?void 0:l.todayIncome)}})]})})},"resize-observer"),(0,r.jsxs)(K.t,{defaultCollapsed:!0,split:!0,onFinish:A,children:[(0,r.jsx)(x.Z,{label:"\u5E73\u53F0",name:"platform",valueEnum:{1:"\u7A7F\u5C71\u7532",2:"\u817E\u8BAF",3:"\u767E\u5EA6\u8054\u76DF",4:"Mintegral",5:"\u5FEB\u624B",6:"\u6E38\u53EF\u8D62",7:"Sigmob",8:"Admob"}}),(0,r.jsx)(x.Z,{name:"advType",label:"\u5E7F\u544A\u7C7B\u578B",valueEnum:{1:"\u6A2A\u5E45",2:"\u63D2\u9875",3:"\u6FC0\u52B1\u89C6\u9891"}}),(0,r.jsx)(L.Z,{fieldProps:{disabledDate:function(e){return e&&e>=z()().startOf("day")}},name:"date",label:"\u65F6\u95F4"})]}),(0,r.jsx)(B.Z,u()({},_e))]},"1"),(0,r.jsx)(O.Z,{tab:"\u5E7F\u544A\u8BE6\u60C5",children:(0,r.jsx)(W.Z,{headerTitle:H.formatMessage({id:"pages.searchTable.title",defaultMessage:"Enquiry form"}),actionRef:M,rowKey:"key",search:{labelWidth:120},request:V,columns:J})},"2")]})})};h.default=N}}]); "use strict";(self.webpackChunkant_design_pro=self.webpackChunkant_design_pro||[]).push([[857],{46701:function(ne,h,t){t.r(h);var b=t(5574),f=t.n(b),C=t(15009),d=t.n(C),U=t(97857),u=t.n(U),y=t(99289),p=t.n(y),D=t(48357),B=t(92296),c=t(31847),g=t(90930),K=t(57470),x=t(64317),L=t(34540),W=t(85601),S=t(35312),Z=t(13169),O=t(16250),F=t(27484),z=t.n(F),$=t(9220),m=t(67294),G=t(96974),r=t(85893),N=function(){var M=(0,m.useRef)(),H=(0,S.useIntl)(),J=[{title:"\u8BBE\u5907id",dataIndex:"deviceId",valueType:"textarea",ellipsis:!0,copyable:!0},{title:"\u5E94\u7528\u540D\u79F0",hideInSearch:!0,dataIndex:"appName",valueType:"textarea"},{title:"\u5E73\u53F0",dataIndex:"platform",valueEnum:{1:{text:"\u7A7F\u5C71\u7532"},2:{text:"\u817E\u8BAF"},3:{text:"\u767E\u5EA6\u8054\u76DF"},4:{text:"Mintegral"},5:{text:"\u5FEB\u624B"},6:{text:"\u6E38\u53EF\u8D62"},7:{text:"Sigmob"},8:{text:"Admob"}}},{title:"\u5E7F\u544A\u7C7B\u578B",dataIndex:"advType",valueEnum:{1:{text:"\u6A2A\u5E45",status:"Default"},2:{text:"\u63D2\u9875",status:"Processing"},3:{text:"\u6FC0\u52B1\u89C6\u9891",status:"Success"}}},{title:"ecpm(\u5143)",dataIndex:"ecpm",hideInSearch:!0,renderText:function(e){return e/100}},{title:"\u8BBE\u5907\u54C1\u724C",dataIndex:"deviceBrand",hideInSearch:!0,valueType:"textarea"},{title:"\u8BBE\u5907\u540D",dataIndex:"deviceName",hideInSearch:!0,valueType:"textarea"},{title:"ip",dataIndex:"ip",hideInSearch:!0,valueType:"textarea"},{title:"\u65F6\u95F4",hideInSearch:!0,dataIndex:"createdAt",valueType:"dateTime"},{title:"\u65F6\u95F4",hideInTable:!0,dataIndex:"createdAt",valueType:"dateRange"}],Q=(0,G.UO)(),v=Q.code,V=function(){var a=p()(d()().mark(function e(s){var n,i,_;return d()().wrap(function(o){for(;;)switch(o.prev=o.next){case 0:return o.next=2,(0,D._5)(u()(u()({},s),{},{code:v}));case 2:return _=o.sent,o.abrupt("return",{data:(n=_.data)===null||n===void 0?void 0:n.data,total:(i=_.data)===null||i===void 0?void 0:i.total,success:!0});case 4:case"end":return o.stop()}},e)}));return function(s){return a.apply(this,arguments)}}(),X=(0,m.useState)(),P=f()(X,2),l=P[0],Y=P[1],w=(0,m.useState)([]),I=f()(w,2),T=I[0],k=I[1],q=c.Z.Divider,ee=(0,m.useState)(!1),j=f()(ee,2),R=j[0],te=j[1],ae=function(){var a=p()(d()().mark(function e(s){var n;return d()().wrap(function(_){for(;;)switch(_.prev=_.next){case 0:return _.next=2,(0,D.d1)({appCode:s});case 2:n=_.sent,n.data&&Y(n.data);case 4:case"end":return _.stop()}},e)}));return function(s){return a.apply(this,arguments)}}(),A=function(){var a=p()(d()().mark(function e(s){var n;return d()().wrap(function(_){for(;;)switch(_.prev=_.next){case 0:return _.next=2,(0,D.Zb)(u()(u()({},s),{},{code:v}));case 2:n=_.sent,n.data&&k(n.data);case 4:case"end":return _.stop()}},e)}));return function(s){return a.apply(this,arguments)}}();(0,m.useEffect)(function(){var a;(a=M.current)===null||a===void 0||a.reload(),ae(v),A({code:v})},[v]);var E=function(e){return e?parseFloat((e/1e5).toFixed(2)):0},re=T.map(function(a){return{date:function(){var e=a.date+"",s=e.slice(0,4),n=e.slice(4,6),i=e.slice(6,8);return"".concat(s,"-").concat(n,"-").concat(i)}(),income:E(a.income)}}),_e={data:re,xField:"date",yField:"income",tooltip:{name:"\u6536\u5165",field:"income"},axis:{date:{title:"\u65E5\u671F"}},title:"\u7D2F\u8BA1"+E(T.reduce(function(a,e){return a+(e.income?e.income:0)},0))+"\u5143",height:400,label:{text:function(e){return e.income>0?e.income:""},textBaseline:"bottom"}};return(0,r.jsx)(g._z,{children:(0,r.jsxs)(Z.Z,{defaultActiveKey:"1",centered:!0,style:{backgroundColor:"white",padding:"20px"},children:[(0,r.jsxs)(O.Z,{tab:"\u6570\u636E\u603B\u89C8",children:[(0,r.jsx)($.Z,{onResize:function(e){te(e.width<596)},children:(0,r.jsx)(c.Z,{children:(0,r.jsxs)(c.Z.Group,{direction:R?"column":"row",children:[(0,r.jsx)(c.Z,{statistic:{title:"\u7D2F\u8BA1\u6536\u5165\uFF08\u5143\uFF09",value:E(l==null?void 0:l.totalIncome)}}),(0,r.jsx)(q,{type:R?"horizontal":"vertical"}),(0,r.jsx)(c.Z,{statistic:{title:"\u4ECA\u65E5\u6536\u5165\uFF08\u5143\uFF09",value:E(l==null?void 0:l.todayIncome)}})]})})},"resize-observer"),(0,r.jsxs)(K.t,{defaultCollapsed:!0,split:!0,onFinish:A,children:[(0,r.jsx)(x.Z,{label:"\u5E73\u53F0",name:"platform",valueEnum:{1:"\u7A7F\u5C71\u7532",2:"\u817E\u8BAF",3:"\u767E\u5EA6\u8054\u76DF",4:"Mintegral",5:"\u5FEB\u624B",6:"\u6E38\u53EF\u8D62",7:"Sigmob",8:"Admob"}}),(0,r.jsx)(x.Z,{name:"advType",label:"\u5E7F\u544A\u7C7B\u578B",valueEnum:{1:"\u6A2A\u5E45",2:"\u63D2\u9875",3:"\u6FC0\u52B1\u89C6\u9891"}}),(0,r.jsx)(L.Z,{fieldProps:{disabledDate:function(e){return e&&e>=z()().startOf("day")}},name:"date",label:"\u65F6\u95F4"})]}),(0,r.jsx)(B.Z,u()({},_e))]},"1"),(0,r.jsx)(O.Z,{tab:"\u5E7F\u544A\u8BE6\u60C5",children:(0,r.jsx)(W.Z,{headerTitle:H.formatMessage({id:"pages.searchTable.title",defaultMessage:"Enquiry form"}),actionRef:M,rowKey:"key",search:{labelWidth:120},request:V,columns:J})},"2")]})})};h.default=N}}]);

1
dist/p__Bind.49c22a98.async.js

File diff suppressed because one or more lines are too long

1
dist/p__DeviceOwnerApp.67a5dc65.async.js

File diff suppressed because one or more lines are too long

1
dist/p__User__Login__index.b793c4e2.async.js

File diff suppressed because one or more lines are too long

1
dist/p__User__Login__index.b7ec804e.async.js

File diff suppressed because one or more lines are too long

1
dist/p__Welcome.61596037.async.js

@ -0,0 +1 @@
"use strict";(self.webpackChunkant_design_pro=self.webpackChunkant_design_pro||[]).push([[185],{9622:function(g,i,n){n.r(i);var o=n(90930),d=n(35312),r=n(9361),s=n(4393),c=n(67294),a=n(85893),l=function(){var e,u=r.Z.useToken(),_=u.token,A=(0,d.useModel)("@@initialState"),t=A.initialState;return(0,a.jsx)(o._z,{children:(0,a.jsx)(s.Z,{style:{borderRadius:8},bodyStyle:{backgroundImage:(t==null||(e=t.settings)===null||e===void 0?void 0:e.navTheme)==="realDark"?"background-image: linear-gradient(75deg, #1A1B1F 0%, #191C1F 100%)":"background-image: linear-gradient(75deg, #FBFDFF 0%, #F5F7FF 100%)"},children:(0,a.jsx)("div",{style:{backgroundPosition:"100% -30%",backgroundRepeat:"no-repeat",backgroundSize:"274px auto",backgroundImage:"url('https://gw.alipayobjects.com/mdn/rms_a9745b/afts/img/A*BuFmQqsB2iAAAAAAAAAAAAAAARQnAQ')"},children:(0,a.jsx)("div",{style:{fontSize:"20px",color:_.colorTextHeading},children:"\u6B22\u8FCE\u4F7F\u7528 Matrix"})})})})};i.default=l}}]);

10
dist/p__Welcome.845d8956.async.js

File diff suppressed because one or more lines are too long

112
dist/umi.685e7ce1.js → dist/umi.622a7616.js

File diff suppressed because one or more lines are too long

4
src/access.ts

@ -4,8 +4,8 @@
export default function access(initialState: { currentUser?: API.MatrixAdmin } | undefined) { export default function access(initialState: { currentUser?: API.MatrixAdmin } | undefined) {
const { currentUser } = initialState ?? {}; const { currentUser } = initialState ?? {};
let data = { let data = {
canAdmin: currentUser && currentUser.role && currentUser.role < 3 canAdmin: currentUser && currentUser.role && currentUser.role <= 3,
canDeviceOwner: currentUser && currentUser.role && currentUser.role > 3,
}; };
return data; return data;
} }

80
src/app.tsx

@ -1,17 +1,15 @@
import { AvatarDropdown, AvatarName, Footer, Question, SelectLang } from '@/components'; import { AvatarDropdown, AvatarName, Question, SelectLang } from '@/components';
import { current } from '@/services/matrix/admin'; import { current } from '@/services/matrix/admin';
import { LinkOutlined } from '@ant-design/icons'; import { LinkOutlined } from '@ant-design/icons';
import { MenuDataItem, SettingDrawer } from '@ant-design/pro-components'; import { MenuDataItem, SettingDrawer } from '@ant-design/pro-components';
import { history, Link } from '@umijs/max'; import { Link, history } from '@umijs/max';
import React from 'react';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import type { RunTimeLayoutConfig } from '@umijs/max';
import defaultSettings from '../config/defaultSettings'; import defaultSettings from '../config/defaultSettings';
import access from './access';
import { errorConfig } from './requestErrorConfig'; import { errorConfig } from './requestErrorConfig';
import { appList } from './services/matrix/admin'; import { appList } from './services/matrix/admin';
import access from './access';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import type { RunTimeLayoutConfig } from '@umijs/max';
const isDev = process.env.NODE_ENV === 'development'; const isDev = process.env.NODE_ENV === 'development';
const loginPath = '/user/login'; const loginPath = '/user/login';
@ -61,34 +59,56 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
}, },
request: async () => { request: async () => {
const apps = await appList(); const apps = await appList();
const menuData:MenuDataItem[] = []; const menuData: MenuDataItem[] = [];
apps.data?.forEach((x) => { apps.data?.forEach((x) => {
menuData.push({ menuData.push({
"path": "/advList/" + x.code, path: '/advList/' + x.code,
"name": x.name, name: x.name,
"component": "./AdvRecordList" access: 'canAdmin',
}) component: './AdvRecordList',
}) });
menuData.push( {
path: '/adminList', menuData.push({
name: '人员管理', path: '/app/' + x.code,
access: 'canAdmin' name: x.name,
}) access: 'canDeviceOwner',
component: './DeviceOwnerApp',
});
});
menuData.push({
path: '/adminList',
name: '人员管理',
access: 'canAdmin',
});
menuData.push({
path: '/bind',
name: '绑定设备',
access: 'canDeviceOwner',
});
return menuData; return menuData;
}, },
}, },
// 添加权限校验逻辑 // 添加权限校验逻辑
menuDataRender: (menuData) => menuDataRender: (menuData) =>
menuData.map((item) => { menuData.map((item) => {
if (item.access && !access(initialState).canAdmin) { const val = item.access;
return { if (!val) {
...item,
hideInMenu: true, // 隐藏菜单项
};
}
return item; return item;
}), }
const accessData: { [key: string]: boolean | 0 | undefined } = access(initialState);
if (!accessData[val]) {
return {
...item,
hideInMenu: true,
};
}
return item;
}),
actionsRender: () => [<Question key="doc" />, <SelectLang key="SelectLang" />], actionsRender: () => [<Question key="doc" />, <SelectLang key="SelectLang" />],
avatarProps: { avatarProps: {
// src: initialState?.currentUser?.avatar, // src: initialState?.currentUser?.avatar,
@ -97,10 +117,10 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
return <AvatarDropdown>{avatarChildren}</AvatarDropdown>; return <AvatarDropdown>{avatarChildren}</AvatarDropdown>;
}, },
}, },
waterMarkProps: { // waterMarkProps: {
content: initialState?.currentUser?.name, // content: initialState?.currentUser?.name,
}, // },
footerRender: () => <Footer />, // footerRender: () => <Footer />,
onPageChange: () => { onPageChange: () => {
const { location } = history; const { location } = history;
// 如果没有登录,重定向到 login // 如果没有登录,重定向到 login

104
src/pages/AdminManagement.tsx

@ -1,30 +1,33 @@
import { useModel } from '@umijs/max'; import { useModel } from '@umijs/max';
import { Button, Form, Input, Modal, Select, Table, Tag } from 'antd'; import { Button, Col, Form, Input, InputNumber, Modal, Row, Select, Table, Tag } from 'antd';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { adminList, appList, saveAdmin } from '../services/matrix/admin'; import { adminList, appList, saveAdmin } from '../services/matrix/admin';
const AdminManagement = () => { const AdminManagement = () => {
const [data, setData] = useState<API.MatrixAdminBo[]>([]); const [data, setData] = useState<API.MatrixAdminBo[]>([]);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [editing, setEditing] = useState(false);
const [role, setRole] = useState<number>(0);
const [form] = Form.useForm(); const [form] = Form.useForm();
const [appArr, setAppArr] = useState<API.MatrixApp[]>([]); const [appArr, setAppArr] = useState<API.MatrixApp[]>([]);
const { initialState } = useModel('@@initialState'); const { initialState } = useModel('@@initialState');
const currentUser = initialState?.currentUser; const currentUser = initialState?.currentUser;
const getAppNameById = (appId:number) => { const getAppNameById = (appId: number) => {
const app = appArr.find(app => app.id === appId); const app = appArr.find((app) => app.id === appId);
return app ? app.name : ''; return app ? app.name : '';
}; };
const handleEdit = (record:API.MatrixAdminBo) => { const handleEdit = (record: API.MatrixAdminBo) => {
form.setFieldsValue(record); form.setFieldsValue(record);
setVisible(true); setVisible(true);
setEditing(true);
setRole(record.role ? record.role : 0);
}; };
const columns: ColumnsType<API.MatrixAdminBo> = [
const columns:ColumnsType<API.MatrixAdminBo> = [
{ {
title: '姓名', title: '姓名',
dataIndex: 'name', dataIndex: 'name',
@ -33,9 +36,9 @@ const AdminManagement = () => {
{ {
title: '应用IDs', title: '应用IDs',
dataIndex: 'appIds', dataIndex: 'appIds',
render: (text:[]) => ( render: (text: []) => (
<div> <div>
{text?.map(appId => ( {text?.map((appId) => (
<Tag color="blue" key={appId}> <Tag color="blue" key={appId}>
{getAppNameById(appId)} {getAppNameById(appId)}
</Tag> </Tag>
@ -46,7 +49,7 @@ const AdminManagement = () => {
{ {
title: '角色', title: '角色',
dataIndex: 'role', dataIndex: 'role',
render: (r:number) => { render: (r: number) => {
let roleText = ''; let roleText = '';
switch (r) { switch (r) {
case 1: case 1:
@ -58,6 +61,9 @@ const AdminManagement = () => {
case 3: case 3:
roleText = '普通账号'; roleText = '普通账号';
break; break;
case 4:
roleText = '设备主';
break;
default: default:
roleText = ''; roleText = '';
} }
@ -66,13 +72,14 @@ const AdminManagement = () => {
}, },
{ {
title: '操作', title: '操作',
render: (record:API.MatrixAdminBo) => [ render: (record: API.MatrixAdminBo) => [
<a key="edit" onClick={() => handleEdit(record)}></a>, <a key="edit" onClick={() => handleEdit(record)}>
</a>,
], ],
}, },
]; ];
const handleOk = () => { const handleOk = () => {
form.submit(); form.submit();
}; };
@ -85,15 +92,15 @@ const AdminManagement = () => {
const res = await adminList(); const res = await adminList();
if (res.data) { if (res.data) {
setData(res.data); setData(res.data);
} }
}; };
const fetchApp = async() =>{ const fetchApp = async () => {
const res = await appList(); const res = await appList();
if (res.data) { if (res.data) {
setAppArr(res.data); setAppArr(res.data);
} }
} };
useEffect(() => { useEffect(() => {
fetchData(); fetchData();
@ -103,10 +110,12 @@ const AdminManagement = () => {
const handleNew = () => { const handleNew = () => {
form.resetFields(); // 重置表单字段 form.resetFields(); // 重置表单字段
setVisible(true); setVisible(true);
setEditing(false);
setRole(0);
}; };
const handleSaveAdmin = async (values: API.MatrixAdminBo) => { const handleSaveAdmin = async (values: API.MatrixAdminBo) => {
try{ try {
await saveAdmin(values); await saveAdmin(values);
} catch (e) { } catch (e) {
return; return;
@ -120,42 +129,55 @@ const AdminManagement = () => {
<Button onClick={handleNew}></Button> <Button onClick={handleNew}></Button>
<Table columns={columns} dataSource={data} /> <Table columns={columns} dataSource={data} />
<Modal <Modal title="编辑" visible={visible} onOk={handleOk} onCancel={handleCancel}>
title="编辑"
visible={visible}
onOk={handleOk}
onCancel={handleCancel}
>
<Form form={form} onFinish={handleSaveAdmin}> <Form form={form} onFinish={handleSaveAdmin}>
<Form.Item name="id" style={{ display: 'none' }}> <Form.Item name="id" style={{ display: 'none' }}>
<Input type="hidden" /> <Input type="hidden" />
</Form.Item> </Form.Item>
<Form.Item label="用户名" name="name"> <Form.Item label="用户名" name="name">
<Input /> <Input disabled={editing} />
</Form.Item> </Form.Item>
<Form.Item label="密码" name="password"> <Form.Item label="密码" name="password">
<Input.Password /> <Input.Password disabled={editing} />
</Form.Item> </Form.Item>
<Form.Item label="应用" name="appIds"> <Form.Item label="应用" name="appIds">
<Select mode="multiple"> <Select mode="multiple">
{appArr.map(app => ( {appArr.map((app) => (
<Select.Option key={app.id} value={app.id}> <Select.Option key={app.id} value={app.id}>
{app.name} {app.name}
</Select.Option> </Select.Option>
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item label="角色" name="role"> <Form.Item label="角色" name="role">
<Select> <Select disabled={editing} onSelect={setRole}>
<Select.Option disabled={currentUser?.role && currentUser.role > 1} value={2}></Select.Option> <Select.Option disabled={currentUser?.role && currentUser.role > 1} value={2}>
<Select.Option value={3}></Select.Option>
</Select.Option>
<Select.Option disabled={currentUser?.role && currentUser.role > 2} value={3}>
</Select.Option>
<Select.Option value={4}></Select.Option>
</Select> </Select>
</Form.Item> </Form.Item>
{role > 3 && (
<Row>
<Col span={12}>
<Form.Item label="收入比例" name="incomeRate">
<InputNumber placeholder="1-100整数" style={{ width: '80%' }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="设备数" name="deviceCnt">
<InputNumber style={{ width: '80%' }} />
</Form.Item>
</Col>
</Row>
)}
</Form> </Form>
</Modal> </Modal>
</div> </div>
); );
}; };
export default AdminManagement; export default AdminManagement;

19
src/pages/Bind.tsx

@ -0,0 +1,19 @@
import { PageContainer } from '@ant-design/pro-components';
import { useModel } from '@umijs/max';
import { Card, QRCode } from 'antd';
const Bind: React.FC = () => {
const { initialState } = useModel('@@initialState');
const currentUser = initialState?.currentUser;
return (
<PageContainer>
<Card>
<QRCode style={{ margin: 'auto' }} value={currentUser?.name || ''} />
<p style={{ textAlign: 'center', marginTop: '20px' }}>使app扫码绑定设备</p>
</Card>
</PageContainer>
);
};
export default Bind;

248
src/pages/DeviceOwnerApp.tsx

@ -0,0 +1,248 @@
import { advList } from '@/services/matrix/admin';
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
import { useIntl, useModel } from '@umijs/max';
import { Tabs } from 'antd';
import TabPane from 'antd/es/tabs/TabPane';
import React, { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router-dom';
// import { RequestOptionsType, ProFieldRequestData } from "@ant-design/pro-utils";
import { deviceList, offline } from '@/services/matrix/device';
import type { ActionType } from '@ant-design/pro-components';
const DeviceOwnerApp: React.FC = () => {
const actionRef = useRef<ActionType>();
const deviceRef = useRef<ActionType>();
const [usedDeviceCnt, setUsedDeviceCnt] = useState(0);
/**
* @en-US International configuration
* @zh-CN
* */
const intl = useIntl();
const { code } = useParams();
const { initialState } = useModel('@@initialState');
const currentUser = initialState?.currentUser;
const fetchDevice = async () => {
const res = await deviceList({ appCode: code ? code : '' });
setUsedDeviceCnt(res.data?.filter((device) => device.status === 0).length);
return {
data: res.data,
total: res.data?.length,
success: true,
};
};
const handleSetOffline = async (deviceId: string | undefined) => {
if (!deviceId) {
return;
}
await offline({ deviceId: deviceId });
deviceRef.current?.reload();
};
const columns: ProColumns<API.MatrixAdvRecordBo>[] = [
{
title: '设备id',
dataIndex: 'deviceId',
valueType: 'textarea',
ellipsis: true,
copyable: true,
},
{
title: '应用名称',
hideInSearch: true,
dataIndex: 'appName',
valueType: 'textarea',
},
{
title: '平台',
dataIndex: 'platform',
valueEnum: {
1: {
text: '穿山甲',
},
2: {
text: '腾讯',
},
3: {
text: '百度联盟',
},
4: {
text: 'Mintegral',
},
5: {
text: '快手',
},
6: {
text: '游可赢',
},
7: {
text: 'Sigmob',
},
8: {
text: 'Admob',
},
},
},
{
title: '广告类型',
dataIndex: 'advType',
valueEnum: {
1: {
text: '横幅',
status: 'Default',
},
2: {
text: '插页',
status: 'Processing',
},
3: {
text: '激励视频',
status: 'Success',
},
},
},
{
title: 'ecpm(元)',
dataIndex: 'ecpm',
hideInSearch: true,
renderText: (x) => {
return x / 100;
},
},
{
title: '设备品牌',
dataIndex: 'deviceBrand',
hideInSearch: true,
valueType: 'textarea',
},
{
title: '设备名',
dataIndex: 'deviceName',
hideInSearch: true,
valueType: 'textarea',
},
{
title: 'ip',
dataIndex: 'ip',
hideInSearch: true,
valueType: 'textarea',
},
{
title: '时间',
hideInSearch: true,
dataIndex: 'createdAt',
valueType: 'dateTime',
},
{
title: '时间',
hideInTable: true,
dataIndex: 'createdAt',
valueType: 'dateRange',
},
// {
// title: "应用名称",
// hideInTable: true,
// dataIndex: 'appId',
// valueType: "select",
// request: appNameMap
// }
];
const deviceColumns: ProColumns<API.MatrixAdminDevice>[] = [
{
title: '设备id',
dataIndex: 'deviceId',
valueType: 'text',
ellipsis: true,
width: 400,
copyable: true,
},
{
title: '状态',
dataIndex: 'status',
valueEnum: {
0: {
text: '正常',
},
'-1': {
text: '已下线',
},
},
filters: true,
onFilter: true,
},
{
title: '绑定时间',
hideInSearch: true,
dataIndex: 'createdAt',
valueType: 'dateTime',
},
{
title: '操作',
dataIndex: 'operation',
hideInSearch: true,
render: (_, record) => {
if (record.status === 0) {
return <a onClick={() => handleSetOffline(record.deviceId)}>线</a>;
}
return null;
},
},
];
const fetchData = async (params: any) => {
const res = await advList({ ...params, code: code });
return {
data: res.data?.data,
total: res.data?.total,
success: true,
};
};
useEffect(() => {
actionRef.current?.reload();
deviceRef.current?.reload();
}, [code]);
return (
<PageContainer>
<Tabs defaultActiveKey="1" centered style={{ backgroundColor: 'white', padding: '20px' }}>
<TabPane tab="设备列表" key="1">
<p style={{ textAlign: 'center' }}>
{'正常使用设备数:' +
usedDeviceCnt +
',剩余可绑定设备数:' +
Math.max(0, currentUser?.deviceCnt - usedDeviceCnt)}
</p>
<ProTable<API.MatrixAdminDevice>
actionRef={deviceRef}
rowKey="id"
search={false}
request={fetchDevice}
columns={deviceColumns}
/>
</TabPane>
<TabPane tab="广告详情" key="2">
<ProTable<API.MatrixAdvRecordBo, API.AdvRecordQuery>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
actionRef={actionRef}
rowKey="id"
search={{
labelWidth: 120,
}}
request={fetchData}
columns={columns}
/>
</TabPane>
</Tabs>
</PageContainer>
);
};
export default DeviceOwnerApp;

33
src/services/matrix/device.ts

@ -0,0 +1,33 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** 此处后端没有提供注释 GET /api/admin/device/list */
export async function deviceList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deviceListParams,
options?: { [key: string]: any },
) {
return request<API.RListMatrixAdminDevice>('/api/admin/device/list', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /api/admin/device/offline */
export async function offline(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.offlineParams,
options?: { [key: string]: any },
) {
return request<API.RString>('/api/admin/device/offline', {
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}

2
src/services/matrix/index.ts

@ -4,11 +4,13 @@
// API 唯一标识: // API 唯一标识:
import * as admin from './admin'; import * as admin from './admin';
import * as appController from './appController'; import * as appController from './appController';
import * as device from './device';
import * as loginController from './loginController'; import * as loginController from './loginController';
import * as matrixController from './matrixController'; import * as matrixController from './matrixController';
export default { export default {
matrixController, matrixController,
loginController, loginController,
admin, admin,
device,
appController, appController,
}; };

30
src/services/matrix/matrixController.ts

@ -17,6 +17,21 @@ export async function addWhiteList(
}); });
} }
/** 此处后端没有提供注释 POST /api/game/matrix/bindDevice */
export async function bindDevice(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.bindDeviceParams,
options?: { [key: string]: any },
) {
return request<API.RString>('/api/game/matrix/bindDevice', {
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /api/game/matrix/saveAdvRecord */ /** 此处后端没有提供注释 POST /api/game/matrix/saveAdvRecord */
export async function saveAdvRecord( export async function saveAdvRecord(
body: API.MatrixAdvRecordEditBo, body: API.MatrixAdvRecordEditBo,
@ -32,6 +47,21 @@ export async function saveAdvRecord(
}); });
} }
/** 此处后端没有提供注释 POST /api/game/matrix/saveAdvRecordV2 */
export async function saveAdvRecordV2(
body: API.MatrixAdvRecordEditBo,
options?: { [key: string]: any },
) {
return request<API.RVoid>('/api/game/matrix/saveAdvRecordV2', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /api/game/matrix/whiteList */ /** 此处后端没有提供注释 GET /api/game/matrix/whiteList */
export async function whiteList( export async function whiteList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象) // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)

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

@ -17,6 +17,7 @@ declare namespace API {
deviceId?: string; deviceId?: string;
code?: string; code?: string;
createdAt?: string[]; createdAt?: string[];
adminId?: number;
}; };
type AppInfo = { type AppInfo = {
@ -27,6 +28,12 @@ declare namespace API {
recommend?: AppInfo[]; recommend?: AppInfo[];
}; };
type bindDeviceParams = {
deviceId: string;
appCode: string;
adminName: string;
};
type CurrentUser = { type CurrentUser = {
avatarUrl?: string; avatarUrl?: string;
nickName?: string; nickName?: string;
@ -39,6 +46,10 @@ declare namespace API {
income?: number; income?: number;
}; };
type deviceListParams = {
appCode: string;
};
type getAppInfoParams = { type getAppInfoParams = {
appId?: string; appId?: string;
}; };
@ -91,6 +102,9 @@ declare namespace API {
appIds?: string; appIds?: string;
role?: number; role?: number;
channel?: string; channel?: string;
parentAdminId?: number;
deviceCnt?: number;
incomeRate?: number;
}; };
type MatrixAdminBo = { type MatrixAdminBo = {
@ -99,6 +113,18 @@ declare namespace API {
password?: string; password?: string;
appIds?: number[]; appIds?: number[];
role?: number; role?: number;
deviceCnt?: number;
incomeRate?: number;
};
type MatrixAdminDevice = {
id?: number;
deviceId?: string;
appId?: number;
adminId?: number;
status?: number;
createdAt?: string;
updatedAt?: string;
}; };
type MatrixAdvRecordBo = { type MatrixAdvRecordBo = {
@ -110,6 +136,8 @@ declare namespace API {
deviceBrand?: string; deviceBrand?: string;
deviceName?: string; deviceName?: string;
ip?: string; ip?: string;
advId?: number;
sign?: string;
appName?: string; appName?: string;
appId?: number; appId?: number;
createdAt?: number; createdAt?: number;
@ -125,6 +153,8 @@ declare namespace API {
deviceBrand?: string; deviceBrand?: string;
deviceName?: string; deviceName?: string;
ip?: string; ip?: string;
advId?: number;
sign?: string;
}; };
type MatrixApp = { type MatrixApp = {
@ -134,6 +164,11 @@ declare namespace API {
url?: string; url?: string;
income?: number; income?: number;
channel?: string; channel?: string;
secret?: string;
};
type offlineParams = {
deviceId: string;
}; };
type OverviewBo = { type OverviewBo = {
@ -194,6 +229,12 @@ declare namespace API {
data?: MatrixAdminBo[]; data?: MatrixAdminBo[];
}; };
type RListMatrixAdminDevice = {
code?: number;
message?: string;
data?: MatrixAdminDevice[];
};
type RListMatrixApp = { type RListMatrixApp = {
code?: number; code?: number;
message?: string; message?: string;

Loading…
Cancel
Save