@jiangood/open-admin 1.2.2 → 1.2.4

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.
@@ -10,7 +10,7 @@ export type { RuntimeConfig } from './core/defineApp'
10
10
  export { createBrowserHistory, createHashHistory, createMemoryHistory, Helmet, HelmetProvider, createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, useAppData, useClientLoaderData, useLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, renderClient, __getRoot, Link, useRouteData, __useFetcher, withRouter } from '/home/runner/work/open-admin/open-admin/web/node_modules/.pnpm/@umijs+renderer-react@4.6.33_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@umijs/renderer-react';
11
11
  export type { History, ClientLoader } from '/home/runner/work/open-admin/open-admin/web/node_modules/.pnpm/@umijs+renderer-react@4.6.33_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@umijs/renderer-react'
12
12
  // umi/client/client/plugin
13
- export { ApplyPluginsType, PluginManager } from '/home/runner/work/open-admin/open-admin/web/node_modules/.pnpm/umi@4.6.33_@babel+core@7.29.0_@types+node@25.5.0_@types+react@19.2.14_eslint@8.57.1_lig_f543cb11e6d746f2acaaf8cf866d6b1b/node_modules/umi/client/client/plugin.js';
13
+ export { ApplyPluginsType, PluginManager } from '/home/runner/work/open-admin/open-admin/web/node_modules/.pnpm/umi@4.6.33_@babel+core@7.29.0_@types+node@25.5.0_@types+react@19.2.14_eslint@8.57.1_lig_3d6241fcee791bc19d42955a9bb8309c/node_modules/umi/client/client/plugin.js';
14
14
  export { history, createHistory } from './core/history';
15
15
  export { terminal } from './core/terminal';
16
16
  // react ssr
@@ -27,7 +27,7 @@
27
27
  "src/.umi/*"
28
28
  ],
29
29
  "umi": [
30
- "../../node_modules/.pnpm/umi@4.6.33_@babel+core@7.29.0_@types+node@25.5.0_@types+react@19.2.14_eslint@8.57.1_lig_f543cb11e6d746f2acaaf8cf866d6b1b/node_modules/umi"
30
+ "../../node_modules/.pnpm/umi@4.6.33_@babel+core@7.29.0_@types+node@25.5.0_@types+react@19.2.14_eslint@8.57.1_lig_3d6241fcee791bc19d42955a9bb8309c/node_modules/umi"
31
31
  ],
32
32
  "umi/typings": [
33
33
  "src/.umi/typings"
@@ -27,8 +27,8 @@ export default class Toolbar extends React.Component {
27
27
  <div className='pro-table-toolbar-left'>
28
28
  {showSearch && <Input.Search placeholder='搜索...'
29
29
  allowClear
30
- onChange={(e) => {
31
- this.props.onSearch({searchText: e.target.value})
30
+ onSearch={e=>{
31
+ this.props.onSearch({searchText: e})
32
32
  }}
33
33
  />}
34
34
  </div>
@@ -80,9 +80,10 @@ export class ProTable extends React.Component {
80
80
 
81
81
  this.setState({loading: true})
82
82
  request(params).then(rs => {
83
- const {content, totalElements, extData} = rs;
83
+ const {content, totalElements, size,extData} = rs;
84
84
 
85
- this.setState({dataSource: content, total: parseInt(totalElements)})
85
+
86
+ this.setState({dataSource: content, total: parseInt(totalElements),pageSize:size})
86
87
  if (extData) {
87
88
  this.setState({extData})
88
89
  }
@@ -2,16 +2,16 @@ import React from "react";
2
2
  import {Select} from "antd";
3
3
  import {DictUtils} from "../../utils";
4
4
 
5
- export function FieldDictSelect(props) {
6
- const {value, onChange, typeCode, ...rest} = props;
7
- const options = DictUtils.dictOptions(typeCode);
5
+ export class FieldDictSelect extends React.Component {
6
+ render() {
7
+ const {value, typeCode} = this.props;
8
+ const options = DictUtils.dictOptions(typeCode);
9
+ const strValue = value == null ? null : String(value);
8
10
 
9
-
10
- return <Select value={String(value)}
11
- onChange={onChange}
12
- style={{width: '100%', minWidth: 200}}
13
- options={options}
14
- {...rest}>
15
-
16
- </Select>;
11
+ return <Select value={strValue}
12
+ onChange={this.props.onChange}
13
+ style={{width: '100%', minWidth: 200}}
14
+ options={options}
15
+ />
16
+ }
17
17
  }
@@ -3,123 +3,64 @@ import { Select, Spin, message } from 'antd';
3
3
  import { debounce } from 'lodash';
4
4
  import { HttpUtils } from "../../utils";
5
5
 
6
- export const FieldRemoteSelect = ({
7
- url,
8
- debounceTime = 500,
9
- paramsProcessor,
10
- dataProcessor,
11
- cacheSize = 10,
12
- initialLoad = true,
13
- clearOnSearch = false,
14
- onError,
15
- onLoad,
16
- value,
17
- ...rest
18
- }) => {
19
- const [options, setOptions] = useState([]);
20
- const [loading, setLoading] = useState(false);
21
- const [cache, setCache] = useState(new Map());
22
- const fetchIdRef = useRef(0);
23
- const searchHistoryRef = useRef([]);
6
+ export class FieldRemoteSelect extends React.Component {
24
7
 
25
- const loadData = useCallback(async (searchText = '') => {
26
- const fetchId = ++fetchIdRef.current;
27
- const cacheKey = searchText || '_initial_';
8
+ static defaultProps = {
9
+ placeholder: '请搜索选择'
10
+ }
28
11
 
29
- // 检查缓存
30
- if (cache.has(cacheKey)) {
31
- const cachedData = cache.get(cacheKey);
32
- setOptions(cachedData || []);
33
- onLoad?.(cachedData);
34
- return;
35
- }
12
+ state = {
13
+ dataLoading:true,
14
+ data: {}
15
+ }
36
16
 
37
- setLoading(true);
17
+ componentDidMount() {
18
+ this.loadData(null);
19
+ }
38
20
 
39
- try {
40
- let params = { searchText, selected: value };
41
- if (paramsProcessor) {
42
- params = paramsProcessor(params);
43
- }
21
+ loadData = (searchText) => {
22
+ this.setState({dataLoading:true})
23
+ const {url} = this.props;
24
+ const params = {
25
+ searchText,
26
+ selected: this.props.value
27
+ };
44
28
 
45
- const data = await HttpUtils.get(url, params);
46
- const processedData = dataProcessor ? dataProcessor(data) : data;
29
+ HttpUtils.get(url,params).then(data => {
30
+ this.setState({data})
31
+ }).finally(() => {
32
+ this.setState({dataLoading: false})
33
+ })
34
+ };
35
+ handleSearch = searchText => {
36
+ this.loadData(searchText)
37
+ };
47
38
 
48
- if (fetchId === fetchIdRef.current) {
49
- setOptions(processedData || []);
50
-
51
- // 更新缓存
52
- setCache(prevCache => {
53
- const newCache = new Map(prevCache);
54
- newCache.set(cacheKey, processedData || []);
55
-
56
- // 限制缓存大小
57
- if (newCache.size > cacheSize) {
58
- const firstKey = newCache.keys().next().value;
59
- newCache.delete(firstKey);
60
- }
61
-
62
- return newCache;
63
- });
39
+ render() {
40
+ let {
41
+ value,
42
+ placeholder,
43
+ ...rest
44
+ } = this.props;
64
45
 
65
- onLoad?.(processedData);
66
- }
67
- } catch (error) {
68
- console.error('远程搜索失败:', error);
69
- message.error('搜索失败,请重试');
70
- setOptions([]);
71
- onError?.(error);
72
- } finally {
73
- if (fetchId === fetchIdRef.current) {
74
- setLoading(false);
75
- }
76
- }
77
- }, [url, value, paramsProcessor, dataProcessor, cache, cacheSize, onError, onLoad]);
46
+ return (
47
+ <Select
48
+ showSearch={{
49
+ filterOption: false,
50
+ onSearch: this.handleSearch,
51
+ }}
52
+ options={this.state.data}
53
+ notFoundContent={this.state.dataLoading ? <Spin size="small"/> : '数据为空'}
54
+ style={{width: '100%', minWidth: 200}}
55
+ allowClear
56
+ loading={this.state.dataLoading}
57
+ value={value}
58
+ {...rest}
59
+ />
60
+ );
61
+ }
62
+ }
78
63
 
79
- // 使用 useMemo 缓存 debounce 函数
80
- const debouncedLoadData = useCallback(
81
- debounce((value) => loadData(value), debounceTime),
82
- [loadData, debounceTime]
83
- );
84
64
 
85
- useEffect(() => {
86
- if (initialLoad) {
87
- loadData();
88
- }
89
- }, [initialLoad, loadData]);
90
65
 
91
- const handleSearch = useCallback((searchValue) => {
92
- const trimmedValue = searchValue.trim();
93
-
94
- // 记录搜索历史
95
- if (trimmedValue && !searchHistoryRef.current.includes(trimmedValue)) {
96
- searchHistoryRef.current = [trimmedValue, ...searchHistoryRef.current].slice(0, 5);
97
- }
98
-
99
- if (trimmedValue === '') {
100
- setOptions([]);
101
- return;
102
- }
103
-
104
- debouncedLoadData(trimmedValue);
105
- }, [debouncedLoadData]);
106
66
 
107
- return (
108
- <Select
109
- showSearch={{
110
- filterOption: false,
111
- onSearch: handleSearch,
112
- }}
113
- options={options}
114
- notFoundContent={loading ? <Spin size="small" /> : '数据为空'}
115
- style={{ width: '100%', minWidth: 200 }}
116
- allowClear
117
- loading={loading}
118
- {...rest}
119
- />
120
- );
121
- };
122
-
123
- FieldRemoteSelect.defaultProps = {
124
- placeholder: '请搜索选择'
125
- };
@@ -7,7 +7,7 @@ import React from 'react';
7
7
  import {StringUtils} from "../StringUtils";
8
8
 
9
9
  export interface DictItem {
10
- value: string | number;
10
+ code: string | number;
11
11
  label: string;
12
12
  color?: string;
13
13
  }
@@ -31,14 +31,14 @@ export class DictUtils {
31
31
  * @returns 对应的字典项列表,未找到返回空数组
32
32
  */
33
33
  public static dictList(code: string): DictItem[] {
34
- const map = SysUtils.getDictInfo();
35
- if (!map) {
34
+ const info = SysUtils.getDictInfo();
35
+ if (!info) {
36
36
  return [];
37
37
  }
38
38
 
39
- code = StringUtils.toUnderlineCase(code).toUpperCase();
39
+ let list = info.filter(e=>e.typeCode === code);
40
40
 
41
- return map[code] || [];
41
+ return list
42
42
  }
43
43
 
44
44
  /**
@@ -50,7 +50,7 @@ export class DictUtils {
50
50
  const list: DictItem[] = DictUtils.dictList(typeCode);
51
51
  return list.map(i => {
52
52
  return {
53
- value: i.value,
53
+ value: i.code,
54
54
  label: i.label,
55
55
  }
56
56
  });
@@ -85,8 +85,8 @@ class _Layouts extends React.Component {
85
85
 
86
86
  HttpUtils.get('/admin/public/checkLogin')
87
87
  .then(rs => {
88
- const {needUpdatePwd, dictMap, loginInfo} = rs
89
- SysUtils.setDictInfo(dictMap)
88
+ const {needUpdatePwd, dictInfo, loginInfo} = rs
89
+ SysUtils.setDictInfo(dictInfo)
90
90
  SysUtils.setLoginInfo(loginInfo)
91
91
  if (!needUpdatePwd) {
92
92
  this.setState({loginInfoFinish: true});
@@ -2,21 +2,17 @@ import React from "react";
2
2
  import {Button, Form, Input, InputNumber, Modal, Popconfirm, Splitter, Tag, Tree, Typography} from "antd";
3
3
  import {
4
4
  ButtonList,
5
- FieldBoolean, FieldDictSelect,
5
+ FieldBoolean, FieldDictSelect, FieldRemoteSelect,
6
6
  HttpUtils,
7
7
  Page,
8
- PageLoading,
9
8
  ProTable,
10
- ViewBooleanEnableDisable
9
+ ViewBooleanEnableDisable, ViewText
11
10
  } from "../../../framework";
12
11
  import {PlusOutlined} from "@ant-design/icons";
13
12
 
14
13
  export default class extends React.Component {
15
14
 
16
15
  state = {
17
- treeData: [],
18
- treeLoading: true,
19
- typeCode: null,
20
16
  formValues: {},
21
17
  formOpen: false
22
18
  }
@@ -24,17 +20,9 @@ export default class extends React.Component {
24
20
  formRef = React.createRef()
25
21
  tableRef = React.createRef()
26
22
 
27
- async componentDidMount() {
28
- const treeData = await HttpUtils.get('admin/dict/tree');
29
- this.setState({treeData, treeLoading: false});
30
- }
31
23
 
32
- onSelect = (selectedKeys) => {
33
- const key = selectedKeys.length === 1 ? selectedKeys[0] : null;
34
- this.setState({typeCode: key}, () => {
35
- this.tableRef.current.reload()
36
- })
37
- }
24
+
25
+
38
26
  handleAdd = () => {
39
27
  this.setState({formOpen: true, formValues: {}})
40
28
  }
@@ -44,7 +32,6 @@ export default class extends React.Component {
44
32
  }
45
33
 
46
34
  onFinish = values => {
47
- values.sysDict = {id: this.props.sysDictId}
48
35
  HttpUtils.post('admin/dict/save', values).then(rs => {
49
36
  this.setState({formOpen: false})
50
37
  this.tableRef.current.reload()
@@ -59,8 +46,16 @@ export default class extends React.Component {
59
46
 
60
47
  columns = [
61
48
  {
62
- title: '文本',
63
- dataIndex: 'name',
49
+ title: '类型标签',
50
+ dataIndex: 'typeLabel',
51
+ },
52
+ {
53
+ title: '类型编码',
54
+ dataIndex: 'typeCode',
55
+ },
56
+ {
57
+ title: '标签',
58
+ dataIndex: 'label',
64
59
  },
65
60
  {
66
61
  title: '编码',
@@ -94,6 +89,9 @@ export default class extends React.Component {
94
89
  title: '操作',
95
90
  dataIndex: 'option',
96
91
  render: (_, record) => {
92
+ if(!record.id){ // 非数据库定义的不让修改
93
+ return
94
+ }
97
95
 
98
96
  return (
99
97
  <ButtonList>
@@ -110,45 +108,25 @@ export default class extends React.Component {
110
108
  ]
111
109
 
112
110
  render() {
113
- if (this.state.treeLoading) {
114
- return <PageLoading/>
115
- }
116
-
117
- return <Page>
118
- <Splitter>
119
- <Splitter.Panel defaultSize={600} style={{paddingRight: 16}}>
120
- <Tree
121
- treeData={this.state.treeData}
122
- onSelect={this.onSelect}
123
-
124
- showIcon
125
- blockNode
126
- showLine
127
- defaultExpandAll
128
- >
129
- </Tree>
130
- </Splitter.Panel>
131
- <Splitter.Panel style={{paddingLeft: 16}}>
132
- {this.renderTypeInfo()}
133
- <ProTable
134
- rowKey='code'
135
- actionRef={this.tableRef}
136
- toolBarRender={() => {
137
- return <ButtonList>
138
- <Button perm='sysDict:save' type='primary' onClick={this.handleAdd} disabled={!this.state.typeCode}>
139
- <PlusOutlined/> 新增
140
- </Button>
141
- </ButtonList>
142
- }}
143
- request={(params) => {
144
- params.typeCode = this.state.typeCode
145
- return HttpUtils.get('admin/dict/page', params);
146
- }}
147
- columns={this.columns}
148
- search={false}
149
- />
150
- </Splitter.Panel>
151
- </Splitter>
111
+ return <Page padding>
112
+ <ProTable
113
+ rowKey='uid'
114
+ actionRef={this.tableRef}
115
+ toolBarRender={() => {
116
+ return <ButtonList>
117
+ <Button perm='sysDict:save' type='primary' onClick={this.handleAdd} >
118
+ <PlusOutlined/> 新增
119
+ </Button>
120
+ </ButtonList>
121
+ }}
122
+ request={(params) => {
123
+ params.typeCode = this.state.typeCode
124
+ return HttpUtils.get('admin/dict/page', params);
125
+ }}
126
+ columns={this.columns}
127
+ showToolbarSearch={true}
128
+ scrollY={500}
129
+ />
152
130
  <Modal
153
131
  title='编辑数据字典项'
154
132
  open={this.state.formOpen}
@@ -161,13 +139,16 @@ export default class extends React.Component {
161
139
  initialValues={this.state.formValues}
162
140
  onFinish={this.onFinish}>
163
141
  <Form.Item name='id' noStyle></Form.Item>
164
- <Form.Item label='类型编码' name='typeCode' rules={[{required: true}]} initialValue={this.state.typeCode}>
165
- <Input/>
142
+ <Form.Item label='类型' name='color' rules={[{required: true}]} >
143
+ <ViewText />
144
+ </Form.Item>
145
+ <Form.Item label='类型' name='typeCode' rules={[{required: true}]} >
146
+ <FieldRemoteSelect url='/admin/dict/typeOptions' />
166
147
  </Form.Item>
167
148
  <Form.Item label='编码' name='code' rules={[{required: true}]}>
168
149
  <Input/>
169
150
  </Form.Item>
170
- <Form.Item label='文本' name='name' rules={[{required: true}]} >
151
+ <Form.Item label='标签' name='label' rules={[{required: true}]} help='显示文本'>
171
152
  <Input/>
172
153
  </Form.Item>
173
154
  <Form.Item label='颜色' name='color' rules={[{required: true}]}>
@@ -188,14 +169,5 @@ export default class extends React.Component {
188
169
 
189
170
  }
190
171
 
191
- renderTypeInfo() {
192
- if(this.state.typeCode){
193
- return <>
194
- <Typography.Text italic> 类型:</Typography.Text>
195
- <Typography.Text copyable>
196
- {this.state.typeCode}
197
- </Typography.Text>
198
- </>;
199
- }
200
- }
172
+
201
173
  }