@jiangood/open-admin 2.0.1 → 2.2.5

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 (47) hide show
  1. package/config/common-plugin.js +51 -0
  2. package/config/config.js +1 -56
  3. package/package.json +5 -2
  4. package/src/.umi-production/appData.json +73 -100
  5. package/src/.umi-production/umi.ts +2 -2
  6. package/src/framework/components/DownloadFileButton/index.tsx +1 -1
  7. package/src/framework/components/OrgTree/index.tsx +1 -1
  8. package/src/framework/components/Page/index.less +1 -1
  9. package/src/framework/components/Page/index.tsx +19 -22
  10. package/src/framework/components/PageLoading/index.tsx +5 -3
  11. package/src/framework/components/ProModal/index.tsx +2 -2
  12. package/src/framework/components/ProTable/components/ToolBar/index.tsx +1 -1
  13. package/src/framework/fields/FieldEditor/index.tsx +3 -2
  14. package/src/framework/fields/FieldRemoteTreeSelect/index.tsx +3 -3
  15. package/src/framework/fields/FieldRemoteTreeSelectMultiple/index.tsx +3 -3
  16. package/src/framework/fields/FieldUploadFile/index.tsx +8 -4
  17. package/src/framework/utils/MessageUtils.tsx +21 -99
  18. package/src/framework/utils/system/HttpUtils.ts +5 -1
  19. package/src/framework/utils/system/SysUtils.ts +8 -0
  20. package/src/framework/utils/system/ThemeUtils.ts +37 -12
  21. package/src/framework/views/ViewFile/index.tsx +1 -1
  22. package/src/framework/views/ViewProcessInstanceProgress/index.tsx +1 -0
  23. package/src/layouts/PageRender.tsx +29 -0
  24. package/src/layouts/admin/HeaderRight.jsx +1 -0
  25. package/src/layouts/admin/TabPageRender.jsx +138 -158
  26. package/src/layouts/admin/index.jsx +123 -19
  27. package/src/layouts/admin/index.less +124 -6
  28. package/src/layouts/index.jsx +94 -161
  29. package/src/pages/404.jsx +7 -5
  30. package/src/pages/about.jsx +3 -3
  31. package/src/pages/index.jsx +4 -5
  32. package/src/pages/login.jsx +18 -9
  33. package/src/pages/login.less +0 -1
  34. package/src/pages/system/dict/index.jsx +8 -11
  35. package/src/pages/system/file/index.jsx +6 -6
  36. package/src/pages/system/job/index.jsx +26 -11
  37. package/src/pages/system/log/index.jsx +4 -5
  38. package/src/pages/system/manual/index.jsx +8 -6
  39. package/src/pages/system/org/index.jsx +4 -2
  40. package/src/pages/system/role/index.jsx +16 -14
  41. package/src/pages/system/role/perm.jsx +3 -4
  42. package/src/pages/system/user/UserPerm.jsx +1 -1
  43. package/src/pages/system/user/index.jsx +9 -7
  44. package/src/pages/userCenter/index.jsx +2 -2
  45. package/src/pages/userCenter/message.jsx +4 -2
  46. package/src/layouts/PageRender.d.ts +0 -22
  47. package/src/layouts/PageRender.jsx +0 -90
@@ -5,7 +5,6 @@
5
5
  "@types/lodash": "^4.17.23",
6
6
  "@types/react": "^19.2.2",
7
7
  "@types/react-dom": "^19.0.0",
8
- "@umijs/plugins": "^4.3.17",
9
8
  "babel-plugin-react-compiler": "^1.0.0",
10
9
  "typescript": "^6.0.3"
11
10
  },
@@ -24,6 +23,10 @@
24
23
  "umi": "^4.0.0"
25
24
  },
26
25
  "name": "@jiangood/open-admin",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/jiangood/open-admin"
29
+ },
27
30
  "description": "open-admin",
28
31
  "files": [
29
32
  "src/*",
@@ -36,7 +39,7 @@
36
39
  "dev": "umi dev",
37
40
  "build": "umi build"
38
41
  },
39
- "version": "2.0.1"
42
+ "version": "2.2.5"
40
43
  },
41
44
  "pkgPath": "/home/runner/work/open-admin/open-admin/web/package.json",
42
45
  "plugins": {
@@ -79,7 +82,7 @@
79
82
  0
80
83
  ]
81
84
  },
82
- "register": 2
85
+ "register": 3
83
86
  },
84
87
  "enableBy": "register"
85
88
  },
@@ -93,7 +96,7 @@
93
96
  "time": {
94
97
  "hooks": {
95
98
  "onStart": [
96
- 1
99
+ 0
97
100
  ]
98
101
  },
99
102
  "register": 2
@@ -113,7 +116,7 @@
113
116
  0
114
117
  ]
115
118
  },
116
- "register": 1
119
+ "register": 0
117
120
  },
118
121
  "enableBy": "register"
119
122
  },
@@ -140,10 +143,10 @@
140
143
  "time": {
141
144
  "hooks": {
142
145
  "modifyAppData": [
143
- 58
146
+ 59
144
147
  ]
145
148
  },
146
- "register": 21
149
+ "register": 23
147
150
  },
148
151
  "enableBy": "register"
149
152
  },
@@ -190,7 +193,7 @@
190
193
  "time": {
191
194
  "hooks": {
192
195
  "onCheck": [
193
- 1
196
+ 0
194
197
  ]
195
198
  },
196
199
  "register": 1
@@ -223,7 +226,7 @@
223
226
  0
224
227
  ]
225
228
  },
226
- "register": 5
229
+ "register": 6
227
230
  },
228
231
  "enableBy": "register"
229
232
  },
@@ -1089,7 +1092,7 @@
1089
1092
  "time": {
1090
1093
  "hooks": {
1091
1094
  "onStart": [
1092
- 0
1095
+ 1
1093
1096
  ]
1094
1097
  },
1095
1098
  "register": 0
@@ -1118,7 +1121,7 @@
1118
1121
  "config": {},
1119
1122
  "time": {
1120
1123
  "hooks": {},
1121
- "register": 98
1124
+ "register": 100
1122
1125
  },
1123
1126
  "enableBy": "register"
1124
1127
  },
@@ -1158,7 +1161,7 @@
1158
1161
  "time": {
1159
1162
  "hooks": {
1160
1163
  "modifyAppData": [
1161
- 0
1164
+ 1
1162
1165
  ]
1163
1166
  },
1164
1167
  "register": 0
@@ -1212,7 +1215,7 @@
1212
1215
  "config": {},
1213
1216
  "time": {
1214
1217
  "hooks": {},
1215
- "register": 0
1218
+ "register": 1
1216
1219
  },
1217
1220
  "enableBy": "config"
1218
1221
  },
@@ -1421,7 +1424,7 @@
1421
1424
  "config": {},
1422
1425
  "time": {
1423
1426
  "hooks": {},
1424
- "register": 3
1427
+ "register": 2
1425
1428
  },
1426
1429
  "enableBy": "config"
1427
1430
  },
@@ -1434,7 +1437,7 @@
1434
1437
  "config": {},
1435
1438
  "time": {
1436
1439
  "hooks": {},
1437
- "register": 0
1440
+ "register": 1
1438
1441
  },
1439
1442
  "enableBy": "config"
1440
1443
  },
@@ -1459,7 +1462,7 @@
1459
1462
  "config": {},
1460
1463
  "time": {
1461
1464
  "hooks": {},
1462
- "register": 20
1465
+ "register": 21
1463
1466
  },
1464
1467
  "enableBy": "config"
1465
1468
  },
@@ -1472,7 +1475,7 @@
1472
1475
  "config": {},
1473
1476
  "time": {
1474
1477
  "hooks": {},
1475
- "register": 1
1478
+ "register": 0
1476
1479
  }
1477
1480
  },
1478
1481
  "./node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent": {
@@ -1563,7 +1566,7 @@
1563
1566
  "config": {},
1564
1567
  "time": {
1565
1568
  "hooks": {},
1566
- "register": 0
1569
+ "register": 1
1567
1570
  },
1568
1571
  "enableBy": "config"
1569
1572
  },
@@ -1588,7 +1591,7 @@
1588
1591
  "config": {},
1589
1592
  "time": {
1590
1593
  "hooks": {},
1591
- "register": 3
1594
+ "register": 2
1592
1595
  }
1593
1596
  },
1594
1597
  "./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad": {
@@ -1612,7 +1615,7 @@
1612
1615
  "config": {},
1613
1616
  "time": {
1614
1617
  "hooks": {},
1615
- "register": 2
1618
+ "register": 1
1616
1619
  },
1617
1620
  "enableBy": "config"
1618
1621
  },
@@ -1638,7 +1641,7 @@
1638
1641
  "config": {},
1639
1642
  "time": {
1640
1643
  "hooks": {},
1641
- "register": 3
1644
+ "register": 4
1642
1645
  },
1643
1646
  "enableBy": "register"
1644
1647
  },
@@ -1651,7 +1654,7 @@
1651
1654
  "config": {},
1652
1655
  "time": {
1653
1656
  "hooks": {},
1654
- "register": 45
1657
+ "register": 44
1655
1658
  },
1656
1659
  "enableBy": "register"
1657
1660
  },
@@ -1664,7 +1667,7 @@
1664
1667
  "config": {},
1665
1668
  "time": {
1666
1669
  "hooks": {},
1667
- "register": 16
1670
+ "register": 17
1668
1671
  }
1669
1672
  },
1670
1673
  "./node_modules/@umijs/preset-umi/dist/commands/help": {
@@ -1702,7 +1705,7 @@
1702
1705
  "config": {},
1703
1706
  "time": {
1704
1707
  "hooks": {},
1705
- "register": 1
1708
+ "register": 0
1706
1709
  },
1707
1710
  "enableBy": "register"
1708
1711
  },
@@ -1715,7 +1718,7 @@
1715
1718
  "config": {},
1716
1719
  "time": {
1717
1720
  "hooks": {},
1718
- "register": 0
1721
+ "register": 1
1719
1722
  },
1720
1723
  "enableBy": "register"
1721
1724
  },
@@ -1728,7 +1731,7 @@
1728
1731
  "config": {},
1729
1732
  "time": {
1730
1733
  "hooks": {},
1731
- "register": 1
1734
+ "register": 0
1732
1735
  },
1733
1736
  "enableBy": "register"
1734
1737
  },
@@ -1741,7 +1744,7 @@
1741
1744
  "config": {},
1742
1745
  "time": {
1743
1746
  "hooks": {},
1744
- "register": 1
1747
+ "register": 2
1745
1748
  },
1746
1749
  "enableBy": "register"
1747
1750
  },
@@ -1754,7 +1757,7 @@
1754
1757
  "config": {},
1755
1758
  "time": {
1756
1759
  "hooks": {},
1757
- "register": 1
1760
+ "register": 0
1758
1761
  },
1759
1762
  "enableBy": "register"
1760
1763
  },
@@ -1767,7 +1770,7 @@
1767
1770
  "config": {},
1768
1771
  "time": {
1769
1772
  "hooks": {},
1770
- "register": 0
1773
+ "register": 1
1771
1774
  },
1772
1775
  "enableBy": "register"
1773
1776
  },
@@ -1780,7 +1783,7 @@
1780
1783
  "config": {},
1781
1784
  "time": {
1782
1785
  "hooks": {},
1783
- "register": 1
1786
+ "register": 0
1784
1787
  },
1785
1788
  "enableBy": "register"
1786
1789
  },
@@ -1793,7 +1796,7 @@
1793
1796
  "config": {},
1794
1797
  "time": {
1795
1798
  "hooks": {},
1796
- "register": 0
1799
+ "register": 1
1797
1800
  },
1798
1801
  "enableBy": "register"
1799
1802
  },
@@ -1819,7 +1822,7 @@
1819
1822
  "config": {},
1820
1823
  "time": {
1821
1824
  "hooks": {},
1822
- "register": 1
1825
+ "register": 0
1823
1826
  },
1824
1827
  "enableBy": "register"
1825
1828
  },
@@ -1832,7 +1835,7 @@
1832
1835
  "config": {},
1833
1836
  "time": {
1834
1837
  "hooks": {},
1835
- "register": 0
1838
+ "register": 1
1836
1839
  },
1837
1840
  "enableBy": "register"
1838
1841
  },
@@ -1845,7 +1848,7 @@
1845
1848
  "config": {},
1846
1849
  "time": {
1847
1850
  "hooks": {},
1848
- "register": 1
1851
+ "register": 0
1849
1852
  },
1850
1853
  "enableBy": "register"
1851
1854
  },
@@ -1858,7 +1861,7 @@
1858
1861
  "config": {},
1859
1862
  "time": {
1860
1863
  "hooks": {},
1861
- "register": 0
1864
+ "register": 1
1862
1865
  },
1863
1866
  "enableBy": "register"
1864
1867
  },
@@ -1910,7 +1913,7 @@
1910
1913
  "config": {},
1911
1914
  "time": {
1912
1915
  "hooks": {},
1913
- "register": 20
1916
+ "register": 22
1914
1917
  },
1915
1918
  "enableBy": "register"
1916
1919
  },
@@ -1961,8 +1964,12 @@
1961
1964
  "key": "open-admin",
1962
1965
  "config": {},
1963
1966
  "time": {
1964
- "hooks": {},
1965
- "register": 6
1967
+ "hooks": {
1968
+ "modifyConfig": [
1969
+ 0
1970
+ ]
1971
+ },
1972
+ "register": 7
1966
1973
  },
1967
1974
  "enableBy": "register"
1968
1975
  }
@@ -1973,34 +1980,9 @@
1973
1980
  "_": []
1974
1981
  },
1975
1982
  "userConfig": {
1976
- "hash": true,
1977
- "history": {
1978
- "type": "hash"
1979
- },
1980
- "mfsu": false,
1981
- "esbuildMinifyIIFE": true,
1982
1983
  "plugins": [
1983
1984
  "./config/common-plugin"
1984
- ],
1985
- "proxy": {
1986
- "/admin": {
1987
- "target": "http://127.0.0.1:8080",
1988
- "changeOrigin": true
1989
- },
1990
- "/preview": {
1991
- "target": "http://127.0.0.1:8080",
1992
- "changeOrigin": true
1993
- },
1994
- "/ureport": {
1995
- "target": "http://127.0.0.1:8080",
1996
- "changeOrigin": true
1997
- },
1998
- "/admin/ws": {
1999
- "target": "ws://127.0.0.1:8080",
2000
- "changeOrigin": true,
2001
- "ws": true
2002
- }
2003
- }
1985
+ ]
2004
1986
  },
2005
1987
  "mainConfigFile": "/home/runner/work/open-admin/open-admin/web/config/config.js",
2006
1988
  "config": {
@@ -2013,7 +1995,7 @@
2013
1995
  },
2014
1996
  "base": "/",
2015
1997
  "svgr": {},
2016
- "publicPath": "/",
1998
+ "publicPath": "./",
2017
1999
  "mfsu": false,
2018
2000
  "ignoreMomentLocale": true,
2019
2001
  "externals": {},
@@ -2028,32 +2010,23 @@
2028
2010
  "@@": "/home/runner/work/open-admin/open-admin/web/src/.umi-production",
2029
2011
  "regenerator-runtime": "/home/runner/work/open-admin/open-admin/web/node_modules/regenerator-runtime"
2030
2012
  },
2031
- "hash": true,
2032
- "esbuildMinifyIIFE": true,
2033
2013
  "plugins": [
2034
2014
  "./config/common-plugin"
2035
2015
  ],
2016
+ "targets": {
2017
+ "chrome": 80
2018
+ },
2019
+ "define": {
2020
+ "SERVLET_CONTEXT": "/change-this-servlet-context"
2021
+ },
2022
+ "hash": true,
2023
+ "esbuildMinifyIIFE": true,
2036
2024
  "proxy": {
2037
- "/admin": {
2038
- "target": "http://127.0.0.1:8080",
2039
- "changeOrigin": true
2040
- },
2041
- "/preview": {
2025
+ "/change-this-servlet-context": {
2042
2026
  "target": "http://127.0.0.1:8080",
2043
- "changeOrigin": true
2044
- },
2045
- "/ureport": {
2046
- "target": "http://127.0.0.1:8080",
2047
- "changeOrigin": true
2048
- },
2049
- "/admin/ws": {
2050
- "target": "ws://127.0.0.1:8080",
2051
2027
  "changeOrigin": true,
2052
2028
  "ws": true
2053
2029
  }
2054
- },
2055
- "targets": {
2056
- "chrome": 80
2057
2030
  }
2058
2031
  },
2059
2032
  "routes": {
@@ -2063,7 +2036,7 @@
2063
2036
  "parentId": "@@/global-layout",
2064
2037
  "file": "404.jsx",
2065
2038
  "absPath": "/*",
2066
- "__content": "import React from \"react\";\nimport {Result} from \"antd\";\n\nexport default class extends React.Component {\n\n render() {\n return <Result\n status={404}\n title='页面不存在'\n />\n\n }\n}\n",
2039
+ "__content": "import React from \"react\";\nimport {Result} from \"antd\";\nimport {Page} from \"../framework\";\n\nexport default class extends React.Component {\n\n render() {\n return <Page>\n <Result\n status={404}\n title='页面不存在'\n />\n </Page>\n }\n}\n",
2067
2040
  "__isJSFile": true,
2068
2041
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/404.jsx"
2069
2042
  },
@@ -2083,7 +2056,7 @@
2083
2056
  "parentId": "@@/global-layout",
2084
2057
  "file": "system/user/UserPerm.jsx",
2085
2058
  "absPath": "/system/user/UserPerm",
2086
- "__content": "import {Form, Modal} from 'antd';\nimport React from 'react';\nimport {FieldDictSelect, FieldRemoteSelectMultiple, FieldSysOrgTree, HttpUtils} from \"../../../framework\";\n\n\nexport default class UserPerm extends React.Component {\n\n\n state = {\n visible: false,\n\n confirmLoading: false,\n\n formValues: {\n dataPermType: null\n },\n }\n formRef = React.createRef()\n\n show(item) {\n this.setState({visible: true})\n\n HttpUtils.get('admin/sysUser/get-perm-info', {id: item.id}).then(rs => {\n this.setState({formValues: rs})\n this.formRef.current.setFieldsValue(rs)\n })\n }\n\n handleSave = (values) => {\n values.grantOrgIdList = this.state.checked\n\n this.setState({\n confirmLoading: true\n })\n\n\n HttpUtils.post('admin/sysUser/grant-perm', values).then(rs => {\n this.setState({\n visible: false,\n confirmLoading: false\n })\n this.props.onOk()\n }).finally(() => {\n this.setState({\n confirmLoading: false\n })\n\n })\n }\n\n render() {\n const {visible, confirmLoading} = this.state\n\n return <Modal\n title=\"授权\"\n destroyOnClose\n width={600}\n open={visible}\n confirmLoading={confirmLoading}\n onCancel={() => this.setState({visible: false})}\n onOk={() => this.formRef.current.submit()}\n >\n\n <Form ref={this.formRef}\n onFinish={this.handleSave}\n onValuesChange={(change, values) => {\n this.setState({formValues: values})\n }}\n labelCol={{flex: '100px'}}\n >\n <Form.Item name='id' noStyle></Form.Item>\n <Form.Item label='角色' name='roleIds' rules={[{required: true}]}>\n <FieldRemoteSelectMultiple url='admin/sysRole/options'/>\n </Form.Item>\n <Form.Item label='数据权限' name='dataPermType' rules={[{required: true}]}>\n <FieldDictSelect typeCode='dataPermType'/>\n </Form.Item>\n\n\n {this.state.formValues.dataPermType === 'CUSTOM' && <>\n <Form.Item label='组织机构' name='orgIds'>\n <FieldSysOrgTree/>\n </Form.Item>\n </>}\n\n\n </Form>\n\n\n </Modal>\n }\n\n\n}\n",
2059
+ "__content": "import {Form, Modal} from 'antd';\nimport React from 'react';\nimport {FieldDictSelect, FieldRemoteSelectMultiple, FieldSysOrgTree, HttpUtils} from \"../../../framework\";\n\n\nexport default class UserPerm extends React.Component {\n\n\n state = {\n visible: false,\n\n confirmLoading: false,\n\n formValues: {\n dataPermType: null\n },\n }\n formRef = React.createRef()\n\n show(item) {\n this.setState({visible: true})\n\n HttpUtils.get('admin/sysUser/get-perm-info', {id: item.id}).then(rs => {\n this.setState({formValues: rs})\n this.formRef.current.setFieldsValue(rs)\n })\n }\n\n handleSave = (values) => {\n values.grantOrgIdList = this.state.checked\n\n this.setState({\n confirmLoading: true\n })\n\n\n HttpUtils.post('admin/sysUser/grant-perm', values).then(rs => {\n this.setState({\n visible: false,\n confirmLoading: false\n })\n this.props.onOk()\n }).finally(() => {\n this.setState({\n confirmLoading: false\n })\n\n })\n }\n\n render() {\n const {visible, confirmLoading} = this.state\n\n return <Modal\n title=\"授权\"\n destroyOnHidden\n width={600}\n open={visible}\n confirmLoading={confirmLoading}\n onCancel={() => this.setState({visible: false})}\n onOk={() => this.formRef.current.submit()}\n >\n\n <Form ref={this.formRef}\n onFinish={this.handleSave}\n onValuesChange={(change, values) => {\n this.setState({formValues: values})\n }}\n labelCol={{flex: '100px'}}\n >\n <Form.Item name='id' noStyle></Form.Item>\n <Form.Item label='角色' name='roleIds' rules={[{required: true}]}>\n <FieldRemoteSelectMultiple url='admin/sysRole/options'/>\n </Form.Item>\n <Form.Item label='数据权限' name='dataPermType' rules={[{required: true}]}>\n <FieldDictSelect typeCode='dataPermType'/>\n </Form.Item>\n\n\n {this.state.formValues.dataPermType === 'CUSTOM' && <>\n <Form.Item label='组织机构' name='orgIds'>\n <FieldSysOrgTree/>\n </Form.Item>\n </>}\n\n\n </Form>\n\n\n </Modal>\n }\n\n\n}\n",
2087
2060
  "__isJSFile": true,
2088
2061
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/user/UserPerm.jsx"
2089
2062
  },
@@ -2093,7 +2066,7 @@
2093
2066
  "parentId": "@@/global-layout",
2094
2067
  "file": "system/manual/index.jsx",
2095
2068
  "absPath": "/system/manual",
2096
- "__content": "import {PlusOutlined} from '@ant-design/icons'\nimport {Button, Form, Input, Modal, Popconfirm} from 'antd'\nimport React from 'react'\nimport {ButtonList, FieldUploadFile, HttpUtils, Page, ProTable} from \"../../../framework\";\n\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false\n }\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n this.setState({formOpen: true, formValues: record})\n }\n\n onFinish = values => {\n HttpUtils.post('admin/sysManual/save', values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n handleDelete = record => {\n HttpUtils.post('admin/sysManual/delete', {id: record.id}).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n\n {\n title: '名称',\n dataIndex: 'name',\n\n\n },\n\n {\n title: '版本',\n dataIndex: 'version',\n render(version) {\n return 'v' + version;\n }\n },\n\n {\n title: '文件',\n dataIndex: 'fileId',\n render(id) {\n const url = 'admin/sysFile/preview/' + id;\n return <a href={url} target='_blank'>查看文件</a>\n }\n\n },\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => (\n <ButtonList>\n <Button size='small' perm='sysManual:save' onClick={() => this.handleEdit(record)}>编辑</Button>\n <Popconfirm perm='sysManual:delete' title='是否确定删除操作手册'\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>\n ),\n },\n\n ]\n\n render() {\n return <Page>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={(params, {selectedRows, selectedRowKeys}) => {\n return <ButtonList>\n <Button perm='sysManual:save' type='primary' onClick={this.handleAdd}>\n <PlusOutlined/> 新增\n </Button>\n </ButtonList>\n }}\n request={(params) => HttpUtils.get('admin/sysManual/page', params)}\n columns={this.columns}\n\n />\n\n <Modal title='操作手册'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnClose\n maskClosable={false}\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}\n >\n <Form.Item name='id' noStyle></Form.Item>\n\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n <Form.Item label='文件' name='fileId' rules={[{required: true}]}>\n <FieldUploadFile accept=\".pdf\" maxCount={1}/>\n </Form.Item>\n\n </Form>\n </Modal>\n </Page>\n\n\n }\n}\n\n\n",
2069
+ "__content": "import {PlusOutlined} from '@ant-design/icons'\nimport {Button, Form, Input, Modal, Popconfirm} from 'antd'\nimport React from 'react'\nimport {ButtonList, FieldUploadFile, HttpUtils, Page, ProTable} from \"../../../framework\";\n\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false\n }\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n this.setState({formOpen: true, formValues: record})\n }\n\n onFinish = values => {\n const isNew = !values.id;\n const url = isNew ? 'admin/sysManual/create' : 'admin/sysManual/update';\n HttpUtils.post(url, values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n handleDelete = record => {\n HttpUtils.post('admin/sysManual/delete', {id: record.id}).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n\n {\n title: '名称',\n dataIndex: 'name',\n\n\n },\n\n {\n title: '版本',\n dataIndex: 'version',\n render(version) {\n return 'v' + version;\n }\n },\n\n {\n title: '文件',\n dataIndex: 'fileId',\n render(id) {\n const url = 'admin/sysFile/preview/' + id;\n return <a href={url} target='_blank'>查看文件</a>\n }\n\n },\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => (\n <ButtonList>\n <Button size='small' perm='sys-manual:update' onClick={() => this.handleEdit(record)}>编辑</Button>\n <Popconfirm perm='sys-manual:delete' title='是否确定删除操作手册'\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>\n ),\n },\n\n ]\n\n render() {\n return <Page>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={(params, {selectedRows, selectedRowKeys}) => {\n return <ButtonList>\n <Button perm='sys-manual:create' type='primary' onClick={this.handleAdd}>\n <PlusOutlined/> 新增\n </Button>\n </ButtonList>\n }}\n request={(params) => HttpUtils.get('admin/sysManual/page', params)}\n columns={this.columns}\n\n />\n\n <Modal title='操作手册'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnHidden\n mask={{ closable: false }}\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}\n >\n <Form.Item name='id' noStyle></Form.Item>\n\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n <Form.Item label='文件' name='fileId' rules={[{required: true}]}>\n <FieldUploadFile accept=\".pdf\" maxCount={1}/>\n </Form.Item>\n\n </Form>\n </Modal>\n </Page>\n\n\n }\n}\n\n\n",
2097
2070
  "__isJSFile": true,
2098
2071
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/manual/index.jsx"
2099
2072
  },
@@ -2103,7 +2076,7 @@
2103
2076
  "parentId": "@@/global-layout",
2104
2077
  "file": "userCenter/message.jsx",
2105
2078
  "absPath": "/userCenter/message",
2106
- "__content": "import React from \"react\";\nimport {Button, Card, Tabs, Tag} from \"antd\";\nimport {ProTable} from \"../../framework\";\n\nexport default class extends React.Component {\n\n tableRef = React.createRef()\n\n read = (record) => {\n HttpUtils.post(\"admin/user/msg/read\", record).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n {\n title: '时间',\n dataIndex: 'createTime',\n width: 150\n },\n {\n title: '标题',\n dataIndex: 'title',\n },\n {\n title: '内容',\n dataIndex: 'content',\n render(content, row) {\n return <div dangerouslySetInnerHTML={{__html: content}}/>\n }\n },\n {\n title: '已读时间',\n dataIndex: 'readTime',\n width: 150\n },\n {\n title: '状态',\n dataIndex: 'isRead',\n render: (v, row) => {\n return v == true ? <Tag color='green'>已读</Tag> : <Tag color='red'>未读</Tag>;\n },\n width: 80\n },\n\n {\n title: '-',\n dataIndex: 'option',\n render: (read, row) => {\n if (!row.isRead)\n return <Button size='small' onClick={() => this.read(row)}> 标记已读 </Button>\n }, width: 80\n }\n ]\n\n render() {\n return <Card variant={\"borderless\"}>\n\n <Tabs defaultActiveKey=\"0\" destroyOnClose\n >\n <Tabs.TabPane key='0' tab='所有消息'>\n <ProTable\n actionRef={this.tableRef}\n request={(params) => HttpUtils.get(\"admin/user/msg/page\", params)}\n columns={this.columns}\n toolbarOptions={{showSearch: false}}\n size='small'\n />\n </Tabs.TabPane>\n <Tabs.TabPane key='1' tab='未读消息'>\n <ProTable\n actionRef={this.tableRef}\n request={(params) => HttpUtils.get(\"admin/user/msg/page?read=false\", params)}\n columns={this.columns}\n rowSelection={false}\n rowKey='id'\n toolbarOptions={{showSearch: false}}\n size='small'\n />\n\n\n </Tabs.TabPane>\n <Tabs.TabPane key='2' tab='已读消息'>\n\n <ProTable\n actionRef={this.tableRef}\n request={(params) => HttpUtils.get(\"admin/user/msg/page?read=true\", params)}\n rowSelection={false}\n rowKey='id'\n toolbarOptions={{showSearch: false}}\n options={false}\n size='small'\n columns={this.columns}\n />\n\n\n </Tabs.TabPane>\n\n </Tabs>\n\n </Card>\n }\n}\n",
2079
+ "__content": "import React from \"react\";\nimport {Button, Card, Tabs, Tag} from \"antd\";\nimport {HttpUtils, Page, ProTable} from \"../../framework\";\n\nexport default class extends React.Component {\n\n tableRef = React.createRef()\n\n read = (record) => {\n HttpUtils.post(\"admin/user/msg/read\", record).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n {\n title: '时间',\n dataIndex: 'createTime',\n width: 150\n },\n {\n title: '标题',\n dataIndex: 'title',\n },\n {\n title: '内容',\n dataIndex: 'content',\n render(content, row) {\n return <div dangerouslySetInnerHTML={{__html: content}}/>\n }\n },\n {\n title: '已读时间',\n dataIndex: 'readTime',\n width: 150\n },\n {\n title: '状态',\n dataIndex: 'isRead',\n render: (v, row) => {\n return v == true ? <Tag color='green'>已读</Tag> : <Tag color='red'>未读</Tag>;\n },\n width: 80\n },\n\n {\n title: '-',\n dataIndex: 'option',\n render: (read, row) => {\n if (!row.isRead)\n return <Button size='small' onClick={() => this.read(row)}> 标记已读 </Button>\n }, width: 80\n }\n ]\n\n render() {\n return <Page>\n <Card variant={\"borderless\"}>\n\n <Tabs defaultActiveKey=\"0\" destroyOnClose\n >\n <Tabs.TabPane key='0' tab='所有消息'>\n <ProTable\n actionRef={this.tableRef}\n request={(params) => HttpUtils.get(\"admin/user/msg/page\", params)}\n columns={this.columns}\n toolbarOptions={{showSearch: false}}\n size='small'\n />\n </Tabs.TabPane>\n <Tabs.TabPane key='1' tab='未读消息'>\n <ProTable\n actionRef={this.tableRef}\n request={(params) => HttpUtils.get(\"admin/user/msg/page?read=false\", params)}\n columns={this.columns}\n rowSelection={false}\n rowKey='id'\n toolbarOptions={{showSearch: false}}\n size='small'\n />\n\n\n </Tabs.TabPane>\n <Tabs.TabPane key='2' tab='已读消息'>\n\n <ProTable\n actionRef={this.tableRef}\n request={(params) => HttpUtils.get(\"admin/user/msg/page?read=true\", params)}\n rowSelection={false}\n rowKey='id'\n toolbarOptions={{showSearch: false}}\n options={false}\n size='small'\n columns={this.columns}\n />\n\n\n </Tabs.TabPane>\n\n </Tabs>\n\n </Card>\n </Page>\n }\n}\n",
2107
2080
  "__isJSFile": true,
2108
2081
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/userCenter/message.jsx"
2109
2082
  },
@@ -2113,7 +2086,7 @@
2113
2086
  "parentId": "@@/global-layout",
2114
2087
  "file": "system/dict/index.jsx",
2115
2088
  "absPath": "/system/dict",
2116
- "__content": "import React from \"react\";\nimport {Button, Form, Input, InputNumber, Modal, Popconfirm, Splitter, Tag, Tree, Typography} from \"antd\";\nimport {PlusOutlined} from \"@ant-design/icons\";\n\nimport {\n ButtonList,\n FieldBoolean, FieldDictSelect, FieldRemoteSelect,\n HttpUtils,\n Page,\n ProTable,\n ViewBooleanEnableDisable, ViewText\n} from \"../../../framework\";\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false\n }\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n\n\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n this.setState({formOpen: true, formValues: record})\n }\n\n onFinish = values => {\n HttpUtils.post('admin/dict/save', values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n handleDelete = row => {\n HttpUtils.post('admin/dict/delete', row).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n {\n title: '类型标签',\n dataIndex: 'typeLabel',\n },\n {\n title: '类型编码',\n dataIndex: 'typeCode',\n },\n {\n title: '标签',\n dataIndex: 'label',\n },\n {\n title: '编码',\n dataIndex: 'code',\n },\n\n {\n title: '启用',\n dataIndex: 'enabled',\n render(v) {\n return <ViewBooleanEnableDisable value={v}/>\n }\n\n },\n {\n title: '显示颜色',\n dataIndex: 'color',\n render(v) {\n if (v) {\n return <Tag color={v.toLowerCase()}>{v}</Tag>\n }\n\n }\n },\n\n {\n title: '序号',\n dataIndex: 'seq',\n },\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => {\n if(!record.id){ // 非数据库定义的不让修改\n return\n }\n\n return (\n <ButtonList>\n <Button size='small' perm='sysDict:save'\n onClick={() => this.handleEdit(record)}> 编辑 </Button>\n <Popconfirm perm='sysDict:delete' title='是否确定删除字典项'\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>\n );\n },\n },\n ]\n\n render() {\n return <Page padding>\n <ProTable\n rowKey='uid'\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button perm='sysDict:save' type='primary' onClick={this.handleAdd} >\n <PlusOutlined/> 新增\n </Button>\n </ButtonList>\n }}\n request={(params) => {\n params.typeCode = this.state.typeCode\n return HttpUtils.get('admin/dict/page', params);\n }}\n columns={this.columns}\n showToolbarSearch={true}\n scrollY={500}\n />\n <Modal\n title='编辑数据字典项'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnClose\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}>\n <Form.Item name='id' noStyle></Form.Item>\n <Form.Item label='类型' name='color' rules={[{required: true}]} >\n <ViewText />\n </Form.Item>\n <Form.Item label='类型' name='typeCode' rules={[{required: true}]} >\n <FieldRemoteSelect url='/admin/dict/type-options' />\n </Form.Item>\n <Form.Item label='编码' name='code' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n <Form.Item label='标签' name='label' rules={[{required: true}]} help='显示文本'>\n <Input/>\n </Form.Item>\n <Form.Item label='颜色' name='color' rules={[{required: true}]}>\n <FieldDictSelect typeCode='statusColor' />\n </Form.Item>\n <Form.Item label='序号' name='seq' rules={[{required: true}]}>\n <InputNumber/>\n </Form.Item>\n\n <Form.Item label='启用' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n\n </Form>\n </Modal>\n </Page>\n\n\n }\n\n\n}\n",
2089
+ "__content": "import React from \"react\";\nimport {Button, Form, Input, InputNumber, Modal, Popconfirm, Splitter, Tag, Tree, Typography} from \"antd\";\nimport {PlusOutlined} from \"@ant-design/icons\";\n\nimport {\n ButtonList,\n FieldBoolean, FieldDictSelect, FieldRemoteSelect,\n HttpUtils,\n Page,\n ProTable,\n ViewBooleanEnableDisable, ViewText\n} from \"../../../framework\";\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false\n }\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n\n\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n this.setState({formOpen: true, formValues: record})\n }\n\n onFinish = values => {\n const isNew = !values.id;\n const url = isNew ? 'admin/dict/create' : 'admin/dict/update';\n HttpUtils.post(url, values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n handleDelete = row => {\n HttpUtils.post('admin/dict/delete', row).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n {\n title: '类型标签',\n dataIndex: 'typeLabel',\n },\n {\n title: '类型编码',\n dataIndex: 'typeCode',\n },\n {\n title: '标签',\n dataIndex: 'label',\n },\n {\n title: '编码',\n dataIndex: 'code',\n },\n\n {\n title: '启用',\n dataIndex: 'enabled',\n render(v) {\n return <ViewBooleanEnableDisable value={v}/>\n }\n\n },\n {\n title: '显示颜色',\n dataIndex: 'color',\n render(v) {\n if (v) {\n return <Tag color={v.toLowerCase()}>{v}</Tag>\n }\n\n }\n },\n\n {\n title: '序号',\n dataIndex: 'seq',\n },\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => {\n return (\n <ButtonList>\n <Button size='small' perm='sys-dict:update'\n onClick={() => this.handleEdit(record)}> 编辑 </Button>\n <Popconfirm perm='sys-dict:delete' title='是否确定删除字典项'\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>\n );\n },\n },\n ]\n\n render() {\n return <Page>\n <ProTable\n rowKey='uid'\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button perm='sys-dict:create' type='primary' onClick={this.handleAdd} >\n <PlusOutlined/> 新增\n </Button>\n </ButtonList>\n }}\n request={(params) => {\n params.typeCode = this.state.typeCode\n return HttpUtils.get('admin/dict/page', params);\n }}\n columns={this.columns}\n showToolbarSearch={true}\n />\n <Modal\n title='编辑数据字典项'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnHidden\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}>\n <Form.Item name='id' noStyle></Form.Item>\n <Form.Item label='类型' name='color' rules={[{required: true}]} >\n <ViewText />\n </Form.Item>\n <Form.Item label='类型' name='typeCode' rules={[{required: true}]} >\n <FieldRemoteSelect url='/admin/dict/type-options' />\n </Form.Item>\n <Form.Item label='编码' name='code' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n <Form.Item label='标签' name='label' rules={[{required: true}]} help='显示文本'>\n <Input/>\n </Form.Item>\n <Form.Item label='颜色' name='color' rules={[{required: true}]}>\n <FieldDictSelect typeCode='statusColor' />\n </Form.Item>\n <Form.Item label='序号' name='seq' rules={[{required: true}]}>\n <InputNumber/>\n </Form.Item>\n\n <Form.Item label='启用' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n\n </Form>\n </Modal>\n </Page>\n\n\n }\n\n\n}\n",
2117
2090
  "__isJSFile": true,
2118
2091
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/dict/index.jsx"
2119
2092
  },
@@ -2123,7 +2096,7 @@
2123
2096
  "parentId": "@@/global-layout",
2124
2097
  "file": "system/file/index.jsx",
2125
2098
  "absPath": "/system/file",
2126
- "__content": "import React from 'react'\nimport {Button, Form, Input, Modal, Popconfirm} from 'antd'\nimport {CloudUploadOutlined} from \"@ant-design/icons\";\n\nimport {ButtonList, FieldDateRange, FieldDictSelect, FieldUploadFile, HttpUtils, ProTable} from \"../../../framework\";\n\nexport default class extends React.Component {\n\n state = {\n formOpen: false,\n formValues: {}\n }\n\n tableRef = React.createRef()\n formRef = React.createRef()\n\n handleDelete = row => {\n HttpUtils.post('admin/sysFile/delete', row).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n {\n title: '原始名称',\n tooltip: '上传时候的文件名',\n dataIndex: 'originName',\n width: 200,\n },\n {\n title: '存储名称',\n dataIndex: 'objectName',\n tooltip: '文件唯一标识id'\n },\n\n {\n title: '文件大小',\n dataIndex: 'sizeInfo',\n },\n\n {\n title: 'mime',\n dataIndex: 'mimeType',\n },\n {\n title: '扩展名',\n dataIndex: 'suffix',\n },\n\n {\n title: '上传时间',\n dataIndex: 'createTime',\n },\n {\n title: '上传者',\n dataIndex: 'createUserLabel',\n },\n {\n title: '预览',\n dataIndex: 'id',\n render(id, record) {\n const nodes = [<a href={'/admin/sysFile/preview/' + record.id} target='_blank'>预览</a>]\n\n\n if (record.imageUrls?.length > 0) {\n for (let item of record.imageUrls) {\n const url = item.url;\n const label = item.label;\n nodes.push(<a href={(url)} target='_blank' style={{marginLeft: 8}}>{label}</a>)\n }\n }\n\n return nodes;\n\n }\n },\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => (\n <ButtonList>\n <Popconfirm perm='sysFile:delete' title='是否确定删除文件信息'\n onConfirm={() => this.handleDelete(record)}>\n <a>删除</a>\n </Popconfirm>\n </ButtonList>\n ),\n },\n ]\n\n render() {\n return <>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <Button type='primary' icon={<CloudUploadOutlined/>}\n onClick={() => this.setState({formOpen: true})}>\n 上传文件\n </Button>\n }}\n request={(params) => {\n return HttpUtils.get('admin/sysFile/page', params);\n }}\n\n columns={this.columns}\n\n >\n <Form.Item label='文件名' name='originName'>\n <Input/>\n </Form.Item>\n <Form.Item label='对象名称' name='objectName'>\n <Input/>\n </Form.Item>\n <Form.Item label='类型' name='type'>\n <FieldDictSelect typeCode='materialType'/>\n </Form.Item>\n\n <Form.Item label='上传时间' name='dateRange'>\n <FieldDateRange/>\n </Form.Item>\n </ProTable>\n\n <Modal open={this.state.formOpen} title='上传文件'\n width={800}\n onCancel={() => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n }}\n footer={null}\n destroyOnClose\n >\n <Form ref={this.formRef}\n initialValues={this.state.formValues}\n >\n <Form.Item name='文件'>\n <FieldUploadFile accept=\"*/*\"/>\n </Form.Item>\n\n\n </Form>\n </Modal>\n\n </>\n }\n}\n\n\n\n",
2099
+ "__content": "import React from 'react'\nimport {Button, Form, Input, Modal, Popconfirm} from 'antd'\nimport {CloudUploadOutlined} from \"@ant-design/icons\";\n\nimport {ButtonList, FieldDateRange, FieldDictSelect, FieldUploadFile, HttpUtils, Page, ProTable, SysUtils} from \"../../../framework\";\n\nexport default class extends React.Component {\n\n state = {\n formOpen: false,\n formValues: {}\n }\n\n tableRef = React.createRef()\n formRef = React.createRef()\n\n handleDelete = row => {\n HttpUtils.post('admin/sysFile/delete', row).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n {\n title: '原始名称',\n tooltip: '上传时候的文件名',\n dataIndex: 'originName',\n width: 200,\n },\n {\n title: '存储名称',\n dataIndex: 'objectName',\n tooltip: '文件唯一标识id'\n },\n\n {\n title: '文件大小',\n dataIndex: 'sizeInfo',\n },\n\n {\n title: 'mime',\n dataIndex: 'mimeType',\n },\n {\n title: '扩展名',\n dataIndex: 'suffix',\n },\n\n {\n title: '上传时间',\n dataIndex: 'createTime',\n },\n {\n title: '上传者',\n dataIndex: 'createUserLabel',\n },\n {\n title: '预览',\n dataIndex: 'id',\n render(id, record) {\n const nodes = [<a href={SysUtils.contextPath('/admin/sysFile/preview/' + record.id)} target='_blank'>预览</a>]\n\n\n if (record.imageUrls?.length > 0) {\n for (let item of record.imageUrls) {\n const url = item.url;\n const label = item.label;\n nodes.push(<a href={(url)} target='_blank' style={{marginLeft: 8}}>{label}</a>)\n }\n }\n\n return nodes;\n\n }\n },\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => (\n <ButtonList>\n <Popconfirm perm='sys-file:delete' title='是否确定删除文件信息'\n onConfirm={() => this.handleDelete(record)}>\n <a>删除</a>\n </Popconfirm>\n </ButtonList>\n ),\n },\n ]\n\n render() {\n return <Page>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <Button type='primary' icon={<CloudUploadOutlined/>}\n onClick={() => this.setState({formOpen: true})}>\n 上传文件\n </Button>\n }}\n request={(params) => {\n return HttpUtils.get('admin/sysFile/page', params);\n }}\n\n columns={this.columns}\n\n >\n <Form.Item label='文件名' name='originName'>\n <Input/>\n </Form.Item>\n <Form.Item label='对象名称' name='objectName'>\n <Input/>\n </Form.Item>\n <Form.Item label='类型' name='type'>\n <FieldDictSelect typeCode='materialType'/>\n </Form.Item>\n\n <Form.Item label='上传时间' name='dateRange'>\n <FieldDateRange/>\n </Form.Item>\n </ProTable>\n\n <Modal open={this.state.formOpen} title='上传文件'\n width={800}\n onCancel={() => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n }}\n footer={null}\n destroyOnHidden\n >\n <Form ref={this.formRef}\n initialValues={this.state.formValues}\n >\n <Form.Item name='文件'>\n <FieldUploadFile accept=\"*/*\"/>\n </Form.Item>\n\n\n </Form>\n </Modal>\n\n </Page>\n }\n}\n\n\n\n",
2127
2100
  "__isJSFile": true,
2128
2101
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/file/index.jsx"
2129
2102
  },
@@ -2133,7 +2106,7 @@
2133
2106
  "parentId": "@@/global-layout",
2134
2107
  "file": "system/role/index.jsx",
2135
2108
  "absPath": "/system/role",
2136
- "__content": "import {PlusOutlined} from '@ant-design/icons'\nimport {Button, Form, Input, InputNumber, Modal, Popconfirm, Transfer, Tree} from 'antd'\nimport React from 'react'\nimport {ButtonList, FieldBoolean, HttpUtils, Page, PageUtils, ProTable, ViewText} from \"../../../framework\";\n\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false,\n\n usersModalOpen: false,\n\n\n userList: [],\n targetKeys: [],\n selectedKeys: [],\n\n menuOpen: false,\n menuTree: [],\n menuTreeLoading: false,\n menuChecked: [],\n menuHalfChecked: []\n }\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n this.setState({formOpen: true, formValues: record}, () => {\n\n })\n }\n\n handleEditUser = record => {\n this.setState({usersModalOpen: true, formValues: record})\n HttpUtils.get('admin/sysRole/user-list', {id: record.id}).then(rs => {\n this.setState({userList: rs.list, targetKeys: rs.selectedKeys})\n })\n }\n\n onFinish = values => {\n HttpUtils.post('admin/sysRole/save', values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n handleDelete = record => {\n HttpUtils.post('admin/sysRole/delete', {id: record.id}).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n\n {\n title: '名称',\n dataIndex: 'name',\n\n\n },\n\n {\n title: '编号',\n dataIndex: 'code',\n\n\n },\n\n {\n title: '排序',\n dataIndex: 'seq',\n\n\n },\n\n {\n title: '备注',\n dataIndex: 'remark',\n\n\n },\n\n {\n title: '启用',\n dataIndex: 'enabled',\n\n\n render(v) {\n return v == null ? null : (v ? '是' : '否')\n },\n\n\n },\n {\n title: '是否内置',\n dataIndex: 'builtin',\n\n\n render(v) {\n return v == null ? null : (v ? '是' : '否')\n },\n\n\n },\n\n {\n title: '权限码',\n dataIndex: 'perms',\n width: 300,\n render(v) {\n if (v) {\n return <ViewText value={v.join(',')} ellipsis={true} />\n }\n }\n\n },\n\n\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => {\n\n return (\n <ButtonList>\n <Button size='small' perm='sysRole:manage'\n onClick={() => this.handleEditUser(record)}>用户设置</Button>\n\n <Button size='small' perm='sysRole:manage' disabled={record.builtin}\n onClick={() => PageUtils.open('/system/role/perm?id=' + record.id, '角色权限设置')}>权限设置</Button>\n\n <Button size='small' perm='sysRole:manage' disabled={record.builtin}\n onClick={() => this.handleEdit(record)}>编辑</Button>\n <Popconfirm perm='sysRole:manage' disabled={record.builtin} title='是否确定删除系统角色'\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>\n );\n },\n },\n ]\n\n handleSaveUsers = () => {\n const params = {\n id: this.state.formValues.id,\n userIdList: this.state.targetKeys\n }\n HttpUtils.post('admin/sysRole/grant-users', params).then(rs => {\n this.setState({usersModalOpen: false})\n })\n }\n\n handleEditMenu = (record) => {\n this.setState({menuOpen: true, formValues: record, menuTreeLoading: true})\n HttpUtils.get('admin/sysRole/ownMenu', {id: record.id}).then(rs => {\n this.setState({menuChecked: rs.checked, menuHalfChecked: rs.halfChecked})\n })\n HttpUtils.get('admin/sysRole/menuTree').then(rs => {\n this.setState({menuTree: rs, menuTreeLoading: false})\n })\n }\n handleGrantMenu = () => {\n const params = {\n id: this.state.formValues.id,\n menuIds: [...this.state.menuChecked, ...this.state.menuHalfChecked]\n }\n HttpUtils.post('admin/sysRole/grantMenu', params).then(rs => {\n this.setState({menuOpen: false})\n })\n }\n\n render() {\n return <Page padding>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button perm='sysRole:manage' type='primary' onClick={this.handleAdd}>\n <PlusOutlined/> 新增\n </Button>\n </ButtonList>\n }}\n request={(params) => HttpUtils.get('admin/sysRole/page', params)}\n columns={this.columns}\n\n />\n\n <Modal title='系统角色'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnClose\n maskClosable={false}\n width={600}\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}\n >\n <Form.Item name='id' noStyle></Form.Item>\n\n\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n <Form.Item label='编码' name='code' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label='排序' name='seq'>\n <InputNumber/>\n </Form.Item>\n\n\n <Form.Item label='备注' name='remark'>\n <Input/>\n </Form.Item>\n\n <Form.Item label='启用' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n\n\n </Form>\n </Modal>\n\n\n <Modal title={'角色用户' + \"【\" + this.state.formValues?.name + '】'}\n open={this.state.usersModalOpen}\n destroyOnClose\n maskClosable={false}\n width={800}\n onCancel={() => this.setState({usersModalOpen: false})}\n onOk={this.handleSaveUsers}\n >\n\n\n <Transfer\n listStyle={{height: '60vh', width: 300}}\n\n dataSource={this.state.userList} titles={[\"未选择\", \"已选择\"]}\n targetKeys={this.state.targetKeys}\n selectedKeys={this.state.selectedKeys}\n render={item => item.title}\n onChange={(nextTargetKeys, direction, moveKeys) => {\n this.setState({\n targetKeys: nextTargetKeys\n })\n }}\n onSelectChange={(sourceSelectedKeys, targetSelectedKeys) => {\n this.setState({\n selectedKeys: [...sourceSelectedKeys, ...targetSelectedKeys]\n })\n }}\n showSearch\n />\n\n\n </Modal>\n\n <Modal title={'角色授权菜单权限' + \"【\" + this.state.formValues?.name + '】'}\n open={this.state.menuOpen}\n destroyOnClose\n maskClosable={false}\n width={800}\n onCancel={() => this.setState({menuOpen: false})}\n onOk={this.handleGrantMenu}\n loading={this.state.menuTreeLoading}\n >\n <Tree\n height={600}\n treeData={this.state.menuTree}\n multiple\n checkable\n checkedKeys={{checked: this.state.menuChecked}}\n onCheck={(keys, e) => {\n this.setState({menuChecked: keys, menuHalfChecked: e.halfCheckedKeys})\n }}\n defaultExpandAll\n titleRender={node => {\n return <span title={node.perm}>{node.title}</span>\n }}\n />\n </Modal>\n </Page>\n\n\n }\n}\n\n",
2109
+ "__content": "import {PlusOutlined} from '@ant-design/icons'\nimport {Button, Form, Input, InputNumber, Modal, Popconfirm, Transfer, Tree} from 'antd'\nimport React from 'react'\nimport {ButtonList, FieldBoolean, HttpUtils, Page, PageUtils, ProTable, ViewText} from \"../../../framework\";\n\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false,\n\n usersModalOpen: false,\n\n\n userList: [],\n targetKeys: [],\n selectedKeys: [],\n\n menuOpen: false,\n menuTree: [],\n menuTreeLoading: false,\n menuChecked: [],\n menuHalfChecked: []\n }\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n this.setState({formOpen: true, formValues: record}, () => {\n\n })\n }\n\n handleEditUser = record => {\n this.setState({usersModalOpen: true, formValues: record})\n HttpUtils.get('admin/sysRole/user-list', {id: record.id}).then(rs => {\n this.setState({userList: rs.list, targetKeys: rs.selectedKeys})\n })\n }\n\n onFinish = values => {\n const isNew = !values.id;\n const url = isNew ? 'admin/sysRole/create' : 'admin/sysRole/update';\n HttpUtils.post(url, values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n handleDelete = record => {\n HttpUtils.post('admin/sysRole/delete', {id: record.id}).then(rs => {\n this.tableRef.current.reload()\n })\n }\n\n columns = [\n\n {\n title: '名称',\n dataIndex: 'name',\n\n\n },\n\n {\n title: '编号',\n dataIndex: 'code',\n\n\n },\n\n {\n title: '排序',\n dataIndex: 'seq',\n\n\n },\n\n {\n title: '备注',\n dataIndex: 'remark',\n\n\n },\n\n {\n title: '启用',\n dataIndex: 'enabled',\n\n\n render(v) {\n return v == null ? null : (v ? '是' : '否')\n },\n\n\n },\n {\n title: '是否内置',\n dataIndex: 'builtin',\n\n\n render(v) {\n return v == null ? null : (v ? '是' : '否')\n },\n\n\n },\n\n {\n title: '权限码',\n dataIndex: 'perms',\n width: 300,\n render(v) {\n if (v) {\n return <ViewText value={v.join(',')} ellipsis={true} />\n }\n }\n\n },\n\n\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => {\n\n return (\n <ButtonList>\n <Button size='small' perm='sys-role:grant-permission'\n onClick={() => this.handleEditUser(record)}>用户设置</Button>\n\n <Button size='small' perm='sys-role:grant-permission' disabled={record.builtin}\n onClick={() => PageUtils.open('/system/role/perm?id=' + record.id, '角色权限设置')}>权限设置</Button>\n\n <Button size='small' perm='sys-role:update' disabled={record.builtin}\n onClick={() => this.handleEdit(record)}>编辑</Button>\n <Popconfirm perm='sys-role:delete' disabled={record.builtin} title='是否确定删除系统角色'\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>\n );\n },\n },\n ]\n\n handleSaveUsers = () => {\n const params = {\n id: this.state.formValues.id,\n userIdList: this.state.targetKeys\n }\n HttpUtils.post('admin/sysRole/grant-users', params).then(rs => {\n this.setState({usersModalOpen: false})\n })\n }\n\n handleEditMenu = (record) => {\n this.setState({menuOpen: true, formValues: record, menuTreeLoading: true})\n HttpUtils.get('admin/sysRole/ownMenu', {id: record.id}).then(rs => {\n this.setState({menuChecked: rs.checked, menuHalfChecked: rs.halfChecked})\n })\n HttpUtils.get('admin/sysRole/menuTree').then(rs => {\n this.setState({menuTree: rs, menuTreeLoading: false})\n })\n }\n handleGrantMenu = () => {\n const params = {\n id: this.state.formValues.id,\n menuIds: [...this.state.menuChecked, ...this.state.menuHalfChecked]\n }\n HttpUtils.post('admin/sysRole/grantMenu', params).then(rs => {\n this.setState({menuOpen: false})\n })\n }\n\n render() {\n return <Page>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button perm='sys-role:create' type='primary' onClick={this.handleAdd}>\n <PlusOutlined/> 新增\n </Button>\n </ButtonList>\n }}\n request={(params) => HttpUtils.get('admin/sysRole/page', params)}\n columns={this.columns}\n\n />\n\n <Modal title='系统角色'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnHidden\n mask={{ closable: false }}\n width={600}\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}\n >\n <Form.Item name='id' noStyle></Form.Item>\n\n\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n <Form.Item label='编码' name='code' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label='排序' name='seq'>\n <InputNumber/>\n </Form.Item>\n\n\n <Form.Item label='备注' name='remark'>\n <Input/>\n </Form.Item>\n\n <Form.Item label='启用' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n\n\n </Form>\n </Modal>\n\n\n <Modal title={'角色用户' + \"【\" + this.state.formValues?.name + '】'}\n open={this.state.usersModalOpen}\n destroyOnHidden\n mask={{ closable: false }}\n width={800}\n onCancel={() => this.setState({usersModalOpen: false})}\n onOk={this.handleSaveUsers}\n >\n\n\n <Transfer\n styles={{ section: { height: '60vh', width: 300 } }}\n\n dataSource={this.state.userList} titles={[\"未选择\", \"已选择\"]}\n targetKeys={this.state.targetKeys}\n selectedKeys={this.state.selectedKeys}\n render={item => item.title}\n onChange={(nextTargetKeys, direction, moveKeys) => {\n this.setState({\n targetKeys: nextTargetKeys\n })\n }}\n onSelectChange={(sourceSelectedKeys, targetSelectedKeys) => {\n this.setState({\n selectedKeys: [...sourceSelectedKeys, ...targetSelectedKeys]\n })\n }}\n showSearch\n />\n\n\n </Modal>\n\n <Modal title={'角色授权菜单权限' + \"【\" + this.state.formValues?.name + '】'}\n open={this.state.menuOpen}\n destroyOnHidden\n mask={{ closable: false }}\n width={800}\n onCancel={() => this.setState({menuOpen: false})}\n onOk={this.handleGrantMenu}\n loading={this.state.menuTreeLoading}\n >\n <Tree\n height={600}\n treeData={this.state.menuTree}\n multiple\n checkable\n checkedKeys={{checked: this.state.menuChecked}}\n onCheck={(keys, e) => {\n this.setState({menuChecked: keys, menuHalfChecked: e.halfCheckedKeys})\n }}\n defaultExpandAll\n titleRender={node => {\n return <span title={node.perm}>{node.title}</span>\n }}\n />\n </Modal>\n </Page>\n\n\n }\n}\n\n",
2137
2110
  "__isJSFile": true,
2138
2111
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/role/index.jsx"
2139
2112
  },
@@ -2143,7 +2116,7 @@
2143
2116
  "parentId": "@@/global-layout",
2144
2117
  "file": "system/user/index.jsx",
2145
2118
  "absPath": "/system/user",
2146
- "__content": "import {PlusOutlined} from '@ant-design/icons';\nimport {Button, Form, Input, Modal, Popconfirm, Splitter, Tabs} from 'antd';\nimport React from 'react';\nimport {\n ButtonList,\n DictUtils,\n FieldBoolean,\n FieldSysOrgTreeSelect,\n HttpUtils,\n OrgTree,\n Page,\n ProTable,\n RoleTree\n} from \"../../../framework\";\nimport UserPerm from \"./UserPerm\";\n\nexport default class extends React.Component {\n\n state = {\n showAddForm: false,\n showEditForm: false,\n formValues: {},\n\n currentOrgId: null,\n currentRoleId: null,\n }\n permRef = React.createRef();\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n resetPwd(row) {\n HttpUtils.post('admin/sysUser/reset-pwd', {id: row.id}).then(rs => {\n Modal.success({\n title: '重置密码成功',\n content: rs\n })\n })\n }\n\n handleDelete = r => {\n HttpUtils.post('admin/sysUser/delete', {id: r.id}).then(rs => {\n this.tableRef.current.reload();\n })\n }\n\n onSelectOrg = (key) => {\n this.setState({currentOrgId: key}, () => this.tableRef.current.reload())\n }\n\n onSelectRole = (key) => {\n this.setState({currentRoleId: key}, () => this.tableRef.current.reload())\n }\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n record.deptId = record.deptId || record.unitId\n this.setState({formOpen: true, formValues: record})\n }\n\n columns = [\n {\n title: '单位',\n dataIndex: 'unitLabel',\n },\n {\n title: '部门',\n dataIndex: 'deptLabel',\n },\n {\n title: '姓名',\n dataIndex: 'name',\n sorter: true\n },\n {\n title: '登录账号',\n dataIndex: 'account',\n sorter: true\n },\n\n\n {\n title: '手机',\n dataIndex: 'phone'\n },\n {\n title: '邮箱',\n dataIndex: 'email'\n },\n\n {\n title: '角色',\n dataIndex: 'roleIds',\n render: (_, row) => {\n if (row.roleNames) {\n return row.roleNames.join(',')\n }\n },\n },\n {\n title: '状态',\n dataIndex: 'enabled',\n render(v) {\n return v == null ? null : (v ? '是' : '否')\n },\n },\n {\n title: '数据权限',\n dataIndex: 'dataPermType',\n render(v) {\n return DictUtils.dictTag('dataPermType', v)\n }\n },\n\n {\n title: '创建时间',\n dataIndex: 'createTime',\n },\n {\n title: '操作',\n dataIndex: 'option',\n fixed: 'right',\n render: (_, record) => {\n return <ButtonList>\n <Button size='small' perm='sysUser:save' onClick={() => this.handleEdit(record)}> 编辑 </Button>\n\n <Button size='small' perm='sysUser:grantPerm'\n onClick={() => this.permRef.current.show(record)}> 授权 </Button>\n\n <Popconfirm perm='sysUser:resetPwd' title='确认重置密码?' onConfirm={() => this.resetPwd(record)}>\n <Button size='small'>重置密码</Button>\n </Popconfirm>\n\n <Popconfirm perm='sysUser:delete' title={'是否确定删除用户'}\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>;\n },\n },\n ];\n\n onFinish = values => {\n HttpUtils.post('admin/sysUser/save', values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n render() {\n\n return <Page>\n <Splitter>\n <Splitter.Panel defaultSize={400}>\n <Tabs\n type='card'\n size='small'\n items={[\n {\n key: 'org',\n label: '按组织机构',\n children: <OrgTree onChange={this.onSelectOrg}/>\n },\n {\n key: 'role',\n label: '按角色',\n children: <RoleTree onSelect={this.onSelectRole}/>\n }\n ]}/>\n\n </Splitter.Panel>\n <Splitter.Panel style={{paddingLeft: 16}}>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button\n perm='sysUser:save'\n type=\"primary\"\n onClick={this.handleAdd}>\n <PlusOutlined/> 新增\n </Button>\n\n\n </ButtonList>\n }}\n showToolbarSearch\n request={(params) => {\n params.orgId = this.state.currentOrgId\n params.roleId = this.state.currentRoleId\n return HttpUtils.get('admin/sysUser/page', params)\n }\n }\n columns={this.columns}\n >\n\n </ProTable>\n </Splitter.Panel>\n </Splitter>\n\n\n <Modal title='系统用户'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnClose\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}>\n <Form.Item name='id' noStyle></Form.Item>\n\n <Form.Item label='所属机构' name='deptId' rules={[{required: true}]}>\n <FieldSysOrgTreeSelect/>\n </Form.Item>\n\n <Form.Item label='姓名' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n <Form.Item label='账号' name='account' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label='电话' name='phone'>\n <Input/>\n </Form.Item>\n <Form.Item label='邮箱' name='email'>\n <Input/>\n </Form.Item>\n\n <Form.Item label='启用状态' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n\n </Form>\n </Modal>\n\n\n <UserPerm ref={this.permRef} onOk={() => this.tableRef.current.reload()}/>\n\n </Page>\n }\n\n\n}\n\n\n\n",
2119
+ "__content": "import {PlusOutlined} from '@ant-design/icons';\nimport {Button, Form, Input, Modal, Popconfirm, Splitter, Tabs} from 'antd';\nimport React from 'react';\nimport {\n ButtonList,\n DictUtils,\n FieldBoolean,\n FieldSysOrgTreeSelect,\n HttpUtils,\n OrgTree,\n Page,\n ProTable,\n RoleTree\n} from \"../../../framework\";\nimport UserPerm from \"./UserPerm\";\n\nexport default class extends React.Component {\n\n state = {\n showAddForm: false,\n showEditForm: false,\n formValues: {},\n\n currentOrgId: null,\n currentRoleId: null,\n }\n permRef = React.createRef();\n\n formRef = React.createRef()\n tableRef = React.createRef()\n\n resetPwd(row) {\n HttpUtils.post('admin/sysUser/reset-pwd', {id: row.id}).then(rs => {\n Modal.success({\n title: '重置密码成功',\n content: rs\n })\n })\n }\n\n handleDelete = r => {\n HttpUtils.post('admin/sysUser/delete', {id: r.id}).then(rs => {\n this.tableRef.current.reload();\n })\n }\n\n onSelectOrg = (key) => {\n this.setState({currentOrgId: key}, () => this.tableRef.current.reload())\n }\n\n onSelectRole = (key) => {\n this.setState({currentRoleId: key}, () => this.tableRef.current.reload())\n }\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}})\n }\n\n handleEdit = record => {\n record.deptId = record.deptId || record.unitId\n this.setState({formOpen: true, formValues: record})\n }\n\n columns = [\n {\n title: '单位',\n dataIndex: 'unitLabel',\n },\n {\n title: '部门',\n dataIndex: 'deptLabel',\n },\n {\n title: '姓名',\n dataIndex: 'name',\n sorter: true\n },\n {\n title: '登录账号',\n dataIndex: 'account',\n sorter: true\n },\n\n\n {\n title: '手机',\n dataIndex: 'phone'\n },\n {\n title: '邮箱',\n dataIndex: 'email'\n },\n\n {\n title: '角色',\n dataIndex: 'roleIds',\n render: (_, row) => {\n if (row.roleNames) {\n return row.roleNames.join(',')\n }\n },\n },\n {\n title: '状态',\n dataIndex: 'enabled',\n render(v) {\n return v == null ? null : (v ? '是' : '否')\n },\n },\n {\n title: '数据权限',\n dataIndex: 'dataPermType',\n render(v) {\n return DictUtils.dictTag('dataPermType', v)\n }\n },\n\n {\n title: '创建时间',\n dataIndex: 'createTime',\n },\n {\n title: '操作',\n dataIndex: 'option',\n fixed: 'right',\n render: (_, record) => {\n return <ButtonList>\n <Button size='small' perm='sys-user:update' onClick={() => this.handleEdit(record)}> 编辑 </Button>\n\n <Button size='small' perm='sys-user:grant-permission'\n onClick={() => this.permRef.current.show(record)}> 授权 </Button>\n\n <Popconfirm perm='sys-user:reset-password' title='确认重置密码?' onConfirm={() => this.resetPwd(record)}>\n <Button size='small'>重置密码</Button>\n </Popconfirm>\n\n <Popconfirm perm='sys-user:delete' title={'是否确定删除用户'}\n onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </ButtonList>;\n },\n },\n ];\n\n onFinish = values => {\n const isNew = !values.id;\n const url = isNew ? 'admin/sysUser/create' : 'admin/sysUser/update';\n HttpUtils.post(url, values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload()\n })\n }\n\n render() {\n\n return <Page>\n <Splitter>\n <Splitter.Panel defaultSize={400}>\n <Tabs\n type='card'\n size='small'\n items={[\n {\n key: 'org',\n label: '按组织机构',\n children: <OrgTree onChange={this.onSelectOrg}/>\n },\n {\n key: 'role',\n label: '按角色',\n children: <RoleTree onSelect={this.onSelectRole}/>\n }\n ]}/>\n\n </Splitter.Panel>\n <Splitter.Panel style={{paddingLeft: 16}}>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button\n perm='sys-user:create'\n type=\"primary\"\n onClick={this.handleAdd}>\n <PlusOutlined/> 新增\n </Button>\n\n\n </ButtonList>\n }}\n showToolbarSearch\n request={(params) => {\n params.orgId = this.state.currentOrgId\n params.roleId = this.state.currentRoleId\n return HttpUtils.get('admin/sysUser/page', params)\n }\n }\n columns={this.columns}\n >\n\n </ProTable>\n </Splitter.Panel>\n </Splitter>\n\n\n <Modal title='系统用户'\n open={this.state.formOpen}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n destroyOnHidden\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onFinish={this.onFinish}>\n <Form.Item name='id' noStyle></Form.Item>\n\n <Form.Item label='所属机构' name='deptId' rules={[{required: true}]}>\n <FieldSysOrgTreeSelect/>\n </Form.Item>\n\n <Form.Item label='姓名' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n <Form.Item label='账号' name='account' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label='电话' name='phone'>\n <Input/>\n </Form.Item>\n <Form.Item label='邮箱' name='email'>\n <Input/>\n </Form.Item>\n\n <Form.Item label='启用状态' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n\n </Form>\n </Modal>\n\n\n <UserPerm ref={this.permRef} onOk={() => this.tableRef.current.reload()}/>\n\n </Page>\n }\n\n\n}\n\n\n\n",
2147
2120
  "__isJSFile": true,
2148
2121
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/user/index.jsx"
2149
2122
  },
@@ -2163,7 +2136,7 @@
2163
2136
  "parentId": "@@/global-layout",
2164
2137
  "file": "system/job/index.jsx",
2165
2138
  "absPath": "/system/job",
2166
- "__content": "import React from 'react'\nimport {\n Alert,\n AutoComplete,\n Button,\n Divider,\n Form,\n Input,\n message,\n Modal,\n Popconfirm,\n Select,\n Space,\n Switch,\n Tag\n} from 'antd'\nimport {PlusOutlined} from \"@ant-design/icons\";\n\nimport {ButtonList, HttpUtils, Page, ProTable, StringUtils, ValueType} from \"../../../framework\";\n\n\nconst cronOptions = [\n {\n label: '*/5 * * * * ? 每隔5秒',\n value: '*/5 * * * * ?'\n },\n {\n label: '0 */5 * * * ? 每隔5分钟',\n value: '0 */5 * * * ?'\n },\n {\n label: '0 0 22 * * ? 每天22点',\n value: '0 0 22 * * ?'\n },\n {\n label: '0 0 1 * * ? 每天1点',\n value: '0 0 1 * * ?'\n },\n {\n label: '0 0 1 1 * ? 每月1号凌晨1点',\n value: '0 0 1 1 * ?'\n }\n]\n\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false,\n\n selectedRowKeys: [],\n\n jobClassOptions: [],\n\n paramList: [],\n\n statusOpen: false,\n status: null,\n\n executeRecordOpen: false,\n }\n tableRef = React.createRef()\n formRef = React.createRef()\n\n componentDidMount() {\n HttpUtils.get('admin/job/job-class-options').then(rs => {\n this.setState({jobClassOptions: rs})\n })\n }\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}, paramList: []})\n }\n\n handleEdit = (record) => {\n this.loadJobParamFields(record.jobClass, record.jobData)\n this.setState({formOpen: true, formValues: record,})\n }\n\n loadJobParamFields(className, jobData) {\n HttpUtils.post(\"admin/job/get-job-param-fields\", jobData || {}, {className}).then(rs => {\n this.setState({paramList: rs})\n })\n }\n\n onFinish = (values) => {\n HttpUtils.post('admin/job/save', values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload();\n })\n }\n\n handleDelete = row => {\n const hide = message.loading(\"删除作业中...\")\n HttpUtils.post('admin/job/delete', {id: row.id}).then(rs => {\n this.tableRef.current.reload();\n }).catch(hide)\n }\n\n handleTriggerJob = row => {\n HttpUtils.get('admin/job/trigger-job', {id: row.id}).then(rs => {\n this.tableRef.current.reload();\n })\n }\n\n columns = [\n {\n title: '名称',\n dataIndex: 'name',\n\n },\n {\n title: '执行类',\n dataIndex: 'jobClass',\n\n },\n\n {\n title: 'cron',\n dataIndex: 'cron',\n },\n\n\n {\n title: '参数',\n dataIndex: 'jobData',\n render(list) {\n if (list)\n return JSON.stringify(list)\n }\n },\n\n\n {\n title: '启用状态',\n dataIndex: 'enabled',\n render: (v, record) => {\n return record.enabled ? <Tag color='green'>启用</Tag> : <Tag color='red'>停用</Tag>\n },\n },\n\n {\n title: '操作',\n dataIndex: 'option',\n fixed: 'right',\n render: (_, record) => {\n\n return (\n <Space>\n <Button size='small' onClick={() => this.showExecuteRecord(record)}>执行记录</Button>\n <Button size='small' onClick={() => this.handleTriggerJob(record)}>执行一次</Button>\n <Button size='small' onClick={() => this.handleEdit(record)}> 编辑 </Button>\n <Popconfirm title='是否确定删除?' onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </Space>\n );\n },\n },\n\n ]\n\n showStatus = () => {\n this.setState({statusOpen: true})\n HttpUtils.get('admin/job/status').then(rs => {\n this.setState({status: rs})\n })\n };\n\n showExecuteRecord(record) {\n this.setState({executeRecordOpen: true, formValues: record})\n }\n\n\n render() {\n return <Page padding>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button type='primary' onClick={() => this.handleAdd()} icon={<PlusOutlined/>}>\n 新增\n </Button>\n <Button onClick={this.showStatus}>\n 查看状态\n </Button>\n </ButtonList>\n }}\n request={(params) => HttpUtils.get('admin/job/page', params)}\n columns={this.columns}\n showToolbarSearch\n />\n\n\n <Modal title='作业调度'\n open={this.state.formOpen}\n destroyOnClose\n width={800}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onValuesChange={this.onValuesChange}\n onFinish={this.onFinish}>\n <Form.Item name='id' noStyle>\n </Form.Item>\n <Form.Item label='执行类' name='jobClass' rules={[{required: true}]}\n tooltip='org.quartz.Job接口,参考io.tmgg.job.builtin.DemoJob'>\n <Select options={this.state.jobClassOptions}/>\n </Form.Item>\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n <Form.Item label='cron表达式' name='cron' help='格式:秒分时日月周,留空表示手动执行'\n rules={[{required: true}]}>\n <AutoComplete placeholder='如 0 */5 * * * ?' options={cronOptions}/>\n </Form.Item>\n\n <Form.Item label='启用' name='enabled' valuePropName='checked' rules={[{required: true}]}>\n <Switch/>\n </Form.Item>\n\n\n {this.state.paramList?.map(p => (\n <div key={p.name}>\n <Divider>作业参数</Divider>\n <Form.Item label={p.label}\n name={['jobData', p.name]}\n key={p.name}\n rules={[{required: p.required}]}>\n {ValueType.renderField(p.componentType, p.componentProps)}\n </Form.Item>\n </div>\n ))}\n </Form>\n </Modal>\n\n <Modal title='作业调度状态'\n open={this.state.statusOpen}\n onCancel={() => this.setState({statusOpen: false})}\n footer={null}\n width={1024}\n >\n <Alert message={<pre>{this.state.status}</pre>}></Alert>\n\n </Modal>\n\n <Modal title='作业调度记录'\n open={this.state.executeRecordOpen}\n onCancel={() => this.setState({executeRecordOpen: false})}\n footer={null}\n width={1024}\n destroyOnClose\n >\n <ProTable columns={[{\n title: '开始时间',\n dataIndex: 'beginTime',\n },\n {\n title: '结束时间',\n dataIndex: 'endTime',\n },\n {\n title: '耗时',\n dataIndex: 'jobRunTimeLabel',\n\n },\n {\n title: '是否成功',\n dataIndex: 'success',\n width: 200,\n render: v => {\n if (v != null) {\n return v ? '成功' : '异常'\n }\n }\n },\n {\n title: '返回结果',\n dataIndex: 'result',\n width: 300\n },\n\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => {\n const url = '/admin/sys/log/' + record.id;\n return <a href={url} target='_blank'>日志</a>;\n },\n }\n ]} request={params => {\n params.jobId = this.state.formValues.id\n return HttpUtils.get('admin/job/execute-record', params);\n }}></ProTable>\n\n </Modal>\n </Page>\n }\n\n onValuesChange = (changed, values) => {\n if (changed.jobClass) {\n this.loadJobParamFields(values.jobClass)\n const option = this.state.jobClassOptions.find(o => o.value === changed.jobClass)\n if (option) {\n const {label} = option;\n if (StringUtils.contains(label, \" \")) { // 取中文名部门设置为name\n this.formRef.current.setFieldValue(\"name\", label.split(\" \")[1])\n }\n }\n }\n\n if (changed.jobData) {\n this.loadJobParamFields(values.jobClass, values.jobData)\n }\n\n };\n}\n\n\n\n",
2139
+ "__content": "import React from 'react'\nimport {\n Alert,\n AutoComplete,\n Button,\n Divider,\n Form,\n Input,\n message,\n Modal,\n Popconfirm,\n Select,\n Space,\n Switch,\n Tag\n} from 'antd'\nimport {PlusOutlined} from \"@ant-design/icons\";\n\nimport {ButtonList, HttpUtils, Page, ProTable, StringUtils, SysUtils, ValueType} from \"../../../framework\";\n\n\nconst cronOptions = [\n {\n label: '*/5 * * * * ? 每隔5秒',\n value: '*/5 * * * * ?'\n },\n {\n label: '0 */5 * * * ? 每隔5分钟',\n value: '0 */5 * * * ?'\n },\n {\n label: '0 0 22 * * ? 每天22点',\n value: '0 0 22 * * ?'\n },\n {\n label: '0 0 1 * * ? 每天1点',\n value: '0 0 1 * * ?'\n },\n {\n label: '0 0 1 1 * ? 每月1号凌晨1点',\n value: '0 0 1 1 * ?'\n }\n]\n\n\nexport default class extends React.Component {\n\n state = {\n formValues: {},\n formOpen: false,\n\n selectedRowKeys: [],\n\n jobClassOptions: [],\n\n paramList: [],\n\n statusOpen: false,\n status: null,\n\n executeRecordOpen: false,\n }\n tableRef = React.createRef()\n formRef = React.createRef()\n\n componentDidMount() {\n HttpUtils.get('admin/job/job-class-options').then(rs => {\n this.setState({jobClassOptions: rs})\n }).catch(e => {\n console.error('[Job] 加载作业类选项失败:', e);\n })\n }\n\n handleAdd = () => {\n this.setState({formOpen: true, formValues: {}, paramList: []})\n }\n\n handleEdit = (record) => {\n this.loadJobParamFields(record.jobClass, record.jobData)\n this.setState({formOpen: true, formValues: record,})\n }\n\n loadJobParamFields(className, jobData) {\n HttpUtils.post(\"admin/job/get-job-param-fields\", jobData || {}, {className}).then(rs => {\n this.setState({paramList: rs})\n }).catch(e => {\n console.error('[Job] 加载作业参数字段失败:', e);\n })\n }\n\n onFinish = (values) => {\n const isNew = !values.id;\n const url = isNew ? 'admin/job/create' : 'admin/job/update';\n HttpUtils.post(url, values).then(rs => {\n this.setState({formOpen: false})\n this.tableRef.current.reload();\n }).catch(e => {\n console.error('[Job] 保存作业失败:', e);\n })\n }\n\n handleDelete = row => {\n const hide = message.loading(\"删除作业中...\")\n HttpUtils.post('admin/job/delete', {id: row.id}).then(rs => {\n this.tableRef.current.reload();\n }).catch(e => {\n console.error('[Job] 删除作业失败:', e);\n hide();\n })\n }\n\n handleTriggerJob = row => {\n HttpUtils.get('admin/job/trigger-job', {id: row.id}).then(rs => {\n this.tableRef.current.reload();\n }).catch(e => {\n console.error('[Job] 触发作业失败:', e);\n })\n }\n\n columns = [\n {\n title: '名称',\n dataIndex: 'name',\n\n },\n {\n title: '执行类',\n dataIndex: 'jobClass',\n\n },\n\n {\n title: 'cron',\n dataIndex: 'cron',\n },\n\n\n {\n title: '参数',\n dataIndex: 'jobData',\n render(list) {\n if (list)\n return JSON.stringify(list)\n }\n },\n\n\n {\n title: '启用状态',\n dataIndex: 'enabled',\n render: (v, record) => {\n return record.enabled ? <Tag color='green'>启用</Tag> : <Tag color='red'>停用</Tag>\n },\n },\n\n {\n title: '操作',\n dataIndex: 'option',\n fixed: 'right',\n render: (_, record) => {\n\n return (\n <Space>\n <Button size='small' onClick={() => this.showExecuteRecord(record)}>执行记录</Button>\n <Button size='small' perm='job:trigger' onClick={() => this.handleTriggerJob(record)}>执行一次</Button>\n <Button size='small' perm='job:update' onClick={() => this.handleEdit(record)}> 编辑 </Button>\n <Popconfirm perm='job:delete' title='是否确定删除?' onConfirm={() => this.handleDelete(record)}>\n <Button size='small'>删除</Button>\n </Popconfirm>\n </Space>\n );\n },\n },\n\n ]\n\n showStatus = () => {\n this.setState({statusOpen: true})\n HttpUtils.get('admin/job/status').then(rs => {\n this.setState({status: rs})\n }).catch(e => {\n console.error('[Job] 加载状态失败:', e);\n })\n };\n\n showExecuteRecord(record) {\n this.setState({executeRecordOpen: true, formValues: record})\n }\n\n\n render() {\n return <Page>\n <ProTable\n actionRef={this.tableRef}\n toolBarRender={() => {\n return <ButtonList>\n <Button type='primary' onClick={() => this.handleAdd()} icon={<PlusOutlined/>}>\n 新增\n </Button>\n <Button onClick={this.showStatus}>\n 查看状态\n </Button>\n </ButtonList>\n }}\n request={(params) => HttpUtils.get('admin/job/page', params)}\n columns={this.columns}\n showToolbarSearch\n />\n\n\n <Modal title='作业调度'\n open={this.state.formOpen}\n destroyOnHidden\n width={800}\n onOk={() => this.formRef.current.submit()}\n onCancel={() => this.setState({formOpen: false})}\n >\n\n <Form ref={this.formRef} labelCol={{flex: '100px'}}\n initialValues={this.state.formValues}\n onValuesChange={this.onValuesChange}\n onFinish={this.onFinish}>\n <Form.Item name='id' noStyle>\n </Form.Item>\n <Form.Item label='执行类' name='jobClass' rules={[{required: true}]}\n tooltip='org.quartz.Job接口,参考io.tmgg.job.builtin.DemoJob'>\n <Select options={this.state.jobClassOptions}/>\n </Form.Item>\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n <Form.Item label='cron表达式' name='cron' help='格式:秒分时日月周,留空表示手动执行'\n rules={[{required: true}]}>\n <AutoComplete placeholder='如 0 */5 * * * ?' options={cronOptions}/>\n </Form.Item>\n\n <Form.Item label='启用' name='enabled' valuePropName='checked' rules={[{required: true}]}>\n <Switch/>\n </Form.Item>\n\n\n {this.state.paramList?.map(p => (\n <div key={p.name}>\n <Divider>作业参数</Divider>\n <Form.Item label={p.label}\n name={['jobData', p.name]}\n key={p.name}\n rules={[{required: p.required}]}>\n {ValueType.renderField(p.componentType, p.componentProps)}\n </Form.Item>\n </div>\n ))}\n </Form>\n </Modal>\n\n <Modal title='作业调度状态'\n open={this.state.statusOpen}\n onCancel={() => this.setState({statusOpen: false})}\n footer={null}\n width={1024}\n >\n <Alert title={<pre>{this.state.status}</pre>}></Alert>\n\n </Modal>\n\n <Modal title='作业调度记录'\n open={this.state.executeRecordOpen}\n onCancel={() => this.setState({executeRecordOpen: false})}\n footer={null}\n width={1024}\n destroyOnHidden\n >\n <ProTable columns={[{\n title: '开始时间',\n dataIndex: 'beginTime',\n },\n {\n title: '结束时间',\n dataIndex: 'endTime',\n },\n {\n title: '耗时',\n dataIndex: 'jobRunTimeLabel',\n\n },\n {\n title: '是否成功',\n dataIndex: 'success',\n width: 200,\n render: v => {\n if (v != null) {\n return v ? '成功' : '异常'\n }\n }\n },\n {\n title: '返回结果',\n dataIndex: 'result',\n width: 300\n },\n\n {\n title: '操作',\n dataIndex: 'option',\n render: (_, record) => {\n const url = SysUtils.contextPath('/admin/sys/log/' + record.id);\n return <a href={url} target='_blank'>日志</a>;\n },\n }\n ]} request={params => {\n params.jobId = this.state.formValues.id\n return HttpUtils.get('admin/job/execute-record', params);\n }}></ProTable>\n\n </Modal>\n </Page>\n }\n\n onValuesChange = (changed, values) => {\n if (changed.jobClass) {\n this.loadJobParamFields(values.jobClass)\n const option = this.state.jobClassOptions.find(o => o.value === changed.jobClass)\n if (option) {\n const {label} = option;\n if (StringUtils.contains(label, \" \")) { // 取中文名部门设置为name\n this.formRef.current.setFieldValue(\"name\", label.split(\" \")[1])\n }\n }\n }\n\n if (changed.jobData) {\n this.loadJobParamFields(values.jobClass, values.jobData)\n }\n\n };\n}\n\n\n\n",
2167
2140
  "__isJSFile": true,
2168
2141
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/job/index.jsx"
2169
2142
  },
@@ -2173,7 +2146,7 @@
2173
2146
  "parentId": "@@/global-layout",
2174
2147
  "file": "system/log/index.jsx",
2175
2148
  "absPath": "/system/log",
2176
- "__content": "import React, {Fragment} from 'react';\nimport {Form, Input, Tag} from \"antd\";\nimport {ViewText, FieldDateRange, HttpUtils, ProTable} from \"../../../framework\";\n\nexport default class extends React.Component {\n\n\n columns = [\n {\n title: '操作',\n dataIndex: 'operation',\n },\n {\n title: '操作者',\n dataIndex: 'username'\n },\n\n {\n title: 'ip',\n dataIndex: 'ip',\n },\n\n\n {\n title: '时间',\n dataIndex: 'operationTime',\n sorter: true,\n },\n {\n title: '参数',\n dataIndex: 'params',\n render(v) {\n return <ViewText value={v} ellipsis={true} />\n }\n\n },\n {\n title: '结果',\n dataIndex: 'success',\n render(v) {\n return <>\n <Tag color={v ? 'green' : 'red'}>{v ? '成功' : '失败'}</Tag>\n </>\n }\n },\n {\n title: '错误消息',\n dataIndex: 'error',\n render(v) {\n return <ViewText value={v} ellipsis={true} />\n }\n },\n ];\n\n\n render() {\n return <>\n <ProTable\n request={(params) => HttpUtils.get('admin/sysLog/page', params)}\n columns={this.columns}\n >\n <Form.Item label='操作' name='operation'>\n <Input/>\n </Form.Item>\n <Form.Item label='时间' name='dateRange'>\n <FieldDateRange/>\n </Form.Item>\n </ProTable>\n\n </>\n }\n\n\n}\n\n\n\n",
2149
+ "__content": "import React from 'react';\nimport {Form, Input, Tag} from \"antd\";\nimport {ViewText, FieldDateRange, HttpUtils, Page, ProTable} from \"../../../framework\";\n\nexport default class extends React.Component {\n\n\n columns = [\n {\n title: '操作',\n dataIndex: 'operation',\n },\n {\n title: '操作者',\n dataIndex: 'username'\n },\n\n {\n title: 'ip',\n dataIndex: 'ip',\n },\n\n\n {\n title: '时间',\n dataIndex: 'operationTime',\n sorter: true,\n },\n {\n title: '参数',\n dataIndex: 'params',\n render(v) {\n return <ViewText value={v} ellipsis={true} />\n }\n\n },\n {\n title: '结果',\n dataIndex: 'success',\n render(v) {\n return <>\n <Tag color={v ? 'green' : 'red'}>{v ? '成功' : '失败'}</Tag>\n </>\n }\n },\n {\n title: '错误消息',\n dataIndex: 'error',\n render(v) {\n return <ViewText value={v} ellipsis={true} />\n }\n },\n ];\n\n\n render() {\n return <Page>\n <ProTable\n request={(params) => HttpUtils.get('admin/sysLog/page', params)}\n columns={this.columns}\n >\n <Form.Item label='操作' name='operation'>\n <Input/>\n </Form.Item>\n <Form.Item label='时间' name='dateRange'>\n <FieldDateRange/>\n </Form.Item>\n </ProTable>\n </Page>\n }\n\n\n}\n\n\n\n",
2177
2150
  "__isJSFile": true,
2178
2151
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/log/index.jsx"
2179
2152
  },
@@ -2183,7 +2156,7 @@
2183
2156
  "parentId": "@@/global-layout",
2184
2157
  "file": "system/org/index.jsx",
2185
2158
  "absPath": "/system/org",
2186
- "__content": "import {DeleteOutlined, EditOutlined, PlusOutlined, SyncOutlined} from '@ant-design/icons';\nimport {Button, Card, Checkbox, Empty, Form, Input, Popconfirm, Space, Splitter, Switch, Tree} from 'antd';\nimport React from 'react';\nimport {\n FieldBoolean,\n FieldDictSelect,\n FieldRemoteTreeSelect,\n FieldUserSelect,\n Gap,\n HttpUtils,\n NamedIcon,\n Page\n} from \"../../../framework\";\n\n\nexport default class extends React.Component {\n\n state = {\n formLoading: false,\n formValues: undefined,\n submitLoading: false,\n formEditing: false,\n\n\n params: {\n onlyShowEnabled: true,\n onlyShowUnit: false,\n searchText: null\n },\n\n treeData: [],\n treeLoading: false,\n draggable: false,\n }\n actionRef = React.createRef();\n treeRef = React.createRef();\n\n componentDidMount() {\n this.loadTree()\n }\n\n loadTree = () => {\n this.setState({treeLoading: true})\n\n const {params} = this.state\n HttpUtils.get('admin/sysOrg/tree', params).then(rs => {\n const treeData = rs;\n this.setState({treeData})\n }).finally(() => {\n this.setState({treeLoading: false});\n })\n }\n\n handleDelete = record => {\n HttpUtils.post('admin/sysOrg/delete', {id: record.id})\n .then(rs => {\n this.setState({formValues: null})\n this.loadTree()\n })\n }\n\n\n onSelect = (selectedKeys) => {\n if (selectedKeys.length === 0) {\n this.setState({formValues: null})\n return\n }\n\n const key = selectedKeys[0]\n this.setState({formLoading: true, formEditing: false})\n HttpUtils.get(\"admin/sysOrg/detail\", {id: key}).then(rs => {\n this.setState({formValues: rs})\n }).finally(() => {\n this.setState({formLoading: false})\n })\n }\n\n onFinish = (values) => {\n this.setState({submitLoading: true, formEditing: false})\n HttpUtils.post('admin/sysOrg/save', values).then(rs => {\n this.loadTree()\n }).finally(() => {\n this.setState({submitLoading: false})\n })\n }\n\n\n onDraggableChange = e => {\n this.setState({draggable: e})\n };\n\n\n render() {\n const {formValues} = this.state;\n const disabled = formValues == null;\n const params = this.state.params;\n return <Page padding>\n <Card>\n <Space>\n\n <Input.Search placeholder='搜索' value={params.searchText} onChange={e => {\n params.searchText = e.target.value\n this.setState({params}, this.loadTree)\n }}/>\n <Checkbox checked={params.onlyShowEnabled}\n onChange={e => {\n params.onlyShowEnabled = e.target.checked;\n this.setState({params}, this.loadTree);\n }}>仅显示启用</Checkbox>\n\n <Checkbox checked={params.onlyShowUnit}\n onChange={e => {\n params.onlyShowUnit = e.target.checked;\n this.setState({params}, this.loadTree);\n }}>仅显示单位</Checkbox>\n\n\n </Space>\n </Card>\n <Gap/>\n <Splitter>\n <Splitter.Panel defaultSize={500}>\n <Card loading={this.state.treeLoading}\n title='组织机构'\n extra={<Space>\n\n <div>\n 拖拽排序&nbsp;<Switch\n value={this.state.draggable}\n onChange={this.onDraggableChange}/>\n </div>\n <Button size='small' shape={\"round\"} icon={<SyncOutlined/>}\n onClick={this.loadTree}></Button>\n </Space>}>\n\n\n <Tree ref={this.treeRef}\n treeData={this.state.treeData}\n onSelect={this.onSelect}\n showIcon\n blockNode\n icon={item => {\n return <NamedIcon name={item.data.iconName}/>;\n }}\n draggable={this.state.draggable}\n onDrop={this.onDrop}\n showLine\n defaultExpandAll\n />\n {this.state.treeData.length === 0 && <Empty/>}\n </Card>\n </Splitter.Panel>\n\n <Splitter>\n <Card\n loading={this.state.formLoading}\n extra={<Space>\n <Button type='primary' onClick={() => {\n this.setState({\n formLoading: true,\n formEditing: true,\n formValues: {\n pid: formValues?.id,\n }\n }, () => {\n this.setState({formLoading: false})\n })\n }}>\n <PlusOutlined/> 新增\n </Button>\n <Button disabled={disabled} onClick={() => {\n this.setState({\n formEditing: true\n })\n }}>\n <EditOutlined/> 编辑\n </Button>\n\n <Popconfirm title={'是否确定删除组织机构'} disabled={disabled}\n onConfirm={() => this.handleDelete(formValues)}>\n <Button icon={<DeleteOutlined/>} disabled={disabled}>删除</Button>\n </Popconfirm>\n\n\n </Space>}\n >\n\n {formValues == null ? <Empty description='未选择机构'/> : <Form\n disabled={!this.state.formEditing}\n labelCol={{flex: '150px'}}\n wrapperCol={{flex: '400px'}}\n initialValues={formValues}\n onFinish={this.onFinish}\n >\n <Form.Item noStyle name='id'>\n </Form.Item>\n <Form.Item label='父节点' name='pid'>\n <FieldRemoteTreeSelect url='admin/sysOrg/tree'/>\n </Form.Item>\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label='类型' name='type' rules={[{required: true}]}>\n <FieldDictSelect typeCode='orgType'/>\n </Form.Item>\n\n <Form.Item label='部门领导' name={['leader', 'id']}>\n <FieldUserSelect/>\n </Form.Item>\n <Form.Item label='启用' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n <Form.Item label='扩展字段1' name='extra1'>\n <Input/>\n </Form.Item>\n <Form.Item label='扩展字段2' name='extra2'>\n <Input/>\n </Form.Item>\n <Form.Item label='扩展字段3' name='extra3'>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label=' ' colon={false}>\n <Button type=\"primary\" htmlType='submit'\n loading={this.state.submitLoading}>保存</Button>\n </Form.Item>\n\n </Form>\n }\n\n\n </Card>\n </Splitter>\n\n </Splitter>\n\n\n </Page>\n }\n\n onDrop = (e) => {\n const {dragNode, dropToGap, node} = e;\n const dropKey = node.key;\n const dragKey = dragNode.key;\n\n const dropPos = e.node.pos.split('-');\n const dropPosition = e.dropPosition - Number(dropPos[dropPos.length - 1]); // the drop position relative to the drop node, inside 0, top -1, bottom 1\n\n\n HttpUtils.post('admin/sysOrg/sort', {dropPosition, dropToGap, dropKey, dragKey}).then(this.loadTree)\n };\n}\n\n\n\n",
2159
+ "__content": "import {DeleteOutlined, EditOutlined, PlusOutlined, SyncOutlined} from '@ant-design/icons';\nimport {Button, Card, Checkbox, Empty, Form, Input, Popconfirm, Space, Splitter, Switch, Tree} from 'antd';\nimport React from 'react';\nimport {\n FieldBoolean,\n FieldDictSelect,\n FieldRemoteTreeSelect,\n FieldUserSelect,\n Gap,\n HttpUtils,\n NamedIcon,\n Page\n} from \"../../../framework\";\n\n\nexport default class extends React.Component {\n\n state = {\n formLoading: false,\n formValues: undefined,\n submitLoading: false,\n formEditing: false,\n\n\n params: {\n onlyShowEnabled: true,\n onlyShowUnit: false,\n searchText: null\n },\n\n treeData: [],\n treeLoading: false,\n draggable: false,\n }\n actionRef = React.createRef();\n treeRef = React.createRef();\n\n componentDidMount() {\n this.loadTree()\n }\n\n loadTree = () => {\n this.setState({treeLoading: true})\n\n const {params} = this.state\n HttpUtils.get('admin/sysOrg/tree', params).then(rs => {\n const treeData = rs;\n this.setState({treeData})\n }).finally(() => {\n this.setState({treeLoading: false});\n })\n }\n\n handleDelete = record => {\n HttpUtils.post('admin/sysOrg/delete', {id: record.id})\n .then(rs => {\n this.setState({formValues: null})\n this.loadTree()\n })\n }\n\n\n onSelect = (selectedKeys) => {\n if (selectedKeys.length === 0) {\n this.setState({formValues: null})\n return\n }\n\n const key = selectedKeys[0]\n this.setState({formLoading: true, formEditing: false})\n HttpUtils.get(\"admin/sysOrg/detail\", {id: key}).then(rs => {\n this.setState({formValues: rs})\n }).finally(() => {\n this.setState({formLoading: false})\n })\n }\n\n onFinish = (values) => {\n this.setState({submitLoading: true, formEditing: false})\n const isNew = !values.id;\n const url = isNew ? 'admin/sysOrg/create' : 'admin/sysOrg/update';\n HttpUtils.post(url, values).then(rs => {\n this.loadTree()\n }).finally(() => {\n this.setState({submitLoading: false})\n })\n }\n\n\n onDraggableChange = e => {\n this.setState({draggable: e})\n };\n\n\n render() {\n const {formValues} = this.state;\n const disabled = formValues == null;\n const params = this.state.params;\n return <Page>\n <Card>\n <Space>\n\n <Input.Search placeholder='搜索' value={params.searchText} onChange={e => {\n params.searchText = e.target.value\n this.setState({params}, this.loadTree)\n }}/>\n <Checkbox checked={params.onlyShowEnabled}\n onChange={e => {\n params.onlyShowEnabled = e.target.checked;\n this.setState({params}, this.loadTree);\n }}>仅显示启用</Checkbox>\n\n <Checkbox checked={params.onlyShowUnit}\n onChange={e => {\n params.onlyShowUnit = e.target.checked;\n this.setState({params}, this.loadTree);\n }}>仅显示单位</Checkbox>\n\n\n </Space>\n </Card>\n <Gap/>\n <Splitter>\n <Splitter.Panel defaultSize={500}>\n <Card loading={this.state.treeLoading}\n title='组织机构'\n extra={<Space>\n\n <div>\n 拖拽排序&nbsp;<Switch\n value={this.state.draggable}\n onChange={this.onDraggableChange}/>\n </div>\n <Button size='small' shape={\"round\"} icon={<SyncOutlined/>}\n onClick={this.loadTree}></Button>\n </Space>}>\n\n\n <Tree ref={this.treeRef}\n treeData={this.state.treeData}\n onSelect={this.onSelect}\n showIcon\n blockNode\n icon={item => {\n return <NamedIcon name={item.data.iconName}/>;\n }}\n draggable={this.state.draggable}\n onDrop={this.onDrop}\n showLine\n defaultExpandAll\n />\n {this.state.treeData.length === 0 && <Empty/>}\n </Card>\n </Splitter.Panel>\n\n <Splitter>\n <Card\n loading={this.state.formLoading}\n extra={<Space>\n <Button type='primary' onClick={() => {\n this.setState({\n formLoading: true,\n formEditing: true,\n formValues: {\n pid: formValues?.id,\n }\n }, () => {\n this.setState({formLoading: false})\n })\n }}>\n <PlusOutlined/> 新增\n </Button>\n <Button disabled={disabled} onClick={() => {\n this.setState({\n formEditing: true\n })\n }}>\n <EditOutlined/> 编辑\n </Button>\n\n <Popconfirm title={'是否确定删除组织机构'} disabled={disabled}\n onConfirm={() => this.handleDelete(formValues)}>\n <Button icon={<DeleteOutlined/>} disabled={disabled}>删除</Button>\n </Popconfirm>\n\n\n </Space>}\n >\n\n {formValues == null ? <Empty description='未选择机构'/> : <Form\n disabled={!this.state.formEditing}\n labelCol={{flex: '150px'}}\n wrapperCol={{flex: '400px'}}\n initialValues={formValues}\n onFinish={this.onFinish}\n >\n <Form.Item noStyle name='id'>\n </Form.Item>\n <Form.Item label='父节点' name='pid'>\n <FieldRemoteTreeSelect url='admin/sysOrg/tree'/>\n </Form.Item>\n <Form.Item label='名称' name='name' rules={[{required: true}]}>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label='类型' name='type' rules={[{required: true}]}>\n <FieldDictSelect typeCode='orgType'/>\n </Form.Item>\n\n <Form.Item label='部门领导' name={['leader', 'id']}>\n <FieldUserSelect/>\n </Form.Item>\n <Form.Item label='启用' name='enabled' rules={[{required: true}]}>\n <FieldBoolean/>\n </Form.Item>\n <Form.Item label='扩展字段1' name='extra1'>\n <Input/>\n </Form.Item>\n <Form.Item label='扩展字段2' name='extra2'>\n <Input/>\n </Form.Item>\n <Form.Item label='扩展字段3' name='extra3'>\n <Input/>\n </Form.Item>\n\n\n <Form.Item label=' ' colon={false}>\n <Button type=\"primary\" htmlType='submit'\n loading={this.state.submitLoading}>保存</Button>\n </Form.Item>\n\n </Form>\n }\n\n\n </Card>\n </Splitter>\n\n </Splitter>\n\n\n </Page>\n }\n\n onDrop = (e) => {\n const {dragNode, dropToGap, node} = e;\n const dropKey = node.key;\n const dragKey = dragNode.key;\n\n const dropPos = e.node.pos.split('-');\n const dropPosition = e.dropPosition - Number(dropPos[dropPos.length - 1]); // the drop position relative to the drop node, inside 0, top -1, bottom 1\n\n\n HttpUtils.post('admin/sysOrg/sort', {dropPosition, dropToGap, dropKey, dragKey}).then(this.loadTree)\n };\n}\n\n\n\n",
2187
2160
  "__isJSFile": true,
2188
2161
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/org/index.jsx"
2189
2162
  },
@@ -2193,7 +2166,7 @@
2193
2166
  "parentId": "@@/global-layout",
2194
2167
  "file": "system/role/perm.jsx",
2195
2168
  "absPath": "/system/role/perm",
2196
- "__content": "import React from \"react\";\nimport {Button, Card, Checkbox, Table, Typography} from \"antd\";\nimport {SaveOutlined} from \"@ant-design/icons\";\nimport {ArrayUtils, HttpUtils, PageUtils} from \"../../../framework\";\nexport default class extends React.Component {\n\n\n state = {\n loading: false,\n roleInfo: {},\n\n dataSource: [],\n rowSelectedKeys: {},\n }\n\n columns = [\n {\n title: '菜单',\n dataIndex: 'name',\n },\n\n {\n title: '权限',\n dataIndex: 'permCodes',\n render: (permCodes, record) => {\n if (permCodes == null) {\n return\n }\n const {permNames} = record\n const options = [];\n for (let i = 0; i < permCodes.length; i++) {\n const label = permNames[i];\n const value = permCodes[i];\n options.push({label, value});\n }\n\n\n const rowSelectedKey = this.state.rowSelectedKeys[record.id];\n return <Checkbox.Group options={options}\n value={rowSelectedKey}\n onChange={(ks) => {\n const rowSelectedKeys = this.state.rowSelectedKeys;\n rowSelectedKeys[record.id] = ks;\n this.setState({rowSelectedKeys})\n }}/>\n }\n }\n ]\n\n componentDidMount() {\n this.roleId = PageUtils.currentParams().id;\n this.loadData();\n }\n\n\n loadData() {\n this.setState({loading: true})\n Promise.all([\n HttpUtils.get('admin/sysRole/get', {id: this.roleId}).then(rs => {\n this.setState({roleInfo: rs})\n }),\n HttpUtils.get('admin/sysRole/perm-tree-table', {id: this.roleId}).then(rs => {\n this.setState({dataSource: rs})\n }),\n HttpUtils.get('admin/sysRole/own-perms', {id: this.roleId}).then(rs => {\n this.setState({rowSelectedKeys: rs})\n })\n ]).then(rs => {\n this.setState({loading: false})\n })\n }\n\n savePerms = () => {\n const {rowSelectedKeys} = this.state;\n const perms = [];\n const menus = []\n for (let menuId in rowSelectedKeys) {\n const ks = rowSelectedKeys[menuId];\n if (ks == null || ks.length === 0) {\n continue;\n }\n menus.push(menuId)\n ArrayUtils.addAll(perms, ks)\n }\n HttpUtils.post('admin/sysRole/save-perms', {id: this.roleId, perms, menus}).then(rs => {\n // Page.open(PageUtils.currentPathname(), PageUtils.currentLabel())\n })\n };\n\n\n render() {\n return <>\n\n\n <Card title='角色权限设置' loading={this.state.loading}\n variant={\"borderless\"}\n extra={<Button type='primary' icon={<SaveOutlined/>} onClick={this.savePerms}>保存权限</Button>}>\n <Typography.Text>角色名称:{this.state.roleInfo.name}, 编码:{this.state.roleInfo.code} </Typography.Text>\n <Table dataSource={this.state.dataSource}\n columns={this.columns}\n size='small' bordered pagination={false} rowKey='id'\n expandable={{defaultExpandAllRows: true}}\n ></Table>\n </Card>\n </>\n }\n}\n",
2169
+ "__content": "import React from \"react\";\nimport {Button, Card, Checkbox, Table, Typography} from \"antd\";\nimport {SaveOutlined} from \"@ant-design/icons\";\nimport {ArrayUtils, HttpUtils, Page, PageUtils} from \"../../../framework\";\nexport default class extends React.Component {\n\n\n state = {\n loading: false,\n roleInfo: {},\n\n dataSource: [],\n rowSelectedKeys: {},\n }\n\n columns = [\n {\n title: '菜单',\n dataIndex: 'name',\n },\n\n {\n title: '权限',\n dataIndex: 'permCodes',\n render: (permCodes, record) => {\n if (permCodes == null) {\n return\n }\n const {permNames} = record\n const options = [];\n for (let i = 0; i < permCodes.length; i++) {\n const label = permNames[i];\n const value = permCodes[i];\n options.push({label, value});\n }\n\n\n const rowSelectedKey = this.state.rowSelectedKeys[record.id];\n return <Checkbox.Group options={options}\n value={rowSelectedKey}\n onChange={(ks) => {\n const rowSelectedKeys = this.state.rowSelectedKeys;\n rowSelectedKeys[record.id] = ks;\n this.setState({rowSelectedKeys})\n }}/>\n }\n }\n ]\n\n componentDidMount() {\n this.roleId = PageUtils.currentParams().id;\n this.loadData();\n }\n\n\n loadData() {\n this.setState({loading: true})\n Promise.all([\n HttpUtils.get('admin/sysRole/get', {id: this.roleId}).then(rs => {\n this.setState({roleInfo: rs})\n }),\n HttpUtils.get('admin/sysRole/perm-tree-table', {id: this.roleId}).then(rs => {\n this.setState({dataSource: rs})\n }),\n HttpUtils.get('admin/sysRole/own-perms', {id: this.roleId}).then(rs => {\n this.setState({rowSelectedKeys: rs})\n })\n ]).then(rs => {\n this.setState({loading: false})\n })\n }\n\n savePerms = () => {\n const {rowSelectedKeys} = this.state;\n const perms = [];\n const menus = []\n for (let menuId in rowSelectedKeys) {\n const ks = rowSelectedKeys[menuId];\n if (ks == null || ks.length === 0) {\n continue;\n }\n menus.push(menuId)\n ArrayUtils.addAll(perms, ks)\n }\n HttpUtils.post('admin/sysRole/save-perms', {id: this.roleId, perms, menus}).then(rs => {\n // Page.open(PageUtils.currentPathname(), PageUtils.currentLabel())\n })\n };\n\n\n render() {\n return <Page>\n\n <Card title='角色权限设置' loading={this.state.loading}\n variant={\"borderless\"}\n extra={<Button type='primary' icon={<SaveOutlined/>} onClick={this.savePerms}>保存权限</Button>}>\n <Typography.Text>角色名称:{this.state.roleInfo.name}, 编码:{this.state.roleInfo.code} </Typography.Text>\n <Table dataSource={this.state.dataSource}\n columns={this.columns}\n size='small' bordered pagination={false} rowKey='id'\n expandable={{defaultExpandAllRows: true}}\n ></Table>\n </Card>\n </Page>\n }\n}\n",
2197
2170
  "__isJSFile": true,
2198
2171
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/role/perm.jsx"
2199
2172
  },
@@ -2203,7 +2176,7 @@
2203
2176
  "parentId": "@@/global-layout",
2204
2177
  "file": "userCenter/index.jsx",
2205
2178
  "absPath": "/userCenter",
2206
- "__content": "import React from \"react\";\nimport {Avatar, Card, Col, Row, Tabs} from \"antd\";\nimport ChangePassword from \"./ChangePassword\";\nimport {HttpUtils, Page} from \"../../framework\";\n\nexport default class extends React.Component {\n\n state = {\n info: {}\n }\n\n componentDidMount() {\n HttpUtils.get('admin/userCenter/info').then(rs => {\n this.setState({info: rs})\n })\n }\n\n render() {\n const {info} = this.state;\n return <Page padding backgroundGray>\n <Row gutter={[16, 16]}>\n <Col md={6} sm={24}>\n <Card title='个人信息'>\n\n <div className='flex-center' style={{marginBottom: 32}}>\n <Avatar size={128} title='点击修改头像'/>\n </div>\n\n\n <table className='tmgg-table'>\n <tbody>\n <tr>\n <td>用户名称</td>\n <td align='right'>{info.name}</td>\n </tr>\n <tr>\n <td>账号</td>\n <td align='right'>{info.account}</td>\n </tr>\n <tr>\n <td>手机号码</td>\n <td>{info.phone}</td>\n </tr>\n <tr>\n <td>用户邮箱</td>\n <td>{info.email}</td>\n </tr>\n <tr>\n <td>所属部门</td>\n <td>{info.unit} {info.dept}</td>\n </tr>\n <tr>\n <td>所属角色</td>\n <td>{info.roles}</td>\n </tr>\n <tr>\n <td>创建日期</td>\n <td>{info.createTime}</td>\n </tr>\n </tbody>\n </table>\n </Card>\n </Col>\n <Col md={18} sm={24}>\n <Card title='个人设置'>\n <Tabs\n items={[\n {\n label: '修改密码', key: 'pwd', children: <div>\n <ChangePassword/>\n </div>\n },\n {\n label: '消息订阅', key: 'topic', children: <div>\n 当账号管理邮箱后,系统消息会发送邮件给您\n </div>\n }\n ]}\n tabPosition='left'\n >\n </Tabs>\n </Card>\n </Col>\n </Row>\n\n\n </Page>\n\n }\n}\n",
2179
+ "__content": "import React from \"react\";\nimport {Avatar, Card, Col, Row, Tabs} from \"antd\";\nimport ChangePassword from \"./ChangePassword\";\nimport {HttpUtils, Page} from \"../../framework\";\n\nexport default class extends React.Component {\n\n state = {\n info: {}\n }\n\n componentDidMount() {\n HttpUtils.get('admin/userCenter/info').then(rs => {\n this.setState({info: rs})\n })\n }\n\n render() {\n const {info} = this.state;\n return <Page backgroundGray>\n <Row gutter={[16, 16]}>\n <Col md={6} sm={24}>\n <Card title='个人信息'>\n\n <div className='flex-center' style={{marginBottom: 32}}>\n <Avatar size={128} title='点击修改头像'/>\n </div>\n\n\n <table className='tmgg-table'>\n <tbody>\n <tr>\n <td>用户名称</td>\n <td align='right'>{info.name}</td>\n </tr>\n <tr>\n <td>账号</td>\n <td align='right'>{info.account}</td>\n </tr>\n <tr>\n <td>手机号码</td>\n <td>{info.phone}</td>\n </tr>\n <tr>\n <td>用户邮箱</td>\n <td>{info.email}</td>\n </tr>\n <tr>\n <td>所属部门</td>\n <td>{info.unit} {info.dept}</td>\n </tr>\n <tr>\n <td>所属角色</td>\n <td>{info.roles}</td>\n </tr>\n <tr>\n <td>创建日期</td>\n <td>{info.createTime}</td>\n </tr>\n </tbody>\n </table>\n </Card>\n </Col>\n <Col md={18} sm={24}>\n <Card title='个人设置'>\n <Tabs\n items={[\n {\n label: '修改密码', key: 'pwd', children: <div>\n <ChangePassword/>\n </div>\n },\n {\n label: '消息订阅', key: 'topic', children: <div>\n 当账号管理邮箱后,系统消息会发送邮件给您\n </div>\n }\n ]}\n tabPlacement='left'\n >\n </Tabs>\n </Card>\n </Col>\n </Row>\n\n\n </Page>\n\n }\n}\n",
2207
2180
  "__isJSFile": true,
2208
2181
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/userCenter/index.jsx"
2209
2182
  },
@@ -2213,7 +2186,7 @@
2213
2186
  "parentId": "@@/global-layout",
2214
2187
  "file": "about.jsx",
2215
2188
  "absPath": "/about",
2216
- "__content": "import React from \"react\";\n\nexport default class extends React.Component {\n\n\n render() {\n return <>\n <h1>关于</h1>\n </>\n\n }\n}\n",
2189
+ "__content": "import React from \"react\";\nimport {Page} from \"../framework\";\n\nexport default class extends React.Component {\n\n\n render() {\n return <Page>\n <h1>关于</h1>\n </Page>\n }\n}\n",
2217
2190
  "__isJSFile": true,
2218
2191
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/about.jsx"
2219
2192
  },
@@ -2223,7 +2196,7 @@
2223
2196
  "parentId": "@@/global-layout",
2224
2197
  "file": "index.jsx",
2225
2198
  "absPath": "/",
2226
- "__content": "import React from \"react\";\nimport {Card} from \"antd\";\n\n\nexport default function () {\n\n return <Card>\n 欢迎使用本系统\n </Card>\n}\n",
2199
+ "__content": "import React from \"react\";\nimport {Card} from \"antd\";\nimport {Page} from \"../framework\";\n\nexport default function () {\n return <Page>\n <Card>欢迎使用本系统</Card>\n </Page>\n}\n",
2227
2200
  "__isJSFile": true,
2228
2201
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/index.jsx"
2229
2202
  },
@@ -2233,7 +2206,7 @@
2233
2206
  "parentId": "@@/global-layout",
2234
2207
  "file": "login.jsx",
2235
2208
  "absPath": "/login",
2236
- "__content": "import React from 'react';\nimport {Button, Form, Input, message, Space} from 'antd';\nimport {LockOutlined, SafetyCertificateOutlined, UserOutlined, WarningOutlined} from '@ant-design/icons';\nimport {JSEncrypt} from \"jsencrypt\";\nimport {history} from 'umi';\nimport {EventBusUtils, HttpUtils, PageUtils, MessageUtils, SysUtils} from \"../framework/utils\";\n\nimport \"./login.less\"\n\nfunction getRedirect() {\n let redirect = PageUtils.currentParams()['redirect'];\n if (redirect) {\n redirect = decodeURIComponent(redirect)\n } else {\n redirect = '/'\n }\n return redirect;\n}\n\nfunction postLogin(values) {\n return new Promise((resolve, reject) => {\n HttpUtils.post('/admin/auth/login', values).then(rs => {\n EventBusUtils.emit('loginSuccess')\n history.push(getRedirect())\n resolve(rs)\n }).catch(e => {\n reject(e)\n })\n })\n}\n\nexport default class extends React.Component {\n\n state = {\n logging: false,\n siteInfo: {},\n random: Math.random()\n }\n\n async componentDidMount() {\n if (localStorage.length === 0) {\n MessageUtils.alert('站点数据缺失,刷新当前页面...')\n window.location.reload()\n return\n }\n\n const siteInfo = SysUtils.getSiteInfo()\n this.setState({siteInfo})\n }\n\n submit = values => {\n this.setState({logging: true})\n\n const pubkey = this.state.siteInfo.rsaPublicKey;\n if (!pubkey) {\n message.error(\"未获取密钥,请刷新浏览器再试\")\n this.setState({logging: false})\n return\n }\n const crypt = new JSEncrypt();\n crypt.setPublicKey(pubkey);\n values.password = crypt.encrypt(values.password)\n\n postLogin(values).finally(() => {\n this.setState({logging: false})\n })\n }\n\n render() {\n const {siteInfo} = this.state\n\n const pageStyle = {}\n if (siteInfo.loginBackground) {\n const url = 'admin/sysFile/preview/' + siteInfo.loginBackground;\n pageStyle.backgroundImage = 'url(\"' + url + '\")'\n }\n\n return (\n <section className='login-page' style={pageStyle}>\n <div className=\"login-content\">\n <h1>{siteInfo.title}</h1>\n {this.getForm(siteInfo)}\n {this.renderFormBottom()}\n </div>\n </section>\n );\n }\n\n getForm = siteInfo => {\n const form = (\n <Form\n name=\"normal_login\"\n className=\"login-form\"\n initialValues={{remember: true}}\n onFinish={this.submit}\n requiredMark={false}\n colon={false}\n >\n <Form.Item name=\"username\" rules={[{required: true, message: '请输入用户名!'}]}>\n <Input size='large' prefix={<UserOutlined/>} placeholder=\"用户名\" autoComplete=\"off\"/>\n </Form.Item>\n <Form.Item name=\"password\" rules={[{required: true, message: '请输入密码!'}]}>\n <Input autoComplete=\"off\" prefix={<LockOutlined/>} type=\"password\" placeholder=\"密码\"\n size='large'\n />\n </Form.Item>\n\n {siteInfo.captcha && (\n <Form.Item name='captchaCode' rules={[{required: true}]}>\n <Space style={{alignItems: 'center'}}>\n <Input size='large' placeholder='验证码' prefix={<SafetyCertificateOutlined/>}/>\n <img height={36} width={100}\n src={\"/admin/auth/captcha-image?_random=\" + this.state.random}\n onClick={() => this.setState({random: Math.random()})}/>\n </Space>\n </Form.Item>\n )}\n\n <Form.Item style={{marginTop: 10}}>\n <Button loading={this.state.logging} type=\"primary\" htmlType=\"submit\"\n block size='large'>\n 登录\n </Button>\n </Form.Item>\n </Form>\n );\n\n if (this.props.formRender) {\n return this.props.formRender(form);\n }\n return form;\n };\n\n renderFormBottom() {\n const siteInfo = this.state.siteInfo;\n if (siteInfo.loginBoxBottomTip) {\n return (\n <div style={{color: 'white', marginTop: 50, fontSize: '14px', textAlign: 'center'}}>\n <WarningOutlined/> {siteInfo.loginBoxBottomTip}\n </div>\n )\n }\n }\n}\n",
2209
+ "__content": "import React from 'react';\nimport {Button, Form, Input, message, Space} from 'antd';\nimport {LockOutlined, SafetyCertificateOutlined, UserOutlined, WarningOutlined} from '@ant-design/icons';\nimport {JSEncrypt} from \"jsencrypt\";\nimport {history} from 'umi';\nimport {EventBusUtils, HttpUtils, PageUtils, MessageUtils, SysUtils} from \"../framework/utils\";\n\nimport \"./login.less\"\n\nfunction getRedirect() {\n let redirect = PageUtils.currentParams()['redirect'];\n if (redirect) {\n redirect = decodeURIComponent(redirect)\n } else {\n redirect = '/'\n }\n return redirect;\n}\n\nfunction postLogin(values) {\n return new Promise((resolve, reject) => {\n HttpUtils.post('/admin/auth/login', values).then(rs => {\n EventBusUtils.emit('loginSuccess')\n history.push(getRedirect())\n resolve(rs)\n }).catch(e => {\n console.error('[Login] 登录失败:', e);\n reject(e)\n })\n })\n}\n\nexport default class extends React.Component {\n\n state = {\n logging: false,\n siteInfo: {},\n random: Math.random()\n }\n\n async componentDidMount() {\n const siteInfo = SysUtils.getSiteInfo()\n if (siteInfo && siteInfo.rsaPublicKey) {\n this.setState({siteInfo})\n return\n }\n // localStorage 中无站点信息,从服务端重新加载\n try {\n const rs = await HttpUtils.get('/admin/public/site-info')\n SysUtils.setSiteInfo(rs)\n this.setState({siteInfo: rs})\n } catch (e) {\n console.error('[Login] 加载站点信息失败:', e);\n message.error('加载站点信息失败,请刷新页面重试')\n }\n }\n\n submit = values => {\n this.setState({logging: true})\n\n const pubkey = this.state.siteInfo.rsaPublicKey;\n if (!pubkey) {\n message.error(\"未获取密钥,请刷新浏览器再试\")\n this.setState({logging: false})\n return\n }\n const crypt = new JSEncrypt();\n crypt.setPublicKey(pubkey);\n values.password = crypt.encrypt(values.password)\n\n postLogin(values).finally(() => {\n this.setState({logging: false})\n })\n }\n\n render() {\n const {siteInfo} = this.state\n\n const pageStyle = {\n backgroundImage: `url(\"${SysUtils.contextPath('/admin/public/login_bg.jpg')}\")`\n }\n if (siteInfo.loginBackground) {\n const url = SysUtils.contextPath('/admin/sysFile/preview/' + siteInfo.loginBackground);\n pageStyle.backgroundImage = 'url(\"' + url + '\")'\n }\n\n return (\n <section className='login-page' style={pageStyle}>\n <div className=\"login-content\">\n <h1>{siteInfo.title}</h1>\n {this.getForm(siteInfo)}\n {this.renderFormBottom()}\n </div>\n </section>\n );\n }\n\n getForm = siteInfo => {\n const form = (\n <Form\n name=\"normal_login\"\n className=\"login-form\"\n initialValues={{remember: true}}\n onFinish={this.submit}\n requiredMark={false}\n colon={false}\n >\n <Form.Item name=\"username\" rules={[{required: true, message: '请输入用户名!'}]}>\n <Input size='large' prefix={<UserOutlined/>} placeholder=\"用户名\" autoComplete=\"off\"/>\n </Form.Item>\n <Form.Item name=\"password\" rules={[{required: true, message: '请输入密码!'}]}>\n <Input autoComplete=\"off\" prefix={<LockOutlined/>} type=\"password\" placeholder=\"密码\"\n size='large'\n />\n </Form.Item>\n\n {siteInfo.captcha && (\n <Form.Item name='captchaCode' rules={[{required: true}]}>\n <Space style={{alignItems: 'center'}}>\n <Input size='large' placeholder='验证码' prefix={<SafetyCertificateOutlined/>}/>\n <img height={36} width={100}\n src={SysUtils.contextPath(\"/admin/auth/captcha-image?_random=\" + this.state.random)}\n onClick={() => this.setState({random: Math.random()})}/>\n </Space>\n </Form.Item>\n )}\n\n <Form.Item style={{marginTop: 10}}>\n <Button loading={this.state.logging} type=\"primary\" htmlType=\"submit\"\n block size='large'>\n 登录\n </Button>\n </Form.Item>\n </Form>\n );\n\n if (this.props.formRender) {\n return this.props.formRender(form);\n }\n return form;\n };\n\n renderFormBottom() {\n const siteInfo = this.state.siteInfo;\n if (siteInfo.loginBoxBottomTip) {\n return (\n <div style={{color: 'white', marginTop: 50, fontSize: '14px', textAlign: 'center'}}>\n <WarningOutlined/> {siteInfo.loginBoxBottomTip}\n </div>\n )\n }\n }\n}\n",
2237
2210
  "__isJSFile": true,
2238
2211
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/login.jsx"
2239
2212
  },
@@ -2250,7 +2223,7 @@
2250
2223
  "hasSrcDir": true,
2251
2224
  "npmClient": "cnpm",
2252
2225
  "umi": {
2253
- "version": "4.6.55",
2226
+ "version": "4.6.57",
2254
2227
  "name": "Umi",
2255
2228
  "importSource": "umi",
2256
2229
  "cliName": "umi"