@jiangood/open-admin 3.0.15 → 3.1.1

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 (82) hide show
  1. package/package.json +15 -2
  2. package/src/framework/biz/OrgTree.tsx +10 -6
  3. package/src/framework/biz/PermActions.tsx +5 -3
  4. package/src/framework/biz/RoleTree.tsx +10 -6
  5. package/src/framework/biz/index.tsx +1 -0
  6. package/src/framework/components/ContextMenu/index.tsx +17 -1
  7. package/src/framework/components/DownloadModal/index.tsx +40 -33
  8. package/src/framework/components/DrawerForm/index.tsx +108 -0
  9. package/src/framework/components/FormModal/index.tsx +16 -9
  10. package/src/framework/components/NamedIcon/index.tsx +2 -2
  11. package/src/framework/components/OrgSwitcher/index.tsx +6 -7
  12. package/src/framework/components/PageLoading/index.tsx +3 -3
  13. package/src/framework/components/ProTable/index.tsx +28 -25
  14. package/src/framework/components/ValueType/index.tsx +1 -1
  15. package/src/framework/components/index.ts +1 -0
  16. package/src/framework/config/themeConfig.ts +5 -5
  17. package/src/framework/fields/BaseRemoteSelect/index.tsx +23 -21
  18. package/src/framework/fields/FieldBoolean/index.tsx +6 -6
  19. package/src/framework/fields/FieldDate/index.tsx +10 -10
  20. package/src/framework/fields/FieldDateRange/index.tsx +20 -20
  21. package/src/framework/fields/FieldDictSelect/index.tsx +2 -2
  22. package/src/framework/fields/FieldEditor/index.tsx +1 -1
  23. package/src/framework/fields/FieldNumberRange/index.tsx +16 -17
  24. package/src/framework/fields/FieldPercent/index.tsx +2 -2
  25. package/src/framework/fields/FieldRemoteSelect/index.tsx +4 -4
  26. package/src/framework/fields/FieldRemoteTree/index.tsx +1 -1
  27. package/src/framework/fields/FieldRemoteTreeCascader/index.tsx +1 -1
  28. package/src/framework/fields/FieldRemoteTreeSelect/index.tsx +1 -1
  29. package/src/framework/fields/FieldSysOrgTree/index.tsx +1 -1
  30. package/src/framework/fields/FieldSysOrgTreeSelect/index.tsx +1 -1
  31. package/src/framework/fields/FieldTable/index.tsx +15 -13
  32. package/src/framework/fields/FieldTableSelect/index.tsx +5 -5
  33. package/src/framework/fields/FieldUploadFile/index.tsx +3 -3
  34. package/src/framework/fields/FieldUploadImage/index.tsx +31 -29
  35. package/src/framework/fields/types.ts +0 -2
  36. package/src/framework/router/PageFrame.tsx +1 -1
  37. package/src/framework/router/matcher.ts +2 -2
  38. package/src/framework/utils/ArrayUtils.ts +2 -2
  39. package/src/framework/utils/DateUtils.ts +1 -1
  40. package/src/framework/utils/{system/DictUtils.ts → DictUtils.ts} +1 -1
  41. package/src/framework/utils/EventBus.ts +7 -7
  42. package/src/framework/utils/HttpClient.ts +283 -0
  43. package/src/framework/utils/{system/PageUtils.ts → PageUtils.ts} +4 -4
  44. package/src/framework/utils/{system/PermUtils.ts → PermUtils.ts} +3 -3
  45. package/src/framework/utils/StringUtils.ts +10 -8
  46. package/src/framework/utils/TreeUtils.ts +3 -3
  47. package/src/framework/utils/UrlUtils.ts +2 -2
  48. package/src/framework/utils/index.ts +4 -1
  49. package/src/framework/views/ViewApproveStatus/index.tsx +1 -2
  50. package/src/framework/views/ViewBoolean/index.tsx +4 -1
  51. package/src/framework/views/ViewFile/index.tsx +4 -4
  52. package/src/framework/views/ViewImage/index.tsx +2 -2
  53. package/src/framework/views/ViewPassword/index.tsx +3 -2
  54. package/src/framework/views/ViewText/index.tsx +12 -3
  55. package/src/framework/views/types.ts +2 -4
  56. package/src/layouts/admin/AdminTabs.jsx +9 -0
  57. package/src/layouts/admin/AdminTabs.less +2 -2
  58. package/src/layouts/admin/HeaderRight.jsx +8 -7
  59. package/src/layouts/admin/TabLayout.jsx +2 -2
  60. package/src/layouts/admin/index.jsx +15 -11
  61. package/src/layouts/admin/index.less +16 -1
  62. package/src/layouts/index.tsx +24 -18
  63. package/src/pages/404.jsx +1 -1
  64. package/src/pages/article/$code.jsx +4 -4
  65. package/src/pages/index.jsx +1 -1
  66. package/src/pages/public/login.jsx +34 -27
  67. package/src/pages/public/test.jsx +1 -1
  68. package/src/pages/standalone/forceUpdatePwd.jsx +9 -7
  69. package/src/pages/system/article/index.jsx +9 -8
  70. package/src/pages/system/dict/index.jsx +19 -16
  71. package/src/pages/system/file/index.jsx +9 -9
  72. package/src/pages/system/job/index.jsx +17 -17
  73. package/src/pages/system/log/index.jsx +5 -7
  74. package/src/pages/system/org/index.jsx +31 -18
  75. package/src/pages/system/role/index.jsx +13 -12
  76. package/src/pages/system/role/rolePerm.jsx +25 -21
  77. package/src/pages/system/user/index.jsx +35 -33
  78. package/src/pages/system/user/userPerm.jsx +12 -12
  79. package/src/pages/userCenter/index.jsx +11 -9
  80. package/src/pages/userCenter/permView.jsx +7 -7
  81. package/src/framework/utils/system/HttpUtils.ts +0 -97
  82. package/src/framework/utils/system/index.ts +0 -4
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import {Layout, Menu, Skeleton, Watermark} from 'antd';
3
3
 
4
4
  import "./index.less"
5
- import {HttpUtils, NamedIcon, PageUtils, GlobalData, TreeUtils, history, Link, ARTICLE_HEADER_LEFT, OrgSwitcher} from "../../framework";
5
+ import {HttpClient, NamedIcon, PageUtils, GlobalData, TreeUtils, history, Link, ARTICLE_HEADER_LEFT, OrgSwitcher} from "../../framework";
6
6
 
7
7
  import { HeaderRight } from "./HeaderRight";
8
8
  import { TabLayout } from "./TabLayout";
@@ -10,7 +10,7 @@ const {Header, Sider, Content} = Layout;
10
10
  /**
11
11
  * 带菜单的布局,主要处理布局宇框架结构
12
12
  */
13
- export default class extends React.Component {
13
+ export default class AdminLayout extends React.Component {
14
14
 
15
15
  state = {
16
16
  loginInfo: {},
@@ -50,8 +50,8 @@ export default class extends React.Component {
50
50
 
51
51
  initMenu = () => {
52
52
  this.setState({menuLoading: true})
53
- HttpUtils.get('/admin/menu-info').then(info => {
54
- const {menuTree, pathMenuMap, menuMap} = info
53
+ HttpClient.get('/admin/menu-info', null, {toastError: false}).then(info => {
54
+ const {menuTree, pathMenuMap, menuMap} = info.data
55
55
  this.setState({menuMap})
56
56
 
57
57
  const pathname = PageUtils.currentPathname();
@@ -86,15 +86,15 @@ export default class extends React.Component {
86
86
  }
87
87
 
88
88
  this.setState({menuTree, pathMenuMap, topMenus, sideMenus, activeTopMenuKey, currentMenuKey})
89
+ this.setState({menuLoading: false})
89
90
 
90
91
  }).catch(err => {
91
92
  console.error('加载菜单失败:', err)
92
93
  this.setState({menuTree: [], topMenus: [], sideMenus: []})
93
- }).finally(()=>{
94
94
  this.setState({menuLoading: false})
95
95
  })
96
96
  }
97
- actionRef = React.createRef()
97
+ actionRef = React.createRef() // NOSONAR: React ref 由父组件通过 ref 访问
98
98
 
99
99
  classifyMenus = (menuTree) => {
100
100
  const topMenus = [];
@@ -166,13 +166,14 @@ export default class extends React.Component {
166
166
  return (
167
167
  <nav className="top-nav">
168
168
  {topMenus.map(item => (
169
- <span
169
+ <button
170
170
  key={item.key}
171
+ type="button"
171
172
  className={'top-nav-item' + (item.key === activeTopMenuKey ? ' active' : '')}
172
173
  onClick={() => this.onTopMenuClick({key: item.key})}
173
174
  >
174
175
  {item.label}
175
- </span>
176
+ </button>
176
177
  ))}
177
178
  </nav>
178
179
  );
@@ -188,7 +189,10 @@ return <Layout className='main-layout'>
188
189
  breakpoint={'md'}
189
190
  >
190
191
  <div className='sider-header'>
191
- <img className='logo-img' src="./logo.png" onClick={() => history.push('/')} alt='logo'/>
192
+ <button type="button" className='logo-img'
193
+ onClick={() => history.push('/')}>
194
+ <img src="./logo.png" alt='logo'/>
195
+ </button>
192
196
  <h3 className='hide-on-mobile'>
193
197
  <Link to="/" style={{color: 'rgba(255,255,255,0.85)'}}>{siteInfo.title}</Link>
194
198
  </h3>
@@ -201,8 +205,8 @@ return <Layout className='main-layout'>
201
205
  <Header className='header'>
202
206
  {this.renderTopMenu()}
203
207
  {this.state.headerLeftArticles.map(a => (
204
- <div key={a.code} className='item' style={{cursor: 'pointer', padding: '0 12px', whiteSpace: 'nowrap'}}
205
- onClick={() => PageUtils.open('/article/' + a.code, a.title)}>{a.title}</div>
208
+ <button key={a.code} type="button" className='item'
209
+ onClick={() => PageUtils.open('/article/' + a.code, a.title)}>{a.title}</button>
206
210
  ))}
207
211
  {this.props.showOrgSwitcher?.({
208
212
  activeTopMenu: this.getActiveTopMenu(),
@@ -27,6 +27,9 @@
27
27
  color: rgba(0, 0, 0, 0.65);
28
28
  transition: color 0.2s;
29
29
  white-space: nowrap;
30
+ background: none;
31
+ border: none;
32
+ font: inherit;
30
33
 
31
34
  &:hover {
32
35
  color: var(--primary-color, var(--primary-color, #1961AC));
@@ -50,10 +53,13 @@
50
53
  align-items: center;
51
54
  padding: 0 0.5rem;
52
55
  cursor: pointer;
56
+ background: none;
57
+ border: none;
58
+ font: inherit;
53
59
 
54
60
  &:hover {
55
61
  background: var(--primary-color-hover, #4990CD);
56
- color: white;
62
+ color: white; /* NOSONAR: 主题色悬停态,对比度由主题色决定 */
57
63
  }
58
64
  }
59
65
  }
@@ -74,6 +80,15 @@
74
80
  .logo-img {
75
81
  height: 36px;
76
82
  cursor: pointer;
83
+ background: none;
84
+ border: none;
85
+ padding: 0;
86
+ display: inline-flex;
87
+ align-items: center;
88
+
89
+ img {
90
+ height: 36px;
91
+ }
77
92
  }
78
93
 
79
94
  h3 {
@@ -3,12 +3,10 @@ import {ConfigProvider, Modal} from "antd";
3
3
  import zhCN from 'antd/locale/zh_CN';
4
4
  import dayjs from 'dayjs';
5
5
  import 'dayjs/locale/zh-cn';
6
- import {history, PageFrame} from "../framework";
6
+ import {ErrorBoundary, GlobalData, HttpClient, PageFrame, PageLoading, PageUtils, history, getThemeConfig, setThemeColors, EventBus} from "../framework";
7
+ import type {ThemeColors} from "../framework";
7
8
 
8
9
  import AdminLayout from "./admin"
9
- import {HttpUtils, PageLoading, PageUtils, GlobalData, getThemeConfig, setThemeColors, EventBus} from "../framework";
10
- import {ErrorBoundary} from "../framework";
11
- import type {ThemeColors} from "../framework";
12
10
 
13
11
  import '../style/global.less'
14
12
  import './index.less'
@@ -76,8 +74,8 @@ export class Layouts extends React.Component<LayoutsProps> {
76
74
  }
77
75
 
78
76
  loadSiteInfo() {
79
- HttpUtils.get("/admin/public/site-info").then(data => {
80
- GlobalData.setSiteInfo(data);
77
+ HttpClient.get("/admin/public/site-info", null, {toastError: false}).then(data => {
78
+ GlobalData.setSiteInfo(data.data);
81
79
  this.setState({siteInfoLoaded: true});
82
80
  }).catch(() => {
83
81
  console.error('[Layout] 加载站点信息失败');
@@ -85,12 +83,12 @@ export class Layouts extends React.Component<LayoutsProps> {
85
83
  }
86
84
 
87
85
  loadLoginInfo() {
88
- HttpUtils.get('/admin/public/login-info').then(data => {
89
- GlobalData.setDictInfo(data.dictInfo);
90
- GlobalData.setLoginInfo(data.loginInfo);
91
- GlobalData.setSiteArticles(data.siteArticles);
86
+ HttpClient.get('/admin/public/login-info', null, {toastError: false}).then(data => {
87
+ GlobalData.setDictInfo(data.data.dictInfo);
88
+ GlobalData.setLoginInfo(data.data.loginInfo);
89
+ GlobalData.setSiteArticles(data.data.siteArticles);
92
90
 
93
- if (data.needUpdatePwd) {
91
+ if (data.data.needUpdatePwd) {
94
92
  this.setState({loginChecked: true});
95
93
  history.push('/standalone/forceUpdatePwd');
96
94
  return;
@@ -116,7 +114,7 @@ export class Layouts extends React.Component<LayoutsProps> {
116
114
  this.loadData();
117
115
  }
118
116
 
119
- componentDidUpdate(prevProps: {}, prevState: typeof this.state) {
117
+ componentDidUpdate(prevProps: LayoutsProps, prevState: typeof this.state) {
120
118
  if (this.state.location !== prevState.location) {
121
119
  this.loadData();
122
120
  }
@@ -144,18 +142,26 @@ export class Layouts extends React.Component<LayoutsProps> {
144
142
  return (
145
143
  <ErrorBoundary minimal>
146
144
  <ConfigProvider {...baseConfigProps} theme={getThemeConfig()}>
147
- {showPageFrame ? <PageFrame url={pathname + search}/> : ready ? <AdminLayout headerExtra={this.props.headerExtra} showOrgSwitcher={this.props.showOrgSwitcher} loginInfo={GlobalData.getLoginInfo()}/> : (
148
- <PageLoading messages={[
149
- !siteInfoLoaded && '加载站点信息...',
150
- !loginChecked && '检查登录中...',
151
- ].filter(Boolean)}/>
152
- )}
145
+ {this.renderContent(showPageFrame, ready, pathname, search)}
153
146
  {this.renderLoginExpiredModal()}
154
147
  </ConfigProvider>
155
148
  </ErrorBoundary>
156
149
  );
157
150
  }
158
151
 
152
+ renderContent(showPageFrame: boolean, ready: boolean, pathname: string, search: string) {
153
+ if (showPageFrame) {
154
+ return <PageFrame url={pathname + search}/>;
155
+ }
156
+ if (ready) {
157
+ return <AdminLayout headerExtra={this.props.headerExtra} showOrgSwitcher={this.props.showOrgSwitcher} loginInfo={GlobalData.getLoginInfo()}/>;
158
+ }
159
+ return <PageLoading messages={[
160
+ !this.state.siteInfoLoaded && '加载站点信息...',
161
+ !this.state.loginChecked && '检查登录中...',
162
+ ].filter(Boolean)}/>;
163
+ }
164
+
159
165
  renderLoginExpiredModal() {
160
166
  return (
161
167
  <Modal open={this.state.loginExpiredVisible} title="确认操作" okText="确定"
package/src/pages/404.jsx CHANGED
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import {Result} from "antd";
3
3
  import {Page} from "../framework";
4
4
 
5
- export default class extends React.Component {
5
+ export default class NotFound extends React.Component {
6
6
 
7
7
  render() {
8
8
  return <Page>
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
- import {HttpUtils, Page, UrlUtils} from "../../framework";
2
+ import {HttpClient, Page, UrlUtils} from "../../framework";
3
3
  import "./article.less";
4
4
 
5
- export default class extends React.Component {
5
+ export default class ArticlePage extends React.Component {
6
6
 
7
7
  state = {
8
8
  article: null,
@@ -12,8 +12,8 @@ export default class extends React.Component {
12
12
  componentDidMount() {
13
13
  const code = this.props.params?.code
14
14
  if (code) {
15
- HttpUtils.get('admin/article/getByCode', {code}).then(rs => {
16
- this.setState({article: rs, loading: false})
15
+ HttpClient.get('admin/article/getByCode', {code}, {toastError: false}).then(rs => {
16
+ this.setState({article: rs.data, loading: false})
17
17
  }).catch(() => {
18
18
  this.setState({loading: false})
19
19
  })
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import {Card} from "antd";
3
3
  import {Page} from "../framework";
4
4
 
5
- export default class extends React.Component {
5
+ export default class HomePage extends React.Component {
6
6
  render() {
7
7
  return <Page title="首页" description="欢迎使用本系统">
8
8
  <Card>欢迎使用本系统</Card>
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import {Button, Form, Input, message} from 'antd';
3
3
  import {LockOutlined, UserOutlined, WarningOutlined} from '@ant-design/icons';
4
- import {EventBus, HttpUtils, GlobalData, history} from "../../framework";
4
+ import {EventBus, HttpClient, GlobalData, history} from "../../framework";
5
5
 
6
6
  import "./login.less"
7
7
 
@@ -13,54 +13,61 @@ function getRedirect(query) {
13
13
  return redirect;
14
14
  }
15
15
 
16
- function postLogin(values, query) {
17
- return new Promise((resolve, reject) => {
18
- HttpUtils.post('/admin/auth/login', values).then(rs => {
19
- EventBus.emit('loginSuccess')
20
- history.push(getRedirect(query))
21
- resolve(rs)
22
- }).catch(e => {
23
- console.error('[Login] 登录失败:', e);
24
- reject(e)
25
- })
16
+ function postLogin(values, query, success, error) {
17
+ HttpClient.post('/admin/auth/login', values, null, {toastError: false}).then(rs => {
18
+ EventBus.emit('loginSuccess')
19
+ history.push(getRedirect(query))
20
+ success?.(rs)
21
+ }).catch(e => {
22
+ console.error('[Login] 登录失败:', e);
23
+ message.error(HttpClient.errToMsg(e))
24
+ error?.(e)
26
25
  })
27
26
  }
28
27
 
29
28
  function encodePassword(pwd) {
30
29
  const chars = [];
31
30
  for (let i = 0; i < pwd.length; i++)
32
- chars.push(pwd.charCodeAt(i) + i + 2);
33
- return btoa(String.fromCharCode(...chars));
31
+ chars.push(pwd.codePointAt(i) + i + 2);
32
+ return btoa(String.fromCodePoint(...chars));
34
33
  }
35
34
 
36
- export default class extends React.Component {
35
+ export default class LoginPage extends React.Component {
37
36
 
38
37
  state = {
39
38
  logging: false,
40
39
  siteInfo: {}
41
40
  }
42
41
 
43
- async componentDidMount() {
42
+ componentDidMount() {
44
43
  const siteInfo = GlobalData.getSiteInfo()
45
- if (siteInfo && siteInfo.title) {
44
+ if (siteInfo?.title) {
46
45
  this.setState({siteInfo})
47
46
  return
48
47
  }
49
48
  // localStorage 中无站点信息,从服务端重新加载
50
- try {
51
- const rs = await HttpUtils.get('/admin/public/site-info', null, { showError: false })
52
- GlobalData.setSiteInfo(rs)
53
- this.setState({siteInfo: rs})
54
- } catch (e) {
55
- console.error('[Login] 加载站点信息失败:', e);
49
+ HttpClient.get('/admin/public/site-info', null, {toastError: false}).then(rs => {
50
+ GlobalData.setSiteInfo(rs.data)
51
+ this.setState({siteInfo: rs.data})
52
+ }).catch(() => {
53
+ console.error('[Login] 加载站点信息失败');
56
54
  message.error('加载站点信息失败,请刷新页面重试')
57
- }
55
+ })
58
56
  }
59
57
 
60
58
  submit = values => {
61
59
  this.setState({logging: true})
62
- values.password = encodePassword(values.password)
63
- postLogin(values, this.props.location?.query).finally(() => {
60
+ try {
61
+ values.password = encodePassword(values.password)
62
+ } catch (e) {
63
+ console.error('[Login] 密码编码失败:', e);
64
+ this.setState({logging: false})
65
+ message.error('密码含不支持字符,请联系管理员重置')
66
+ return
67
+ }
68
+ postLogin(values, this.props.location?.query, () => {
69
+ this.setState({logging: false})
70
+ }, () => {
64
71
  this.setState({logging: false})
65
72
  })
66
73
  }
@@ -76,14 +83,14 @@ export default class extends React.Component {
76
83
  <section className='login-page' style={pageStyle}>
77
84
  <div className="login-content">
78
85
  <h1>{siteInfo.title}</h1>
79
- {this.getForm(siteInfo)}
86
+ {this.getForm()}
80
87
  {this.renderFormBottom()}
81
88
  </div>
82
89
  </section>
83
90
  );
84
91
  }
85
92
 
86
- getForm = siteInfo => {
93
+ getForm = () => {
87
94
  const form = (
88
95
  <Form
89
96
  name="normal_login"
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import {Page} from "../../framework";
3
3
  import {Button, message, Modal, Space} from "antd";
4
4
 
5
- export default class extends React.Component {
5
+ export default class TestPage extends React.Component {
6
6
 
7
7
  state = {
8
8
  modalOpen:false
@@ -1,19 +1,20 @@
1
1
  import React from "react";
2
2
  import {Button, Form, Input, message} from "antd";
3
- import {HttpUtils, history} from "../../framework";
3
+ import {HttpClient, history} from "../../framework";
4
4
 
5
- export default class extends React.Component {
5
+ export default class ForceUpdatePwdPage extends React.Component {
6
6
 
7
7
  onFinish = (values) => {
8
- HttpUtils.post('admin/userCenter/update-pwd', values).then(() => {
8
+ HttpClient.post('admin/userCenter/update-pwd', values, null).then(() => {
9
9
  message.success('修改密码成功,请重新登录');
10
10
  history.push('/public/login');
11
11
  })
12
12
  }
13
13
 
14
- validator = (rule, value) => {
15
- return HttpUtils.get("admin/sysUser/pwd-strength", {password: value}, {showError: false})
16
- }
14
+ validator = (rule, value) => HttpClient.get("admin/sysUser/pwd-strength", {password: value}, {toastError: false})
15
+ .catch(e => {
16
+ throw new Error(e.message)
17
+ })
17
18
 
18
19
  render() {
19
20
  return (
@@ -42,10 +43,11 @@ export default class extends React.Component {
42
43
  extra={'请输入字母、数字、特殊字符'}
43
44
  rules={[
44
45
  {required: true, message: '请输入新密码'},
46
+ {pattern: /^[\x20-\x7E]{1,64}$/, message: '密码仅支持英文、数字与常见符号,长度不超过64位'},
45
47
  {validator: this.validator}
46
48
  ]}
47
49
  >
48
- <Input.Password/>
50
+ <Input.Password maxLength={64}/>
49
51
  </Form.Item>
50
52
  <Form.Item style={{marginTop: 40}}>
51
53
  <Button type="primary" htmlType="submit" block size='large'>
@@ -8,7 +8,7 @@ import {
8
8
  FieldEditor,
9
9
  FieldUploadImage,
10
10
  FormModal,
11
- HttpUtils,
11
+ HttpClient,
12
12
  Page,
13
13
  PageUtils,
14
14
  PermActions,
@@ -16,7 +16,7 @@ import {
16
16
  ViewImage
17
17
  } from "../../../framework";
18
18
 
19
- export default class extends React.Component {
19
+ export default class ArticleListPage extends React.Component {
20
20
 
21
21
  state = {
22
22
  editing: false,
@@ -42,12 +42,12 @@ export default class extends React.Component {
42
42
  onFinish = async values => {
43
43
  const isNew = !values.id;
44
44
  const url = isNew ? 'admin/article/create' : 'admin/article/update';
45
- await HttpUtils.post(url, values)
45
+ await HttpClient.post(url, values)
46
46
  this.tableRef.current.reload()
47
47
  }
48
48
 
49
49
  handleDelete = record => {
50
- HttpUtils.post('admin/article/delete', {id: record.id}).then(rs => {
50
+ HttpClient.post('admin/article/delete', {id: record.id}, null).then(() => {
51
51
  this.tableRef.current.reload()
52
52
  })
53
53
  }
@@ -84,7 +84,8 @@ export default class extends React.Component {
84
84
  title: '启用',
85
85
  dataIndex: 'enabled',
86
86
  render(v) {
87
- return v == null ? null : (v ? '是' : '否')
87
+ if (v == null) return null;
88
+ return v ? '是' : '否';
88
89
  },
89
90
  },
90
91
  {
@@ -111,14 +112,14 @@ export default class extends React.Component {
111
112
  >
112
113
  <ProTable
113
114
  actionRef={this.tableRef}
114
- toolBarRender={() => (
115
+ toolBarRender={() => ( // NOSONAR: AntD 渲染函数惯例
115
116
  <PermActions>
116
117
  <Button perm='article:create' type='primary' icon={<PlusOutlined/>} onClick={this.handleAdd}>新增</Button>
117
118
  </PermActions>
118
119
  )}
119
- request={(params) => HttpUtils.get('admin/article/page', params)}
120
+ request={(params) => HttpClient.get('admin/article/page', params)}
120
121
  columns={this.columns}
121
- searchFormRender={() => (
122
+ searchFormRender={() => ( // NOSONAR: AntD 渲染函数惯例
122
123
  <>
123
124
  <Form.Item label='编码' name='code'>
124
125
  <Input/>
@@ -5,7 +5,7 @@ import {
5
5
  PermActions,
6
6
  FieldBoolean,
7
7
  FormModal,
8
- HttpUtils,
8
+ HttpClient,
9
9
  Page,
10
10
  ProTable,
11
11
  ViewSwitch,
@@ -23,7 +23,7 @@ const COLOR_OPTIONS = [
23
23
  {value: 'GRAY', label: '灰色'},
24
24
  ]
25
25
 
26
- export default class extends React.Component {
26
+ export default class DictPage extends React.Component {
27
27
 
28
28
  state = {
29
29
  typeTree: [],
@@ -42,9 +42,10 @@ export default class extends React.Component {
42
42
 
43
43
  loadTree = () => {
44
44
  this.setState({treeLoading: true})
45
- HttpUtils.get('admin/dict/type-tree').then(rs => {
46
- this.setState({typeTree: rs})
47
- }).finally(() => {
45
+ HttpClient.get('admin/dict/type-tree', null, {toastError: false}).then(rs => {
46
+ this.setState({typeTree: rs.data})
47
+ this.setState({treeLoading: false})
48
+ }).catch(() => {
48
49
  this.setState({treeLoading: false})
49
50
  })
50
51
  }
@@ -62,7 +63,7 @@ export default class extends React.Component {
62
63
  handleTypeDelete = () => {
63
64
  const {selectedType} = this.state
64
65
  if (!selectedType) return
65
- HttpUtils.post('admin/dict/type-delete', {id: selectedType.id}).then(() => {
66
+ HttpClient.post('admin/dict/type-delete', {id: selectedType.id}, null).then(() => {
66
67
  this.setState({selectedType: null, selectedTypeCode: null})
67
68
  this.loadTree()
68
69
  })
@@ -71,7 +72,7 @@ export default class extends React.Component {
71
72
  handleTypeFormFinish = async values => {
72
73
  const isNew = !values.id
73
74
  const url = isNew ? 'admin/dict/type-create' : 'admin/dict/type-update'
74
- await HttpUtils.post(url, values)
75
+ await HttpClient.post(url, values)
75
76
  this.loadTree()
76
77
  }
77
78
 
@@ -98,11 +99,13 @@ export default class extends React.Component {
98
99
  this.setState({selectedType: null, selectedTypeCode: null})
99
100
  return
100
101
  }
101
- const node = this.findNode(this.state.typeTree, selectedKeys[0])
102
- this.setState({
103
- selectedType: node,
104
- selectedTypeCode: node?.typeCode || null
105
- },()=>this.tableRef.current.reload())
102
+ this.setState((prevState) => {
103
+ const node = this.findNode(prevState.typeTree, selectedKeys[0])
104
+ return {
105
+ selectedType: node,
106
+ selectedTypeCode: node?.typeCode || null
107
+ }
108
+ }, () => this.tableRef.current.reload())
106
109
  }
107
110
 
108
111
  handleItemAdd = () => {
@@ -114,7 +117,7 @@ export default class extends React.Component {
114
117
  }
115
118
 
116
119
  handleItemDelete = row => {
117
- HttpUtils.post('admin/dict/delete', row).then(rs => {
120
+ HttpClient.post('admin/dict/delete', row, null).then(() => {
118
121
  this.tableRef.current.reload()
119
122
  })
120
123
  }
@@ -122,7 +125,7 @@ export default class extends React.Component {
122
125
  onItemFormFinish = async values => {
123
126
  const isNew = !values.id
124
127
  const url = isNew ? 'admin/dict/create' : 'admin/dict/update'
125
- await HttpUtils.post(url, values)
128
+ await HttpClient.post(url, values)
126
129
  this.tableRef.current.reload()
127
130
  }
128
131
 
@@ -220,7 +223,7 @@ export default class extends React.Component {
220
223
  actionRef={this.tableRef}
221
224
  request={(params) => {
222
225
  params.typeCode = selectedTypeCode
223
- return HttpUtils.get('admin/dict/page', params)
226
+ return HttpClient.get('admin/dict/page', params)
224
227
  }}
225
228
  columns={this.columns}
226
229
  />
@@ -266,7 +269,7 @@ export default class extends React.Component {
266
269
  allowClear
267
270
  maxLength={20}
268
271
  options={COLOR_OPTIONS}
269
- filterOption={(input, option) =>
272
+ filterOption={(input, option) => // NOSONAR: AntD AutoComplete 过滤回调惯例
270
273
  (option.value + option.label).toLowerCase().includes(input.toLowerCase())
271
274
  }
272
275
  placeholder='如 SUCCESS、#ff0000'
@@ -2,9 +2,9 @@ import React from 'react'
2
2
  import {Button, Form, Input, Modal, Space} from 'antd'
3
3
  import {CloudUploadOutlined} from "@ant-design/icons";
4
4
 
5
- import {PermActions, DictUtils, FieldDateRange, FieldDictSelect, FieldUploadFile, HttpUtils, Page, ProTable, UrlUtils, ViewImage} from "../../../framework";
5
+ import {PermActions, DictUtils, FieldDateRange, FieldDictSelect, FieldUploadFile, HttpClient, Page, ProTable, UrlUtils, ViewImage} from "../../../framework";
6
6
 
7
- export default class extends React.Component {
7
+ export default class FilePage extends React.Component {
8
8
 
9
9
  state = {
10
10
  formOpen: false,
@@ -15,13 +15,13 @@ export default class extends React.Component {
15
15
  formRef = React.createRef()
16
16
 
17
17
  handleDelete = row => {
18
- HttpUtils.post('admin/sysFile/delete', {value: row.objectName}).then(rs => {
18
+ HttpClient.post('admin/sysFile/delete', {value: row.objectName}, null).then(() => {
19
19
  this.tableRef.current.reload()
20
20
  })
21
21
  }
22
22
 
23
23
  handleBatchDelete = ids => {
24
- HttpUtils.post('admin/sysFile/deleteBatch', ids).then(rs => {
24
+ HttpClient.post('admin/sysFile/deleteBatch', ids, null).then(() => {
25
25
  this.tableRef.current.reload()
26
26
  this.tableRef.current.clearSelection()
27
27
  })
@@ -32,7 +32,7 @@ export default class extends React.Component {
32
32
  title: '缩略图',
33
33
  dataIndex: 'objectName',
34
34
  width: 80,
35
- render: (objectName, record) => {
35
+ render: (objectName, record) => { // NOSONAR: 返回元素或占位文本,类型不同属预期
36
36
  if (record.type !== 'image') {
37
37
  return '-'
38
38
  }
@@ -151,12 +151,12 @@ export default class extends React.Component {
151
151
  <ProTable
152
152
  actionRef={this.tableRef}
153
153
  rowSelection={{}}
154
- toolBarRender={(params, selection) => (
154
+ toolBarRender={(params, selection) => ( // NOSONAR: AntD 渲染函数惯例
155
155
  <Space>
156
156
  <Button type='primary' icon={<CloudUploadOutlined/>} onClick={() => this.setState({formOpen: true})}>上传文件</Button>
157
157
  <PermActions
158
158
  actions={[{
159
- label: `批量删除${selection.selectedRowKeys.length ? `(${selection.selectedRowKeys.length})` : ''}`,
159
+ label: '批量删除' + (selection.selectedRowKeys.length ? `(${selection.selectedRowKeys.length})` : ''),
160
160
  perm: 'sys-file:delete',
161
161
  danger: true,
162
162
  disabled: !selection.selectedRowKeys.length,
@@ -167,11 +167,11 @@ export default class extends React.Component {
167
167
  </Space>
168
168
  )}
169
169
  request={(params) => {
170
- return HttpUtils.get('admin/sysFile/page', params);
170
+ return HttpClient.get('admin/sysFile/page', params);
171
171
  }}
172
172
 
173
173
  columns={this.columns}
174
- searchFormRender={() => (
174
+ searchFormRender={() => ( // NOSONAR: AntD 渲染函数惯例
175
175
  <>
176
176
  <Form.Item label='文件名' name='originName'>
177
177
  <Input/>