crud-page-react 0.0.6 → 0.0.7
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/dist/index.d.ts +5 -5
- package/dist/index.esm.js +95 -21
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +95 -21
- package/dist/index.js.map +1 -1
- package/dist/types/schema.d.ts +5 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -161,11 +161,11 @@ interface CrudPageSchema {
|
|
|
161
161
|
id: string;
|
|
162
162
|
title: string;
|
|
163
163
|
api: {
|
|
164
|
-
list: string;
|
|
165
|
-
create?: string;
|
|
166
|
-
update?: string;
|
|
167
|
-
delete?: string;
|
|
168
|
-
detail?: string;
|
|
164
|
+
list: string | ActionApiConfig;
|
|
165
|
+
create?: string | ActionApiConfig;
|
|
166
|
+
update?: string | ActionApiConfig;
|
|
167
|
+
delete?: string | ActionApiConfig;
|
|
168
|
+
detail?: string | ActionApiConfig;
|
|
169
169
|
[key: string]: string | ActionApiConfig | undefined;
|
|
170
170
|
};
|
|
171
171
|
fields: FieldSchema[];
|
package/dist/index.esm.js
CHANGED
|
@@ -810,13 +810,6 @@ function DynamicForm({ schema, mode, visible, initialValues, onSubmit, onCancel,
|
|
|
810
810
|
}
|
|
811
811
|
|
|
812
812
|
const { Title } = Typography;
|
|
813
|
-
/** 动态替换 URL 模板中的占位符 */
|
|
814
|
-
function buildUrl(template, record) {
|
|
815
|
-
return template.replace(/:(\w+)/g, (match, fieldName) => {
|
|
816
|
-
const value = record[fieldName];
|
|
817
|
-
return value !== undefined ? String(value) : match;
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
813
|
/** 处理模板数据,支持 {{fieldName}} 格式的变量替换 */
|
|
821
814
|
function processTemplateData(data, record) {
|
|
822
815
|
const result = {};
|
|
@@ -834,6 +827,24 @@ function processTemplateData(data, record) {
|
|
|
834
827
|
}
|
|
835
828
|
return result;
|
|
836
829
|
}
|
|
830
|
+
/** 解析 API 配置,支持字符串和对象两种格式 */
|
|
831
|
+
function parseApiConfig(apiDef) {
|
|
832
|
+
if (!apiDef)
|
|
833
|
+
return undefined;
|
|
834
|
+
if (typeof apiDef === 'string') {
|
|
835
|
+
// 简单字符串 URL 配置
|
|
836
|
+
return {
|
|
837
|
+
url: apiDef,
|
|
838
|
+
method: 'GET',
|
|
839
|
+
responseType: 'json'
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
else if (typeof apiDef === 'object') {
|
|
843
|
+
// 完整的 API 配置对象
|
|
844
|
+
return apiDef;
|
|
845
|
+
}
|
|
846
|
+
return undefined;
|
|
847
|
+
}
|
|
837
848
|
/** 通用请求封装 */
|
|
838
849
|
async function apiRequest(url, options) {
|
|
839
850
|
const res = await fetch(url, Object.assign({ headers: { 'Content-Type': 'application/json' } }, options));
|
|
@@ -882,19 +893,39 @@ const CrudPage = ({ schema, initialData = [], apiRequest: customApiRequest }) =>
|
|
|
882
893
|
}, []);
|
|
883
894
|
// ---------- 获取列表 ----------
|
|
884
895
|
const fetchList = useCallback(async (params = filterParams, p = page, ps = pageSize) => {
|
|
885
|
-
|
|
896
|
+
const listApiConfig = parseApiConfig(schema.api.list);
|
|
897
|
+
if (!listApiConfig) {
|
|
886
898
|
// 没有配置 API,使用初始数据
|
|
887
899
|
initializeData();
|
|
888
900
|
return;
|
|
889
901
|
}
|
|
890
902
|
setLoading(true);
|
|
891
903
|
try {
|
|
904
|
+
// 构建查询参数
|
|
892
905
|
const query = new URLSearchParams({ page: String(p), pageSize: String(ps) });
|
|
893
906
|
Object.entries(params).forEach(([k, v]) => {
|
|
894
907
|
if (v !== undefined && v !== null && v !== '')
|
|
895
908
|
query.set(k, String(v));
|
|
896
909
|
});
|
|
897
|
-
|
|
910
|
+
// 构建请求选项
|
|
911
|
+
const options = {
|
|
912
|
+
method: listApiConfig.method || 'GET',
|
|
913
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, listApiConfig.headers)
|
|
914
|
+
};
|
|
915
|
+
// 如果是 POST 请求,将查询参数放到请求体中
|
|
916
|
+
let url = listApiConfig.url;
|
|
917
|
+
if (listApiConfig.method === 'POST') {
|
|
918
|
+
const queryParams = {};
|
|
919
|
+
query.forEach((value, key) => {
|
|
920
|
+
queryParams[key] = value;
|
|
921
|
+
});
|
|
922
|
+
const requestData = Object.assign(Object.assign({}, queryParams), listApiConfig.data);
|
|
923
|
+
options.body = JSON.stringify(requestData);
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
url = `${url}?${query}`;
|
|
927
|
+
}
|
|
928
|
+
const json = await request(url, options);
|
|
898
929
|
const { list, total: tot } = extractListResponse(json);
|
|
899
930
|
setData(list);
|
|
900
931
|
setTotal(tot);
|
|
@@ -932,12 +963,29 @@ const CrudPage = ({ schema, initialData = [], apiRequest: customApiRequest }) =>
|
|
|
932
963
|
}, []);
|
|
933
964
|
// ---------- 删除 ----------
|
|
934
965
|
const handleDelete = useCallback(async (record) => {
|
|
935
|
-
|
|
966
|
+
const deleteApiConfig = parseApiConfig(schema.api.delete);
|
|
967
|
+
if (!deleteApiConfig) {
|
|
936
968
|
messageApi.error('删除功能未配置');
|
|
937
969
|
return;
|
|
938
970
|
}
|
|
939
971
|
try {
|
|
940
|
-
|
|
972
|
+
// 构建 URL,动态替换占位符
|
|
973
|
+
let url = deleteApiConfig.url;
|
|
974
|
+
url = url.replace(/:(\w+)/g, (match, fieldName) => {
|
|
975
|
+
const value = record[fieldName];
|
|
976
|
+
return value !== undefined ? String(value) : match;
|
|
977
|
+
});
|
|
978
|
+
// 构建请求选项
|
|
979
|
+
const options = {
|
|
980
|
+
method: deleteApiConfig.method || 'DELETE',
|
|
981
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, deleteApiConfig.headers)
|
|
982
|
+
};
|
|
983
|
+
// 处理请求体数据
|
|
984
|
+
if (deleteApiConfig.data && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(deleteApiConfig.method || 'DELETE')) {
|
|
985
|
+
const processedData = processTemplateData(deleteApiConfig.data, record);
|
|
986
|
+
options.body = JSON.stringify(Object.assign(Object.assign({}, processedData), { recordId: record[rowKey], timestamp: new Date().toISOString() }));
|
|
987
|
+
}
|
|
988
|
+
await request(url, options);
|
|
941
989
|
messageApi.success('删除成功');
|
|
942
990
|
fetchList();
|
|
943
991
|
}
|
|
@@ -945,7 +993,7 @@ const CrudPage = ({ schema, initialData = [], apiRequest: customApiRequest }) =>
|
|
|
945
993
|
console.error('Delete failed:', error);
|
|
946
994
|
messageApi.error('删除失败,请稍后重试');
|
|
947
995
|
}
|
|
948
|
-
}, [request, schema.api.delete, fetchList, messageApi]);
|
|
996
|
+
}, [request, schema.api.delete, fetchList, messageApi, rowKey]);
|
|
949
997
|
// ---------- 操作列点击 ----------
|
|
950
998
|
const handleAction = useCallback(async (action, record) => {
|
|
951
999
|
if (action.type === 'view') {
|
|
@@ -1039,15 +1087,25 @@ const CrudPage = ({ schema, initialData = [], apiRequest: customApiRequest }) =>
|
|
|
1039
1087
|
const handleFormOk = useCallback(async (values) => {
|
|
1040
1088
|
const isCreate = modalState.mode === 'create';
|
|
1041
1089
|
if (isCreate) {
|
|
1042
|
-
|
|
1090
|
+
const createApiConfig = parseApiConfig(schema.api.create);
|
|
1091
|
+
if (!createApiConfig) {
|
|
1043
1092
|
messageApi.error('新增功能未配置');
|
|
1044
1093
|
return;
|
|
1045
1094
|
}
|
|
1046
1095
|
try {
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1096
|
+
// 构建请求选项
|
|
1097
|
+
const options = {
|
|
1098
|
+
method: createApiConfig.method || 'POST',
|
|
1099
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, createApiConfig.headers)
|
|
1100
|
+
};
|
|
1101
|
+
// 处理请求体数据
|
|
1102
|
+
let requestData = Object.assign({}, values);
|
|
1103
|
+
if (createApiConfig.data) {
|
|
1104
|
+
const processedData = processTemplateData(createApiConfig.data, values);
|
|
1105
|
+
requestData = Object.assign(Object.assign(Object.assign({}, requestData), processedData), { timestamp: new Date().toISOString() });
|
|
1106
|
+
}
|
|
1107
|
+
options.body = JSON.stringify(requestData);
|
|
1108
|
+
await request(createApiConfig.url, options);
|
|
1051
1109
|
messageApi.success('新增成功');
|
|
1052
1110
|
setModalState({ open: false, mode: 'create' });
|
|
1053
1111
|
fetchList();
|
|
@@ -1058,15 +1116,31 @@ const CrudPage = ({ schema, initialData = [], apiRequest: customApiRequest }) =>
|
|
|
1058
1116
|
}
|
|
1059
1117
|
}
|
|
1060
1118
|
else {
|
|
1061
|
-
|
|
1119
|
+
const updateApiConfig = parseApiConfig(schema.api.update);
|
|
1120
|
+
if (!updateApiConfig) {
|
|
1062
1121
|
messageApi.error('编辑功能未配置');
|
|
1063
1122
|
return;
|
|
1064
1123
|
}
|
|
1065
1124
|
try {
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1125
|
+
// 构建 URL,动态替换占位符
|
|
1126
|
+
let url = updateApiConfig.url;
|
|
1127
|
+
url = url.replace(/:(\w+)/g, (match, fieldName) => {
|
|
1128
|
+
const value = values[fieldName];
|
|
1129
|
+
return value !== undefined ? String(value) : match;
|
|
1069
1130
|
});
|
|
1131
|
+
// 构建请求选项
|
|
1132
|
+
const options = {
|
|
1133
|
+
method: updateApiConfig.method || 'PUT',
|
|
1134
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, updateApiConfig.headers)
|
|
1135
|
+
};
|
|
1136
|
+
// 处理请求体数据
|
|
1137
|
+
let requestData = Object.assign({}, values);
|
|
1138
|
+
if (updateApiConfig.data) {
|
|
1139
|
+
const processedData = processTemplateData(updateApiConfig.data, values);
|
|
1140
|
+
requestData = Object.assign(Object.assign(Object.assign({}, requestData), processedData), { timestamp: new Date().toISOString() });
|
|
1141
|
+
}
|
|
1142
|
+
options.body = JSON.stringify(requestData);
|
|
1143
|
+
await request(url, options);
|
|
1070
1144
|
messageApi.success('编辑成功');
|
|
1071
1145
|
setModalState({ open: false, mode: 'create' });
|
|
1072
1146
|
fetchList();
|