vome-core 0.0.1

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 (209) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/server/index.d.ts +1 -0
  4. package/dist/server/index.js +1 -0
  5. package/dist/src/auth/define-macro.d.ts +8 -0
  6. package/dist/src/auth/index.d.ts +2 -0
  7. package/dist/src/comm/daily-log.d.ts +8 -0
  8. package/dist/src/comm/env.d.ts +4 -0
  9. package/dist/src/comm/format-time.d.ts +10 -0
  10. package/dist/src/comm/merge.d.ts +2 -0
  11. package/dist/src/comm/scan.d.ts +4 -0
  12. package/dist/src/comm/startBanner.d.ts +1 -0
  13. package/dist/src/core/app.d.ts +37 -0
  14. package/dist/src/core/config.d.ts +2 -0
  15. package/dist/src/core/context/index.d.ts +22 -0
  16. package/dist/src/core/host-infra.d.ts +20 -0
  17. package/dist/src/core/index.d.ts +20 -0
  18. package/dist/src/core/plugins/async-context.d.ts +3 -0
  19. package/dist/src/core/plugins/error.d.ts +5 -0
  20. package/dist/src/core/plugins/logging.d.ts +3 -0
  21. package/dist/src/core/plugins/openapi.d.ts +3 -0
  22. package/dist/src/core/vome-config.d.ts +2 -0
  23. package/dist/src/ext/base-plugin.d.ts +13 -0
  24. package/dist/src/ext/index.d.ts +15 -0
  25. package/dist/src/ext/load-plugin.d.ts +12 -0
  26. package/dist/src/ext/micro-apps.d.ts +60 -0
  27. package/dist/src/ext/module-gateway.d.ts +10 -0
  28. package/dist/src/ext/module-registry.d.ts +45 -0
  29. package/dist/src/ext/path.d.ts +8 -0
  30. package/dist/src/index.d.ts +10 -0
  31. package/dist/src/ioc/container.d.ts +29 -0
  32. package/dist/src/ioc/decorators.d.ts +35 -0
  33. package/dist/src/ioc/host.d.ts +2 -0
  34. package/dist/src/ioc/index.d.ts +6 -0
  35. package/dist/src/ioc/metadata.d.ts +12 -0
  36. package/dist/src/ioc/scope.d.ts +9 -0
  37. package/dist/src/logger/bootstrap.d.ts +2 -0
  38. package/dist/src/logger/exception.d.ts +22 -0
  39. package/dist/src/logger/index.d.ts +5 -0
  40. package/dist/src/logger/logger.d.ts +18 -0
  41. package/dist/src/logger/pino.d.ts +8 -0
  42. package/dist/src/orm/base-columns.d.ts +11 -0
  43. package/dist/src/orm/column-comments.d.ts +25 -0
  44. package/dist/src/orm/crud-config.d.ts +7 -0
  45. package/dist/src/orm/crud-register.d.ts +5 -0
  46. package/dist/src/orm/data-scope.d.ts +24 -0
  47. package/dist/src/orm/db-store.d.ts +12 -0
  48. package/dist/src/orm/entity-schema.d.ts +7 -0
  49. package/dist/src/orm/index.d.ts +22 -0
  50. package/dist/src/orm/query-builder.d.ts +12 -0
  51. package/dist/src/orm/query-op.d.ts +27 -0
  52. package/dist/src/orm/repository.d.ts +74 -0
  53. package/dist/src/orm/service.d.ts +71 -0
  54. package/dist/src/orm/tenant.d.ts +24 -0
  55. package/dist/src/routing/base.d.ts +27 -0
  56. package/dist/src/routing/context.d.ts +14 -0
  57. package/dist/src/routing/crud-summary.d.ts +2 -0
  58. package/dist/src/routing/decorators.d.ts +48 -0
  59. package/dist/src/routing/eps.d.ts +16 -0
  60. package/dist/src/routing/index.d.ts +8 -0
  61. package/dist/src/routing/metadata.d.ts +28 -0
  62. package/dist/src/routing/openapi-tags.d.ts +23 -0
  63. package/dist/src/routing/path-utils.d.ts +5 -0
  64. package/dist/src/routing/perm.d.ts +18 -0
  65. package/dist/src/routing/register.d.ts +7 -0
  66. package/dist/src/server/index.d.ts +10 -0
  67. package/dist/src/shared/index.d.ts +8 -0
  68. package/dist/src/shared/tree.d.ts +18 -0
  69. package/dist/typings/comm/crud.d.ts +24 -0
  70. package/dist/typings/comm/page.d.ts +16 -0
  71. package/dist/typings/comm/scan.d.ts +6 -0
  72. package/dist/typings/common.d.ts +6 -0
  73. package/dist/typings/context/data.d.ts +10 -0
  74. package/dist/typings/ext/module.d.ts +45 -0
  75. package/dist/typings/ext/plugin.d.ts +40 -0
  76. package/dist/typings/ioc/metadata.d.ts +31 -0
  77. package/dist/typings/logger/config.d.ts +6 -0
  78. package/dist/typings/routing/crud.d.ts +99 -0
  79. package/dist/typings/routing/eps.d.ts +53 -0
  80. package/dist/typings/routing/meta.d.ts +56 -0
  81. package/dist/typings/routing/register.d.ts +15 -0
  82. package/dist/typings/routing/scan-context.d.ts +6 -0
  83. package/package.json +96 -0
  84. package/src/admin/api/client.ts +184 -0
  85. package/src/admin/components/vm-aside.vue +227 -0
  86. package/src/admin/components/vm-auto-perm-dialog.vue +361 -0
  87. package/src/admin/components/vm-check-tree.vue +338 -0
  88. package/src/admin/components/vm-dept-tree.vue +549 -0
  89. package/src/admin/components/vm-empty.vue +62 -0
  90. package/src/admin/components/vm-eps-perm-picker.vue +114 -0
  91. package/src/admin/components/vm-group-cascader.vue +563 -0
  92. package/src/admin/components/vm-icon-picker.vue +616 -0
  93. package/src/admin/components/vm-markdown.vue +141 -0
  94. package/src/admin/components/vm-ri-icon.vue +21 -0
  95. package/src/admin/components/vm-role-picker.vue +314 -0
  96. package/src/admin/components/vm-view-path-picker.vue +56 -0
  97. package/src/admin/config/plugin-dev.ts +31 -0
  98. package/src/admin/crud/components/vm-column-custom.vue +196 -0
  99. package/src/admin/crud/components/vm-context-menu.vue +99 -0
  100. package/src/admin/crud/components/vm-date-picker.vue +74 -0
  101. package/src/admin/crud/components/vm-date-range.vue +291 -0
  102. package/src/admin/crud/components/vm-date-text.vue +41 -0
  103. package/src/admin/crud/components/vm-dict-tag.vue +47 -0
  104. package/src/admin/crud/components/vm-file-icon.vue +54 -0
  105. package/src/admin/crud/components/vm-multi-select.vue +181 -0
  106. package/src/admin/crud/components/vm-number-range.vue +200 -0
  107. package/src/admin/crud/components/vm-radio.vue +87 -0
  108. package/src/admin/crud/components/vm-select.vue +131 -0
  109. package/src/admin/crud/components/vm-switch.vue +128 -0
  110. package/src/admin/crud/components/vm-tree-select.vue +456 -0
  111. package/src/admin/crud/components/vm-upload-item.vue +215 -0
  112. package/src/admin/crud/components/vm-upload.vue +323 -0
  113. package/src/admin/crud/components/vm-user-select.vue +234 -0
  114. package/src/admin/crud/config.ts +38 -0
  115. package/src/admin/crud/confirm.ts +135 -0
  116. package/src/admin/crud/dict.ts +49 -0
  117. package/src/admin/crud/index.ts +79 -0
  118. package/src/admin/crud/key.ts +47 -0
  119. package/src/admin/crud/mitt.ts +27 -0
  120. package/src/admin/crud/plugins.ts +298 -0
  121. package/src/admin/crud/registry.ts +45 -0
  122. package/src/admin/crud/span.ts +48 -0
  123. package/src/admin/crud/style.ts +112 -0
  124. package/src/admin/crud/useCrud.ts +81 -0
  125. package/src/admin/crud/validate.ts +109 -0
  126. package/src/admin/crud/vm-add-btn.vue +68 -0
  127. package/src/admin/crud/vm-adv-search.vue +73 -0
  128. package/src/admin/crud/vm-crud.vue +517 -0
  129. package/src/admin/crud/vm-dialog.vue +234 -0
  130. package/src/admin/crud/vm-flex1.vue +14 -0
  131. package/src/admin/crud/vm-form.vue +239 -0
  132. package/src/admin/crud/vm-multi-delete-btn.vue +48 -0
  133. package/src/admin/crud/vm-pagination.vue +125 -0
  134. package/src/admin/crud/vm-refresh-btn.vue +34 -0
  135. package/src/admin/crud/vm-row.vue +42 -0
  136. package/src/admin/crud/vm-search-key.vue +76 -0
  137. package/src/admin/crud/vm-search.vue +367 -0
  138. package/src/admin/crud/vm-table.vue +852 -0
  139. package/src/admin/crud/vm-toolbar.vue +245 -0
  140. package/src/admin/crud/vm-upsert.vue +530 -0
  141. package/src/admin/data/remixicon-all.json +1 -0
  142. package/src/admin/directives/perm.ts +18 -0
  143. package/src/admin/env.d.ts +5 -0
  144. package/src/admin/hooks/useBrowser.ts +27 -0
  145. package/src/admin/hooks/useUpload.ts +82 -0
  146. package/src/admin/hooks/useVome.ts +13 -0
  147. package/src/admin/index.ts +59 -0
  148. package/src/admin/lib/browser.ts +28 -0
  149. package/src/admin/lib/cn.ts +7 -0
  150. package/src/admin/lib/dialog-float.ts +14 -0
  151. package/src/admin/lib/eps.ts +43 -0
  152. package/src/admin/lib/menu.ts +15 -0
  153. package/src/admin/lib/module.ts +112 -0
  154. package/src/admin/lib/tree.ts +2 -0
  155. package/src/admin/lib/upload.ts +102 -0
  156. package/src/admin/router/index.ts +61 -0
  157. package/src/admin/router/menu-routes.ts +126 -0
  158. package/src/admin/service/base.ts +96 -0
  159. package/src/admin/service/index.ts +281 -0
  160. package/src/admin/static/fileicon/demo.css +539 -0
  161. package/src/admin/static/fileicon/demo_index.html +901 -0
  162. package/src/admin/static/fileicon/iconfont.css +139 -0
  163. package/src/admin/static/fileicon/iconfont.js +1 -0
  164. package/src/admin/static/fileicon/iconfont.json +226 -0
  165. package/src/admin/static/fileicon/iconfont.ttf +0 -0
  166. package/src/admin/static/fileicon/iconfont.woff +0 -0
  167. package/src/admin/static/fileicon/iconfont.woff2 +0 -0
  168. package/src/admin/static/scarce//344/270/213/350/275/275/345/244/261/350/264/245.svg +1 -0
  169. package/src/admin/static/scarce//346/224/257/344/273/230/346/210/220/345/212/237.svg +1 -0
  170. package/src/admin/static/scarce//346/232/202/346/227/240/344/274/230/346/203/240/345/210/270.svg +1 -0
  171. package/src/admin/static/scarce//346/232/202/346/227/240/345/206/205/345/256/271.svg +1 -0
  172. package/src/admin/static/scarce//346/232/202/346/227/240/345/217/221/347/245/250.svg +1 -0
  173. package/src/admin/static/scarce//346/232/202/346/227/240/345/233/276/347/211/207.svg +1 -0
  174. package/src/admin/static/scarce//346/232/202/346/227/240/345/234/260/345/235/200.svg +1 -0
  175. package/src/admin/static/scarce//346/232/202/346/227/240/345/272/227/351/223/272.svg +1 -0
  176. package/src/admin/static/scarce//346/232/202/346/227/240/346/216/250/351/200/201.svg +1 -0
  177. package/src/admin/static/scarce//346/232/202/346/227/240/346/220/234/347/264/242/347/273/223/346/236/234.svg +1 -0
  178. package/src/admin/static/scarce//346/232/202/346/227/240/346/224/266/350/227/217.svg +1 -0
  179. package/src/admin/static/scarce//346/232/202/346/227/240/346/225/260/346/215/256.svg +1 -0
  180. package/src/admin/static/scarce//346/232/202/346/227/240/346/235/203/351/231/220.svg +1 -0
  181. package/src/admin/static/scarce//346/232/202/346/227/240/346/266/210/346/201/257.svg +1 -0
  182. package/src/admin/static/scarce//346/232/202/346/227/240/347/244/274/347/211/251.svg +1 -0
  183. package/src/admin/static/scarce//346/232/202/346/227/240/347/247/257/345/210/206.svg +1 -0
  184. package/src/admin/static/scarce//346/232/202/346/227/240/347/275/221/347/273/234.svg +1 -0
  185. package/src/admin/static/scarce//346/232/202/346/227/240/350/247/206/351/242/221.svg +1 -0
  186. package/src/admin/static/scarce//346/232/202/346/227/240/350/256/242/345/215/225.svg +1 -0
  187. package/src/admin/static/scarce//346/232/202/346/227/240/350/257/204/350/256/272.svg +1 -0
  188. package/src/admin/static/scarce//346/232/202/346/227/240/351/205/215/351/200/201.svg +1 -0
  189. package/src/admin/static/scarce//346/232/202/346/227/240/351/223/266/350/241/214/345/215/241.svg +1 -0
  190. package/src/admin/static/scarce//346/232/202/346/227/240/351/237/263/344/271/220.svg +1 -0
  191. package/src/admin/static/scarce//351/241/265/351/235/242/344/270/215/345/255/230/345/234/250.svg +1 -0
  192. package/src/admin/stores/app.ts +30 -0
  193. package/src/admin/stores/tags.ts +73 -0
  194. package/src/admin/stores/user.ts +52 -0
  195. package/src/admin/styles/base.css +137 -0
  196. package/src/admin/tsconfig.json +19 -0
  197. package/typings/admin/base/auth.ts +23 -0
  198. package/typings/admin/base/permission.ts +19 -0
  199. package/typings/admin/comm/cascader.ts +7 -0
  200. package/typings/admin/comm/check-tree.ts +7 -0
  201. package/typings/admin/comm/crud.ts +294 -0
  202. package/typings/admin/comm/eps.ts +52 -0
  203. package/typings/admin/comm/request.ts +12 -0
  204. package/typings/admin/comm/service.ts +35 -0
  205. package/typings/admin/comm/upload.ts +39 -0
  206. package/typings/admin/host.d.ts +61 -0
  207. package/typings/admin/vome/browser.ts +11 -0
  208. package/typings/admin/vome/module.ts +13 -0
  209. package/typings/admin/vome/tags.ts +9 -0
@@ -0,0 +1,234 @@
1
+ <template>
2
+ <div class="vm-user-select" @click="open = true">
3
+ <template v-if="selected.length">
4
+ <span
5
+ v-for="u in selected"
6
+ :key="String(u.id)"
7
+ class="vm-user-select__tag"
8
+ >
9
+ {{ u[labelKey] }}
10
+ </span>
11
+ <button type="button" class="vm-user-select__clear" @click.stop="clear">
12
+ <i class="ri-close-circle-line" />
13
+ </button>
14
+ </template>
15
+ <span v-else class="vm-user-select__ph">{{ placeholder }}</span>
16
+ </div>
17
+
18
+ <vm-dialog v-model:open="open" :title="title" width="520px">
19
+ <Input
20
+ v-model="keyWord"
21
+ class="vm-user-select__search"
22
+ placeholder="搜索用户名 / 昵称"
23
+ @keydown.enter.prevent="load"
24
+ />
25
+ <div class="vm-user-select__list">
26
+ <button
27
+ v-for="u in list"
28
+ :key="String(u.id)"
29
+ type="button"
30
+ class="vm-user-select__item"
31
+ :class="{ 'is-on': isSelected(u.id) }"
32
+ @click="toggle(u)"
33
+ >
34
+ <span>{{ u[labelKey] || u.username }}</span>
35
+ <span class="vm-user-select__meta">{{ u.username }}</span>
36
+ </button>
37
+ <p v-if="!list.length" class="vm-user-select__empty">暂无用户</p>
38
+ </div>
39
+ <template #footer>
40
+ <button type="button" class="vm-user-select__btn is-ghost" @click="open = false">
41
+ 取消
42
+ </button>
43
+ <button type="button" class="vm-user-select__btn is-primary" @click="confirm">
44
+ 确定
45
+ </button>
46
+ </template>
47
+ </vm-dialog>
48
+ </template>
49
+
50
+ <script setup lang="ts">
51
+ import { service } from '../../service'
52
+
53
+ defineOptions({ name: 'vm-user-select' })
54
+
55
+ const props = withDefaults(
56
+ defineProps<{
57
+ modelValue?: string | number | Array<string | number> | null
58
+ multiple?: boolean
59
+ title?: string
60
+ placeholder?: string
61
+ labelKey?: string
62
+ immediate?: boolean
63
+ }>(),
64
+ {
65
+ multiple: false,
66
+ title: '选择成员',
67
+ placeholder: '请选择',
68
+ labelKey: 'nickName',
69
+ immediate: false,
70
+ },
71
+ )
72
+
73
+ const emit = defineEmits<{
74
+ 'update:modelValue': [v: string | number | Array<string | number> | null]
75
+ }>()
76
+
77
+ const open = ref(false)
78
+ const keyWord = ref('')
79
+ const list = ref<Record<string, unknown>[]>([])
80
+ const picked = ref<Record<string, unknown>[]>([])
81
+
82
+ const selected = computed(() => picked.value)
83
+
84
+ watch(
85
+ () => props.immediate,
86
+ (v) => {
87
+ if (v) void load()
88
+ },
89
+ { immediate: true },
90
+ )
91
+
92
+ watch(open, (v) => {
93
+ if (v) void load()
94
+ })
95
+
96
+ async function load() {
97
+ try {
98
+ const res = await service.base.user.page({
99
+ page: 1,
100
+ size: 50,
101
+ keyWord: keyWord.value || undefined,
102
+ })
103
+ list.value = res.list || []
104
+ } catch {
105
+ list.value = []
106
+ }
107
+ }
108
+
109
+ function isSelected(id: unknown) {
110
+ return picked.value.some((u) => String(u.id) === String(id))
111
+ }
112
+
113
+ function toggle(u: Record<string, unknown>) {
114
+ if (props.multiple) {
115
+ if (isSelected(u.id)) {
116
+ picked.value = picked.value.filter((x) => String(x.id) !== String(u.id))
117
+ } else {
118
+ picked.value = [...picked.value, u]
119
+ }
120
+ } else {
121
+ picked.value = [u]
122
+ }
123
+ }
124
+
125
+ function clear() {
126
+ picked.value = []
127
+ emit('update:modelValue', props.multiple ? [] : null)
128
+ }
129
+
130
+ function confirm() {
131
+ if (props.multiple) {
132
+ emit(
133
+ 'update:modelValue',
134
+ picked.value.map((u) => u.id as string | number),
135
+ )
136
+ } else {
137
+ emit('update:modelValue', (picked.value[0]?.id as string | number) ?? null)
138
+ }
139
+ open.value = false
140
+ }
141
+ </script>
142
+
143
+ <style lang="scss" scoped>
144
+ .vm-user-select {
145
+ display: flex;
146
+ min-height: var(--vm-control-height);
147
+ align-items: center;
148
+ gap: 6px;
149
+ padding: 0 var(--vm-control-padding-x);
150
+ border: 1px solid var(--border);
151
+ border-radius: var(--vm-control-radius);
152
+ background: var(--card);
153
+ cursor: pointer;
154
+ }
155
+
156
+ .vm-user-select__ph {
157
+ color: var(--muted-foreground);
158
+ font-size: 13px;
159
+ }
160
+
161
+ .vm-user-select__tag {
162
+ padding: 2px 8px;
163
+ border-radius: 8px;
164
+ background: var(--brand-soft);
165
+ color: var(--brand);
166
+ font-size: 12px;
167
+ font-weight: 600;
168
+ }
169
+
170
+ .vm-user-select__clear {
171
+ margin-left: auto;
172
+ border: none;
173
+ background: transparent;
174
+ color: var(--muted-foreground);
175
+ cursor: pointer;
176
+ }
177
+
178
+ .vm-user-select__search {
179
+ margin-bottom: 10px;
180
+ }
181
+
182
+ .vm-user-select__list {
183
+ max-height: 360px;
184
+ overflow: auto;
185
+ }
186
+
187
+ .vm-user-select__item {
188
+ display: flex;
189
+ width: 100%;
190
+ align-items: center;
191
+ justify-content: space-between;
192
+ padding: 10px 12px;
193
+ border: none;
194
+ border-radius: 10px;
195
+ background: transparent;
196
+ text-align: left;
197
+ cursor: pointer;
198
+
199
+ &:hover,
200
+ &.is-on {
201
+ background: var(--brand-soft);
202
+ }
203
+ }
204
+
205
+ .vm-user-select__meta {
206
+ color: var(--muted-foreground);
207
+ font-size: 12px;
208
+ }
209
+
210
+ .vm-user-select__empty {
211
+ padding: 24px;
212
+ color: var(--muted-foreground);
213
+ text-align: center;
214
+ }
215
+
216
+ .vm-user-select__btn {
217
+ height: 36px;
218
+ padding: 0 14px;
219
+ border: none;
220
+ border-radius: 12px;
221
+ font-size: 13px;
222
+ font-weight: 600;
223
+ cursor: pointer;
224
+
225
+ &.is-ghost {
226
+ background: var(--muted);
227
+ }
228
+
229
+ &.is-primary {
230
+ background: var(--brand);
231
+ color: #fff;
232
+ }
233
+ }
234
+ </style>
@@ -0,0 +1,38 @@
1
+ import { getCrudConfig } from './style'
2
+ import { CRUD_LABELS, DEFAULT_CRUD_DICT } from './dict'
3
+
4
+ export { CRUD_LABELS, DEFAULT_CRUD_DICT }
5
+
6
+ export const DEFAULT_CRUD_PERMISSION: CrudPermission = {
7
+ page: true,
8
+ list: true,
9
+ info: true,
10
+ add: true,
11
+ delete: true,
12
+ update: true,
13
+ }
14
+
15
+ export function mergeDict(partial?: Partial<CrudDict>): CrudDict {
16
+ const base = getCrudConfig().dict
17
+ if (!partial) return { ...base, label: { ...base.label } }
18
+ return {
19
+ ...base,
20
+ ...partial,
21
+ api: { ...base.api, ...partial.api },
22
+ pagination: { ...base.pagination, ...partial.pagination },
23
+ search: { ...base.search, ...partial.search },
24
+ sort: { ...base.sort, ...partial.sort },
25
+ label: { ...base.label, ...partial.label },
26
+ }
27
+ }
28
+
29
+ export function mergePermission(
30
+ partial?: Partial<CrudPermission>,
31
+ fromService?: Partial<CrudPermission>,
32
+ ): CrudPermission {
33
+ return {
34
+ ...DEFAULT_CRUD_PERMISSION,
35
+ ...fromService,
36
+ ...partial,
37
+ }
38
+ }
@@ -0,0 +1,135 @@
1
+ import { createApp, h, ref } from 'vue'
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogFooter,
6
+ DialogHeader,
7
+ DialogTitle,
8
+ } from '#vome-host/components/ui/dialog'
9
+
10
+ type ConfirmOptions = {
11
+ title?: string
12
+ message: string
13
+ confirmText?: string
14
+ cancelText?: string
15
+ }
16
+
17
+ /**
18
+ * 确认对话框
19
+ */
20
+ export function vmConfirm(options: ConfirmOptions | string): Promise<boolean> {
21
+ const opts: ConfirmOptions =
22
+ typeof options === 'string' ? { message: options } : options
23
+
24
+ return new Promise((resolve) => {
25
+ const open = ref(true)
26
+ const host = document.createElement('div')
27
+ document.body.appendChild(host)
28
+
29
+ const app = createApp({
30
+ setup() {
31
+ function finish(ok: boolean) {
32
+ open.value = false
33
+ resolve(ok)
34
+ setTimeout(() => {
35
+ app.unmount()
36
+ host.remove()
37
+ }, 200)
38
+ }
39
+
40
+ return () =>
41
+ h(
42
+ Dialog,
43
+ {
44
+ open: open.value,
45
+ 'onUpdate:open': (v: boolean) => {
46
+ if (!v) finish(false)
47
+ },
48
+ },
49
+ {
50
+ default: () =>
51
+ h(
52
+ DialogContent,
53
+ { class: 'vm-confirm', showCloseButton: false },
54
+ {
55
+ default: () => [
56
+ h(DialogHeader, { class: 'vm-confirm__head' }, () =>
57
+ h(DialogTitle, { class: 'vm-confirm__title' }, () =>
58
+ opts.title || '提示',
59
+ ),
60
+ ),
61
+ h('div', { class: 'vm-confirm__body' }, opts.message),
62
+ h(DialogFooter, { class: 'vm-confirm__foot' }, () => [
63
+ h(
64
+ 'button',
65
+ {
66
+ type: 'button',
67
+ class: 'vm-confirm__btn is-ghost',
68
+ onClick: () => finish(false),
69
+ },
70
+ opts.cancelText || '取消',
71
+ ),
72
+ h(
73
+ 'button',
74
+ {
75
+ type: 'button',
76
+ class: 'vm-confirm__btn is-primary',
77
+ onClick: () => finish(true),
78
+ },
79
+ opts.confirmText || '确定',
80
+ ),
81
+ ]),
82
+ ],
83
+ },
84
+ ),
85
+ },
86
+ )
87
+ },
88
+ })
89
+
90
+ app.mount(host)
91
+ })
92
+ }
93
+
94
+ if (typeof document !== 'undefined' && !document.getElementById('vm-confirm-style')) {
95
+ const style = document.createElement('style')
96
+ style.id = 'vm-confirm-style'
97
+ style.textContent = `
98
+ .vm-confirm[data-slot='dialog-content'] {
99
+ width: min(400px, calc(100vw - 32px)) !important;
100
+ max-width: min(400px, calc(100vw - 32px)) !important;
101
+ gap: 0 !important;
102
+ padding: 0 !important;
103
+ border: none !important;
104
+ border-radius: 24px !important;
105
+ box-shadow: var(--shadow-soft) !important;
106
+ }
107
+ .vm-confirm__head { padding: 18px 22px 0; border-bottom: none; }
108
+ .vm-confirm__title { font-size: 16px; font-weight: 650; }
109
+ .vm-confirm__body {
110
+ padding: 12px 22px 8px;
111
+ color: var(--foreground);
112
+ font-size: 14px;
113
+ line-height: 1.6;
114
+ }
115
+ .vm-confirm__foot {
116
+ display: flex;
117
+ justify-content: flex-end;
118
+ gap: 8px;
119
+ padding: 14px 22px;
120
+ }
121
+ .vm-confirm__btn {
122
+ height: 36px;
123
+ padding: 0 16px;
124
+ border: none;
125
+ border-radius: 12px;
126
+ font-size: 13px;
127
+ font-weight: 600;
128
+ cursor: pointer;
129
+ }
130
+ .vm-confirm__btn.is-primary { background: var(--brand); color: #fff; }
131
+ .vm-confirm__btn.is-primary:hover { background: var(--brand-deep); }
132
+ .vm-confirm__btn.is-ghost { background: var(--muted); color: var(--foreground); }
133
+ `
134
+ document.head.appendChild(style)
135
+ }
@@ -0,0 +1,49 @@
1
+ /** 表格/表单默认文案(zh-cn) */
2
+ export const CRUD_LABELS: CrudDict['label'] = {
3
+ op: '操作',
4
+ add: '新增',
5
+ delete: '删除',
6
+ multiDelete: '删除',
7
+ update: '编辑',
8
+ refresh: '刷新',
9
+ info: '详情',
10
+ search: '搜索',
11
+ reset: '重置',
12
+ clear: '清空',
13
+ save: '保存',
14
+ close: '取消',
15
+ confirm: '确定',
16
+ advSearch: '高级搜索',
17
+ searchKey: '搜索关键字',
18
+ placeholder: '请输入',
19
+ tips: '提示',
20
+ saveSuccess: '保存成功',
21
+ deleteSuccess: '删除成功',
22
+ deleteConfirm: '此操作将数据标记为已删除,是否继续?',
23
+ forceDeleteConfirm: '此操作将永久删除选中数据,是否继续?',
24
+ empty: '暂无数据',
25
+ desc: '降序',
26
+ asc: '升序',
27
+ select: '选择',
28
+ deselect: '取消选择',
29
+ seeMore: '查看更多',
30
+ hideContent: '隐藏内容',
31
+ nonEmpty: '不能为空',
32
+ }
33
+
34
+ export const DEFAULT_CRUD_DICT: CrudDict = {
35
+ primaryId: 'id',
36
+ api: {
37
+ list: 'list',
38
+ add: 'add',
39
+ update: 'update',
40
+ delete: 'delete',
41
+ info: 'info',
42
+ page: 'page',
43
+ },
44
+ pagination: { page: 'page', size: 'size' },
45
+ search: { keyWord: 'keyWord', query: 'query' },
46
+ // QueryOp:order=字段名,sort=asc|desc(键名为 order/sort)
47
+ sort: { prop: 'order', order: 'sort' },
48
+ label: CRUD_LABELS,
49
+ }
@@ -0,0 +1,79 @@
1
+ export { default as VmCrud } from './vm-crud.vue'
2
+ export { default as VmSearch } from './vm-search.vue'
3
+ export { default as VmSearchKey } from './vm-search-key.vue'
4
+ export { default as VmTable } from './vm-table.vue'
5
+ export { default as VmPagination } from './vm-pagination.vue'
6
+ export { default as VmUpsert } from './vm-upsert.vue'
7
+ export { default as VmToolbar } from './vm-toolbar.vue'
8
+ export { default as VmRow } from './vm-row.vue'
9
+ export { default as VmFlex1 } from './vm-flex1.vue'
10
+ export { default as VmAddBtn } from './vm-add-btn.vue'
11
+ export { default as VmRefreshBtn } from './vm-refresh-btn.vue'
12
+ export { default as VmMultiDeleteBtn } from './vm-multi-delete-btn.vue'
13
+ export { default as VmDialog } from './vm-dialog.vue'
14
+ export { default as VmForm } from './vm-form.vue'
15
+ export { default as VmAdvSearch } from './vm-adv-search.vue'
16
+
17
+ export { default as VmSwitch } from './components/vm-switch.vue'
18
+ export { default as VmSelect } from './components/vm-select.vue'
19
+ export { default as VmTreeSelect } from './components/vm-tree-select.vue'
20
+ export { default as VmRadio } from './components/vm-radio.vue'
21
+ export { default as VmDateText } from './components/vm-date-text.vue'
22
+ export { default as VmDatePicker } from './components/vm-date-picker.vue'
23
+ export { default as VmDateRange } from './components/vm-date-range.vue'
24
+ export { default as VmNumberRange } from './components/vm-number-range.vue'
25
+ export { default as VmMultiSelect } from './components/vm-multi-select.vue'
26
+ export { default as VmDictTag } from './components/vm-dict-tag.vue'
27
+ export { default as VmUserSelect } from './components/vm-user-select.vue'
28
+ export { default as VmColumnCustom } from './components/vm-column-custom.vue'
29
+ export { default as VmContextMenu } from './components/vm-context-menu.vue'
30
+ export { default as VmUpload } from './components/vm-upload.vue'
31
+ export { default as VmUploadItem } from './components/vm-upload-item.vue'
32
+ export { default as VmFileIcon } from './components/vm-file-icon.vue'
33
+
34
+ export { vmConfirm } from './confirm'
35
+ export {
36
+ useCrud,
37
+ useTable,
38
+ useUpsert,
39
+ useSearch,
40
+ useCore,
41
+ CRUD_KEY,
42
+ } from './useCrud'
43
+
44
+ export { Plugins, toTree, setFocus, setRules, setAuto, buildAutoSearchItems } from './plugins'
45
+ export { deepTree, flattenTree } from '../lib/tree'
46
+ export { resolveCrudComponent, registerCrudComponent } from './registry'
47
+ export {
48
+ setCrudConfig,
49
+ getCrudConfig,
50
+ getCrudStyle,
51
+ DEFAULT_CRUD_STYLE,
52
+ } from './style'
53
+
54
+ export {
55
+ FORM_COLS_DESKTOP,
56
+ FORM_COLS_MOBILE,
57
+ FORM_SPAN_FULL,
58
+ FORM_MQ_MOBILE,
59
+ getFormCols,
60
+ resolveFormSpan,
61
+ useFormCols,
62
+ } from './span'
63
+
64
+ export { mergeDict, mergePermission, DEFAULT_CRUD_DICT, CRUD_LABELS } from './config'
65
+
66
+ export type {
67
+ CrudService,
68
+ CrudColumn,
69
+ CrudSearchItem,
70
+ CrudFormItem,
71
+ CrudContext,
72
+ CrudTrashMode,
73
+ CrudOptions,
74
+ CrudTableOptions,
75
+ CrudUpsertOptions,
76
+ CrudSearchOptions,
77
+ CrudPermission,
78
+ CrudDict,
79
+ } from '../../../typings/admin/comm/crud'
@@ -0,0 +1,47 @@
1
+ import { inject, type InjectionKey } from 'vue'
2
+ import type {
3
+ CrudColumn,
4
+ CrudContext,
5
+ CrudOptions,
6
+ CrudSearchOptions,
7
+ CrudTableOptions,
8
+ CrudUpsertOptions,
9
+ } from '../../../typings/admin/comm/crud'
10
+ import type { Mitt } from './mitt'
11
+
12
+ export const CRUD_KEY: InjectionKey<CrudContext> = Symbol('vm-crud')
13
+ export const CRUD_MITT_KEY: InjectionKey<Mitt> = Symbol('vm-crud-mitt')
14
+ export const CRUD_OPTIONS_KEY: InjectionKey<CrudOptions> = Symbol('useCrud__options')
15
+ export const TABLE_OPTIONS_KEY: InjectionKey<CrudTableOptions> =
16
+ Symbol('useTable__options')
17
+ export const UPSERT_OPTIONS_KEY: InjectionKey<CrudUpsertOptions> =
18
+ Symbol('useUpsert__options')
19
+ export const SEARCH_OPTIONS_KEY: InjectionKey<CrudSearchOptions> =
20
+ Symbol('useSearch__options')
21
+
22
+ /** Table 实例 API(ColumnCustom / showColumn 等) */
23
+ export type TableApi = {
24
+ setColumns: (cols: CrudColumn[]) => void
25
+ showColumn: (prop: string) => void
26
+ hideColumn: (prop: string) => void
27
+ getColumns: () => CrudColumn[]
28
+ }
29
+
30
+ export const TABLE_API_KEY: InjectionKey<TableApi> = Symbol('vm-table-api')
31
+
32
+ /** inject(KEY, undefined) 在严格模式下会推断为 never,统一走 helper */
33
+ export function injectCrudOptions(): CrudOptions | undefined {
34
+ return inject(CRUD_OPTIONS_KEY, undefined as CrudOptions | undefined)
35
+ }
36
+
37
+ export function injectTableOptions(): CrudTableOptions | undefined {
38
+ return inject(TABLE_OPTIONS_KEY, undefined as CrudTableOptions | undefined)
39
+ }
40
+
41
+ export function injectUpsertOptions(): CrudUpsertOptions | undefined {
42
+ return inject(UPSERT_OPTIONS_KEY, undefined as CrudUpsertOptions | undefined)
43
+ }
44
+
45
+ export function injectSearchOptions(): CrudSearchOptions | undefined {
46
+ return inject(SEARCH_OPTIONS_KEY, undefined as CrudSearchOptions | undefined)
47
+ }
@@ -0,0 +1,27 @@
1
+ type Handler = (...args: unknown[]) => void
2
+
3
+ /** 轻量 mitt,crud 事件总线 */
4
+ export class Mitt {
5
+ private map = new Map<string, Set<Handler>>()
6
+
7
+ on(type: string, handler: Handler) {
8
+ if (!this.map.has(type)) this.map.set(type, new Set())
9
+ this.map.get(type)!.add(handler)
10
+ }
11
+
12
+ off(type: string, handler?: Handler) {
13
+ if (!handler) {
14
+ this.map.delete(type)
15
+ return
16
+ }
17
+ this.map.get(type)?.delete(handler)
18
+ }
19
+
20
+ emit(type: string, ...args: unknown[]) {
21
+ this.map.get(type)?.forEach((fn) => fn(...args))
22
+ }
23
+ }
24
+
25
+ export function createMitt() {
26
+ return new Mitt()
27
+ }