neo-cmp-cli 1.12.7 → 1.12.9
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.
- package/README.md +204 -6
- package/dist/index2.js +1 -1
- package/dist/neo/env.js +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +1 -1
- package/template/antd-custom-cmp-template/package.json +1 -1
- package/template/{neo-bi-cmps → asset-manage-template}/README.md +65 -10
- package/template/asset-manage-template/docs/README.md +244 -0
- package/template/asset-manage-template/neo.config.js +60 -0
- package/template/{neo-bi-cmps → asset-manage-template}/package.json +28 -16
- package/template/asset-manage-template/src/assets/img/chart.svg +1 -0
- package/template/asset-manage-template/src/components/README.md +3 -0
- package/template/asset-manage-template/src/components/assetManage__c/assetApi.ts +70 -0
- package/template/asset-manage-template/src/components/assetManage__c/cmps/AssetCreateModal.tsx +260 -0
- package/template/asset-manage-template/src/components/assetManage__c/cmps/AssetGrid.tsx +48 -0
- package/template/asset-manage-template/src/components/assetManage__c/cmps/AssetSidebar.tsx +74 -0
- package/template/asset-manage-template/src/components/assetManage__c/cmps/AssetToolbar.tsx +79 -0
- package/template/asset-manage-template/src/components/assetManage__c/cmps/assetDisplay.tsx +72 -0
- package/template/asset-manage-template/src/components/assetManage__c/constants.ts +28 -0
- package/template/asset-manage-template/src/components/assetManage__c/index.tsx +258 -0
- package/template/asset-manage-template/src/components/assetManage__c/model.ts +75 -0
- package/template/asset-manage-template/src/components/assetManage__c/style.scss +425 -0
- package/template/asset-manage-template/src/components/assetManage__c/types.ts +60 -0
- package/template/asset-manage-template/src/components/bidList__c/cmps/BidCard.tsx +47 -0
- package/template/asset-manage-template/src/components/bidList__c/constants.ts +6 -0
- package/template/asset-manage-template/src/components/bidList__c/formatUtils.ts +14 -0
- package/template/asset-manage-template/src/components/bidList__c/index.tsx +194 -0
- package/template/asset-manage-template/src/components/bidList__c/model.ts +57 -0
- package/template/asset-manage-template/src/components/bidList__c/style.scss +179 -0
- package/template/asset-manage-template/src/components/bidList__c/types.ts +10 -0
- package/template/asset-manage-template/src/components/bidPackage__c/cmps/BidPackageHeader.tsx +140 -0
- package/template/asset-manage-template/src/components/bidPackage__c/cmps/PackageItemTable.tsx +148 -0
- package/template/asset-manage-template/src/components/bidPackage__c/index.tsx +394 -0
- package/template/asset-manage-template/src/components/bidPackage__c/mainTableColumns.tsx +57 -0
- package/template/asset-manage-template/src/components/bidPackage__c/model.ts +86 -0
- package/template/asset-manage-template/src/components/bidPackage__c/style.scss +256 -0
- package/template/asset-manage-template/src/components/bidPackage__c/types.ts +35 -0
- package/template/asset-manage-template/src/components/bidPackage__c/utils.ts +19 -0
- package/template/{neo-bi-cmps → asset-manage-template}/src/utils/axiosFetcher.ts +0 -0
- package/template/{neo-bi-cmps → asset-manage-template}/src/utils/queryObjectData.ts +0 -0
- package/template/asset-manage-template/src/utils/url.ts +82 -0
- package/template/{neo-bi-cmps → asset-manage-template}/src/utils/xobjects.ts +0 -0
- package/template/{neo-bi-cmps → asset-manage-template}/tsconfig.json +1 -1
- package/template/echarts-custom-cmp-template/package.json +1 -1
- package/template/empty-custom-cmp-template/package.json +2 -2
- package/template/neo-custom-cmp-template/package.json +2 -2
- package/template/neo-custom-cmp-template/src/components/entityTable__c/index.tsx +62 -6
- package/template/neo-h5-cmps/neo.config.js +34 -76
- package/template/neo-h5-cmps/package.json +7 -3
- package/template/neo-h5-cmps/src/components/entityList__c/index.tsx +0 -4
- package/template/neo-h5-cmps/src/components/entityList__c/model.ts +10 -5
- package/template/neo-h5-cmps/src/components/entityTabs__c/index.tsx +29 -17
- package/template/neo-h5-cmps/src/components/entityTabs__c/model.ts +25 -5
- package/template/neo-h5-cmps/src/components/entityTabs__c/style.scss +11 -22
- package/template/neo-h5-cmps/src/components/openChatPageBtn__c/index.tsx +3 -1
- package/template/neo-h5-cmps/src/utils/xobjects.ts +8 -3
- package/template/neo-h5-cmps/tsconfig.json +1 -1
- package/template/neo-order-cmps/package.json +2 -2
- package/template/react-custom-cmp-template/package.json +1 -1
- package/template/react-ts-custom-cmp-template/package.json +1 -1
- package/template/vue2-custom-cmp-template/package.json +1 -1
- package/template/develop/BI /351/241/271/347/233/256/345/210/206/346/236/220/346/212/245/345/221/212.md" +0 -562
- package/template/develop/ChatPage /347/273/204/344/273/266/344/275/277/347/224/250/350/257/264/346/230/216/346/226/207/346/241/243.md" +0 -507
- package/template/develop/EntityGrid Web /347/273/204/344/273/266/347/232/204/350/257/246/347/273/206/345/210/206/346/236/220/346/226/207/346/241/243.md" +0 -868
- package/template/develop/EntityList H5 /347/273/204/344/273/266/347/232/204/350/257/246/347/273/206/345/210/206/346/236/220/346/226/207/346/241/243.md" +0 -1386
- package/template/develop/GlobalSearch/347/273/204/344/273/266/345/257/271/346/257/224/345/210/206/346/236/220.md +0 -866
- package/template/develop/Neo /344/270/255/345/217/257/347/224/250 amis /347/273/204/344/273/266.md" +0 -1490
- package/template/develop/cmpEventFunctions.ts +0 -257
- package/template/develop/cmpEvents.ts +0 -864
- package/template/develop/comTree/347/224/237/346/210/220/350/277/207/347/250/213/345/210/206/346/236/220.md +0 -469
- package/template/develop/commonModules.js +0 -55
- package/template/develop/components-table.md +0 -50
- package/template/develop/neo-custom-cmp-template/README.md +0 -48
- package/template/develop/neo-custom-cmp-template/docs/README.md +0 -13
- package/template/develop/neo-custom-cmp-template/neo.config.js +0 -121
- package/template/develop/neo-custom-cmp-template/package.json +0 -63
- package/template/develop/neo-custom-cmp-template/src/components/contactCardList/README.md +0 -65
- package/template/develop/neo-custom-cmp-template/src/components/contactCardList/index.tsx +0 -180
- package/template/develop/neo-custom-cmp-template/src/components/contactCardList/model.ts +0 -50
- package/template/develop/neo-custom-cmp-template/src/components/contactCardList/style.scss +0 -260
- package/template/develop/neo-custom-cmp-template/src/components/contactForm/README.md +0 -94
- package/template/develop/neo-custom-cmp-template/src/components/contactForm/index.tsx +0 -252
- package/template/develop/neo-custom-cmp-template/src/components/contactForm/model.ts +0 -56
- package/template/develop/neo-custom-cmp-template/src/components/contactForm/style.scss +0 -120
- package/template/develop/neo-custom-cmp-template/src/components/neoEntityGrid/README.md +0 -115
- package/template/develop/neo-custom-cmp-template/src/components/neoEntityGrid/index.tsx +0 -304
- package/template/develop/neo-custom-cmp-template/src/components/neoEntityGrid/model.ts +0 -87
- package/template/develop/neo-custom-cmp-template/src/components/neoEntityGrid/style.scss +0 -127
- package/template/develop/neo-custom-cmp-template/src/utils/axiosFetcher.ts +0 -29
- package/template/develop/neo-custom-cmp-template/src/utils/queryObjectData.ts +0 -39
- package/template/develop/neo-custom-cmp-template/src/utils/xobjects.ts +0 -203
- package/template/develop/neo-custom-cmp-template/tsconfig.json +0 -68
- package/template/develop/neo-ui-component-h5.md +0 -105
- package/template/develop/neo-ui-component-web-xregister.md +0 -31
- package/template/develop/neo-ui-component-web.md +0 -292
- package/template/develop/neoCmps.ts +0 -7508
- package/template/develop/neoGlobalSearchInput /347/273/204/344/273/266/347/232/204/350/257/246/347/273/206/345/210/206/346/236/220/346/226/207/346/241/243.md" +0 -497
- package/template/develop/pageSchema1.json +0 -744
- package/template/develop//344/272/213/344/273/266/345/212/250/344/275/234/344/277/235/345/255/230/346/265/201/347/250/213/345/210/206/346/236/220.md +0 -390
- package/template/develop//345/215/225/345/205/203/346/265/213/350/257/225/344/275/277/347/224/250/350/257/264/346/230/216.md +0 -1139
- package/template/neo-bi-cmps/.prettierrc.js +0 -12
- package/template/neo-bi-cmps/commitlint.config.js +0 -59
- package/template/neo-bi-cmps/neo.config.js +0 -124
- package/template/neo-bi-cmps/public/css/base.css +0 -283
- package/template/neo-bi-cmps/public/scripts/app/bluebird.js +0 -6679
- package/template/neo-bi-cmps/public/template.html +0 -13
- package/template/neo-bi-cmps/src/assets/css/common.scss +0 -127
- package/template/neo-bi-cmps/src/assets/css/mixin.scss +0 -47
- package/template/neo-bi-cmps/src/assets/img/NeoCRM.jpg +0 -0
- package/template/neo-bi-cmps/src/assets/img/custom-widget.svg +0 -1
- package/template/neo-bi-cmps/src/assets/img/favicon.png +0 -0
- package/template/neo-bi-cmps/src/assets/img/table.svg +0 -1
- package/template/neo-bi-cmps/src/components/targetNumber__c/README.md +0 -100
- package/template/neo-bi-cmps/src/components/targetNumber__c/customStyleConfig/configSchema.ts +0 -253
- package/template/neo-bi-cmps/src/components/targetNumber__c/customStyleConfig/index.scss +0 -76
- package/template/neo-bi-cmps/src/components/targetNumber__c/customStyleConfig/index.tsx +0 -148
- package/template/neo-bi-cmps/src/components/targetNumber__c/index.tsx +0 -440
- package/template/neo-bi-cmps/src/components/targetNumber__c/model.ts +0 -128
- package/template/neo-bi-cmps/src/components/targetNumber__c/style.scss +0 -173
- package/template/neo-h5-cmps/src/components/simpleTable__c/README.md +0 -90
- package/template/neo-h5-cmps/src/components/simpleTable__c/index.tsx +0 -277
- package/template/neo-h5-cmps/src/components/simpleTable__c/model.ts +0 -91
- package/template/neo-h5-cmps/src/components/simpleTable__c/style.scss +0 -116
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/.prettierrc.js +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/@types/neo-ui-common.d.ts +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/commitlint.config.js +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/public/css/base.css +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/public/scripts/app/bluebird.js +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/public/template.html +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/src/assets/css/common.scss +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/src/assets/css/mixin.scss +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/AIBtn.gif +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/src/assets/img/NeoCRM.jpg +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/aiLogo.png +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/card-list.svg +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/contact-form.svg +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/custom-form.svg +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/src/assets/img/custom-widget.svg +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/data-list.svg +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/detail.svg +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/src/assets/img/favicon.png +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/map.svg +0 -0
- /package/template/{neo-bi-cmps → asset-manage-template}/src/assets/img/search.svg +0 -0
- /package/template/{develop/neo-custom-cmp-template → asset-manage-template}/src/assets/img/table.svg +0 -0
package/template/asset-manage-template/src/components/assetManage__c/cmps/AssetCreateModal.tsx
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 新增资产弹窗(参照 entityTable__c:getDesc 动态表单 + xObject.create)
|
|
3
|
+
*/
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import {
|
|
6
|
+
Modal,
|
|
7
|
+
Form,
|
|
8
|
+
Input,
|
|
9
|
+
Select,
|
|
10
|
+
message,
|
|
11
|
+
Spin,
|
|
12
|
+
Empty,
|
|
13
|
+
DatePicker,
|
|
14
|
+
InputNumber,
|
|
15
|
+
} from 'antd';
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
import { xObject } from 'neo-open-api';
|
|
18
|
+
import moment from 'moment';
|
|
19
|
+
import type { FieldDesc } from '../types';
|
|
20
|
+
|
|
21
|
+
const { Option } = Select;
|
|
22
|
+
|
|
23
|
+
export interface AssetCreateModalProps {
|
|
24
|
+
visible: boolean;
|
|
25
|
+
assetApiKey?: string;
|
|
26
|
+
assetFields?: string[];
|
|
27
|
+
/** 实体显示名,用于标题 */
|
|
28
|
+
entityLabel?: string;
|
|
29
|
+
onClose: () => void;
|
|
30
|
+
onSuccess: () => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const AssetCreateModal: React.FC<AssetCreateModalProps> = ({
|
|
34
|
+
visible,
|
|
35
|
+
assetApiKey,
|
|
36
|
+
assetFields,
|
|
37
|
+
entityLabel,
|
|
38
|
+
onClose,
|
|
39
|
+
onSuccess,
|
|
40
|
+
}) => {
|
|
41
|
+
const [form] = Form.useForm();
|
|
42
|
+
const [loadingMeta, setLoadingMeta] = React.useState(false);
|
|
43
|
+
const [submitting, setSubmitting] = React.useState(false);
|
|
44
|
+
const [fieldList, setFieldList] = React.useState<FieldDesc[]>([]);
|
|
45
|
+
const [entityTypeList, setEntityTypeList] = React.useState<any[]>([]);
|
|
46
|
+
const [objectLabel, setObjectLabel] = React.useState<string>('');
|
|
47
|
+
|
|
48
|
+
const loadMeta = React.useCallback(async () => {
|
|
49
|
+
if (!assetApiKey) return;
|
|
50
|
+
setLoadingMeta(true);
|
|
51
|
+
try {
|
|
52
|
+
const [descRes, typeRes] = await Promise.all([
|
|
53
|
+
xObject.getDesc(assetApiKey),
|
|
54
|
+
xObject.getEntityTypeList(assetApiKey),
|
|
55
|
+
]);
|
|
56
|
+
if (typeRes?.status) {
|
|
57
|
+
setEntityTypeList(typeRes.data || []);
|
|
58
|
+
}
|
|
59
|
+
if (descRes?.status) {
|
|
60
|
+
const data = descRes.data || {};
|
|
61
|
+
const fields: FieldDesc[] = data.fields || [];
|
|
62
|
+
setObjectLabel(data.label || '');
|
|
63
|
+
setFieldList(fields);
|
|
64
|
+
} else {
|
|
65
|
+
setFieldList([]);
|
|
66
|
+
message.error(descRes?.msg || '获取实体字段失败');
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error(e);
|
|
70
|
+
message.error('获取实体字段失败');
|
|
71
|
+
setFieldList([]);
|
|
72
|
+
} finally {
|
|
73
|
+
setLoadingMeta(false);
|
|
74
|
+
}
|
|
75
|
+
}, [assetApiKey]);
|
|
76
|
+
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
if (visible && assetApiKey) {
|
|
79
|
+
form.resetFields();
|
|
80
|
+
loadMeta();
|
|
81
|
+
}
|
|
82
|
+
}, [visible, assetApiKey, form, loadMeta]);
|
|
83
|
+
|
|
84
|
+
const filteredFields = React.useMemo(() => {
|
|
85
|
+
let list = fieldList;
|
|
86
|
+
if (assetFields && assetFields.length > 0) {
|
|
87
|
+
list = list.filter((f) => assetFields.includes(f.apiKey));
|
|
88
|
+
}
|
|
89
|
+
return list.filter((f) => f.apiKey !== 'id');
|
|
90
|
+
}, [fieldList, assetFields]);
|
|
91
|
+
|
|
92
|
+
const handleOk = () => {
|
|
93
|
+
if (!assetApiKey) return;
|
|
94
|
+
form.validateFields().then(async (values: any) => {
|
|
95
|
+
setSubmitting(true);
|
|
96
|
+
const payload = { ...values };
|
|
97
|
+
Object.keys(payload).forEach((fieldKey) => {
|
|
98
|
+
const field = fieldList.find((f) => f.apiKey === fieldKey);
|
|
99
|
+
if (
|
|
100
|
+
field &&
|
|
101
|
+
(field.type === 'date' ||
|
|
102
|
+
field.type === 'datetime' ||
|
|
103
|
+
field.type === 'time')
|
|
104
|
+
) {
|
|
105
|
+
const v = payload[fieldKey];
|
|
106
|
+
if (v && moment.isMoment(v)) {
|
|
107
|
+
payload[fieldKey] = v.valueOf();
|
|
108
|
+
} else if (v instanceof Date) {
|
|
109
|
+
payload[fieldKey] = v.getTime();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
try {
|
|
114
|
+
const response = await xObject.create(assetApiKey, {
|
|
115
|
+
data: payload,
|
|
116
|
+
method: 'POST',
|
|
117
|
+
});
|
|
118
|
+
if (response && (response.code === 200 || response.code === '200')) {
|
|
119
|
+
message.success('创建成功');
|
|
120
|
+
onClose();
|
|
121
|
+
onSuccess();
|
|
122
|
+
} else {
|
|
123
|
+
message.error(response?.message || '创建失败');
|
|
124
|
+
}
|
|
125
|
+
} catch (err) {
|
|
126
|
+
console.error(err);
|
|
127
|
+
message.error('创建失败');
|
|
128
|
+
} finally {
|
|
129
|
+
setSubmitting(false);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const titleName = entityLabel || objectLabel || assetApiKey || '资产';
|
|
135
|
+
|
|
136
|
+
const renderFieldInput = (field: FieldDesc) => {
|
|
137
|
+
const selectitem = field.selectitem || [];
|
|
138
|
+
const checkitem = field.checkitem || [];
|
|
139
|
+
|
|
140
|
+
switch (field.type) {
|
|
141
|
+
case 'entityType':
|
|
142
|
+
case 'entitytype':
|
|
143
|
+
return (
|
|
144
|
+
<Select placeholder="请选择业务类型">
|
|
145
|
+
{entityTypeList.map((item) => (
|
|
146
|
+
<Option key={item.apiKey} value={item.id} disabled={!item.active}>
|
|
147
|
+
{item.label}
|
|
148
|
+
</Option>
|
|
149
|
+
))}
|
|
150
|
+
</Select>
|
|
151
|
+
);
|
|
152
|
+
case 'picklist':
|
|
153
|
+
return (
|
|
154
|
+
<Select placeholder={`请选择${field.label}`}>
|
|
155
|
+
{selectitem.map((item) => (
|
|
156
|
+
<Option key={item.apiKey} value={item.id}>
|
|
157
|
+
{item.label}
|
|
158
|
+
</Option>
|
|
159
|
+
))}
|
|
160
|
+
</Select>
|
|
161
|
+
);
|
|
162
|
+
case 'textarea':
|
|
163
|
+
return <Input.TextArea placeholder={`请输入${field.label}`} rows={3} />;
|
|
164
|
+
case 'multipicklist':
|
|
165
|
+
return (
|
|
166
|
+
<Select placeholder={`请选择${field.label}`} mode="multiple">
|
|
167
|
+
{checkitem.map((item) => (
|
|
168
|
+
<Option key={item.apiKey} value={item.id}>
|
|
169
|
+
{item.label}
|
|
170
|
+
</Option>
|
|
171
|
+
))}
|
|
172
|
+
</Select>
|
|
173
|
+
);
|
|
174
|
+
case 'datetime':
|
|
175
|
+
return (
|
|
176
|
+
<DatePicker
|
|
177
|
+
placeholder={`请选择${field.label}`}
|
|
178
|
+
format="YYYY/MM/DD HH:mm:ss"
|
|
179
|
+
showTime
|
|
180
|
+
style={{ width: '100%' }}
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
case 'date':
|
|
184
|
+
return (
|
|
185
|
+
<DatePicker
|
|
186
|
+
placeholder={`请选择${field.label}`}
|
|
187
|
+
format="YYYY/MM/DD"
|
|
188
|
+
style={{ width: '100%' }}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
case 'time':
|
|
192
|
+
return (
|
|
193
|
+
<DatePicker
|
|
194
|
+
placeholder={`请选择${field.label}`}
|
|
195
|
+
format="HH:mm:ss"
|
|
196
|
+
showTime
|
|
197
|
+
style={{ width: '100%' }}
|
|
198
|
+
/>
|
|
199
|
+
);
|
|
200
|
+
case 'int':
|
|
201
|
+
case 'float':
|
|
202
|
+
return (
|
|
203
|
+
<InputNumber
|
|
204
|
+
placeholder={`请输入${field.label}`}
|
|
205
|
+
style={{ width: '100%' }}
|
|
206
|
+
/>
|
|
207
|
+
);
|
|
208
|
+
default:
|
|
209
|
+
return <Input placeholder={`请输入${field.label}`} />;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<Modal
|
|
215
|
+
title={`新增${titleName}`}
|
|
216
|
+
visible={visible}
|
|
217
|
+
onOk={handleOk}
|
|
218
|
+
onCancel={onClose}
|
|
219
|
+
cancelText="取消"
|
|
220
|
+
okText="确定"
|
|
221
|
+
width={600}
|
|
222
|
+
destroyOnClose
|
|
223
|
+
confirmLoading={submitting}
|
|
224
|
+
>
|
|
225
|
+
{!assetApiKey ? (
|
|
226
|
+
<Empty
|
|
227
|
+
description="未配置资产实体 API Key"
|
|
228
|
+
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
229
|
+
/>
|
|
230
|
+
) : (
|
|
231
|
+
<Spin spinning={loadingMeta} tip="加载表单字段...">
|
|
232
|
+
{filteredFields.length === 0 && !loadingMeta ? (
|
|
233
|
+
<Empty
|
|
234
|
+
description="未获取到可填写的字段,请检查实体权限或 assetFields 配置"
|
|
235
|
+
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
236
|
+
/>
|
|
237
|
+
) : (
|
|
238
|
+
<Form form={form} layout="vertical">
|
|
239
|
+
{filteredFields.map((field) => (
|
|
240
|
+
<Form.Item
|
|
241
|
+
key={field.apiKey}
|
|
242
|
+
name={field.apiKey}
|
|
243
|
+
label={field.label}
|
|
244
|
+
rules={[
|
|
245
|
+
{
|
|
246
|
+
required: !!field.required,
|
|
247
|
+
message: `请填写${field.label}`,
|
|
248
|
+
},
|
|
249
|
+
]}
|
|
250
|
+
>
|
|
251
|
+
{renderFieldInput(field)}
|
|
252
|
+
</Form.Item>
|
|
253
|
+
))}
|
|
254
|
+
</Form>
|
|
255
|
+
)}
|
|
256
|
+
</Spin>
|
|
257
|
+
)}
|
|
258
|
+
</Modal>
|
|
259
|
+
);
|
|
260
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Spin, Empty, Row } from 'antd';
|
|
3
|
+
import type { AssetItem } from '../types';
|
|
4
|
+
import { AssetCard } from './assetDisplay';
|
|
5
|
+
|
|
6
|
+
export interface AssetGridProps {
|
|
7
|
+
assetApiKey?: string;
|
|
8
|
+
assets: AssetItem[];
|
|
9
|
+
loadingAssets: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function AssetGrid({
|
|
13
|
+
assetApiKey,
|
|
14
|
+
assets,
|
|
15
|
+
loadingAssets,
|
|
16
|
+
}: AssetGridProps) {
|
|
17
|
+
if (!assetApiKey) {
|
|
18
|
+
return (
|
|
19
|
+
<section className="asset-grid-wrapper content-placeholder">
|
|
20
|
+
<Empty
|
|
21
|
+
description="请在设计器中配置资产实体 API Key(assetApiKey)"
|
|
22
|
+
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
23
|
+
className="grid-empty"
|
|
24
|
+
/>
|
|
25
|
+
</section>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<section className="asset-grid-wrapper">
|
|
31
|
+
<Spin spinning={loadingAssets} tip="加载资产数据...">
|
|
32
|
+
{assets.length === 0 && !loadingAssets ? (
|
|
33
|
+
<Empty
|
|
34
|
+
description="暂无匹配的资产数据"
|
|
35
|
+
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
36
|
+
className="grid-empty"
|
|
37
|
+
/>
|
|
38
|
+
) : (
|
|
39
|
+
<Row gutter={[20, 20]} className="asset-grid">
|
|
40
|
+
{assets.map((asset) => (
|
|
41
|
+
<AssetCard key={asset.id} asset={asset} />
|
|
42
|
+
))}
|
|
43
|
+
</Row>
|
|
44
|
+
)}
|
|
45
|
+
</Spin>
|
|
46
|
+
</section>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Spin, Empty } from 'antd';
|
|
3
|
+
import { AppstoreOutlined, InboxOutlined } from '@ant-design/icons';
|
|
4
|
+
import type { CategoryItem } from '../types';
|
|
5
|
+
import { CATEGORY_ICONS } from '../constants';
|
|
6
|
+
|
|
7
|
+
export interface AssetSidebarProps {
|
|
8
|
+
categoryApiKey?: string;
|
|
9
|
+
categories: CategoryItem[];
|
|
10
|
+
activeCategoryId: string | null;
|
|
11
|
+
loadingCategories: boolean;
|
|
12
|
+
totalAssets: number;
|
|
13
|
+
onCategoryClick: (categoryId: string | null) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function AssetSidebar({
|
|
17
|
+
categoryApiKey,
|
|
18
|
+
categories,
|
|
19
|
+
activeCategoryId,
|
|
20
|
+
loadingCategories,
|
|
21
|
+
totalAssets,
|
|
22
|
+
onCategoryClick,
|
|
23
|
+
}: AssetSidebarProps) {
|
|
24
|
+
if (!categoryApiKey) {
|
|
25
|
+
return (
|
|
26
|
+
<aside className="asset-sidebar">
|
|
27
|
+
<div className="sidebar-placeholder">
|
|
28
|
+
<Empty
|
|
29
|
+
description="请在设计器中配置分类实体 API Key(categoryApiKey)"
|
|
30
|
+
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
</aside>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<aside className="asset-sidebar">
|
|
39
|
+
<div className="sidebar-header">
|
|
40
|
+
<span className="sidebar-label">资产分类</span>
|
|
41
|
+
</div>
|
|
42
|
+
<Spin spinning={loadingCategories} size="small">
|
|
43
|
+
<nav className="sidebar-nav">
|
|
44
|
+
<div
|
|
45
|
+
className={`sidebar-item ${
|
|
46
|
+
activeCategoryId === null ? 'active' : ''
|
|
47
|
+
}`}
|
|
48
|
+
onClick={() => onCategoryClick(null)}
|
|
49
|
+
>
|
|
50
|
+
<AppstoreOutlined className="sidebar-icon" />
|
|
51
|
+
<span className="sidebar-text">全部资产</span>
|
|
52
|
+
<span className="sidebar-count">{totalAssets}</span>
|
|
53
|
+
</div>
|
|
54
|
+
{categories.map((cat) => {
|
|
55
|
+
const icon = CATEGORY_ICONS[cat.name] || <InboxOutlined />;
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
key={cat.id}
|
|
59
|
+
className={`sidebar-item ${
|
|
60
|
+
activeCategoryId === cat.id ? 'active' : ''
|
|
61
|
+
}`}
|
|
62
|
+
onClick={() => onCategoryClick(cat.id)}
|
|
63
|
+
>
|
|
64
|
+
<span className="sidebar-icon">{icon}</span>
|
|
65
|
+
<span className="sidebar-text">{cat.name}</span>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
})}
|
|
69
|
+
</nav>
|
|
70
|
+
</Spin>
|
|
71
|
+
<div className="sidebar-footer">数据源: {categoryApiKey}</div>
|
|
72
|
+
</aside>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Input, Select, Button } from 'antd';
|
|
3
|
+
import {
|
|
4
|
+
SearchOutlined,
|
|
5
|
+
ReloadOutlined,
|
|
6
|
+
PlusOutlined,
|
|
7
|
+
} from '@ant-design/icons';
|
|
8
|
+
|
|
9
|
+
const { Option } = Select;
|
|
10
|
+
|
|
11
|
+
export interface AssetToolbarProps {
|
|
12
|
+
assetApiKey?: string;
|
|
13
|
+
searchKeyword: string;
|
|
14
|
+
statusFilter: number | undefined;
|
|
15
|
+
loadingAssets: boolean;
|
|
16
|
+
onSearchChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
17
|
+
onStatusChange: React.ComponentProps<typeof Select>['onChange'];
|
|
18
|
+
onRefresh: () => void;
|
|
19
|
+
onAdd: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function AssetToolbar({
|
|
23
|
+
assetApiKey,
|
|
24
|
+
searchKeyword,
|
|
25
|
+
statusFilter,
|
|
26
|
+
loadingAssets,
|
|
27
|
+
onSearchChange,
|
|
28
|
+
onStatusChange,
|
|
29
|
+
onRefresh,
|
|
30
|
+
onAdd,
|
|
31
|
+
}: AssetToolbarProps) {
|
|
32
|
+
const hasAsset = Boolean(assetApiKey);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<section className="asset-toolbar">
|
|
36
|
+
<div className="toolbar-left">
|
|
37
|
+
<Input
|
|
38
|
+
className="search-input"
|
|
39
|
+
placeholder="搜索资产名称、序列号..."
|
|
40
|
+
prefix={<SearchOutlined style={{ color: '#bfbfbf' }} />}
|
|
41
|
+
value={searchKeyword}
|
|
42
|
+
onChange={onSearchChange}
|
|
43
|
+
allowClear
|
|
44
|
+
disabled={!hasAsset}
|
|
45
|
+
/>
|
|
46
|
+
<Select
|
|
47
|
+
className="status-select"
|
|
48
|
+
placeholder="所有状态"
|
|
49
|
+
value={statusFilter}
|
|
50
|
+
onChange={onStatusChange}
|
|
51
|
+
allowClear
|
|
52
|
+
disabled={!hasAsset}
|
|
53
|
+
>
|
|
54
|
+
<Option value={1}>在库</Option>
|
|
55
|
+
<Option value={2}>使用中</Option>
|
|
56
|
+
<Option value={3}>维修中</Option>
|
|
57
|
+
</Select>
|
|
58
|
+
</div>
|
|
59
|
+
<div className="toolbar-right">
|
|
60
|
+
<Button
|
|
61
|
+
type="primary"
|
|
62
|
+
icon={<PlusOutlined />}
|
|
63
|
+
onClick={onAdd}
|
|
64
|
+
disabled={!hasAsset}
|
|
65
|
+
>
|
|
66
|
+
新增资产
|
|
67
|
+
</Button>
|
|
68
|
+
<Button
|
|
69
|
+
icon={<ReloadOutlined />}
|
|
70
|
+
onClick={onRefresh}
|
|
71
|
+
loading={loadingAssets}
|
|
72
|
+
disabled={!hasAsset}
|
|
73
|
+
>
|
|
74
|
+
刷新
|
|
75
|
+
</Button>
|
|
76
|
+
</div>
|
|
77
|
+
</section>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { LaptopOutlined } from '@ant-design/icons';
|
|
3
|
+
import { Col } from 'antd';
|
|
4
|
+
import { STATUS_MAP } from '../constants';
|
|
5
|
+
import type { AssetItem } from '../types';
|
|
6
|
+
|
|
7
|
+
export function formatDate(value: string | number | undefined): string {
|
|
8
|
+
if (!value) return '-';
|
|
9
|
+
const d = new Date(typeof value === 'string' ? value : Number(value));
|
|
10
|
+
if (isNaN(d.getTime())) return '-';
|
|
11
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(
|
|
12
|
+
2,
|
|
13
|
+
'0',
|
|
14
|
+
)}-${String(d.getDate()).padStart(2, '0')}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function renderStatusBadge(status: string | number | undefined) {
|
|
18
|
+
const key = status != null && status !== '' ? String(status) : '';
|
|
19
|
+
const info = STATUS_MAP[key] || {
|
|
20
|
+
label: status != null && status !== '' ? String(status) : '未知',
|
|
21
|
+
color: '#8c8c8c',
|
|
22
|
+
bg: '#f5f5f5',
|
|
23
|
+
};
|
|
24
|
+
return (
|
|
25
|
+
<span
|
|
26
|
+
className="status-badge"
|
|
27
|
+
style={{ color: info.color, backgroundColor: info.bg }}
|
|
28
|
+
>
|
|
29
|
+
{info.label}
|
|
30
|
+
</span>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface AssetCardProps {
|
|
35
|
+
asset: AssetItem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function AssetCard({ asset }: AssetCardProps) {
|
|
39
|
+
const imgUrl =
|
|
40
|
+
asset.productIMG__c?.url || asset.productIMG__c?.fileUrl || null;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Col xs={24} sm={12} md={8} lg={6}>
|
|
44
|
+
<div className="asset-card">
|
|
45
|
+
<div className="card-image">
|
|
46
|
+
{imgUrl ? (
|
|
47
|
+
<img src={imgUrl} alt={asset.name} />
|
|
48
|
+
) : (
|
|
49
|
+
<div className="card-image-placeholder">
|
|
50
|
+
<LaptopOutlined />
|
|
51
|
+
</div>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
<div className="card-body">
|
|
55
|
+
<div className="card-title-row">
|
|
56
|
+
<h3 className="card-name" title={asset.name}>
|
|
57
|
+
{asset.name}
|
|
58
|
+
</h3>
|
|
59
|
+
{renderStatusBadge(asset.status__c)}
|
|
60
|
+
</div>
|
|
61
|
+
<p className="card-serial">SN: {asset.serialNumber__c || '-'}</p>
|
|
62
|
+
<div className="card-footer">
|
|
63
|
+
<span className="card-date">
|
|
64
|
+
入库日期: {formatDate(asset.purchaseDate__c)}
|
|
65
|
+
</span>
|
|
66
|
+
<span className="card-detail-link">详情</span>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</Col>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { LaptopOutlined, CodeOutlined, InboxOutlined } from '@ant-design/icons';
|
|
3
|
+
|
|
4
|
+
/** 资产状态:与常见 picklist 取值 1/2/3 对应 */
|
|
5
|
+
export const STATUS_MAP: Record<
|
|
6
|
+
string,
|
|
7
|
+
{ label: string; color: string; bg: string }
|
|
8
|
+
> = {
|
|
9
|
+
'1': { label: '在库', color: '#52c41a', bg: '#f6ffed' },
|
|
10
|
+
'2': { label: '使用中', color: '#1890ff', bg: '#e6f7ff' },
|
|
11
|
+
'3': { label: '维修中', color: '#ff4d4f', bg: '#fff2f0' },
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const DEFAULT_ASSET_FIELDS = [
|
|
15
|
+
'name',
|
|
16
|
+
'categoryId__c',
|
|
17
|
+
'status__c',
|
|
18
|
+
'serialNumber__c',
|
|
19
|
+
'purchaseDate__c',
|
|
20
|
+
'productIMG__c',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/** 分类名称到图标(无匹配则用通用图标) */
|
|
24
|
+
export const CATEGORY_ICONS: Record<string, React.ReactNode> = {
|
|
25
|
+
办公硬件: React.createElement(LaptopOutlined),
|
|
26
|
+
正版软件: React.createElement(CodeOutlined),
|
|
27
|
+
通用耗材: React.createElement(InboxOutlined),
|
|
28
|
+
};
|