@kine-design/crud 0.0.1-beta.2 → 0.0.1-beta.21

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.
Files changed (118) hide show
  1. package/.vlaude/last-session-id +1 -0
  2. package/components/crudPage/KCrudPage.tsx +178 -0
  3. package/components/crudPage/crudPage.css +64 -0
  4. package/components/crudPage/index.ts +10 -0
  5. package/components/editableTable/KEditableTable.tsx +281 -0
  6. package/components/editableTable/editableTable.css +268 -0
  7. package/components/editableTable/index.ts +10 -0
  8. package/components/formPage/KApprovalDialog.tsx +142 -0
  9. package/components/formPage/KFormCard.tsx +65 -0
  10. package/components/formPage/KFormPage.tsx +128 -0
  11. package/components/formPage/KMasterDetailPage.tsx +205 -0
  12. package/components/formPage/KStickyActionBar.tsx +33 -0
  13. package/components/formPage/formPage.css +629 -0
  14. package/components/formPage/index.ts +14 -0
  15. package/components/layout/KContent.tsx +20 -0
  16. package/components/layout/KHeader.tsx +37 -0
  17. package/components/layout/KLayout.tsx +82 -0
  18. package/components/layout/KSider.tsx +80 -0
  19. package/components/layout/index.ts +18 -0
  20. package/components/layout/layout.css +262 -0
  21. package/components/login/KLoginPage.tsx +129 -0
  22. package/components/login/index.ts +10 -0
  23. package/components/login/login.css +118 -0
  24. package/components/navMenu/KNavMenu.tsx +175 -0
  25. package/components/navMenu/index.ts +2 -0
  26. package/components/navMenu/navMenu.css +197 -0
  27. package/components/pageHeader/KPageHeader.tsx +85 -0
  28. package/components/pageHeader/index.ts +9 -0
  29. package/components/pageHeader/pageHeader.css +93 -0
  30. package/components/searchTable/KSearchTable.tsx +138 -0
  31. package/components/searchTable/index.ts +10 -0
  32. package/components/searchTable/searchTable.css +121 -0
  33. package/components/upload/KFileList.tsx +95 -0
  34. package/components/upload/KImageUpload.tsx +286 -0
  35. package/components/upload/KUpload.tsx +206 -0
  36. package/components/upload/index.ts +13 -0
  37. package/components/upload/types.ts +26 -0
  38. package/components/upload/upload.css +345 -0
  39. package/composables/auth/authGuard.ts +128 -0
  40. package/composables/auth/index.ts +23 -0
  41. package/composables/auth/types.ts +109 -0
  42. package/composables/auth/useAuth.ts +278 -0
  43. package/composables/auth/vCan.ts +95 -0
  44. package/composables/defineRepository.ts +224 -0
  45. package/composables/error/createErrorHandler.ts +46 -0
  46. package/composables/error/defaultFeedbackHandler.ts +76 -0
  47. package/composables/error/dispatchError.ts +70 -0
  48. package/composables/error/index.ts +32 -0
  49. package/composables/error/types.ts +57 -0
  50. package/composables/error/useErrorHandler.ts +41 -0
  51. package/composables/form/index.ts +18 -0
  52. package/composables/form/renderFormField.tsx +119 -0
  53. package/composables/form/types.ts +129 -0
  54. package/composables/form/useFormPage.ts +183 -0
  55. package/composables/index.ts +62 -0
  56. package/composables/page/index.ts +11 -0
  57. package/composables/page/types.ts +62 -0
  58. package/composables/page/useCrudPage.ts +88 -0
  59. package/composables/request/composables.ts +206 -0
  60. package/composables/request/controlGate.ts +143 -0
  61. package/composables/request/createRequest.ts +173 -0
  62. package/composables/request/index.ts +71 -0
  63. package/composables/request/orchestrator.ts +145 -0
  64. package/composables/request/requestBuilder.ts +418 -0
  65. package/composables/request/transport/fetchTransport.ts +79 -0
  66. package/composables/request/transport/xhrTransport.ts +100 -0
  67. package/composables/request/types.ts +226 -0
  68. package/composables/request/upload.ts +146 -0
  69. package/composables/router/createRouterGuard.ts +134 -0
  70. package/composables/router/defineCrudRoutes.ts +116 -0
  71. package/composables/router/index.ts +22 -0
  72. package/composables/router/types.ts +128 -0
  73. package/composables/router/useMenuFromRoutes.ts +109 -0
  74. package/composables/router/useTabStore.ts +183 -0
  75. package/composables/search/index.ts +11 -0
  76. package/composables/search/useAutoCompleteSearch.ts +161 -0
  77. package/composables/setupCrud.ts +43 -0
  78. package/composables/storage/createStorageAdapter.ts +72 -0
  79. package/composables/storage/index.ts +13 -0
  80. package/composables/storage/types.ts +30 -0
  81. package/composables/storage/useStorage.ts +108 -0
  82. package/composables/store/defineUserStore.ts +122 -0
  83. package/composables/store/index.ts +11 -0
  84. package/composables/types.ts +118 -0
  85. package/dist/components/crudPage/KCrudPage.d.ts +14 -0
  86. package/dist/components/crudPage/index.d.ts +9 -0
  87. package/dist/components/editableTable/KEditableTable.d.ts +146 -0
  88. package/dist/components/editableTable/index.d.ts +10 -0
  89. package/dist/components/formPage/KApprovalDialog.d.ts +99 -0
  90. package/dist/components/formPage/KFormCard.d.ts +49 -0
  91. package/dist/components/formPage/KFormPage.d.ts +14 -0
  92. package/dist/components/formPage/KMasterDetailPage.d.ts +14 -0
  93. package/dist/components/formPage/KStickyActionBar.d.ts +16 -0
  94. package/dist/components/formPage/index.d.ts +14 -0
  95. package/dist/components/layout/KLayout.d.ts +7 -4
  96. package/dist/composables/auth/useAuth.d.ts +5 -5
  97. package/dist/composables/error/types.d.ts +2 -1
  98. package/dist/composables/form/index.d.ts +12 -0
  99. package/dist/composables/form/renderFormField.d.ts +11 -0
  100. package/dist/composables/form/types.d.ts +104 -0
  101. package/dist/composables/form/useFormPage.d.ts +38 -0
  102. package/dist/composables/index.d.ts +2 -0
  103. package/dist/composables/page/index.d.ts +10 -0
  104. package/dist/composables/page/types.d.ts +61 -0
  105. package/dist/composables/page/useCrudPage.d.ts +14 -0
  106. package/dist/composables/request/createRequest.d.ts +2 -0
  107. package/dist/composables/request/requestBuilder.d.ts +2 -0
  108. package/dist/composables/search/index.d.ts +10 -0
  109. package/dist/composables/search/useAutoCompleteSearch.d.ts +50 -0
  110. package/dist/crud.css +2499 -663
  111. package/dist/crud.js +11512 -2910
  112. package/dist/index.d.ts +11 -0
  113. package/dist/setup.d.ts +2 -2
  114. package/index.ts +144 -0
  115. package/package.json +20 -19
  116. package/setup.ts +288 -0
  117. package/tsconfig.json +12 -0
  118. package/vite.config.build.ts +52 -0
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @description KMasterDetailPage — 配置驱动的主从表单页组件
3
+ * @author 阿怪
4
+ * @date 2026/3/22
5
+ * @version v0.0.1
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ *
9
+ * 主表字段区 + 多个可编辑子表 + 底部操作栏。
10
+ * 业务页面只需 <KMasterDetailPage :config="config" /> 即可。
11
+ */
12
+ import { defineComponent, ref, type PropType } from 'vue';
13
+ import { useRouter } from 'vue-router';
14
+ import { useFormPage, renderFormField } from '../../composables/form';
15
+ import type { MasterDetailPageConfig, DetailTableConfig } from '../../composables/form/types';
16
+ import type { EditableTableRow } from '../editableTable';
17
+ import KFormCard from './KFormCard';
18
+ import KStickyActionBar from './KStickyActionBar';
19
+ import { KEditableTable } from '../editableTable';
20
+ import KButton from 'kine-ui/components/button/KButton.tsx';
21
+ import './formPage.css';
22
+
23
+ export default defineComponent({
24
+ name: 'KMasterDetailPage',
25
+ props: {
26
+ config: { type: Object as PropType<MasterDetailPageConfig>, required: true },
27
+ },
28
+ setup(props, { slots }) {
29
+ const router = useRouter();
30
+
31
+ const {
32
+ formData,
33
+ isEdit,
34
+ loading,
35
+ submitting,
36
+ errors,
37
+ validateField,
38
+ submit,
39
+ saveDraft,
40
+ goBack,
41
+ } = useFormPage({
42
+ api: props.config.api,
43
+ fields: props.config.fields,
44
+ rowKey: props.config.rowKey,
45
+ redirectPath: props.config.redirectPath,
46
+ });
47
+
48
+ const cols = props.config.columns ?? 3;
49
+
50
+ // 子表 ID 计数器(按子表分)
51
+ const idCounters = ref<Record<string, number>>({});
52
+
53
+ const getNextId = (param: string): number => {
54
+ if (!idCounters.value[param]) {
55
+ // 从现有数据中找最大 _id
56
+ const rows = (formData[param] as EditableTableRow[]) ?? [];
57
+ const maxId = rows.reduce((max, r) => Math.max(max, Number(r._id) || 0), 0);
58
+ idCounters.value[param] = maxId;
59
+ }
60
+ idCounters.value[param]++;
61
+ return idCounters.value[param];
62
+ };
63
+
64
+ const handleAddRow = (tableConfig: DetailTableConfig) => {
65
+ const rows = (formData[tableConfig.param] as EditableTableRow[]) ?? [];
66
+ const newRow: EditableTableRow = { _id: getNextId(tableConfig.param) };
67
+ for (const col of tableConfig.columns) {
68
+ newRow[col.param] = col.editType === 'number' ? 0 : '';
69
+ }
70
+ formData[tableConfig.param] = [...rows, newRow];
71
+ };
72
+
73
+ const handleUpdateRows = (param: string, newRows: EditableTableRow[]) => {
74
+ formData[param] = newRows;
75
+ };
76
+
77
+ // ── 渲染 ──────────────────────────────────────
78
+
79
+ return () => {
80
+ if (loading.value) {
81
+ return <div class="k-fp-loading">加载中...</div>;
82
+ }
83
+
84
+ const title = isEdit.value
85
+ ? `${props.config.title}`
86
+ : `新建${props.config.title}`;
87
+
88
+ return (
89
+ <div class="k-form-page k-master-detail-page">
90
+ {/* 页头 */}
91
+ <div class="k-fp-header">
92
+ <div class="k-fp-header-left">
93
+ {props.config.breadcrumb ? (
94
+ <div class="k-fp-breadcrumb">
95
+ {props.config.breadcrumb.map((item, i) => (
96
+ <>
97
+ {i > 0 && <span class="k-fp-breadcrumb-sep">›</span>}
98
+ {item.path
99
+ ? <a class="k-fp-breadcrumb-link" onClick={() => router.push(item.path!)}>{item.label}</a>
100
+ : <span class="k-fp-breadcrumb-text">{item.label}</span>
101
+ }
102
+ </>
103
+ ))}
104
+ </div>
105
+ ) : (
106
+ <>
107
+ <KButton text="←" onClick={goBack} />
108
+ <h1 class="k-fp-title">{title}</h1>
109
+ </>
110
+ )}
111
+ </div>
112
+ <div class="k-fp-header-right">
113
+ {slots.headerExtra?.({ formData })}
114
+ </div>
115
+ </div>
116
+
117
+ {/* 主表字段区 */}
118
+ <KFormCard title="基本信息">
119
+ {{
120
+ default: () => (
121
+ <div class={`k-fp-grid k-fp-grid--${cols}`}>
122
+ {props.config.fields.map(field => {
123
+ const span = field.span === 'full' ? cols : (field.span ?? 1);
124
+ return (
125
+ <div
126
+ key={field.param}
127
+ class="k-fp-field"
128
+ style={span > 1 ? { gridColumn: `span ${span}` } : undefined}
129
+ >
130
+ <label class="k-fp-label">
131
+ {field.label}
132
+ {field.required && <span class="k-fp-required">*</span>}
133
+ </label>
134
+ {renderFormField(field, formData, errors.value, validateField, slots)}
135
+ {errors.value[field.param] && (
136
+ <span class="k-fp-error">{errors.value[field.param]}</span>
137
+ )}
138
+ </div>
139
+ );
140
+ })}
141
+ </div>
142
+ ),
143
+ }}
144
+ </KFormCard>
145
+
146
+ {/* 子表区 */}
147
+ {props.config.detailTables.map(tableConfig => (
148
+ <KFormCard key={tableConfig.param}>
149
+ {{
150
+ default: () => {
151
+ const tableSlot = slots[`table-${tableConfig.param}`];
152
+ if (tableSlot) {
153
+ return tableSlot({ formData, rows: formData[tableConfig.param] as EditableTableRow[] });
154
+ }
155
+
156
+ return (
157
+ <KEditableTable
158
+ modelValue={(formData[tableConfig.param] as EditableTableRow[]) ?? []}
159
+ onUpdate:modelValue={(rows: EditableTableRow[]) => handleUpdateRows(tableConfig.param, rows)}
160
+ columns={tableConfig.columns}
161
+ title={tableConfig.title}
162
+ showSummary={tableConfig.showSummary}
163
+ summaryLabel={tableConfig.summaryLabel}
164
+ currencyPrefix={tableConfig.currencyPrefix}
165
+ addText={tableConfig.addText}
166
+ onAdd={() => handleAddRow(tableConfig)}
167
+ />
168
+ );
169
+ },
170
+ }}
171
+ </KFormCard>
172
+ ))}
173
+
174
+ {/* 额外内容 */}
175
+ {slots.default?.({ formData })}
176
+
177
+ {/* 底部操作栏 */}
178
+ <KStickyActionBar>
179
+ {{
180
+ default: () => slots.actions?.({ formData, submit, saveDraft, submitting }) ?? (
181
+ <>
182
+ <KButton text="取消" onClick={goBack} />
183
+ {props.config.showDraft && (
184
+ <KButton
185
+ text="保存草稿"
186
+ disabled={submitting.value}
187
+ onClick={() => saveDraft()}
188
+ />
189
+ )}
190
+ <KButton
191
+ type="primary"
192
+ text={submitting.value ? '保存中...' : (props.config.submitText ?? '提交')}
193
+ disabled={submitting.value}
194
+ loading={submitting.value}
195
+ onClick={() => submit()}
196
+ />
197
+ </>
198
+ ),
199
+ }}
200
+ </KStickyActionBar>
201
+ </div>
202
+ );
203
+ };
204
+ },
205
+ });
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @description KStickyActionBar — 底部固定操作栏
3
+ * @author 阿怪
4
+ * @date 2026/3/22
5
+ * @version v0.0.1
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ *
9
+ * 用于表单页底部的固定操作栏(保存草稿 / 提交 / 取消等按钮)。
10
+ * 始终固定在视口底部,带顶部分割线和背景模糊。
11
+ */
12
+ import { defineComponent } from 'vue';
13
+ import './formPage.css';
14
+
15
+ export default defineComponent({
16
+ name: 'KStickyActionBar',
17
+ props: {
18
+ /** 左侧辅助信息,如"最后保存: 今天 14:23" */
19
+ hint: { type: String, default: '' },
20
+ },
21
+ setup(props, { slots }) {
22
+ return () => (
23
+ <div class="k-sticky-action-bar">
24
+ <div class="k-sticky-action-bar-hint">
25
+ {slots.hint?.() ?? (props.hint && <span>{props.hint}</span>)}
26
+ </div>
27
+ <div class="k-sticky-action-bar-actions">
28
+ {slots.default?.()}
29
+ </div>
30
+ </div>
31
+ );
32
+ },
33
+ });