@jiangood/open-admin 2.2.4 → 2.2.6

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 (30) hide show
  1. package/config/common-plugin.js +51 -0
  2. package/config/config.js +1 -51
  3. package/package.json +1 -2
  4. package/src/.umi-production/appData.json +64 -76
  5. package/src/framework/components/DownloadFileButton/index.tsx +1 -1
  6. package/src/framework/components/OrgTree/index.tsx +1 -1
  7. package/src/framework/components/PageLoading/index.tsx +5 -3
  8. package/src/framework/components/ProModal/index.tsx +2 -2
  9. package/src/framework/components/ProTable/components/ToolBar/index.tsx +1 -1
  10. package/src/framework/fields/FieldRemoteTreeSelect/index.tsx +3 -3
  11. package/src/framework/fields/FieldRemoteTreeSelectMultiple/index.tsx +3 -3
  12. package/src/framework/utils/system/HttpUtils.ts +3 -0
  13. package/src/framework/utils/system/ThemeUtils.ts +37 -12
  14. package/src/framework/views/ViewFile/index.tsx +1 -1
  15. package/src/framework/views/ViewProcessInstanceProgress/index.tsx +1 -0
  16. package/src/layouts/{PageRender.jsx → PageRender.tsx} +6 -5
  17. package/src/layouts/admin/HeaderRight.jsx +1 -0
  18. package/src/layouts/admin/index.jsx +5 -4
  19. package/src/layouts/admin/index.less +6 -6
  20. package/src/layouts/index.jsx +59 -43
  21. package/src/pages/login.jsx +2 -0
  22. package/src/pages/system/dict/index.jsx +1 -1
  23. package/src/pages/system/file/index.jsx +1 -1
  24. package/src/pages/system/job/index.jsx +17 -4
  25. package/src/pages/system/manual/index.jsx +2 -2
  26. package/src/pages/system/role/index.jsx +7 -7
  27. package/src/pages/system/user/UserPerm.jsx +1 -1
  28. package/src/pages/system/user/index.jsx +1 -1
  29. package/src/pages/userCenter/index.jsx +1 -1
  30. package/src/layouts/PageRender.d.ts +0 -7
@@ -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
  },
@@ -40,7 +39,7 @@
40
39
  "dev": "umi dev",
41
40
  "build": "umi build"
42
41
  },
43
- "version": "2.2.4"
42
+ "version": "2.2.6"
44
43
  },
45
44
  "pkgPath": "/home/runner/work/open-admin/open-admin/web/package.json",
46
45
  "plugins": {
@@ -117,7 +116,7 @@
117
116
  0
118
117
  ]
119
118
  },
120
- "register": 0
119
+ "register": 1
121
120
  },
122
121
  "enableBy": "register"
123
122
  },
@@ -174,10 +173,10 @@
174
173
  "time": {
175
174
  "hooks": {
176
175
  "onCheckConfig": [
177
- 0
176
+ 1
178
177
  ],
179
178
  "onCheck": [
180
- 0
179
+ 1
181
180
  ]
182
181
  },
183
182
  "register": 1
@@ -197,7 +196,7 @@
197
196
  0
198
197
  ]
199
198
  },
200
- "register": 1
199
+ "register": 0
201
200
  },
202
201
  "enableBy": "register"
203
202
  },
@@ -210,7 +209,7 @@
210
209
  "config": {},
211
210
  "time": {
212
211
  "hooks": {},
213
- "register": 0
212
+ "register": 1
214
213
  },
215
214
  "enableBy": "config"
216
215
  },
@@ -227,7 +226,7 @@
227
226
  0
228
227
  ]
229
228
  },
230
- "register": 6
229
+ "register": 5
231
230
  },
232
231
  "enableBy": "register"
233
232
  },
@@ -1079,7 +1078,7 @@
1079
1078
  "config": {},
1080
1079
  "time": {
1081
1080
  "hooks": {},
1082
- "register": 0
1081
+ "register": 1
1083
1082
  },
1084
1083
  "enableBy": "config"
1085
1084
  },
@@ -1096,7 +1095,7 @@
1096
1095
  0
1097
1096
  ]
1098
1097
  },
1099
- "register": 1
1098
+ "register": 0
1100
1099
  },
1101
1100
  "enableBy": "register"
1102
1101
  },
@@ -1109,7 +1108,7 @@
1109
1108
  "config": {},
1110
1109
  "time": {
1111
1110
  "hooks": {},
1112
- "register": 0
1111
+ "register": 1
1113
1112
  },
1114
1113
  "enableBy": "register"
1115
1114
  },
@@ -1122,7 +1121,7 @@
1122
1121
  "config": {},
1123
1122
  "time": {
1124
1123
  "hooks": {},
1125
- "register": 95
1124
+ "register": 97
1126
1125
  },
1127
1126
  "enableBy": "register"
1128
1127
  },
@@ -1135,7 +1134,7 @@
1135
1134
  "config": {},
1136
1135
  "time": {
1137
1136
  "hooks": {},
1138
- "register": 30
1137
+ "register": 27
1139
1138
  },
1140
1139
  "enableBy": "config"
1141
1140
  },
@@ -1204,7 +1203,7 @@
1204
1203
  "config": {},
1205
1204
  "time": {
1206
1205
  "hooks": {},
1207
- "register": 30
1206
+ "register": 31
1208
1207
  }
1209
1208
  },
1210
1209
  "./node_modules/@umijs/preset-umi/dist/features/mpa/mpa": {
@@ -1268,10 +1267,10 @@
1268
1267
  "time": {
1269
1268
  "hooks": {
1270
1269
  "modifyConfig": [
1271
- 0
1270
+ 1
1272
1271
  ]
1273
1272
  },
1274
- "register": 2
1273
+ "register": 1
1275
1274
  }
1276
1275
  },
1277
1276
  "./node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill": {
@@ -1283,7 +1282,7 @@
1283
1282
  "config": {},
1284
1283
  "time": {
1285
1284
  "hooks": {},
1286
- "register": 0
1285
+ "register": 1
1287
1286
  },
1288
1287
  "enableBy": "register"
1289
1288
  },
@@ -1476,7 +1475,7 @@
1476
1475
  "config": {},
1477
1476
  "time": {
1478
1477
  "hooks": {},
1479
- "register": 0
1478
+ "register": 1
1480
1479
  }
1481
1480
  },
1482
1481
  "./node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent": {
@@ -1555,7 +1554,7 @@
1555
1554
  "config": {},
1556
1555
  "time": {
1557
1556
  "hooks": {},
1558
- "register": 2
1557
+ "register": 3
1559
1558
  }
1560
1559
  },
1561
1560
  "./node_modules/@umijs/preset-umi/dist/features/mako/mako": {
@@ -1567,7 +1566,7 @@
1567
1566
  "config": {},
1568
1567
  "time": {
1569
1568
  "hooks": {},
1570
- "register": 1
1569
+ "register": 0
1571
1570
  },
1572
1571
  "enableBy": "config"
1573
1572
  },
@@ -1580,7 +1579,7 @@
1580
1579
  "config": {},
1581
1580
  "time": {
1582
1581
  "hooks": {},
1583
- "register": 0
1582
+ "register": 1
1584
1583
  }
1585
1584
  },
1586
1585
  "./node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian": {
@@ -1592,7 +1591,7 @@
1592
1591
  "config": {},
1593
1592
  "time": {
1594
1593
  "hooks": {},
1595
- "register": 3
1594
+ "register": 2
1596
1595
  }
1597
1596
  },
1598
1597
  "./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad": {
@@ -1604,7 +1603,7 @@
1604
1603
  "config": {},
1605
1604
  "time": {
1606
1605
  "hooks": {},
1607
- "register": 26
1606
+ "register": 28
1608
1607
  }
1609
1608
  },
1610
1609
  "./node_modules/@umijs/preset-umi/dist/features/forget/forget": {
@@ -1642,7 +1641,7 @@
1642
1641
  "config": {},
1643
1642
  "time": {
1644
1643
  "hooks": {},
1645
- "register": 4
1644
+ "register": 3
1646
1645
  },
1647
1646
  "enableBy": "register"
1648
1647
  },
@@ -1655,7 +1654,7 @@
1655
1654
  "config": {},
1656
1655
  "time": {
1657
1656
  "hooks": {},
1658
- "register": 42
1657
+ "register": 43
1659
1658
  },
1660
1659
  "enableBy": "register"
1661
1660
  },
@@ -1668,7 +1667,7 @@
1668
1667
  "config": {},
1669
1668
  "time": {
1670
1669
  "hooks": {},
1671
- "register": 16
1670
+ "register": 17
1672
1671
  }
1673
1672
  },
1674
1673
  "./node_modules/@umijs/preset-umi/dist/commands/help": {
@@ -1680,7 +1679,7 @@
1680
1679
  "config": {},
1681
1680
  "time": {
1682
1681
  "hooks": {},
1683
- "register": 1
1682
+ "register": 0
1684
1683
  },
1685
1684
  "enableBy": "register"
1686
1685
  },
@@ -1706,7 +1705,7 @@
1706
1705
  "config": {},
1707
1706
  "time": {
1708
1707
  "hooks": {},
1709
- "register": 0
1708
+ "register": 1
1710
1709
  },
1711
1710
  "enableBy": "register"
1712
1711
  },
@@ -1719,7 +1718,7 @@
1719
1718
  "config": {},
1720
1719
  "time": {
1721
1720
  "hooks": {},
1722
- "register": 1
1721
+ "register": 0
1723
1722
  },
1724
1723
  "enableBy": "register"
1725
1724
  },
@@ -1732,7 +1731,7 @@
1732
1731
  "config": {},
1733
1732
  "time": {
1734
1733
  "hooks": {},
1735
- "register": 0
1734
+ "register": 1
1736
1735
  },
1737
1736
  "enableBy": "register"
1738
1737
  },
@@ -1745,7 +1744,7 @@
1745
1744
  "config": {},
1746
1745
  "time": {
1747
1746
  "hooks": {},
1748
- "register": 2
1747
+ "register": 1
1749
1748
  },
1750
1749
  "enableBy": "register"
1751
1750
  },
@@ -1758,7 +1757,7 @@
1758
1757
  "config": {},
1759
1758
  "time": {
1760
1759
  "hooks": {},
1761
- "register": 0
1760
+ "register": 1
1762
1761
  },
1763
1762
  "enableBy": "register"
1764
1763
  },
@@ -1771,7 +1770,7 @@
1771
1770
  "config": {},
1772
1771
  "time": {
1773
1772
  "hooks": {},
1774
- "register": 1
1773
+ "register": 0
1775
1774
  },
1776
1775
  "enableBy": "register"
1777
1776
  },
@@ -1784,7 +1783,7 @@
1784
1783
  "config": {},
1785
1784
  "time": {
1786
1785
  "hooks": {},
1787
- "register": 0
1786
+ "register": 1
1788
1787
  },
1789
1788
  "enableBy": "register"
1790
1789
  },
@@ -1797,7 +1796,7 @@
1797
1796
  "config": {},
1798
1797
  "time": {
1799
1798
  "hooks": {},
1800
- "register": 1
1799
+ "register": 0
1801
1800
  },
1802
1801
  "enableBy": "register"
1803
1802
  },
@@ -1849,7 +1848,7 @@
1849
1848
  "config": {},
1850
1849
  "time": {
1851
1850
  "hooks": {},
1852
- "register": 0
1851
+ "register": 1
1853
1852
  },
1854
1853
  "enableBy": "register"
1855
1854
  },
@@ -1862,7 +1861,7 @@
1862
1861
  "config": {},
1863
1862
  "time": {
1864
1863
  "hooks": {},
1865
- "register": 1
1864
+ "register": 0
1866
1865
  },
1867
1866
  "enableBy": "register"
1868
1867
  },
@@ -1875,7 +1874,7 @@
1875
1874
  "config": {},
1876
1875
  "time": {
1877
1876
  "hooks": {},
1878
- "register": 0
1877
+ "register": 1
1879
1878
  },
1880
1879
  "enableBy": "register"
1881
1880
  },
@@ -1888,7 +1887,7 @@
1888
1887
  "config": {},
1889
1888
  "time": {
1890
1889
  "hooks": {},
1891
- "register": 1
1890
+ "register": 0
1892
1891
  },
1893
1892
  "enableBy": "register"
1894
1893
  },
@@ -1914,7 +1913,7 @@
1914
1913
  "config": {},
1915
1914
  "time": {
1916
1915
  "hooks": {},
1917
- "register": 21
1916
+ "register": 22
1918
1917
  },
1919
1918
  "enableBy": "register"
1920
1919
  },
@@ -1927,7 +1926,7 @@
1927
1926
  "config": {},
1928
1927
  "time": {
1929
1928
  "hooks": {},
1930
- "register": 1
1929
+ "register": 0
1931
1930
  },
1932
1931
  "enableBy": "register"
1933
1932
  },
@@ -1940,7 +1939,7 @@
1940
1939
  "config": {},
1941
1940
  "time": {
1942
1941
  "hooks": {},
1943
- "register": 1
1942
+ "register": 2
1944
1943
  },
1945
1944
  "enableBy": "register"
1946
1945
  },
@@ -1965,7 +1964,11 @@
1965
1964
  "key": "open-admin",
1966
1965
  "config": {},
1967
1966
  "time": {
1968
- "hooks": {},
1967
+ "hooks": {
1968
+ "modifyConfig": [
1969
+ 0
1970
+ ]
1971
+ },
1969
1972
  "register": 6
1970
1973
  },
1971
1974
  "enableBy": "register"
@@ -1977,25 +1980,9 @@
1977
1980
  "_": []
1978
1981
  },
1979
1982
  "userConfig": {
1980
- "define": {
1981
- "SERVLET_CONTEXT": "/change-this-servlet-context"
1982
- },
1983
- "publicPath": "./",
1984
- "hash": true,
1985
- "history": {
1986
- "type": "hash"
1987
- },
1988
- "mfsu": false,
1989
- "esbuildMinifyIIFE": true,
1990
1983
  "plugins": [
1991
1984
  "./config/common-plugin"
1992
- ],
1993
- "proxy": {
1994
- "/change-this-servlet-context": {
1995
- "target": "http://127.0.0.1:8080",
1996
- "changeOrigin": true
1997
- }
1998
- }
1985
+ ]
1999
1986
  },
2000
1987
  "mainConfigFile": "/home/runner/work/open-admin/open-admin/web/config/config.js",
2001
1988
  "config": {
@@ -2023,22 +2010,23 @@
2023
2010
  "@@": "/home/runner/work/open-admin/open-admin/web/src/.umi-production",
2024
2011
  "regenerator-runtime": "/home/runner/work/open-admin/open-admin/web/node_modules/regenerator-runtime"
2025
2012
  },
2013
+ "plugins": [
2014
+ "./config/common-plugin"
2015
+ ],
2016
+ "targets": {
2017
+ "chrome": 80
2018
+ },
2026
2019
  "define": {
2027
2020
  "SERVLET_CONTEXT": "/change-this-servlet-context"
2028
2021
  },
2029
2022
  "hash": true,
2030
2023
  "esbuildMinifyIIFE": true,
2031
- "plugins": [
2032
- "./config/common-plugin"
2033
- ],
2034
2024
  "proxy": {
2035
2025
  "/change-this-servlet-context": {
2036
2026
  "target": "http://127.0.0.1:8080",
2037
- "changeOrigin": true
2027
+ "changeOrigin": true,
2028
+ "ws": true
2038
2029
  }
2039
- },
2040
- "targets": {
2041
- "chrome": 80
2042
2030
  }
2043
2031
  },
2044
2032
  "routes": {
@@ -2068,7 +2056,7 @@
2068
2056
  "parentId": "@@/global-layout",
2069
2057
  "file": "system/user/UserPerm.jsx",
2070
2058
  "absPath": "/system/user/UserPerm",
2071
- "__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",
2072
2060
  "__isJSFile": true,
2073
2061
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/user/UserPerm.jsx"
2074
2062
  },
@@ -2078,7 +2066,7 @@
2078
2066
  "parentId": "@@/global-layout",
2079
2067
  "file": "system/manual/index.jsx",
2080
2068
  "absPath": "/system/manual",
2081
- "__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 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",
2082
2070
  "__isJSFile": true,
2083
2071
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/manual/index.jsx"
2084
2072
  },
@@ -2098,7 +2086,7 @@
2098
2086
  "parentId": "@@/global-layout",
2099
2087
  "file": "system/dict/index.jsx",
2100
2088
  "absPath": "/system/dict",
2101
- "__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 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",
2102
2090
  "__isJSFile": true,
2103
2091
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/dict/index.jsx"
2104
2092
  },
@@ -2108,7 +2096,7 @@
2108
2096
  "parentId": "@@/global-layout",
2109
2097
  "file": "system/file/index.jsx",
2110
2098
  "absPath": "/system/file",
2111
- "__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 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 </Page>\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",
2112
2100
  "__isJSFile": true,
2113
2101
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/file/index.jsx"
2114
2102
  },
@@ -2118,7 +2106,7 @@
2118
2106
  "parentId": "@@/global-layout",
2119
2107
  "file": "system/role/index.jsx",
2120
2108
  "absPath": "/system/role",
2121
- "__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 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",
2122
2110
  "__isJSFile": true,
2123
2111
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/role/index.jsx"
2124
2112
  },
@@ -2128,7 +2116,7 @@
2128
2116
  "parentId": "@@/global-layout",
2129
2117
  "file": "system/user/index.jsx",
2130
2118
  "absPath": "/system/user",
2131
- "__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 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",
2132
2120
  "__isJSFile": true,
2133
2121
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/user/index.jsx"
2134
2122
  },
@@ -2148,7 +2136,7 @@
2148
2136
  "parentId": "@@/global-layout",
2149
2137
  "file": "system/job/index.jsx",
2150
2138
  "absPath": "/system/job",
2151
- "__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 })\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 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 })\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' 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 })\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 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 = 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",
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",
2152
2140
  "__isJSFile": true,
2153
2141
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/system/job/index.jsx"
2154
2142
  },
@@ -2188,7 +2176,7 @@
2188
2176
  "parentId": "@@/global-layout",
2189
2177
  "file": "userCenter/index.jsx",
2190
2178
  "absPath": "/userCenter",
2191
- "__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 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",
2192
2180
  "__isJSFile": true,
2193
2181
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/userCenter/index.jsx"
2194
2182
  },
@@ -2218,7 +2206,7 @@
2218
2206
  "parentId": "@@/global-layout",
2219
2207
  "file": "login.jsx",
2220
2208
  "absPath": "/login",
2221
- "__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 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 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",
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",
2222
2210
  "__isJSFile": true,
2223
2211
  "__absFile": "/home/runner/work/open-admin/open-admin/web/src/pages/login.jsx"
2224
2212
  },