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