@wordrhyme/auto-crud 1.0.1 → 1.0.3
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 +76 -7
- package/dist/index.cjs +594 -96
- package/dist/index.d.cts +174 -34
- package/dist/index.d.ts +174 -34
- package/dist/index.js +586 -96
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -4014,8 +4014,7 @@ function createSelectColumn() {
|
|
|
4014
4014
|
/**
|
|
4015
4015
|
* 创建操作列
|
|
4016
4016
|
*/
|
|
4017
|
-
function createActionsColumn(
|
|
4018
|
-
const { onEdit, onDelete, onView, onCopy } = config;
|
|
4017
|
+
function createActionsColumn(items) {
|
|
4019
4018
|
return {
|
|
4020
4019
|
id: "actions",
|
|
4021
4020
|
cell: ({ row }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuTrigger, {
|
|
@@ -4026,29 +4025,14 @@ function createActionsColumn(config) {
|
|
|
4026
4025
|
className: "flex size-8 p-0 data-[state=open]:bg-muted",
|
|
4027
4026
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Ellipsis, { className: "size-4" })
|
|
4028
4027
|
})
|
|
4029
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4028
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuContent, {
|
|
4030
4029
|
align: "end",
|
|
4031
4030
|
className: "w-40",
|
|
4032
|
-
children: [
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
onEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
4038
|
-
onClick: () => onEdit(row.original),
|
|
4039
|
-
children: "编辑"
|
|
4040
|
-
}),
|
|
4041
|
-
onCopy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
4042
|
-
onClick: () => onCopy(row.original),
|
|
4043
|
-
children: "复制"
|
|
4044
|
-
}),
|
|
4045
|
-
(onView || onEdit || onCopy) && onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuSeparator, {}),
|
|
4046
|
-
onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
4047
|
-
className: "text-destructive",
|
|
4048
|
-
onClick: () => onDelete(row.original),
|
|
4049
|
-
children: "删除"
|
|
4050
|
-
})
|
|
4051
|
-
]
|
|
4031
|
+
children: items.map((item, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [item.separator && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuSeparator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
4032
|
+
className: item.variant === "destructive" ? "text-destructive" : "",
|
|
4033
|
+
onClick: () => item.onClick(row.original),
|
|
4034
|
+
children: item.label
|
|
4035
|
+
})] }, i))
|
|
4052
4036
|
})] }),
|
|
4053
4037
|
size: 40
|
|
4054
4038
|
};
|
|
@@ -4830,7 +4814,7 @@ function getComponentProps(type, parsed) {
|
|
|
4830
4814
|
function createFormSchema(schema, options) {
|
|
4831
4815
|
const shape = schema.shape;
|
|
4832
4816
|
const properties = {};
|
|
4833
|
-
const { overrides, exclude = [], layout = "vertical", gridColumns =
|
|
4817
|
+
const { overrides, exclude = [], layout = "vertical", gridColumns = 1, labelAlign = "top", labelWidth, labelCol, wrapperCol } = options ?? {};
|
|
4834
4818
|
const decoratorProps = { className: "space-y-2" };
|
|
4835
4819
|
if (labelAlign) decoratorProps.labelAlign = labelAlign;
|
|
4836
4820
|
if (labelWidth) decoratorProps.labelWidth = labelWidth;
|
|
@@ -4895,7 +4879,7 @@ const FormilySwitch = (0, __formily_react.connect)(__pixpilot_shadcn.Switch, (0,
|
|
|
4895
4879
|
value: "checked",
|
|
4896
4880
|
onInput: "onCheckedChange"
|
|
4897
4881
|
}));
|
|
4898
|
-
function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns =
|
|
4882
|
+
function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
|
|
4899
4883
|
const form = (0, react.useMemo)(() => (0, __formily_core.createForm)({ initialValues }), [JSON.stringify(initialValues)]);
|
|
4900
4884
|
const formSchema = (0, react.useMemo)(() => createEditFormSchema(zodSchema, {
|
|
4901
4885
|
overrides,
|
|
@@ -4936,10 +4920,462 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
|
|
|
4936
4920
|
}
|
|
4937
4921
|
const AutoForm = (0, react.forwardRef)(AutoFormInner);
|
|
4938
4922
|
|
|
4923
|
+
//#endregion
|
|
4924
|
+
//#region src/i18n/locale.ts
|
|
4925
|
+
const zhCN = {
|
|
4926
|
+
toolbar: {
|
|
4927
|
+
create: "新建",
|
|
4928
|
+
import: "导入",
|
|
4929
|
+
export: "导出",
|
|
4930
|
+
exportSelected: (count) => `导出(${count})`
|
|
4931
|
+
},
|
|
4932
|
+
rowActions: {
|
|
4933
|
+
view: "查看",
|
|
4934
|
+
edit: "编辑",
|
|
4935
|
+
copy: "复制",
|
|
4936
|
+
delete: "删除"
|
|
4937
|
+
},
|
|
4938
|
+
viewModal: { title: "详情" },
|
|
4939
|
+
boolean: {
|
|
4940
|
+
true: "是",
|
|
4941
|
+
false: "否"
|
|
4942
|
+
},
|
|
4943
|
+
formModal: {
|
|
4944
|
+
createTitle: "新建",
|
|
4945
|
+
editTitle: "编辑",
|
|
4946
|
+
cancel: "取消",
|
|
4947
|
+
create: "创建",
|
|
4948
|
+
save: "保存",
|
|
4949
|
+
submitting: "处理中..."
|
|
4950
|
+
},
|
|
4951
|
+
deleteModal: {
|
|
4952
|
+
title: "确认删除",
|
|
4953
|
+
description: "此操作无法撤销。确定要删除这条记录吗?",
|
|
4954
|
+
cancel: "取消",
|
|
4955
|
+
confirm: "确认删除",
|
|
4956
|
+
confirming: "删除中..."
|
|
4957
|
+
},
|
|
4958
|
+
importDialog: {
|
|
4959
|
+
title: "导入数据",
|
|
4960
|
+
uploadDescription: "上传 CSV 或 JSON 文件以批量导入数据",
|
|
4961
|
+
previewDescription: (count) => `已解析 ${count} 条数据,确认后开始导入`,
|
|
4962
|
+
importingDescription: "正在导入数据...",
|
|
4963
|
+
doneDescription: "导入完成",
|
|
4964
|
+
dragHint: "拖拽文件到此处,或点击选择文件",
|
|
4965
|
+
formatHint: "支持 CSV、JSON 格式",
|
|
4966
|
+
downloadTemplate: "下载 CSV 模板",
|
|
4967
|
+
moreColumns: (count) => `+${count} 列`,
|
|
4968
|
+
previewSummary: (rows, fields, format, previewLimit) => `共 ${rows} 条数据${previewLimit ? `(预览前 ${previewLimit} 条)` : ""},${fields} 个字段,格式: ${format.toUpperCase()}`,
|
|
4969
|
+
reselect: "重新选择",
|
|
4970
|
+
confirmImport: "确认导入",
|
|
4971
|
+
importingRows: (count) => `正在导入 ${count} 条数据...`,
|
|
4972
|
+
resultCreated: "新建",
|
|
4973
|
+
resultUpdated: "更新",
|
|
4974
|
+
resultSkipped: "跳过",
|
|
4975
|
+
resultFailed: "验证失败",
|
|
4976
|
+
failedRowHeader: "行号",
|
|
4977
|
+
failedErrorHeader: "错误",
|
|
4978
|
+
close: "关闭",
|
|
4979
|
+
continueImport: "继续导入",
|
|
4980
|
+
errorNoData: "文件中没有数据行",
|
|
4981
|
+
errorParseFailed: "文件解析失败",
|
|
4982
|
+
errorImportFailed: "导入失败"
|
|
4983
|
+
}
|
|
4984
|
+
};
|
|
4985
|
+
const enUS = {
|
|
4986
|
+
toolbar: {
|
|
4987
|
+
create: "New",
|
|
4988
|
+
import: "Import",
|
|
4989
|
+
export: "Export",
|
|
4990
|
+
exportSelected: (count) => `Export (${count})`
|
|
4991
|
+
},
|
|
4992
|
+
rowActions: {
|
|
4993
|
+
view: "View",
|
|
4994
|
+
edit: "Edit",
|
|
4995
|
+
copy: "Copy",
|
|
4996
|
+
delete: "Delete"
|
|
4997
|
+
},
|
|
4998
|
+
viewModal: { title: "Details" },
|
|
4999
|
+
boolean: {
|
|
5000
|
+
true: "Yes",
|
|
5001
|
+
false: "No"
|
|
5002
|
+
},
|
|
5003
|
+
formModal: {
|
|
5004
|
+
createTitle: "New",
|
|
5005
|
+
editTitle: "Edit",
|
|
5006
|
+
cancel: "Cancel",
|
|
5007
|
+
create: "Create",
|
|
5008
|
+
save: "Save",
|
|
5009
|
+
submitting: "Processing..."
|
|
5010
|
+
},
|
|
5011
|
+
deleteModal: {
|
|
5012
|
+
title: "Confirm Delete",
|
|
5013
|
+
description: "This action cannot be undone. Are you sure you want to delete this record?",
|
|
5014
|
+
cancel: "Cancel",
|
|
5015
|
+
confirm: "Delete",
|
|
5016
|
+
confirming: "Deleting..."
|
|
5017
|
+
},
|
|
5018
|
+
importDialog: {
|
|
5019
|
+
title: "Import Data",
|
|
5020
|
+
uploadDescription: "Upload a CSV or JSON file to bulk import data",
|
|
5021
|
+
previewDescription: (count) => `Parsed ${count} records, confirm to start importing`,
|
|
5022
|
+
importingDescription: "Importing data...",
|
|
5023
|
+
doneDescription: "Import complete",
|
|
5024
|
+
dragHint: "Drag file here, or click to select",
|
|
5025
|
+
formatHint: "Supports CSV, JSON formats",
|
|
5026
|
+
downloadTemplate: "Download CSV Template",
|
|
5027
|
+
moreColumns: (count) => `+${count} more`,
|
|
5028
|
+
previewSummary: (rows, fields, format, previewLimit) => `${rows} records${previewLimit ? ` (preview first ${previewLimit})` : ""}, ${fields} fields, format: ${format.toUpperCase()}`,
|
|
5029
|
+
reselect: "Reselect",
|
|
5030
|
+
confirmImport: "Confirm Import",
|
|
5031
|
+
importingRows: (count) => `Importing ${count} records...`,
|
|
5032
|
+
resultCreated: "Created",
|
|
5033
|
+
resultUpdated: "Updated",
|
|
5034
|
+
resultSkipped: "Skipped",
|
|
5035
|
+
resultFailed: "Failed",
|
|
5036
|
+
failedRowHeader: "Row",
|
|
5037
|
+
failedErrorHeader: "Error",
|
|
5038
|
+
close: "Close",
|
|
5039
|
+
continueImport: "Import More",
|
|
5040
|
+
errorNoData: "No data rows found in file",
|
|
5041
|
+
errorParseFailed: "Failed to parse file",
|
|
5042
|
+
errorImportFailed: "Import failed"
|
|
5043
|
+
}
|
|
5044
|
+
};
|
|
5045
|
+
const jaJP = {
|
|
5046
|
+
toolbar: {
|
|
5047
|
+
create: "新規作成",
|
|
5048
|
+
import: "インポート",
|
|
5049
|
+
export: "エクスポート",
|
|
5050
|
+
exportSelected: (count) => `エクスポート(${count})`
|
|
5051
|
+
},
|
|
5052
|
+
rowActions: {
|
|
5053
|
+
view: "詳細",
|
|
5054
|
+
edit: "編集",
|
|
5055
|
+
copy: "コピー",
|
|
5056
|
+
delete: "削除"
|
|
5057
|
+
},
|
|
5058
|
+
viewModal: { title: "詳細" },
|
|
5059
|
+
boolean: {
|
|
5060
|
+
true: "はい",
|
|
5061
|
+
false: "いいえ"
|
|
5062
|
+
},
|
|
5063
|
+
formModal: {
|
|
5064
|
+
createTitle: "新規作成",
|
|
5065
|
+
editTitle: "編集",
|
|
5066
|
+
cancel: "キャンセル",
|
|
5067
|
+
create: "作成",
|
|
5068
|
+
save: "保存",
|
|
5069
|
+
submitting: "処理中..."
|
|
5070
|
+
},
|
|
5071
|
+
deleteModal: {
|
|
5072
|
+
title: "削除の確認",
|
|
5073
|
+
description: "この操作は元に戻せません。このレコードを削除してもよろしいですか?",
|
|
5074
|
+
cancel: "キャンセル",
|
|
5075
|
+
confirm: "削除する",
|
|
5076
|
+
confirming: "削除中..."
|
|
5077
|
+
},
|
|
5078
|
+
importDialog: {
|
|
5079
|
+
title: "データのインポート",
|
|
5080
|
+
uploadDescription: "CSVまたはJSONファイルをアップロードして一括インポート",
|
|
5081
|
+
previewDescription: (count) => `${count}件のデータを解析しました。確認してインポートを開始します`,
|
|
5082
|
+
importingDescription: "データをインポート中...",
|
|
5083
|
+
doneDescription: "インポート完了",
|
|
5084
|
+
dragHint: "ファイルをここにドラッグするか、クリックして選択",
|
|
5085
|
+
formatHint: "CSV・JSON形式に対応",
|
|
5086
|
+
downloadTemplate: "CSVテンプレートをダウンロード",
|
|
5087
|
+
moreColumns: (count) => `+${count}列`,
|
|
5088
|
+
previewSummary: (rows, fields, format, previewLimit) => `${rows}件${previewLimit ? `(上位${previewLimit}件プレビュー)` : ""}、${fields}フィールド、形式: ${format.toUpperCase()}`,
|
|
5089
|
+
reselect: "再選択",
|
|
5090
|
+
confirmImport: "インポートを確認",
|
|
5091
|
+
importingRows: (count) => `${count}件をインポート中...`,
|
|
5092
|
+
resultCreated: "新規作成",
|
|
5093
|
+
resultUpdated: "更新",
|
|
5094
|
+
resultSkipped: "スキップ",
|
|
5095
|
+
resultFailed: "失敗",
|
|
5096
|
+
failedRowHeader: "行番号",
|
|
5097
|
+
failedErrorHeader: "エラー",
|
|
5098
|
+
close: "閉じる",
|
|
5099
|
+
continueImport: "続けてインポート",
|
|
5100
|
+
errorNoData: "ファイルにデータ行がありません",
|
|
5101
|
+
errorParseFailed: "ファイルの解析に失敗しました",
|
|
5102
|
+
errorImportFailed: "インポートに失敗しました"
|
|
5103
|
+
}
|
|
5104
|
+
};
|
|
5105
|
+
const koKR = {
|
|
5106
|
+
toolbar: {
|
|
5107
|
+
create: "새로 만들기",
|
|
5108
|
+
import: "가져오기",
|
|
5109
|
+
export: "내보내기",
|
|
5110
|
+
exportSelected: (count) => `내보내기(${count})`
|
|
5111
|
+
},
|
|
5112
|
+
rowActions: {
|
|
5113
|
+
view: "보기",
|
|
5114
|
+
edit: "편집",
|
|
5115
|
+
copy: "복사",
|
|
5116
|
+
delete: "삭제"
|
|
5117
|
+
},
|
|
5118
|
+
viewModal: { title: "상세 정보" },
|
|
5119
|
+
boolean: {
|
|
5120
|
+
true: "예",
|
|
5121
|
+
false: "아니요"
|
|
5122
|
+
},
|
|
5123
|
+
formModal: {
|
|
5124
|
+
createTitle: "새로 만들기",
|
|
5125
|
+
editTitle: "편집",
|
|
5126
|
+
cancel: "취소",
|
|
5127
|
+
create: "만들기",
|
|
5128
|
+
save: "저장",
|
|
5129
|
+
submitting: "처리 중..."
|
|
5130
|
+
},
|
|
5131
|
+
deleteModal: {
|
|
5132
|
+
title: "삭제 확인",
|
|
5133
|
+
description: "이 작업은 취소할 수 없습니다. 이 레코드를 삭제하시겠습니까?",
|
|
5134
|
+
cancel: "취소",
|
|
5135
|
+
confirm: "삭제",
|
|
5136
|
+
confirming: "삭제 중..."
|
|
5137
|
+
},
|
|
5138
|
+
importDialog: {
|
|
5139
|
+
title: "데이터 가져오기",
|
|
5140
|
+
uploadDescription: "CSV 또는 JSON 파일을 업로드하여 일괄 가져오기",
|
|
5141
|
+
previewDescription: (count) => `${count}개의 데이터를 분석했습니다. 확인 후 가져오기를 시작합니다`,
|
|
5142
|
+
importingDescription: "데이터를 가져오는 중...",
|
|
5143
|
+
doneDescription: "가져오기 완료",
|
|
5144
|
+
dragHint: "파일을 여기에 드래그하거나 클릭하여 선택",
|
|
5145
|
+
formatHint: "CSV, JSON 형식 지원",
|
|
5146
|
+
downloadTemplate: "CSV 템플릿 다운로드",
|
|
5147
|
+
moreColumns: (count) => `+${count}열 더`,
|
|
5148
|
+
previewSummary: (rows, fields, format, previewLimit) => `${rows}개 레코드${previewLimit ? ` (상위 ${previewLimit}개 미리보기)` : ""}, ${fields}개 필드, 형식: ${format.toUpperCase()}`,
|
|
5149
|
+
reselect: "다시 선택",
|
|
5150
|
+
confirmImport: "가져오기 확인",
|
|
5151
|
+
importingRows: (count) => `${count}개의 레코드를 가져오는 중...`,
|
|
5152
|
+
resultCreated: "생성됨",
|
|
5153
|
+
resultUpdated: "업데이트됨",
|
|
5154
|
+
resultSkipped: "건너뜀",
|
|
5155
|
+
resultFailed: "실패",
|
|
5156
|
+
failedRowHeader: "행 번호",
|
|
5157
|
+
failedErrorHeader: "오류",
|
|
5158
|
+
close: "닫기",
|
|
5159
|
+
continueImport: "계속 가져오기",
|
|
5160
|
+
errorNoData: "파일에 데이터 행이 없습니다",
|
|
5161
|
+
errorParseFailed: "파일 파싱에 실패했습니다",
|
|
5162
|
+
errorImportFailed: "가져오기에 실패했습니다"
|
|
5163
|
+
}
|
|
5164
|
+
};
|
|
5165
|
+
const frFR = {
|
|
5166
|
+
toolbar: {
|
|
5167
|
+
create: "Nouveau",
|
|
5168
|
+
import: "Importer",
|
|
5169
|
+
export: "Exporter",
|
|
5170
|
+
exportSelected: (count) => `Exporter (${count})`
|
|
5171
|
+
},
|
|
5172
|
+
rowActions: {
|
|
5173
|
+
view: "Voir",
|
|
5174
|
+
edit: "Modifier",
|
|
5175
|
+
copy: "Copier",
|
|
5176
|
+
delete: "Supprimer"
|
|
5177
|
+
},
|
|
5178
|
+
viewModal: { title: "Détails" },
|
|
5179
|
+
boolean: {
|
|
5180
|
+
true: "Oui",
|
|
5181
|
+
false: "Non"
|
|
5182
|
+
},
|
|
5183
|
+
formModal: {
|
|
5184
|
+
createTitle: "Nouveau",
|
|
5185
|
+
editTitle: "Modifier",
|
|
5186
|
+
cancel: "Annuler",
|
|
5187
|
+
create: "Créer",
|
|
5188
|
+
save: "Enregistrer",
|
|
5189
|
+
submitting: "En cours..."
|
|
5190
|
+
},
|
|
5191
|
+
deleteModal: {
|
|
5192
|
+
title: "Confirmer la suppression",
|
|
5193
|
+
description: "Cette action est irréversible. Voulez-vous vraiment supprimer cet enregistrement ?",
|
|
5194
|
+
cancel: "Annuler",
|
|
5195
|
+
confirm: "Supprimer",
|
|
5196
|
+
confirming: "Suppression..."
|
|
5197
|
+
},
|
|
5198
|
+
importDialog: {
|
|
5199
|
+
title: "Importer des données",
|
|
5200
|
+
uploadDescription: "Téléchargez un fichier CSV ou JSON pour importer en masse",
|
|
5201
|
+
previewDescription: (count) => `${count} enregistrements analysés, confirmez pour démarrer l'import`,
|
|
5202
|
+
importingDescription: "Importation en cours...",
|
|
5203
|
+
doneDescription: "Import terminé",
|
|
5204
|
+
dragHint: "Glissez un fichier ici ou cliquez pour sélectionner",
|
|
5205
|
+
formatHint: "Formats CSV et JSON acceptés",
|
|
5206
|
+
downloadTemplate: "Télécharger le modèle CSV",
|
|
5207
|
+
moreColumns: (count) => `+${count} colonnes`,
|
|
5208
|
+
previewSummary: (rows, fields, format, previewLimit) => `${rows} enregistrements${previewLimit ? ` (aperçu des ${previewLimit} premiers)` : ""}, ${fields} champs, format : ${format.toUpperCase()}`,
|
|
5209
|
+
reselect: "Resélectionner",
|
|
5210
|
+
confirmImport: "Confirmer l'import",
|
|
5211
|
+
importingRows: (count) => `Importation de ${count} enregistrements...`,
|
|
5212
|
+
resultCreated: "Créés",
|
|
5213
|
+
resultUpdated: "Mis à jour",
|
|
5214
|
+
resultSkipped: "Ignorés",
|
|
5215
|
+
resultFailed: "Échoués",
|
|
5216
|
+
failedRowHeader: "Ligne",
|
|
5217
|
+
failedErrorHeader: "Erreur",
|
|
5218
|
+
close: "Fermer",
|
|
5219
|
+
continueImport: "Continuer l'import",
|
|
5220
|
+
errorNoData: "Aucune ligne de données dans le fichier",
|
|
5221
|
+
errorParseFailed: "Échec de l'analyse du fichier",
|
|
5222
|
+
errorImportFailed: "Échec de l'importation"
|
|
5223
|
+
}
|
|
5224
|
+
};
|
|
5225
|
+
const deDE = {
|
|
5226
|
+
toolbar: {
|
|
5227
|
+
create: "Neu",
|
|
5228
|
+
import: "Importieren",
|
|
5229
|
+
export: "Exportieren",
|
|
5230
|
+
exportSelected: (count) => `Exportieren (${count})`
|
|
5231
|
+
},
|
|
5232
|
+
rowActions: {
|
|
5233
|
+
view: "Anzeigen",
|
|
5234
|
+
edit: "Bearbeiten",
|
|
5235
|
+
copy: "Kopieren",
|
|
5236
|
+
delete: "Löschen"
|
|
5237
|
+
},
|
|
5238
|
+
viewModal: { title: "Details" },
|
|
5239
|
+
boolean: {
|
|
5240
|
+
true: "Ja",
|
|
5241
|
+
false: "Nein"
|
|
5242
|
+
},
|
|
5243
|
+
formModal: {
|
|
5244
|
+
createTitle: "Neu",
|
|
5245
|
+
editTitle: "Bearbeiten",
|
|
5246
|
+
cancel: "Abbrechen",
|
|
5247
|
+
create: "Erstellen",
|
|
5248
|
+
save: "Speichern",
|
|
5249
|
+
submitting: "Wird verarbeitet..."
|
|
5250
|
+
},
|
|
5251
|
+
deleteModal: {
|
|
5252
|
+
title: "Löschen bestätigen",
|
|
5253
|
+
description: "Diese Aktion kann nicht rückgängig gemacht werden. Möchten Sie diesen Datensatz wirklich löschen?",
|
|
5254
|
+
cancel: "Abbrechen",
|
|
5255
|
+
confirm: "Löschen",
|
|
5256
|
+
confirming: "Wird gelöscht..."
|
|
5257
|
+
},
|
|
5258
|
+
importDialog: {
|
|
5259
|
+
title: "Daten importieren",
|
|
5260
|
+
uploadDescription: "CSV- oder JSON-Datei hochladen, um Daten massenweise zu importieren",
|
|
5261
|
+
previewDescription: (count) => `${count} Datensätze analysiert, bestätigen Sie den Import`,
|
|
5262
|
+
importingDescription: "Daten werden importiert...",
|
|
5263
|
+
doneDescription: "Import abgeschlossen",
|
|
5264
|
+
dragHint: "Datei hierher ziehen oder klicken zum Auswählen",
|
|
5265
|
+
formatHint: "CSV- und JSON-Formate werden unterstützt",
|
|
5266
|
+
downloadTemplate: "CSV-Vorlage herunterladen",
|
|
5267
|
+
moreColumns: (count) => `+${count} Spalten`,
|
|
5268
|
+
previewSummary: (rows, fields, format, previewLimit) => `${rows} Datensätze${previewLimit ? ` (Vorschau der ersten ${previewLimit})` : ""}, ${fields} Felder, Format: ${format.toUpperCase()}`,
|
|
5269
|
+
reselect: "Neu auswählen",
|
|
5270
|
+
confirmImport: "Import bestätigen",
|
|
5271
|
+
importingRows: (count) => `${count} Datensätze werden importiert...`,
|
|
5272
|
+
resultCreated: "Erstellt",
|
|
5273
|
+
resultUpdated: "Aktualisiert",
|
|
5274
|
+
resultSkipped: "Übersprungen",
|
|
5275
|
+
resultFailed: "Fehlgeschlagen",
|
|
5276
|
+
failedRowHeader: "Zeile",
|
|
5277
|
+
failedErrorHeader: "Fehler",
|
|
5278
|
+
close: "Schließen",
|
|
5279
|
+
continueImport: "Weiteren Import starten",
|
|
5280
|
+
errorNoData: "Keine Datenzeilen in der Datei",
|
|
5281
|
+
errorParseFailed: "Datei konnte nicht analysiert werden",
|
|
5282
|
+
errorImportFailed: "Import fehlgeschlagen"
|
|
5283
|
+
}
|
|
5284
|
+
};
|
|
5285
|
+
const esES = {
|
|
5286
|
+
toolbar: {
|
|
5287
|
+
create: "Nuevo",
|
|
5288
|
+
import: "Importar",
|
|
5289
|
+
export: "Exportar",
|
|
5290
|
+
exportSelected: (count) => `Exportar (${count})`
|
|
5291
|
+
},
|
|
5292
|
+
rowActions: {
|
|
5293
|
+
view: "Ver",
|
|
5294
|
+
edit: "Editar",
|
|
5295
|
+
copy: "Copiar",
|
|
5296
|
+
delete: "Eliminar"
|
|
5297
|
+
},
|
|
5298
|
+
viewModal: { title: "Detalles" },
|
|
5299
|
+
boolean: {
|
|
5300
|
+
true: "Sí",
|
|
5301
|
+
false: "No"
|
|
5302
|
+
},
|
|
5303
|
+
formModal: {
|
|
5304
|
+
createTitle: "Nuevo",
|
|
5305
|
+
editTitle: "Editar",
|
|
5306
|
+
cancel: "Cancelar",
|
|
5307
|
+
create: "Crear",
|
|
5308
|
+
save: "Guardar",
|
|
5309
|
+
submitting: "Procesando..."
|
|
5310
|
+
},
|
|
5311
|
+
deleteModal: {
|
|
5312
|
+
title: "Confirmar eliminación",
|
|
5313
|
+
description: "Esta acción no se puede deshacer. ¿Está seguro de que desea eliminar este registro?",
|
|
5314
|
+
cancel: "Cancelar",
|
|
5315
|
+
confirm: "Eliminar",
|
|
5316
|
+
confirming: "Eliminando..."
|
|
5317
|
+
},
|
|
5318
|
+
importDialog: {
|
|
5319
|
+
title: "Importar datos",
|
|
5320
|
+
uploadDescription: "Suba un archivo CSV o JSON para importar datos de forma masiva",
|
|
5321
|
+
previewDescription: (count) => `Se analizaron ${count} registros, confirme para iniciar la importación`,
|
|
5322
|
+
importingDescription: "Importando datos...",
|
|
5323
|
+
doneDescription: "Importación completada",
|
|
5324
|
+
dragHint: "Arrastre el archivo aquí o haga clic para seleccionar",
|
|
5325
|
+
formatHint: "Formatos CSV y JSON compatibles",
|
|
5326
|
+
downloadTemplate: "Descargar plantilla CSV",
|
|
5327
|
+
moreColumns: (count) => `+${count} columnas`,
|
|
5328
|
+
previewSummary: (rows, fields, format, previewLimit) => `${rows} registros${previewLimit ? ` (vista previa de los primeros ${previewLimit})` : ""}, ${fields} campos, formato: ${format.toUpperCase()}`,
|
|
5329
|
+
reselect: "Volver a seleccionar",
|
|
5330
|
+
confirmImport: "Confirmar importación",
|
|
5331
|
+
importingRows: (count) => `Importando ${count} registros...`,
|
|
5332
|
+
resultCreated: "Creados",
|
|
5333
|
+
resultUpdated: "Actualizados",
|
|
5334
|
+
resultSkipped: "Omitidos",
|
|
5335
|
+
resultFailed: "Fallidos",
|
|
5336
|
+
failedRowHeader: "Fila",
|
|
5337
|
+
failedErrorHeader: "Error",
|
|
5338
|
+
close: "Cerrar",
|
|
5339
|
+
continueImport: "Continuar importando",
|
|
5340
|
+
errorNoData: "No se encontraron filas de datos en el archivo",
|
|
5341
|
+
errorParseFailed: "Error al analizar el archivo",
|
|
5342
|
+
errorImportFailed: "Error en la importación"
|
|
5343
|
+
}
|
|
5344
|
+
};
|
|
5345
|
+
const BUILTIN_LOCALES = {
|
|
5346
|
+
"zh-CN": zhCN,
|
|
5347
|
+
"en-US": enUS,
|
|
5348
|
+
"ja-JP": jaJP,
|
|
5349
|
+
"ko-KR": koKR,
|
|
5350
|
+
"fr-FR": frFR,
|
|
5351
|
+
"de-DE": deDE,
|
|
5352
|
+
"es-ES": esES
|
|
5353
|
+
};
|
|
5354
|
+
function deepMerge(target, source) {
|
|
5355
|
+
const result = { ...target };
|
|
5356
|
+
for (const key of Object.keys(source)) {
|
|
5357
|
+
const sv = source[key];
|
|
5358
|
+
const tv = target[key];
|
|
5359
|
+
if (sv !== void 0 && sv !== null && typeof sv === "object" && !Array.isArray(sv) && typeof tv === "object" && tv !== null && !Array.isArray(tv)) result[key] = deepMerge(tv, sv);
|
|
5360
|
+
else if (sv !== void 0) result[key] = sv;
|
|
5361
|
+
}
|
|
5362
|
+
return result;
|
|
5363
|
+
}
|
|
5364
|
+
/**
|
|
5365
|
+
* 解析 locale prop 为完整的 AutoCrudLocale
|
|
5366
|
+
* - string → 内置语言(fallback: zh-CN)
|
|
5367
|
+
* - object → 以 zh-CN 为基础深合并
|
|
5368
|
+
*/
|
|
5369
|
+
function resolveLocale(localeProp) {
|
|
5370
|
+
if (!localeProp) return zhCN;
|
|
5371
|
+
if (typeof localeProp === "string") return BUILTIN_LOCALES[localeProp] ?? zhCN;
|
|
5372
|
+
return deepMerge(zhCN, localeProp);
|
|
5373
|
+
}
|
|
5374
|
+
|
|
4939
5375
|
//#endregion
|
|
4940
5376
|
//#region src/components/auto-crud/crud-form-modal.tsx
|
|
4941
|
-
function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubmit, loading = false, variant = "dialog", overrides, title, labelAlign, labelWidth }) {
|
|
4942
|
-
const defaultTitle = mode === "create" ?
|
|
5377
|
+
function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubmit, loading = false, variant = "dialog", overrides, title, locale = zhCN.formModal, gridColumns, labelAlign, labelWidth }) {
|
|
5378
|
+
const defaultTitle = mode === "create" ? locale.createTitle : locale.editTitle;
|
|
4943
5379
|
const formRef = (0, react.useRef)(null);
|
|
4944
5380
|
const handleSubmit = async () => {
|
|
4945
5381
|
await formRef.current?.submit();
|
|
@@ -4955,12 +5391,12 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
|
|
|
4955
5391
|
type: "button",
|
|
4956
5392
|
variant: "outline",
|
|
4957
5393
|
onClick: () => onOpenChange(false),
|
|
4958
|
-
children:
|
|
5394
|
+
children: locale.cancel
|
|
4959
5395
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
|
|
4960
5396
|
type: "button",
|
|
4961
5397
|
onClick: handleSubmit,
|
|
4962
5398
|
disabled: loading,
|
|
4963
|
-
children: loading ?
|
|
5399
|
+
children: loading ? locale.submitting : mode === "create" ? locale.create : locale.save
|
|
4964
5400
|
})]
|
|
4965
5401
|
}),
|
|
4966
5402
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoForm, {
|
|
@@ -4971,6 +5407,7 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
|
|
|
4971
5407
|
loading,
|
|
4972
5408
|
onSubmit,
|
|
4973
5409
|
overrides,
|
|
5410
|
+
gridColumns,
|
|
4974
5411
|
labelAlign,
|
|
4975
5412
|
labelWidth,
|
|
4976
5413
|
showSubmitButton: false
|
|
@@ -4980,7 +5417,7 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
|
|
|
4980
5417
|
|
|
4981
5418
|
//#endregion
|
|
4982
5419
|
//#region src/components/auto-crud/import-dialog.tsx
|
|
4983
|
-
function ImportDialog({ open, onOpenChange, onImport, columns = [], title =
|
|
5420
|
+
function ImportDialog({ open, onOpenChange, onImport, columns = [], title, locale = zhCN.importDialog }) {
|
|
4984
5421
|
const [step, setStep] = react.useState("upload");
|
|
4985
5422
|
const [parsedData, setParsedData] = react.useState(null);
|
|
4986
5423
|
const [error, setError] = react.useState(null);
|
|
@@ -5003,13 +5440,13 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5003
5440
|
try {
|
|
5004
5441
|
const data = await parseImportFile(file);
|
|
5005
5442
|
if (data.rows.length === 0) {
|
|
5006
|
-
setError(
|
|
5443
|
+
setError(locale.errorNoData);
|
|
5007
5444
|
return;
|
|
5008
5445
|
}
|
|
5009
5446
|
setParsedData(data);
|
|
5010
5447
|
setStep("preview");
|
|
5011
5448
|
} catch (e) {
|
|
5012
|
-
setError(e instanceof Error ? e.message :
|
|
5449
|
+
setError(e instanceof Error ? e.message : locale.errorParseFailed);
|
|
5013
5450
|
}
|
|
5014
5451
|
}, []);
|
|
5015
5452
|
const handleDrop = react.useCallback((e) => {
|
|
@@ -5029,7 +5466,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5029
5466
|
setResult(await onImport(parsedData.rows));
|
|
5030
5467
|
setStep("result");
|
|
5031
5468
|
} catch (e) {
|
|
5032
|
-
setError(e instanceof Error ? e.message :
|
|
5469
|
+
setError(e instanceof Error ? e.message : locale.errorImportFailed);
|
|
5033
5470
|
setStep("preview");
|
|
5034
5471
|
}
|
|
5035
5472
|
}, [parsedData, onImport]);
|
|
@@ -5049,11 +5486,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5049
5486
|
onOpenChange: handleOpenChange,
|
|
5050
5487
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogContent, {
|
|
5051
5488
|
className: "sm:max-w-[600px]",
|
|
5052
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogDescription, { children: [
|
|
5053
|
-
step === "upload" &&
|
|
5054
|
-
step === "preview" &&
|
|
5055
|
-
step === "importing" &&
|
|
5056
|
-
step === "result" &&
|
|
5489
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: title ?? locale.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogDescription, { children: [
|
|
5490
|
+
step === "upload" && locale.uploadDescription,
|
|
5491
|
+
step === "preview" && locale.previewDescription(parsedData?.rows.length ?? 0),
|
|
5492
|
+
step === "importing" && locale.importingDescription,
|
|
5493
|
+
step === "result" && locale.doneDescription
|
|
5057
5494
|
] })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5058
5495
|
className: "space-y-4",
|
|
5059
5496
|
children: [
|
|
@@ -5084,11 +5521,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5084
5521
|
}),
|
|
5085
5522
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5086
5523
|
className: "text-sm text-muted-foreground",
|
|
5087
|
-
children:
|
|
5524
|
+
children: locale.dragHint
|
|
5088
5525
|
}),
|
|
5089
5526
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5090
5527
|
className: "text-xs text-muted-foreground/60",
|
|
5091
|
-
children:
|
|
5528
|
+
children: locale.formatHint
|
|
5092
5529
|
})
|
|
5093
5530
|
]
|
|
5094
5531
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
@@ -5103,7 +5540,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5103
5540
|
size: "sm",
|
|
5104
5541
|
className: "w-full",
|
|
5105
5542
|
onClick: handleDownloadTemplate,
|
|
5106
|
-
children:
|
|
5543
|
+
children: locale.downloadTemplate
|
|
5107
5544
|
})] }),
|
|
5108
5545
|
step === "preview" && parsedData && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5109
5546
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -5123,13 +5560,9 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5123
5560
|
className: "px-3 py-2 text-left font-medium text-muted-foreground",
|
|
5124
5561
|
children: h
|
|
5125
5562
|
}, h)),
|
|
5126
|
-
parsedData.headers.length > 6 && /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5563
|
+
parsedData.headers.length > 6 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5127
5564
|
className: "px-3 py-2 text-left font-medium text-muted-foreground",
|
|
5128
|
-
children:
|
|
5129
|
-
"+",
|
|
5130
|
-
parsedData.headers.length - 6,
|
|
5131
|
-
" 列"
|
|
5132
|
-
]
|
|
5565
|
+
children: locale.moreColumns(parsedData.headers.length - 6)
|
|
5133
5566
|
})
|
|
5134
5567
|
] })
|
|
5135
5568
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: parsedData.rows.slice(0, 10).map((row, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
@@ -5152,40 +5585,27 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5152
5585
|
})
|
|
5153
5586
|
})
|
|
5154
5587
|
}),
|
|
5155
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5588
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5156
5589
|
className: "text-sm text-muted-foreground",
|
|
5157
|
-
children:
|
|
5158
|
-
"共 ",
|
|
5159
|
-
parsedData.rows.length,
|
|
5160
|
-
" 条数据",
|
|
5161
|
-
parsedData.rows.length > 10 && "(预览前 10 条)",
|
|
5162
|
-
",",
|
|
5163
|
-
parsedData.headers.length,
|
|
5164
|
-
" 个字段 ,格式: ",
|
|
5165
|
-
parsedData.format.toUpperCase()
|
|
5166
|
-
]
|
|
5590
|
+
children: locale.previewSummary(parsedData.rows.length, parsedData.headers.length, parsedData.format, parsedData.rows.length > 10 ? 10 : void 0)
|
|
5167
5591
|
}),
|
|
5168
5592
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5169
5593
|
className: "flex gap-2 justify-end",
|
|
5170
5594
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
|
|
5171
5595
|
variant: "outline",
|
|
5172
5596
|
onClick: reset,
|
|
5173
|
-
children:
|
|
5597
|
+
children: locale.reselect
|
|
5174
5598
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
|
|
5175
5599
|
onClick: handleImport,
|
|
5176
|
-
children:
|
|
5600
|
+
children: locale.confirmImport
|
|
5177
5601
|
})]
|
|
5178
5602
|
})
|
|
5179
5603
|
] }),
|
|
5180
5604
|
step === "importing" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5181
5605
|
className: "flex flex-col items-center gap-4 py-8",
|
|
5182
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" }), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5606
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5183
5607
|
className: "text-sm text-muted-foreground",
|
|
5184
|
-
children:
|
|
5185
|
-
"正在导入 ",
|
|
5186
|
-
parsedData?.rows.length ?? 0,
|
|
5187
|
-
" 条数据..."
|
|
5188
|
-
]
|
|
5608
|
+
children: locale.importingRows(parsedData?.rows.length ?? 0)
|
|
5189
5609
|
})]
|
|
5190
5610
|
}),
|
|
5191
5611
|
step === "result" && result && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -5200,7 +5620,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5200
5620
|
children: result.success
|
|
5201
5621
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5202
5622
|
className: "text-xs text-green-600/80",
|
|
5203
|
-
children:
|
|
5623
|
+
children: locale.resultCreated
|
|
5204
5624
|
})]
|
|
5205
5625
|
}),
|
|
5206
5626
|
(result.updated ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -5210,7 +5630,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5210
5630
|
children: result.updated
|
|
5211
5631
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5212
5632
|
className: "text-xs text-blue-600/80",
|
|
5213
|
-
children:
|
|
5633
|
+
children: locale.resultUpdated
|
|
5214
5634
|
})]
|
|
5215
5635
|
}),
|
|
5216
5636
|
result.skipped > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -5220,7 +5640,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5220
5640
|
children: result.skipped
|
|
5221
5641
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5222
5642
|
className: "text-xs text-yellow-600/80",
|
|
5223
|
-
children:
|
|
5643
|
+
children: locale.resultSkipped
|
|
5224
5644
|
})]
|
|
5225
5645
|
}),
|
|
5226
5646
|
result.failed.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -5230,7 +5650,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5230
5650
|
children: result.failed.length
|
|
5231
5651
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5232
5652
|
className: "text-xs text-red-600/80",
|
|
5233
|
-
children:
|
|
5653
|
+
children: locale.resultFailed
|
|
5234
5654
|
})]
|
|
5235
5655
|
})
|
|
5236
5656
|
]
|
|
@@ -5244,10 +5664,10 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5244
5664
|
className: "sticky top-0 bg-red-50 dark:bg-red-950/30",
|
|
5245
5665
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5246
5666
|
className: "px-3 py-2 text-left font-medium text-red-600",
|
|
5247
|
-
children:
|
|
5667
|
+
children: locale.failedRowHeader
|
|
5248
5668
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5249
5669
|
className: "px-3 py-2 text-left font-medium text-red-600",
|
|
5250
|
-
children:
|
|
5670
|
+
children: locale.failedErrorHeader
|
|
5251
5671
|
})] })
|
|
5252
5672
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: result.failed.map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
5253
5673
|
className: "border-t border-red-100 dark:border-red-900",
|
|
@@ -5267,11 +5687,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
|
|
|
5267
5687
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
|
|
5268
5688
|
variant: "outline",
|
|
5269
5689
|
onClick: () => handleOpenChange(false),
|
|
5270
|
-
children:
|
|
5690
|
+
children: locale.close
|
|
5271
5691
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
|
|
5272
5692
|
variant: "outline",
|
|
5273
5693
|
onClick: reset,
|
|
5274
|
-
children:
|
|
5694
|
+
children: locale.continueImport
|
|
5275
5695
|
})]
|
|
5276
5696
|
})] }),
|
|
5277
5697
|
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -5421,13 +5841,13 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
|
|
|
5421
5841
|
/**
|
|
5422
5842
|
* 渲染字段值
|
|
5423
5843
|
*/
|
|
5424
|
-
function renderFieldValue(value, type) {
|
|
5844
|
+
function renderFieldValue(value, type, booleanLocale) {
|
|
5425
5845
|
if (value === null || value === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5426
5846
|
className: "text-muted-foreground",
|
|
5427
5847
|
children: "-"
|
|
5428
5848
|
});
|
|
5429
5849
|
switch (type) {
|
|
5430
|
-
case "boolean": return value ?
|
|
5850
|
+
case "boolean": return value ? booleanLocale.true : booleanLocale.false;
|
|
5431
5851
|
case "date": return formatDate(value);
|
|
5432
5852
|
case "enum": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
5433
5853
|
variant: "outline",
|
|
@@ -5450,7 +5870,7 @@ function renderFieldValue(value, type) {
|
|
|
5450
5870
|
/**
|
|
5451
5871
|
* ViewModal 组件 - 详情查看弹窗
|
|
5452
5872
|
*/
|
|
5453
|
-
function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldConfig, denyFields }) {
|
|
5873
|
+
function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldConfig, denyFields, locale }) {
|
|
5454
5874
|
if (!data) return null;
|
|
5455
5875
|
const shape = schema.shape;
|
|
5456
5876
|
const denySet = new Set(denyFields ?? []);
|
|
@@ -5470,7 +5890,7 @@ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldCon
|
|
|
5470
5890
|
children: label
|
|
5471
5891
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
5472
5892
|
className: "col-span-2 text-sm",
|
|
5473
|
-
children: renderFieldValue(value, parsed.type)
|
|
5893
|
+
children: renderFieldValue(value, parsed.type, locale.boolean)
|
|
5474
5894
|
})]
|
|
5475
5895
|
}, key);
|
|
5476
5896
|
})
|
|
@@ -5478,23 +5898,89 @@ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldCon
|
|
|
5478
5898
|
if (variant === "sheet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Sheet, {
|
|
5479
5899
|
open,
|
|
5480
5900
|
onOpenChange,
|
|
5481
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.SheetContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetTitle, { children:
|
|
5901
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.SheetContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetTitle, { children: locale.viewModal.title }) }), content] })
|
|
5482
5902
|
});
|
|
5483
5903
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Dialog, {
|
|
5484
5904
|
open,
|
|
5485
5905
|
onOpenChange,
|
|
5486
5906
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogContent, {
|
|
5487
5907
|
className: "max-w-2xl max-h-[80vh] overflow-y-auto",
|
|
5488
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children:
|
|
5908
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: locale.viewModal.title }) }), content]
|
|
5489
5909
|
})
|
|
5490
5910
|
});
|
|
5491
5911
|
}
|
|
5912
|
+
function resolveActions(items, defaults, rowActionsLocale) {
|
|
5913
|
+
const defaultItems = [
|
|
5914
|
+
{
|
|
5915
|
+
label: rowActionsLocale.view,
|
|
5916
|
+
onClick: defaults.openView
|
|
5917
|
+
},
|
|
5918
|
+
...defaults.openEdit ? [{
|
|
5919
|
+
label: rowActionsLocale.edit,
|
|
5920
|
+
onClick: defaults.openEdit
|
|
5921
|
+
}] : [],
|
|
5922
|
+
...defaults.copyRow ? [{
|
|
5923
|
+
label: rowActionsLocale.copy,
|
|
5924
|
+
onClick: defaults.copyRow
|
|
5925
|
+
}] : [],
|
|
5926
|
+
...defaults.openDelete ? [{
|
|
5927
|
+
label: rowActionsLocale.delete,
|
|
5928
|
+
onClick: defaults.openDelete,
|
|
5929
|
+
separator: true,
|
|
5930
|
+
variant: "destructive"
|
|
5931
|
+
}] : []
|
|
5932
|
+
];
|
|
5933
|
+
if (!items || items.length === 0) return defaultItems;
|
|
5934
|
+
if (!items.some((i) => i.type !== "custom")) {
|
|
5935
|
+
const startItems = items.filter((i) => i.type === "custom" && i.position === "start").map(({ label, onClick, separator, variant }) => ({
|
|
5936
|
+
label,
|
|
5937
|
+
onClick,
|
|
5938
|
+
separator,
|
|
5939
|
+
variant
|
|
5940
|
+
}));
|
|
5941
|
+
const endItems = items.filter((i) => i.type === "custom" && i.position !== "start").map(({ label, onClick, separator, variant }) => ({
|
|
5942
|
+
label,
|
|
5943
|
+
onClick,
|
|
5944
|
+
separator,
|
|
5945
|
+
variant
|
|
5946
|
+
}));
|
|
5947
|
+
return [
|
|
5948
|
+
...startItems,
|
|
5949
|
+
...defaultItems,
|
|
5950
|
+
...endItems
|
|
5951
|
+
];
|
|
5952
|
+
}
|
|
5953
|
+
const handlerMap = {
|
|
5954
|
+
view: defaults.openView,
|
|
5955
|
+
edit: defaults.openEdit,
|
|
5956
|
+
copy: defaults.copyRow,
|
|
5957
|
+
delete: defaults.openDelete
|
|
5958
|
+
};
|
|
5959
|
+
const variantMap = { delete: "destructive" };
|
|
5960
|
+
return items.flatMap((item) => {
|
|
5961
|
+
if (item.type === "custom") return [{
|
|
5962
|
+
label: item.label,
|
|
5963
|
+
onClick: item.onClick,
|
|
5964
|
+
separator: item.separator,
|
|
5965
|
+
variant: item.variant
|
|
5966
|
+
}];
|
|
5967
|
+
const handler = item.onClick ?? handlerMap[item.type];
|
|
5968
|
+
if (!handler) return [];
|
|
5969
|
+
return [{
|
|
5970
|
+
label: item.label ?? rowActionsLocale[item.type],
|
|
5971
|
+
onClick: handler,
|
|
5972
|
+
separator: item.separator,
|
|
5973
|
+
variant: variantMap[item.type]
|
|
5974
|
+
}];
|
|
5975
|
+
});
|
|
5976
|
+
}
|
|
5492
5977
|
/**
|
|
5493
5978
|
* AutoCrudTable 组件
|
|
5494
5979
|
*
|
|
5495
5980
|
* 高级 CRUD 表格组件,封装了完整的增删改查流程
|
|
5496
5981
|
*/
|
|
5497
|
-
function AutoCrudTable({ title, description, schema, resource, fields, table: tableConfig, form: formConfig, slots, permissions }) {
|
|
5982
|
+
function AutoCrudTable({ title, description, schema, resource, fields, table: tableConfig, form: formConfig, slots, permissions, actions: actionItems, locale: localeProp }) {
|
|
5983
|
+
const locale = resolveLocale(localeProp);
|
|
5498
5984
|
const can = {
|
|
5499
5985
|
create: permissions?.can?.create ?? true,
|
|
5500
5986
|
update: permissions?.can?.update ?? true,
|
|
@@ -5587,18 +6073,18 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
5587
6073
|
variant: "outline",
|
|
5588
6074
|
size: "sm",
|
|
5589
6075
|
onClick: () => setImportOpen(true),
|
|
5590
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Download, { className: "mr-2 h-4 w-4" }),
|
|
6076
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Download, { className: "mr-2 h-4 w-4" }), locale.toolbar.import]
|
|
5591
6077
|
}),
|
|
5592
6078
|
canExport && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
5593
6079
|
variant: "outline",
|
|
5594
6080
|
size: "sm",
|
|
5595
6081
|
onClick: handleExportClick,
|
|
5596
6082
|
disabled: exporting || selectedCount === 0 && !resource.handlers.export,
|
|
5597
|
-
children: [exporting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "mr-2 h-4 w-4" }), selectedCount > 0 ?
|
|
6083
|
+
children: [exporting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "mr-2 h-4 w-4" }), selectedCount > 0 ? locale.toolbar.exportSelected(selectedCount) : locale.toolbar.export]
|
|
5598
6084
|
}),
|
|
5599
6085
|
can.create && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
|
|
5600
6086
|
onClick: resource.handlers.openCreate,
|
|
5601
|
-
children:
|
|
6087
|
+
children: locale.toolbar.create
|
|
5602
6088
|
})
|
|
5603
6089
|
]
|
|
5604
6090
|
})]
|
|
@@ -5610,12 +6096,12 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
5610
6096
|
overrides: tableOverrides,
|
|
5611
6097
|
exclude: hiddenColumns,
|
|
5612
6098
|
filterMode: tableConfig?.filterModes,
|
|
5613
|
-
actions: {
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
},
|
|
6099
|
+
actions: resolveActions(actionItems, {
|
|
6100
|
+
openView: resource.handlers.openView,
|
|
6101
|
+
openEdit: can.update ? resource.handlers.openEdit : void 0,
|
|
6102
|
+
copyRow: can.create ? resource.handlers.copyRow : void 0,
|
|
6103
|
+
openDelete: can.delete ? resource.handlers.openDelete : void 0
|
|
6104
|
+
}, locale.rowActions),
|
|
5619
6105
|
onDeleteSelected: can.delete ? resource.handlers.deleteMany : void 0,
|
|
5620
6106
|
onUpdateSelected: can.update ? resource.handlers.updateMany : void 0,
|
|
5621
6107
|
batchUpdateFields: can.update ? batchFields : void 0,
|
|
@@ -5636,7 +6122,9 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
5636
6122
|
},
|
|
5637
6123
|
loading: resource.mutations.isCreating || resource.mutations.isUpdating,
|
|
5638
6124
|
variant: resource.modal.variant,
|
|
5639
|
-
overrides: formOverrides
|
|
6125
|
+
overrides: formOverrides,
|
|
6126
|
+
locale: locale.formModal,
|
|
6127
|
+
gridColumns: formConfig?.columns
|
|
5640
6128
|
}),
|
|
5641
6129
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModal, {
|
|
5642
6130
|
open: resource.modal.viewOpen,
|
|
@@ -5645,22 +6133,24 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
5645
6133
|
data: resource.modal.selected,
|
|
5646
6134
|
schema,
|
|
5647
6135
|
fields,
|
|
5648
|
-
denyFields
|
|
6136
|
+
denyFields,
|
|
6137
|
+
locale
|
|
5649
6138
|
}),
|
|
5650
6139
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialog, {
|
|
5651
6140
|
open: resource.modal.deleteOpen,
|
|
5652
6141
|
onOpenChange: (open) => !open && resource.handlers.closeModals(),
|
|
5653
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogTitle, { children:
|
|
6142
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogTitle, { children: locale.deleteModal.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogDescription, { children: locale.deleteModal.description })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogFooter, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogCancel, { children: locale.deleteModal.cancel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogAction, {
|
|
5654
6143
|
onClick: resource.handlers.confirmDelete,
|
|
5655
6144
|
disabled: resource.mutations.isDeleting,
|
|
5656
|
-
children: resource.mutations.isDeleting ?
|
|
6145
|
+
children: resource.mutations.isDeleting ? locale.deleteModal.confirming : locale.deleteModal.confirm
|
|
5657
6146
|
})] })] })
|
|
5658
6147
|
}),
|
|
5659
6148
|
canImport && resource.handlers.import && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImportDialog, {
|
|
5660
6149
|
open: importOpen,
|
|
5661
6150
|
onOpenChange: setImportOpen,
|
|
5662
6151
|
onImport: resource.handlers.import,
|
|
5663
|
-
columns: importColumns
|
|
6152
|
+
columns: importColumns,
|
|
6153
|
+
locale: locale.importDialog
|
|
5664
6154
|
})
|
|
5665
6155
|
]
|
|
5666
6156
|
});
|
|
@@ -7056,13 +7546,19 @@ exports.createSelectColumn = createSelectColumn;
|
|
|
7056
7546
|
exports.createTRPCDataSource = createTRPCDataSource;
|
|
7057
7547
|
exports.createTableSchema = createTableSchema;
|
|
7058
7548
|
exports.dataToCSV = dataToCSV;
|
|
7549
|
+
exports.deDE = deDE;
|
|
7059
7550
|
exports.downloadCSVTemplate = downloadCSVTemplate;
|
|
7551
|
+
exports.enUS = enUS;
|
|
7552
|
+
exports.esES = esES;
|
|
7060
7553
|
exports.exportAllToCSV = exportAllToCSV;
|
|
7061
7554
|
exports.exportTableToCSV = exportTableToCSV;
|
|
7062
7555
|
exports.formatDate = formatDate;
|
|
7556
|
+
exports.frFR = frFR;
|
|
7063
7557
|
exports.generateCSVTemplate = generateCSVTemplate;
|
|
7064
7558
|
exports.getUrlParams = getUrlParams;
|
|
7065
7559
|
exports.humanize = humanize;
|
|
7560
|
+
exports.jaJP = jaJP;
|
|
7561
|
+
exports.koKR = koKR;
|
|
7066
7562
|
exports.noopToastAdapter = noopToastAdapter;
|
|
7067
7563
|
exports.parseAsArrayOf = parseAsArrayOf;
|
|
7068
7564
|
exports.parseAsInteger = parseAsInteger;
|
|
@@ -7072,6 +7568,7 @@ exports.parseCSV = parseCSV;
|
|
|
7072
7568
|
exports.parseImportFile = parseImportFile;
|
|
7073
7569
|
exports.parseJSON = parseJSON;
|
|
7074
7570
|
exports.parseZodField = parseZodField;
|
|
7571
|
+
exports.resolveLocale = resolveLocale;
|
|
7075
7572
|
exports.setSearchParams = setSearchParams;
|
|
7076
7573
|
exports.useAutoCrudResource = useAutoCrudResource;
|
|
7077
7574
|
exports.useDataTable = useDataTable;
|
|
@@ -7079,4 +7576,5 @@ exports.useQueryState = useQueryState;
|
|
|
7079
7576
|
exports.useQueryStates = useQueryStates;
|
|
7080
7577
|
exports.useReadableFilters = useReadableFilters;
|
|
7081
7578
|
exports.useUrlState = useUrlState;
|
|
7082
|
-
exports.useUrlStates = useUrlStates;
|
|
7579
|
+
exports.useUrlStates = useUrlStates;
|
|
7580
|
+
exports.zhCN = zhCN;
|