vome-core 0.3.9 → 0.3.11

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 (120) hide show
  1. package/dist/admin/api/client.js +9 -8
  2. package/dist/admin/components/ui/avatar/index.js +1 -1
  3. package/dist/admin/components/ui/badge/index.d.ts +1 -1
  4. package/dist/admin/components/ui/button/index.d.ts +1 -1
  5. package/dist/admin/components/ui/checkbox/index.js +1 -1
  6. package/dist/admin/components/ui/dialog/index.js +1 -1
  7. package/dist/admin/components/ui/dropdown-menu/index.js +1 -1
  8. package/dist/admin/components/ui/input/Input.vue +2 -1
  9. package/dist/admin/components/ui/input/index.js +1 -1
  10. package/dist/admin/components/ui/label/index.js +1 -1
  11. package/dist/admin/components/ui/scroll-area/index.js +1 -1
  12. package/dist/admin/components/ui/select/index.js +1 -1
  13. package/dist/admin/components/ui/separator/index.js +1 -1
  14. package/dist/admin/components/ui/sheet/index.js +1 -1
  15. package/dist/admin/components/ui/sonner/index.js +1 -1
  16. package/dist/admin/components/ui/table/index.js +1 -1
  17. package/dist/admin/components/ui/tabs/index.js +1 -1
  18. package/dist/admin/components/ui/tooltip/index.js +1 -1
  19. package/dist/admin/components/vm-aside.vue +8 -6
  20. package/dist/admin/components/vm-auto-perm-dialog.vue +12 -11
  21. package/dist/admin/components/vm-check-tree.vue +3 -2
  22. package/dist/admin/components/vm-dept-tree.vue +32 -31
  23. package/dist/admin/components/vm-empty.vue +16 -2
  24. package/dist/admin/components/vm-eps-perm-picker.vue +3 -2
  25. package/dist/admin/components/vm-form-dialog.vue +4 -3
  26. package/dist/admin/components/vm-group-cascader.vue +5 -4
  27. package/dist/admin/components/vm-icon-picker.vue +24 -15
  28. package/dist/admin/components/vm-inline-search.vue +3 -2
  29. package/dist/admin/components/vm-loading.vue +4 -3
  30. package/dist/admin/components/vm-markdown.vue +6 -5
  31. package/dist/admin/components/vm-role-picker.vue +6 -5
  32. package/dist/admin/components/vm-view-path-picker.vue +3 -2
  33. package/dist/admin/crud/auto-fields.js +1 -1
  34. package/dist/admin/crud/components/vm-avatar.vue +2 -1
  35. package/dist/admin/crud/components/vm-color-picker.vue +8 -8
  36. package/dist/admin/crud/components/vm-column-custom.vue +6 -5
  37. package/dist/admin/crud/components/vm-copy-btn.vue +4 -3
  38. package/dist/admin/crud/components/vm-date-calendar-panel.vue +30 -27
  39. package/dist/admin/crud/components/vm-date-picker.vue +6 -5
  40. package/dist/admin/crud/components/vm-date-range.vue +5 -4
  41. package/dist/admin/crud/components/vm-datetime-field.vue +4 -3
  42. package/dist/admin/crud/components/vm-json-code.vue +3 -2
  43. package/dist/admin/crud/components/vm-json-editor.vue +3 -2
  44. package/dist/admin/crud/components/vm-json-kv-editor.vue +13 -12
  45. package/dist/admin/crud/components/vm-multi-select.vue +5 -4
  46. package/dist/admin/crud/components/vm-number-range.vue +5 -4
  47. package/dist/admin/crud/components/vm-preview-viewer.vue +33 -29
  48. package/dist/admin/crud/components/vm-richtext-extensions.js +1 -1
  49. package/dist/admin/crud/components/vm-richtext.vue +33 -30
  50. package/dist/admin/crud/components/vm-select.vue +4 -3
  51. package/dist/admin/crud/components/vm-status-tag.vue +2 -1
  52. package/dist/admin/crud/components/vm-switch.vue +5 -4
  53. package/dist/admin/crud/components/vm-text-link.vue +3 -2
  54. package/dist/admin/crud/components/vm-tree-select.vue +3 -2
  55. package/dist/admin/crud/components/vm-upload-item.vue +6 -4
  56. package/dist/admin/crud/components/vm-upload.vue +6 -5
  57. package/dist/admin/crud/config.js +1 -1
  58. package/dist/admin/crud/confirm.js +1 -1
  59. package/dist/admin/crud/crud-page-request.js +1 -1
  60. package/dist/admin/crud/data-i18n.js +1 -1
  61. package/dist/admin/crud/dict.d.ts +1 -1
  62. package/dist/admin/crud/dict.js +1 -1
  63. package/dist/admin/crud/export-fetch.js +1 -1
  64. package/dist/admin/crud/key.js +1 -1
  65. package/dist/admin/crud/plugins.js +1 -1
  66. package/dist/admin/crud/span.js +1 -1
  67. package/dist/admin/crud/style.js +1 -1
  68. package/dist/admin/crud/validate.js +1 -1
  69. package/dist/admin/crud/vm-crud.vue +15 -15
  70. package/dist/admin/crud/vm-data-i18n-btn.vue +1 -1
  71. package/dist/admin/crud/vm-export-btn.vue +7 -7
  72. package/dist/admin/crud/vm-import-btn.vue +33 -27
  73. package/dist/admin/crud/vm-table.vue +7 -2
  74. package/dist/admin/crud/vm-upsert.vue +1 -0
  75. package/dist/admin/directives/perm.js +1 -1
  76. package/dist/admin/hooks/useUpload.js +1 -1
  77. package/dist/admin/lib/browser.js +1 -1
  78. package/dist/admin/lib/cn.js +1 -1
  79. package/dist/admin/lib/dialog-float.js +1 -1
  80. package/dist/admin/lib/export-excel.js +1 -1
  81. package/dist/admin/lib/file-preview.js +8 -6
  82. package/dist/admin/lib/import-excel.js +1 -1
  83. package/dist/admin/lib/json.d.ts +0 -1
  84. package/dist/admin/lib/json.js +1 -1
  85. package/dist/admin/lib/menu.js +1 -1
  86. package/dist/admin/lib/micro-locale.js +1 -1
  87. package/dist/admin/lib/micro-theme.js +1 -1
  88. package/dist/admin/lib/shell.js +1 -1
  89. package/dist/admin/lib/theme-color-options.d.ts +1 -2
  90. package/dist/admin/lib/theme-color-options.js +1 -1
  91. package/dist/admin/lib/tree.js +1 -1
  92. package/dist/admin/lib/upload.d.ts +5 -0
  93. package/dist/admin/lib/upload.js +1 -1
  94. package/dist/admin/lib/video-frame.js +1 -1
  95. package/dist/admin/router/create.js +1 -1
  96. package/dist/admin/router/guards.js +1 -1
  97. package/dist/ai/index.js +1 -1
  98. package/dist/client/ai-model-registry.js +1 -1
  99. package/dist/client/base.js +1 -1
  100. package/dist/client/configure.js +1 -1
  101. package/dist/client/dict.js +1 -1
  102. package/dist/client/eps-payload.js +1 -1
  103. package/dist/client/eps.js +1 -1
  104. package/dist/client/index.js +1 -1
  105. package/dist/client/locale-store.js +1 -1
  106. package/dist/client/service.js +1 -1
  107. package/dist/client/vite-admin.js +1 -1
  108. package/dist/client/vite-auto-import.js +1 -1
  109. package/dist/client/vite-micro-proxy.js +1 -1
  110. package/dist/client/vite-plugin-eps.js +1 -1
  111. package/dist/client/vite-resolve.js +1 -1
  112. package/dist/config/index.js +1 -1
  113. package/dist/index.js +1 -1
  114. package/dist/server/index.js +1 -1
  115. package/dist/shared/datetime-picker.js +1 -1
  116. package/dist/shared/excel.js +1 -1
  117. package/dist/shared/index.js +1 -1
  118. package/dist/shared/locale-json.js +1 -1
  119. package/dist/shared/tree.js +1 -1
  120. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  <template>
2
2
  <vm-aside
3
- :title="onlyTrashed ? '部门回收站' : '组织架构'"
3
+ :title="onlyTrashed ? crudLabel('deptTrash') : crudLabel('deptOrg')"
4
4
  :empty="emptyText"
5
5
  :loading="loading"
6
6
  :add="canAdd && !onlyTrashed"
7
- add-title="新增顶级部门"
7
+ :add-title="crudLabel('deptAddRoot')"
8
8
  @refresh="emit('refresh')"
9
9
  @add="openAdd(null)"
10
10
  >
@@ -15,7 +15,7 @@
15
15
  @click="select(null)"
16
16
  >
17
17
  <i class="ri-building-2-line" />
18
- <span>{{ rootLabel }}</span>
18
+ <span>{{ rootLabel ?? crudLabel('all') }}</span>
19
19
  </button>
20
20
 
21
21
  <div
@@ -40,7 +40,7 @@
40
40
  <div v-if="onlyTrashed && canTrashOps" class="vm-dept-tree__ops" @click.stop>
41
41
  <button
42
42
  type="button"
43
- title="恢复"
43
+ :title="crudLabel('restore')"
44
44
  :disabled="trashBusyId === row.id"
45
45
  @click="restoreDept(row)"
46
46
  >
@@ -48,7 +48,7 @@
48
48
  </button>
49
49
  <button
50
50
  type="button"
51
- title="彻底删除"
51
+ :title="crudLabel('forceDelete')"
52
52
  :disabled="trashBusyId === row.id"
53
53
  @click="forceDeleteDept(row)"
54
54
  >
@@ -56,13 +56,13 @@
56
56
  </button>
57
57
  </div>
58
58
  <div v-else-if="!onlyTrashed && canManage" class="vm-dept-tree__ops" @click.stop>
59
- <button v-if="canAdd" type="button" title="新增子部门" @click="openAdd(row.id)">
59
+ <button v-if="canAdd" type="button" :title="crudLabel('deptAddChild')" @click="openAdd(row.id)">
60
60
  <i class="ri-add-line" />
61
61
  </button>
62
- <button v-if="canUpdate" type="button" title="编辑" @click="openEdit(row)">
62
+ <button v-if="canUpdate" type="button" :title="crudLabel('update')" @click="openEdit(row)">
63
63
  <i class="ri-edit-line" />
64
64
  </button>
65
- <button v-if="canDelete" type="button" title="删除" @click="remove(row)">
65
+ <button v-if="canDelete" type="button" :title="crudLabel('delete')" @click="remove(row)">
66
66
  <i class="ri-delete-bin-line" />
67
67
  </button>
68
68
  </div>
@@ -72,7 +72,7 @@
72
72
  <vm-form-dialog
73
73
  v-model:open="formOpen"
74
74
  v-model="formData"
75
- :title="formMode === 'add' ? '新增部门' : '编辑部门'"
75
+ :title="formMode === 'add' ? crudLabel('deptAddTitle') : crudLabel('deptEditTitle')"
76
76
  :items="dialogItems"
77
77
  @submit="onFormSubmit"
78
78
  />
@@ -82,6 +82,7 @@
82
82
  import { ref, computed, watch } from 'vue'
83
83
  import { flattenTree } from '../lib/tree'
84
84
  import { vmConfirm } from '../crud/confirm'
85
+ import { crudFormat, crudLabel } from '../crud/style'
85
86
  import { mergeByProp } from '../crud/auto-fields'
86
87
  import type { CrudFormItem } from '../../../typings/admin/comm/crud'
87
88
  import type { VmFormDialogSubmitHelpers } from './vm-form-dialog.vue'
@@ -137,7 +138,7 @@ const props = withDefaults(
137
138
  data: () => [],
138
139
  loading: false,
139
140
  modelValue: null,
140
- rootLabel: '全部',
141
+ rootLabel: undefined,
141
142
  onlyTrashed: false,
142
143
  canAdd: false,
143
144
  canUpdate: false,
@@ -172,21 +173,21 @@ const canTrashOps = computed(() => props.canRestore || props.canDelete)
172
173
  const builtinFormItems = computed((): CrudFormItem[] => [
173
174
  {
174
175
  prop: 'parentLabel',
175
- label: '上级部门',
176
- span: 24,
176
+ label: crudLabel('deptParent'),
177
+ span: 12,
177
178
  disabled: true,
178
179
  },
179
180
  {
180
181
  prop: 'name',
181
- label: '名称',
182
- span: 24,
182
+ label: crudLabel('fieldName'),
183
+ span: 12,
183
184
  required: true,
184
- placeholder: '部门名称',
185
+ placeholder: crudLabel('deptNamePh'),
185
186
  },
186
187
  {
187
188
  prop: 'orderNum',
188
- label: '排序',
189
- span: 24,
189
+ label: crudLabel('orderNum'),
190
+ span: 12,
190
191
  type: 'number',
191
192
  value: 0,
192
193
  },
@@ -247,7 +248,7 @@ const visibleRows = computed((): FlatRow[] => {
247
248
 
248
249
  const emptyText = computed(() => {
249
250
  if (props.loading || visibleRows.value.length) return ''
250
- return props.onlyTrashed ? '回收站为空' : '暂无部门'
251
+ return props.onlyTrashed ? crudLabel('trashEmpty') : crudLabel('deptEmpty')
251
252
  })
252
253
 
253
254
  function resolveFilterIds(id: number | null) {
@@ -291,7 +292,7 @@ watch(
291
292
  )
292
293
 
293
294
  function parentLabelOf(parentId: number | null) {
294
- return parentId == null ? '顶级' : idNameMap.value.get(parentId) || String(parentId)
295
+ return parentId == null ? crudLabel('topLevel') : idNameMap.value.get(parentId) || String(parentId)
295
296
  }
296
297
 
297
298
  function openAdd(parentId: number | null) {
@@ -339,10 +340,10 @@ function onFormSubmit(data: Record<string, unknown>, helpers: VmFormDialogSubmit
339
340
 
340
341
  async function remove(row: FlatRow) {
341
342
  const ok = await vmConfirm({
342
- title: '删除部门',
343
- message: `确定删除「${row.label}」?`,
344
- confirmText: '删除',
345
- cancelText: '取消',
343
+ title: crudLabel('deptDeleteTitle'),
344
+ message: crudFormat(crudLabel('deptDeleteMsg'), row.label),
345
+ confirmText: crudLabel('delete'),
346
+ cancelText: crudLabel('close'),
346
347
  })
347
348
  if (!ok) return
348
349
  if (props.modelValue === row.id) select(null)
@@ -352,10 +353,10 @@ async function remove(row: FlatRow) {
352
353
  async function restoreDept(row: FlatRow) {
353
354
  if (trashBusyId.value === row.id) return
354
355
  const ok = await vmConfirm({
355
- title: '恢复部门',
356
- message: `确定恢复「${row.label}」?`,
357
- confirmText: '恢复',
358
- cancelText: '取消',
356
+ title: crudLabel('deptRestoreTitle'),
357
+ message: crudFormat(crudLabel('deptRestoreMsg'), row.label),
358
+ confirmText: crudLabel('restore'),
359
+ cancelText: crudLabel('close'),
359
360
  })
360
361
  if (!ok) return
361
362
  trashBusyId.value = row.id
@@ -367,10 +368,10 @@ async function restoreDept(row: FlatRow) {
367
368
  async function forceDeleteDept(row: FlatRow) {
368
369
  if (trashBusyId.value === row.id) return
369
370
  const ok = await vmConfirm({
370
- title: '彻底删除',
371
- message: `确定彻底删除「${row.label}」?此操作不可恢复。`,
372
- confirmText: '彻底删除',
373
- cancelText: '取消',
371
+ title: crudLabel('deptForceDeleteTitle'),
372
+ message: crudFormat(crudLabel('deptForceDeleteMsg'), row.label),
373
+ confirmText: crudLabel('forceDelete'),
374
+ cancelText: crudLabel('close'),
374
375
  })
375
376
  if (!ok) return
376
377
  trashBusyId.value = row.id
@@ -1,9 +1,17 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
+ import { crudLabel } from '../crud/style'
3
4
  import { getScarceSvgUrl } from '../lib/scarce-assets'
4
5
 
5
6
  defineOptions({ name: 'vm-empty' })
6
7
 
8
+ /** scarce SVG 文件名 → crudLabel key(文件名保持中文) */
9
+ const KIND_LABEL_KEY: Record<string, string> = {
10
+ 暂无数据: 'empty',
11
+ 暂无内容: 'emptyContent',
12
+ 页面不存在: 'pageNotFound',
13
+ }
14
+
7
15
  const props = withDefaults(
8
16
  defineProps<{
9
17
  /** 对应 scarce 文件名(不含 .svg),如「暂无数据」 */
@@ -18,12 +26,18 @@ const props = withDefaults(
18
26
  )
19
27
 
20
28
  const src = computed(() => getScarceSvgUrl(props.kind))
29
+
30
+ const displayText = computed(() => {
31
+ if (props.description) return props.description
32
+ const key = KIND_LABEL_KEY[props.kind]
33
+ return key ? crudLabel(key) : props.kind
34
+ })
21
35
  </script>
22
36
 
23
37
  <template>
24
38
  <div class="vm-empty" :class="props.class">
25
- <img v-if="src" :src="src" :alt="kind" class="vm-empty__img" />
26
- <p class="vm-empty__text">{{ description || kind }}</p>
39
+ <img v-if="src" :src="src" :alt="displayText" class="vm-empty__img" />
40
+ <p class="vm-empty__text">{{ displayText }}</p>
27
41
  <slot />
28
42
  </div>
29
43
  </template>
@@ -6,7 +6,7 @@
6
6
  :model-value="modelValue ?? ''"
7
7
  :tree="epsTree"
8
8
  multiple
9
- :placeholder="placeholder"
9
+ :placeholder="placeholder ?? crudLabel('pickPerm')"
10
10
  :clearable="true"
11
11
  :editable="false"
12
12
  @update:model-value="(v) => emit('update:modelValue', v)"
@@ -19,6 +19,7 @@
19
19
  </template>
20
20
 
21
21
  <script setup lang="ts">
22
+ import { crudLabel } from '../crud/style'
22
23
  import { ref, computed, watch, onMounted } from 'vue'
23
24
  import { api } from '../api/client'
24
25
  import type { EpsSide } from '../lib/eps'
@@ -39,7 +40,7 @@ const props = withDefaults(
39
40
  side?: EpsSide
40
41
  }>(),
41
42
  {
42
- placeholder: '请选择权限',
43
+ placeholder: undefined,
43
44
  side: 'admin',
44
45
  },
45
46
  )
@@ -115,7 +115,7 @@
115
115
  class="ri-close-circle-fill vm-crud-upsert__textarea-clear"
116
116
  role="button"
117
117
  tabindex="-1"
118
- aria-label="清除"
118
+ :aria-label="crudLabel('clear')"
119
119
  @mousedown.prevent
120
120
  @click="setField(item.prop, '')"
121
121
  />
@@ -144,7 +144,7 @@
144
144
  :disabled="submitting"
145
145
  @click="onCloseClick"
146
146
  >
147
- {{ closeText || '取消' }}
147
+ {{ closeText || crudLabel('close') }}
148
148
  </button>
149
149
  <button
150
150
  v-if="confirm !== false && !readonly"
@@ -153,7 +153,7 @@
153
153
  :disabled="submitting"
154
154
  @click="onConfirmClick"
155
155
  >
156
- {{ submitting ? '提交中…' : confirmText || '确定' }}
156
+ {{ submitting ? crudLabel('submitting') : confirmText || crudLabel('confirm') }}
157
157
  </button>
158
158
  <slot name="footer-append" v-bind="footerSlotProps" />
159
159
  </template>
@@ -163,6 +163,7 @@
163
163
  </template>
164
164
 
165
165
  <script setup lang="ts">
166
+ import { crudLabel } from '../crud/style'
166
167
  import { ref, computed, watch, useSlots, toValue } from 'vue'
167
168
  import { preventDialogOutsideClose } from '../lib/dialog-float'
168
169
  import { resolveCrudComponent } from '../crud/registry'
@@ -10,7 +10,7 @@
10
10
  v-if="editable"
11
11
  class="vm-group-cascader__input"
12
12
  :value="displayText"
13
- :placeholder="placeholder"
13
+ :placeholder="placeholder ?? crudLabel('pleaseSelect')"
14
14
  :disabled="disabled"
15
15
  @focus="openPanel"
16
16
  @input="onInput"
@@ -30,7 +30,7 @@
30
30
  </span>
31
31
  </span>
32
32
  <span v-else-if="displayText" class="vm-group-cascader__value">{{ displayText }}</span>
33
- <span v-else class="vm-group-cascader__ph">{{ placeholder }}</span>
33
+ <span v-else class="vm-group-cascader__ph">{{ placeholder ?? crudLabel('pleaseSelect') }}</span>
34
34
  </button>
35
35
  <i
36
36
  v-if="clearable && hasValue"
@@ -82,7 +82,7 @@
82
82
  class="ri-check-line vm-group-cascader__tick"
83
83
  />
84
84
  </button>
85
- <p v-if="!col.length" class="vm-group-cascader__empty">暂无数据</p>
85
+ <p v-if="!col.length" class="vm-group-cascader__empty">{{ crudLabel('empty') }}</p>
86
86
  </div>
87
87
  </div>
88
88
  </Teleport>
@@ -90,6 +90,7 @@
90
90
  </template>
91
91
 
92
92
  <script setup lang="ts">
93
+ import { crudLabel } from '../crud/style'
93
94
  import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
94
95
  import { POPUP_TRIGGER_GAP } from '../lib/dialog-float'
95
96
  import type { GroupCascaderNode } from '../../../typings/admin/comm/cascader'
@@ -114,7 +115,7 @@ const props = withDefaults(
114
115
  multiple: false,
115
116
  clearable: true,
116
117
  editable: true,
117
- placeholder: '请选择',
118
+ placeholder: undefined,
118
119
  separator: ',',
119
120
  },
120
121
  )
@@ -6,7 +6,7 @@
6
6
  class="vm-icon-picker__preview"
7
7
  :class="{ 'is-open': open }"
8
8
  :disabled="disabled"
9
- :title="normalized || '选择图标'"
9
+ :title="normalized || crudLabel('pickIcon')"
10
10
  @click="toggle"
11
11
  >
12
12
  <i v-if="normalized" :class="normalized" />
@@ -16,7 +16,7 @@
16
16
  <input
17
17
  class="vm-icon-picker__input"
18
18
  :value="displayName"
19
- :placeholder="placeholder"
19
+ :placeholder="placeholder ?? crudLabel('iconPlaceholder')"
20
20
  :disabled="disabled"
21
21
  @focus="openPanel"
22
22
  @input="onNameInput"
@@ -53,7 +53,7 @@
53
53
  ref="searchRef"
54
54
  class="vm-icon-picker__search-input"
55
55
  :value="search"
56
- placeholder="模糊搜索,如 home / shield"
56
+ :placeholder="crudLabel('iconSearchPh')"
57
57
  @input="onSearchInput"
58
58
  @keydown.esc.stop="closePanel"
59
59
  />
@@ -63,7 +63,7 @@
63
63
  @click.stop="clearSearch"
64
64
  />
65
65
  </div>
66
- <div class="vm-icon-picker__styles" role="group" aria-label="图标类型">
66
+ <div class="vm-icon-picker__styles" role="group" :aria-label="crudLabel('iconType')">
67
67
  <button
68
68
  v-for="opt in STYLE_OPTS"
69
69
  :key="opt.value"
@@ -95,8 +95,8 @@
95
95
  type="button"
96
96
  class="vm-icon-picker__page-btn"
97
97
  :disabled="!canPrev"
98
- title="上一页"
99
- aria-label="上一页"
98
+ :title="crudLabel('prevPage')"
99
+ :aria-label="crudLabel('prevPage')"
100
100
  @click.prevent.stop="prevBatch"
101
101
  >
102
102
  <i class="ri-arrow-left-s-line" />
@@ -106,13 +106,13 @@
106
106
  type="button"
107
107
  class="vm-icon-picker__page-btn"
108
108
  :disabled="!canNext"
109
- title="下一页"
110
- aria-label="下一页"
109
+ :title="crudLabel('nextPage')"
110
+ :aria-label="crudLabel('nextPage')"
111
111
  @click.prevent.stop="nextBatch"
112
112
  >
113
113
  <i class="ri-arrow-right-s-line" />
114
114
  </button>
115
- <p v-if="!filtered.length" class="vm-icon-picker__empty">无匹配图标</p>
115
+ <p v-if="!filtered.length" class="vm-icon-picker__empty">{{ crudLabel('noMatchIcon') }}</p>
116
116
  </div>
117
117
  </div>
118
118
  </FocusScope>
@@ -121,6 +121,7 @@
121
121
  </template>
122
122
 
123
123
  <script setup lang="ts">
124
+ import { crudLabel } from '../crud/style'
124
125
  import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
125
126
  import { FocusScope } from 'reka-ui'
126
127
  import { POPUP_TRIGGER_GAP } from '../lib/dialog-float'
@@ -130,11 +131,19 @@ defineOptions({ name: 'vm-icon-picker' })
130
131
 
131
132
  type IconStyle = 'fill' | 'line' | 'other'
132
133
 
133
- const STYLE_OPTS: { value: IconStyle; label: string; title: string }[] = [
134
- { value: 'fill', label: '实心', title: 'Fill 实心图标' },
135
- { value: 'line', label: '线形', title: 'Line 线形图标' },
136
- { value: 'other', label: '其它', title: '无 fill/line 后缀(多为编辑类)' },
137
- ]
134
+ const STYLE_OPTS = computed(() =>
135
+ (
136
+ [
137
+ { value: 'fill' as const, labelKey: 'iconFill', titleKey: 'iconFillTitle' },
138
+ { value: 'line' as const, labelKey: 'iconLine', titleKey: 'iconLineTitle' },
139
+ { value: 'other' as const, labelKey: 'iconOther', titleKey: 'iconOtherTitle' },
140
+ ] as const
141
+ ).map((o) => ({
142
+ value: o.value,
143
+ label: crudLabel(o.labelKey),
144
+ title: crudLabel(o.titleKey),
145
+ })),
146
+ )
138
147
 
139
148
  const props = withDefaults(
140
149
  defineProps<{
@@ -144,7 +153,7 @@ const props = withDefaults(
144
153
  clearable?: boolean
145
154
  }>(),
146
155
  {
147
- placeholder: '如 ri-home-fill',
156
+ placeholder: undefined,
148
157
  clearable: true,
149
158
  },
150
159
  )
@@ -4,7 +4,7 @@
4
4
  <input
5
5
  :value="modelValue"
6
6
  type="search"
7
- :placeholder="placeholder"
7
+ :placeholder="placeholder ?? crudLabel('search')"
8
8
  @input="onInput"
9
9
  @keydown.enter="emit('search')"
10
10
  />
@@ -12,6 +12,7 @@
12
12
  </template>
13
13
 
14
14
  <script setup lang="ts">
15
+ import { crudLabel } from '../crud/style'
15
16
  defineOptions({ name: 'vm-inline-search' })
16
17
 
17
18
  withDefaults(
@@ -21,7 +22,7 @@ withDefaults(
21
22
  }>(),
22
23
  {
23
24
  modelValue: '',
24
- placeholder: '搜索',
25
+ placeholder: undefined,
25
26
  },
26
27
  )
27
28
 
@@ -19,12 +19,13 @@
19
19
  :style="footerStyle"
20
20
  role="status"
21
21
  >
22
- {{ status === 'end' ? endText : loadingText }}
22
+ {{ status === 'end' ? (endText ?? crudLabel('noMore')) : (loadingText ?? crudLabel('loading')) }}
23
23
  </div>
24
24
  </template>
25
25
 
26
26
  <script setup lang="ts">
27
27
  import { computed } from 'vue'
28
+ import { crudLabel } from '../crud/style'
28
29
 
29
30
  defineOptions({ name: 'vm-loading' })
30
31
 
@@ -49,8 +50,8 @@ const props = withDefaults(
49
50
  mode: 'overlay',
50
51
  status: 'loading',
51
52
  fixed: false,
52
- loadingText: '加载中...',
53
- endText: '没有更多了',
53
+ loadingText: undefined,
54
+ endText: undefined,
54
55
  },
55
56
  )
56
57
 
@@ -15,7 +15,7 @@
15
15
  :aria-selected="tab === 'edit'"
16
16
  @click="tab = 'edit'"
17
17
  >
18
- 编辑
18
+ {{ crudLabel('markdownEdit') }}
19
19
  </button>
20
20
  <button
21
21
  type="button"
@@ -25,7 +25,7 @@
25
25
  :aria-selected="tab === 'preview'"
26
26
  @click="tab = 'preview'"
27
27
  >
28
- 预览
28
+ {{ crudLabel('markdownPreview') }}
29
29
  </button>
30
30
  </div>
31
31
 
@@ -36,7 +36,7 @@
36
36
  :style="editorStyle"
37
37
  :value="text"
38
38
  :disabled="disabled || uploading"
39
- :placeholder="placeholder"
39
+ :placeholder="placeholder ?? crudLabel('markdownHint')"
40
40
  @input="onInput"
41
41
  @paste="onPaste"
42
42
  />
@@ -49,11 +49,12 @@
49
49
  v-html="html"
50
50
  />
51
51
 
52
- <p v-if="uploading" class="vm-markdown__hint">图片上传中…</p>
52
+ <p v-if="uploading" class="vm-markdown__hint">{{ crudLabel('markdownUploading') }}</p>
53
53
  </div>
54
54
  </template>
55
55
 
56
56
  <script setup lang="ts">
57
+ import { crudLabel } from '../crud/style'
57
58
  import { computed, nextTick, ref, watch } from 'vue'
58
59
  import DOMPurify from 'dompurify'
59
60
  import { marked } from 'marked'
@@ -78,7 +79,7 @@ const props = withDefaults(
78
79
  edit: false,
79
80
  preview: true,
80
81
  disabled: false,
81
- placeholder: '支持 Markdown;可粘贴图片(需配置 uploadImage)',
82
+ placeholder: undefined,
82
83
  },
83
84
  )
84
85
 
@@ -9,7 +9,7 @@
9
9
  @click="togglePanel"
10
10
  >
11
11
  <span v-if="displayText" class="vm-role-picker__value">{{ displayText }}</span>
12
- <span v-else class="vm-role-picker__ph">{{ placeholder }}</span>
12
+ <span v-else class="vm-role-picker__ph">{{ placeholder ?? crudLabel('pickRole') }}</span>
13
13
  <i
14
14
  v-if="clearable && picked.size"
15
15
  class="ri-close-circle-fill vm-role-picker__clear"
@@ -25,8 +25,8 @@
25
25
  class="vm-role-picker__panel vm-dialog-float"
26
26
  :style="panelStyle"
27
27
  >
28
- <div v-if="loading" class="vm-role-picker__state">加载中…</div>
29
- <div v-else-if="!options.length" class="vm-role-picker__state">暂无角色</div>
28
+ <div v-if="loading" class="vm-role-picker__state">{{ crudLabel('loading') }}</div>
29
+ <div v-else-if="!options.length" class="vm-role-picker__state">{{ crudLabel('noRoles') }}</div>
30
30
  <div v-else class="vm-role-picker__list vm-scroll">
31
31
  <label
32
32
  v-for="opt in options"
@@ -48,6 +48,7 @@
48
48
  </template>
49
49
 
50
50
  <script setup lang="ts">
51
+ import { crudFormat, crudLabel } from '../crud/style'
51
52
  import { useVome } from '../hooks/useVome'
52
53
  import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
53
54
  import { POPUP_TRIGGER_GAP } from '../lib/dialog-float'
@@ -66,7 +67,7 @@ const props = withDefaults(
66
67
  modelValue: () => [],
67
68
  disabled: false,
68
69
  clearable: true,
69
- placeholder: '请选择角色',
70
+ placeholder: undefined,
70
71
  source: 'base',
71
72
  },
72
73
  )
@@ -92,7 +93,7 @@ const displayText = computed(() => {
92
93
  const names = ids
93
94
  .map((id) => options.value.find((o) => o.id === id)?.name || String(id))
94
95
  .filter(Boolean)
95
- if (!names.length) return `已选 ${ids.length} 项`
96
+ if (!names.length) return crudFormat(crudLabel('selectedCount'), ids.length)
96
97
  if (names.length === 1) return names[0]!
97
98
  return `${names[0]} +${names.length - 1}`
98
99
  })
@@ -2,7 +2,7 @@
2
2
  <vm-group-cascader
3
3
  :model-value="modelValue ?? ''"
4
4
  :tree="tree"
5
- :placeholder="placeholder"
5
+ :placeholder="placeholder ?? crudLabel('pickFilePath')"
6
6
  :clearable="clearable"
7
7
  :editable="editable"
8
8
  :disabled="disabled"
@@ -11,6 +11,7 @@
11
11
  </template>
12
12
 
13
13
  <script setup lang="ts">
14
+ import { crudLabel } from '../crud/style'
14
15
  import { ref, onMounted, onUnmounted } from 'vue'
15
16
  import {
16
17
  listViewsTree,
@@ -28,7 +29,7 @@ withDefaults(
28
29
  disabled?: boolean
29
30
  }>(),
30
31
  {
31
- placeholder: '请选择文件路径',
32
+ placeholder: undefined,
32
33
  clearable: true,
33
34
  editable: true,
34
35
  },
@@ -1 +1 @@
1
- const _0x31c7bd=_0x53f2;(function(_0x3232fa,_0x309275){const _0x4c8a3f=_0x53f2,_0x43cfb5=_0x3232fa();while(!![]){try{const _0xc66c58=-parseInt(_0x4c8a3f(0x19e))/0x1*(parseInt(_0x4c8a3f(0x19d))/0x2)+parseInt(_0x4c8a3f(0x1ac))/0x3+parseInt(_0x4c8a3f(0x1a1))/0x4*(-parseInt(_0x4c8a3f(0x181))/0x5)+parseInt(_0x4c8a3f(0x1a9))/0x6+parseInt(_0x4c8a3f(0x189))/0x7+-parseInt(_0x4c8a3f(0x17e))/0x8+parseInt(_0x4c8a3f(0x1a8))/0x9;if(_0xc66c58===_0x309275)break;else _0x43cfb5['push'](_0x43cfb5['shift']());}catch(_0x269425){_0x43cfb5['push'](_0x43cfb5['shift']());}}}(_0x255b,0xaabd6));import{findEpsEntity}from'../lib/eps';import{getDictOptions}from'../../client';export const UPSERT_BUILTIN_IGNORE=['id',_0x31c7bd(0x19a),_0x31c7bd(0x1ae),'updateTime','deleteTime'];export const TABLE_BUILTIN_IGNORE=[_0x31c7bd(0x1ad),'updateTime'];function dictKeyOf(_0x2d60e4){const _0x2cfc21=_0x31c7bd;if(typeof _0x2d60e4[_0x2cfc21(0x199)]===_0x2cfc21(0x17c)&&_0x2d60e4['dict'])return _0x2d60e4[_0x2cfc21(0x199)];if(Array[_0x2cfc21(0x198)](_0x2d60e4[_0x2cfc21(0x199)])&&_0x2d60e4[_0x2cfc21(0x199)][0x0])return _0x2d60e4[_0x2cfc21(0x199)][0x0];return;}function isSwitchDict(_0x3464cc){const _0x32f2b7=_0x31c7bd;return _0x3464cc===_0x32f2b7(0x1a4)||_0x3464cc==='yes_no';}function switchFormItem(_0x8892aa,_0x969fb5,_0x2db20c){const _0x5b69b9=_0x31c7bd;return{..._0x8892aa,'type':_0x5b69b9(0x1b1),'value':_0x2db20c,'dict':_0x969fb5,'component':{'props':()=>mapDictOptions(_0x969fb5)}};}export function mapDictOptions(_0xed5d36){const _0x2c789a=_0x31c7bd;return getDictOptions(_0xed5d36)[_0x2c789a(0x182)](_0x4cd8b2=>{const _0x1829fd=_0x2c789a;let _0x458c05=_0x4cd8b2[_0x1829fd(0x1aa)];return typeof _0x4cd8b2['value']===_0x1829fd(0x17c)&&/^-?\d+(\.\d+)?$/['test'](_0x4cd8b2[_0x1829fd(0x1aa)])&&(_0x458c05=Number(_0x4cd8b2['value'])),{'label':String(_0x4cd8b2[_0x1829fd(0x1b0)]??''),'value':_0x458c05,'color':_0x4cd8b2[_0x1829fd(0x1a5)]};});}function isMainTableCol(_0x23e0ef){const _0x646a35=_0x31c7bd;return!_0x23e0ef[_0x646a35(0x1a0)]||_0x23e0ef[_0x646a35(0x1a0)][_0x646a35(0x183)]('a.');}function epsColumns(_0x396fdf){const _0x391b8c=_0x31c7bd,_0x8ff24e=_0x396fdf[_0x391b8c(0x180)]?findEpsEntity('/'+_0x396fdf['namespace']):undefined;if(!_0x8ff24e)return[];const _0x5564d8=[..._0x8ff24e['columns']||[],..._0x8ff24e['pageColumns']||[]],_0x38b966=new Set(),_0x2a2068=[];for(const _0x2ca7c2 of _0x5564d8){if(!_0x2ca7c2[_0x391b8c(0x18e)]||!isMainTableCol(_0x2ca7c2))continue;if(_0x38b966[_0x391b8c(0x19f)](_0x2ca7c2[_0x391b8c(0x18e)]))continue;_0x38b966[_0x391b8c(0x19b)](_0x2ca7c2[_0x391b8c(0x18e)]),_0x2a2068['push'](_0x2ca7c2);}return _0x2a2068;}function _0x255b(){const _0x220e53=['mtG3nta4n0Lruxj4qq','zgvSzxrLvgLTzq','y3jLyxrLvgLTzq','DgvZDa','BgfIzwW','C3DPDgnO','ChvZAa','yM9VBgvHBG','CMLNAhq','C3rYAw5N','Dg9mB3DLCKnHC2u','nZGYodm2oeDOCwL0zG','AwDUB3jLrMLLBgrZ','BMfTzxnWywnL','mtK4nda1yKzqyKHw','BwfW','C3rHCNrZv2L0Aa','ChjVCa','Aw5WDxq','zgvSzxrL','C2vSzwn0Aw9U','Dgv4DgfYzwe','odyZmJaWogXny0rREq','ugDuzxH0','ugDcB29SzwfU','y29TBwvUDa','DM0TC3DPDgnO','ChjVCgvYDhLoyw1L','ugDtBwfSBeLUDa','ugDcAwDtzxjPywW','C3fSvhLWzq','y29SDw1UvhLWzq','ugDcAwDjBNq','Dgv4Da','DhLWzq','zwrPDa','CMvXDwLYzwq','AxnbCNjHEq','zgLJDa','DgvUyw50swq','ywrK','BNvTyMvY','nJGYEMPZugrb','nda1BLPJyKnJ','AgfZ','C291CMnL','odHZzvnPs3K','ugDszwfS','BNvSBgfIBgu','C3rHDhvZ','y29SB3i','ugDtBwfSBfnLCMLHBa','EwvZx25V','ndyYnde1nuLRshnvtq','mtKWmJa5mersteH5EG','DMfSDwu','AgfZrgvMyxvSDa'];_0x255b=function(){return _0x220e53;};return _0x255b();}function columnTypeOf(_0x3dc708){const _0x22acb7=_0x31c7bd;return String(_0x3dc708[_0x22acb7(0x192)]||'');}function sqlTypeOf(_0x5ddd2d){const _0xe8671f=_0x31c7bd;return String(_0x5ddd2d[_0xe8671f(0x191)]||'')[_0xe8671f(0x17d)]();}function isTextCol(_0x55174a){const _0x2671f4=_0x31c7bd,_0xd8bc2=columnTypeOf(_0x55174a);if(_0xd8bc2===_0x2671f4(0x18a))return!![];return sqlTypeOf(_0x55174a)===_0x2671f4(0x194);}function isIntegerCol(_0x497994){const _0x1c55d1=_0x31c7bd,_0x4058bf=columnTypeOf(_0x497994);if(_0x4058bf==='PgInteger'||_0x4058bf==='PgSerial'||_0x4058bf===_0x1c55d1(0x18f)||_0x4058bf===_0x1c55d1(0x193)||_0x4058bf===_0x1c55d1(0x1a6)||_0x4058bf===_0x1c55d1(0x190))return!![];if(_0x497994[_0x1c55d1(0x195)]===_0x1c55d1(0x19c)&&!isNumericCol(_0x497994))return!![];return/^(integer|serial|smallint|bigint|smallserial|bigserial)\b/[_0x1c55d1(0x1af)](sqlTypeOf(_0x497994));}function isNumericCol(_0x283b78){const _0x59f27=_0x31c7bd,_0x3f65c6=columnTypeOf(_0x283b78);if(_0x3f65c6==='PgNumeric'||_0x3f65c6==='PgDoublePrecision'||_0x3f65c6===_0x59f27(0x1a2))return!![];return/^(numeric|decimal|double|real)\b/['test'](sqlTypeOf(_0x283b78));}function isBooleanCol(_0x127aba){const _0x782310=_0x31c7bd;return columnTypeOf(_0x127aba)===_0x782310(0x18b)||_0x127aba[_0x782310(0x195)]===_0x782310(0x17a)||sqlTypeOf(_0x127aba)[_0x782310(0x183)](_0x782310(0x17a));}function _0x53f2(_0x6d5b15,_0x3840af){_0x6d5b15=_0x6d5b15-0x179;const _0x255b57=_0x255b();let _0x53f2a1=_0x255b57[_0x6d5b15];if(_0x53f2['IbLxAy']===undefined){var _0x1e286a=function(_0x2e7e36){const _0x8d8719='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2d60e4='',_0x3464cc='';for(let _0x8892aa=0x0,_0x969fb5,_0x2db20c,_0xed5d36=0x0;_0x2db20c=_0x2e7e36['charAt'](_0xed5d36++);~_0x2db20c&&(_0x969fb5=_0x8892aa%0x4?_0x969fb5*0x40+_0x2db20c:_0x2db20c,_0x8892aa++%0x4)?_0x2d60e4+=String['fromCharCode'](0xff&_0x969fb5>>(-0x2*_0x8892aa&0x6)):0x0){_0x2db20c=_0x8d8719['indexOf'](_0x2db20c);}for(let _0x4cd8b2=0x0,_0x458c05=_0x2d60e4['length'];_0x4cd8b2<_0x458c05;_0x4cd8b2++){_0x3464cc+='%'+('00'+_0x2d60e4['charCodeAt'](_0x4cd8b2)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3464cc);};_0x53f2['GCZybf']=_0x1e286a,_0x53f2['QOcpBA']={},_0x53f2['IbLxAy']=!![];}const _0xe095cc=_0x255b57[0x0],_0x1c9993=_0x6d5b15+_0xe095cc,_0x19c49a=_0x53f2['QOcpBA'][_0x1c9993];return!_0x19c49a?(_0x53f2a1=_0x53f2['GCZybf'](_0x53f2a1),_0x53f2['QOcpBA'][_0x1c9993]=_0x53f2a1):_0x53f2a1=_0x19c49a,_0x53f2a1;}function numberPrecision(_0x29531e){if(isIntegerCol(_0x29531e))return 0x0;if(typeof _0x29531e['scale']==='number')return _0x29531e['scale'];return 0x2;}export function mergeByProp(_0x188ff3,_0x4dc697){const _0x3e8875=_0x31c7bd,_0x2bf65c=_0x4dc697['filter'](_0x3aaefb=>Boolean(_0x3aaefb[_0x3e8875(0x184)])),_0xced0c0=_0x4dc697['filter'](_0x37691a=>!_0x37691a['prop']&&_0x37691a[_0x3e8875(0x195)]),_0x25bb03=new Map(_0x2bf65c[_0x3e8875(0x182)](_0x444309=>[String(_0x444309[_0x3e8875(0x184)]),_0x444309])),_0x4aba8b=new Set(_0xced0c0[_0x3e8875(0x182)](_0x2e3338=>String(_0x2e3338[_0x3e8875(0x195)]))),_0x2449ae=new Set(),_0x29e512=[];for(const _0xfe2023 of _0x188ff3){if(!_0xfe2023[_0x3e8875(0x184)]&&_0xfe2023[_0x3e8875(0x195)]){if(_0x4aba8b[_0x3e8875(0x19f)](String(_0xfe2023[_0x3e8875(0x195)])))continue;_0x29e512['push'](_0xfe2023);continue;}if(!_0xfe2023[_0x3e8875(0x184)])continue;const _0x1e1824=String(_0xfe2023[_0x3e8875(0x184)]),_0x497866=_0x25bb03['get'](_0x1e1824);_0x497866?(_0x29e512[_0x3e8875(0x179)]({..._0xfe2023,..._0x497866}),_0x2449ae[_0x3e8875(0x19b)](_0x1e1824)):_0x29e512['push'](_0xfe2023);}for(const _0x213189 of _0x2bf65c){const _0x1949c3=String(_0x213189[_0x3e8875(0x184)]);if(!_0x2449ae[_0x3e8875(0x19f)](_0x1949c3))_0x29e512['push'](_0x213189);}return _0x29e512[_0x3e8875(0x179)](..._0xced0c0),_0x29e512;}export function sortRequiredFirst(_0x4b21cb){const _0x17779e=_0x31c7bd,_0x40c434=[],_0x53ff1c=[];for(const _0x5945a0 of _0x4b21cb){_0x5945a0[_0x17779e(0x197)]===!![]||typeof _0x5945a0[_0x17779e(0x197)]==='function'?_0x40c434[_0x17779e(0x179)](_0x5945a0):_0x53ff1c[_0x17779e(0x179)](_0x5945a0);}return[..._0x40c434,..._0x53ff1c];}export function buildAutoUpsertItems(_0x465b20,_0x3a64b8={}){const _0x313722=_0x31c7bd,_0x2bbbc2=new Set([...UPSERT_BUILTIN_IGNORE,..._0x3a64b8[_0x313722(0x17f)]||[]]),_0x3c3a25=[];for(const _0x1986e4 of epsColumns(_0x465b20)){const _0x1fc036=_0x1986e4[_0x313722(0x18e)];if(_0x2bbbc2[_0x313722(0x19f)](_0x1fc036))continue;const _0x10cdea=_0x1986e4[_0x313722(0x18c)]||_0x1fc036,_0x5022f2=dictKeyOf(_0x1986e4),_0xe7eaee=_0x1986e4[_0x313722(0x1a3)]===![]&&_0x1986e4[_0x313722(0x1ab)]!==!![],_0xc939f1={'prop':_0x1fc036,'label':_0x10cdea,'span':0xc,..._0xe7eaee?{'required':!![]}:{}};if(_0x1fc036===_0x313722(0x1a4)){const _0xca6ac6=_0x5022f2||_0x313722(0x1a4);isSwitchDict(_0xca6ac6)?_0x3c3a25[_0x313722(0x179)](switchFormItem(_0xc939f1,_0xca6ac6,0x1)):_0x3c3a25[_0x313722(0x179)]({..._0xc939f1,'type':'select','dict':_0xca6ac6,'value':0x1});continue;}if(_0x5022f2){isSwitchDict(_0x5022f2)?_0x3c3a25['push'](switchFormItem(_0xc939f1,_0x5022f2,_0x5022f2==='yes_no'?![]:0x1)):_0x3c3a25['push']({..._0xc939f1,'type':'select','dict':_0x5022f2,'value':0x0});continue;}if(isTextCol(_0x1986e4)){_0x3c3a25[_0x313722(0x179)]({..._0xc939f1,'type':_0x313722(0x188),'span':0xc});continue;}if(isBooleanCol(_0x1986e4)){_0x3c3a25[_0x313722(0x179)]({..._0xc939f1,'type':_0x313722(0x1b1),'value':![],'component':{'props':()=>mapDictOptions(_0x313722(0x1a7))},'dict':_0x313722(0x1a7)});continue;}if(isIntegerCol(_0x1986e4)||isNumericCol(_0x1986e4)){const _0x2c8345=numberPrecision(_0x1986e4);_0x3c3a25[_0x313722(0x179)]({..._0xc939f1,'type':_0x313722(0x19c),'component':{'props':{'type':_0x313722(0x19c),'precision':_0x2c8345,'controls':![]}}});continue;}_0x3c3a25[_0x313722(0x179)]({..._0xc939f1,'type':_0x313722(0x185)});}return _0x3c3a25;}export function buildAutoTableColumns(_0x2a5ece,_0x4e4155={}){const _0x473d9c=_0x31c7bd,_0xd7beb2=new Set([...TABLE_BUILTIN_IGNORE,..._0x4e4155[_0x473d9c(0x17f)]||[]]),_0x3d9e93=[];!_0xd7beb2[_0x473d9c(0x19f)](_0x473d9c(0x187))&&_0x3d9e93[_0x473d9c(0x179)]({'type':'selection','width':0x32});for(const _0x43ff65 of epsColumns(_0x2a5ece)){const _0x148e93=_0x43ff65['propertyName'];if(_0xd7beb2[_0x473d9c(0x19f)](_0x148e93))continue;const _0x1eb131=_0x43ff65[_0x473d9c(0x18c)]||_0x148e93,_0x406431=dictKeyOf(_0x43ff65);if(_0x148e93===_0x473d9c(0x1a4)){const _0x3bd90c=_0x406431||_0x473d9c(0x1a4);isSwitchDict(_0x3bd90c)?_0x3d9e93[_0x473d9c(0x179)]({'prop':_0x148e93,'label':_0x1eb131,'width':0x50,'fixed':_0x473d9c(0x17b),'component':{'name':_0x473d9c(0x18d),'props':()=>mapDictOptions(_0x3bd90c)}}):_0x3d9e93[_0x473d9c(0x179)]({'prop':_0x148e93,'label':_0x1eb131,'width':0x64,'fixed':_0x473d9c(0x17b),'dict':()=>mapDictOptions(_0x3bd90c)});continue;}if(_0x406431&&isSwitchDict(_0x406431)){_0x3d9e93['push']({'prop':_0x148e93,'label':_0x1eb131,'width':0x50,'component':{'name':_0x473d9c(0x18d),'props':()=>mapDictOptions(_0x406431)}});continue;}if(_0x148e93==='id'){_0x3d9e93[_0x473d9c(0x179)]({'prop':_0x148e93,'label':_0x1eb131,'width':0x50});continue;}if(_0x148e93===_0x473d9c(0x1ae)){_0x3d9e93[_0x473d9c(0x179)]({'prop':_0x148e93,'label':_0x1eb131,'width':0xa0});continue;}if(_0x406431){_0x3d9e93['push']({'prop':_0x148e93,'label':_0x1eb131,'minWidth':0x78,'dict':()=>mapDictOptions(_0x406431)});continue;}if(isTextCol(_0x43ff65)){_0x3d9e93[_0x473d9c(0x179)]({'prop':_0x148e93,'label':_0x1eb131,'minWidth':0xa0,'showOverflowTooltip':!![]});continue;}_0x3d9e93[_0x473d9c(0x179)]({'prop':_0x148e93,'label':_0x1eb131,'minWidth':0x78});}return!_0xd7beb2[_0x473d9c(0x19f)]('op')&&_0x3d9e93['push']({'type':'op','buttons':[_0x473d9c(0x196),_0x473d9c(0x186)]}),_0x3d9e93;}
1
+ const _0x79fca=_0x1cc8;(function(_0x211cad,_0x4a0e1b){const _0x383be9=_0x1cc8,_0x2c7138=_0x211cad();while(!![]){try{const _0x5ed19c=parseInt(_0x383be9(0x95))/0x1+-parseInt(_0x383be9(0x75))/0x2*(-parseInt(_0x383be9(0x88))/0x3)+parseInt(_0x383be9(0x6e))/0x4*(parseInt(_0x383be9(0x84))/0x5)+-parseInt(_0x383be9(0x9e))/0x6*(parseInt(_0x383be9(0xa0))/0x7)+-parseInt(_0x383be9(0x7a))/0x8*(parseInt(_0x383be9(0xa6))/0x9)+-parseInt(_0x383be9(0x82))/0xa+-parseInt(_0x383be9(0xab))/0xb*(-parseInt(_0x383be9(0x91))/0xc);if(_0x5ed19c===_0x4a0e1b)break;else _0x2c7138['push'](_0x2c7138['shift']());}catch(_0x20dcc3){_0x2c7138['push'](_0x2c7138['shift']());}}}(_0xfbcf,0x7a036));import{findEpsEntity}from'../lib/eps';import{getDictOptions}from'../../client';export const UPSERT_BUILTIN_IGNORE=['id',_0x79fca(0x90),'createTime',_0x79fca(0x77),_0x79fca(0x70)];export const TABLE_BUILTIN_IGNORE=[_0x79fca(0x70),'updateTime'];function dictKeyOf(_0xa0cc44){const _0x295c97=_0x79fca;if(typeof _0xa0cc44[_0x295c97(0x81)]===_0x295c97(0x7e)&&_0xa0cc44[_0x295c97(0x81)])return _0xa0cc44[_0x295c97(0x81)];if(Array[_0x295c97(0x7c)](_0xa0cc44[_0x295c97(0x81)])&&_0xa0cc44[_0x295c97(0x81)][0x0])return _0xa0cc44[_0x295c97(0x81)][0x0];return;}function isSwitchDict(_0x1c4619){const _0x51df15=_0x79fca;return _0x1c4619===_0x51df15(0x79)||_0x1c4619==='yes_no_boolean'||_0x1c4619===_0x51df15(0x99);}function switchDefaultValue(_0x5cbce9){const _0x39853c=_0x79fca;if(_0x5cbce9===_0x39853c(0xa4))return![];if(_0x5cbce9==='yes_no_number')return 0x0;return 0x1;}function switchFormItem(_0x5989af,_0x31c9d5,_0x17b3dd){const _0x806e3f=_0x79fca;return{..._0x5989af,'type':_0x806e3f(0xac),'value':_0x17b3dd,'dict':_0x31c9d5,'component':{'props':()=>mapDictOptions(_0x31c9d5)}};}export function mapDictOptions(_0x371c8c){const _0xb96390=_0x79fca;return getDictOptions(_0x371c8c)[_0xb96390(0x89)](_0x211869=>{const _0x2c75b5=_0xb96390;let _0x10658f=_0x211869[_0x2c75b5(0xa5)];return typeof _0x211869['value']===_0x2c75b5(0x7e)&&/^-?\d+(\.\d+)?$/[_0x2c75b5(0x9a)](_0x211869[_0x2c75b5(0xa5)])&&(_0x10658f=Number(_0x211869['value'])),{'label':String(_0x211869[_0x2c75b5(0xa7)]??''),'value':_0x10658f,'color':_0x211869[_0x2c75b5(0xa3)]};});}function isMainTableCol(_0x2cb2ee){const _0x25ecb3=_0x79fca;return!_0x2cb2ee[_0x25ecb3(0x8d)]||_0x2cb2ee[_0x25ecb3(0x8d)][_0x25ecb3(0x8f)]('a.');}function epsColumns(_0x1283d4){const _0x24c4c4=_0x79fca,_0x534fd8=_0x1283d4[_0x24c4c4(0x9f)]?findEpsEntity('/'+_0x1283d4[_0x24c4c4(0x9f)]):undefined;if(!_0x534fd8)return[];const _0x4bef73=[..._0x534fd8[_0x24c4c4(0x7f)]||[],..._0x534fd8['pageColumns']||[]],_0x3296e9=new Set(),_0xf24aa1=[];for(const _0x29e150 of _0x4bef73){if(!_0x29e150[_0x24c4c4(0x80)]||!isMainTableCol(_0x29e150))continue;if(_0x3296e9[_0x24c4c4(0x85)](_0x29e150[_0x24c4c4(0x80)]))continue;_0x3296e9[_0x24c4c4(0x8a)](_0x29e150['propertyName']),_0xf24aa1[_0x24c4c4(0x83)](_0x29e150);}return _0xf24aa1;}function columnTypeOf(_0x51ba19){return String(_0x51ba19['columnType']||'');}function sqlTypeOf(_0x3e18d5){const _0x2c44e9=_0x79fca;return String(_0x3e18d5[_0x2c44e9(0x6f)]||'')[_0x2c44e9(0x8c)]();}function isTextCol(_0x5d53c7){const _0xe63797=columnTypeOf(_0x5d53c7);if(_0xe63797==='PgText')return!![];return sqlTypeOf(_0x5d53c7)==='text';}function isIntegerCol(_0x705da9){const _0x4469b4=_0x79fca,_0x217f15=columnTypeOf(_0x705da9);if(_0x217f15==='PgInteger'||_0x217f15===_0x4469b4(0x78)||_0x217f15===_0x4469b4(0x9d)||_0x217f15===_0x4469b4(0x7d)||_0x217f15===_0x4469b4(0xad)||_0x217f15==='PgBigSerial')return!![];if(_0x705da9[_0x4469b4(0x73)]==='number'&&!isNumericCol(_0x705da9))return!![];return/^(integer|serial|smallint|bigint|smallserial|bigserial)\b/[_0x4469b4(0x9a)](sqlTypeOf(_0x705da9));}function _0x1cc8(_0x2d1c49,_0x45a7ec){_0x2d1c49=_0x2d1c49-0x6e;const _0xfbcf9c=_0xfbcf();let _0x1cc8e9=_0xfbcf9c[_0x2d1c49];if(_0x1cc8['ZsfdBZ']===undefined){var _0x5d3e2b=function(_0x5c5981){const _0x2b639a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0xa0cc44='',_0x1c4619='';for(let _0x5cbce9=0x0,_0x5989af,_0x31c9d5,_0x17b3dd=0x0;_0x31c9d5=_0x5c5981['charAt'](_0x17b3dd++);~_0x31c9d5&&(_0x5989af=_0x5cbce9%0x4?_0x5989af*0x40+_0x31c9d5:_0x31c9d5,_0x5cbce9++%0x4)?_0xa0cc44+=String['fromCharCode'](0xff&_0x5989af>>(-0x2*_0x5cbce9&0x6)):0x0){_0x31c9d5=_0x2b639a['indexOf'](_0x31c9d5);}for(let _0x371c8c=0x0,_0x211869=_0xa0cc44['length'];_0x371c8c<_0x211869;_0x371c8c++){_0x1c4619+='%'+('00'+_0xa0cc44['charCodeAt'](_0x371c8c)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1c4619);};_0x1cc8['AfYcfO']=_0x5d3e2b,_0x1cc8['HcZwyr']={},_0x1cc8['ZsfdBZ']=!![];}const _0x32066e=_0xfbcf9c[0x0],_0x3ac34f=_0x2d1c49+_0x32066e,_0x3b2262=_0x1cc8['HcZwyr'][_0x3ac34f];return!_0x3b2262?(_0x1cc8e9=_0x1cc8['AfYcfO'](_0x1cc8e9),_0x1cc8['HcZwyr'][_0x3ac34f]=_0x1cc8e9):_0x1cc8e9=_0x3b2262,_0x1cc8e9;}function isNumericCol(_0x59e03a){const _0x585142=_0x79fca,_0x6cae02=columnTypeOf(_0x59e03a);if(_0x6cae02===_0x585142(0x7b)||_0x6cae02===_0x585142(0xaa)||_0x6cae02==='PgReal')return!![];return/^(numeric|decimal|double|real)\b/['test'](sqlTypeOf(_0x59e03a));}function isBooleanCol(_0x43d140){const _0x2d22a7=_0x79fca;return columnTypeOf(_0x43d140)===_0x2d22a7(0x97)||_0x43d140['type']===_0x2d22a7(0x8e)||sqlTypeOf(_0x43d140)[_0x2d22a7(0x8f)](_0x2d22a7(0x8e));}function numberPrecision(_0x58c973){const _0x3751d2=_0x79fca;if(isIntegerCol(_0x58c973))return 0x0;if(typeof _0x58c973[_0x3751d2(0xa1)]===_0x3751d2(0x94))return _0x58c973[_0x3751d2(0xa1)];return 0x2;}export function mergeByProp(_0x4b8d48,_0x2cfb90){const _0x45287f=_0x79fca,_0x4753f8=_0x2cfb90[_0x45287f(0x86)](_0x8e8b37=>Boolean(_0x8e8b37[_0x45287f(0x87)])),_0x31edba=_0x2cfb90['filter'](_0x138bc6=>!_0x138bc6[_0x45287f(0x87)]&&_0x138bc6[_0x45287f(0x73)]),_0x288c11=new Map(_0x4753f8[_0x45287f(0x89)](_0x3c7e2c=>[String(_0x3c7e2c[_0x45287f(0x87)]),_0x3c7e2c])),_0x2866d8=new Set(_0x31edba[_0x45287f(0x89)](_0x17019d=>String(_0x17019d[_0x45287f(0x73)]))),_0x3ad967=new Set(),_0x3baea7=[];for(const _0xbc346e of _0x4b8d48){if(!_0xbc346e[_0x45287f(0x87)]&&_0xbc346e[_0x45287f(0x73)]){if(_0x2866d8[_0x45287f(0x85)](String(_0xbc346e[_0x45287f(0x73)])))continue;_0x3baea7[_0x45287f(0x83)](_0xbc346e);continue;}if(!_0xbc346e['prop'])continue;const _0x11dc32=String(_0xbc346e[_0x45287f(0x87)]),_0x48e2bb=_0x288c11[_0x45287f(0xa9)](_0x11dc32);_0x48e2bb?(_0x3baea7['push']({..._0xbc346e,..._0x48e2bb}),_0x3ad967['add'](_0x11dc32)):_0x3baea7[_0x45287f(0x83)](_0xbc346e);}for(const _0x593b86 of _0x4753f8){const _0x2bdbc6=String(_0x593b86[_0x45287f(0x87)]);if(!_0x3ad967['has'](_0x2bdbc6))_0x3baea7[_0x45287f(0x83)](_0x593b86);}return _0x3baea7[_0x45287f(0x83)](..._0x31edba),_0x3baea7;}function _0xfbcf(){const _0x49dcff=['mti4ngrZtMHOzW','AgfZrgvMyxvSDa','BNvSBgfIBgu','BNvTyMvY','nZq1ndi0CvDZzhrz','C2vSzwn0','ugDcB29SzwfU','y3jLyxrLvgLTzq','EwvZx25Vx251BwjLCG','DgvZDa','zNvUy3rPB24','y29TBwvUDa','ugDtBwfSBeLUDa','otC4DvL5reri','BMfTzxnWywnL','nJi1mxHjruDiCW','C2nHBgu','zwrPDa','y29SB3i','EwvZx25Vx2jVB2XLyw4','DMfSDwu','mZuYnJu4n0DdBuf2uW','BgfIzwW','C2vSzwn0Aw9U','z2v0','ugDeB3vIBgvqCMvJAxnPB24','nta2ntv6tuLeCum','C3DPDgnO','ugDtBwfSBfnLCMLHBa','Aw5WDxq','mJKWoffAD09sza','C3fSvhLWzq','zgvSzxrLvgLTzq','Dgv4DgfYzwe','DM0TC3DPDgnO','DhLWzq','AwDUB3jLrMLLBgrZ','neTyzenrAq','CMLNAhq','DxbKyxrLvgLTzq','ugDtzxjPywW','C3rHDhvZ','mtzps25iqui','ugDoDw1LCMLJ','AxnbCNjHEq','ugDcAwDjBNq','C3rYAw5N','y29SDw1UCW','ChjVCgvYDhLoyw1L','zgLJDa','mJGZnZKZmgLSu0rfEa','ChvZAa','ntm1DeDRyw9A','AgfZ','zMLSDgvY','ChjVCa','ntK1mJG0z3rVA3Pc','BwfW','ywrK','CMvXDwLYzwq','Dg9mB3DLCKnHC2u','C291CMnL','yM9VBgvHBG','C3rHCNrZv2L0Aa','DgvUyw50swq'];_0xfbcf=function(){return _0x49dcff;};return _0xfbcf();}export function sortRequiredFirst(_0x29d78e){const _0x2abd68=_0x79fca,_0x4889ec=[],_0x15cef0=[];for(const _0x2a387f of _0x29d78e){_0x2a387f[_0x2abd68(0x8b)]===!![]||typeof _0x2a387f[_0x2abd68(0x8b)]===_0x2abd68(0x9b)?_0x4889ec[_0x2abd68(0x83)](_0x2a387f):_0x15cef0[_0x2abd68(0x83)](_0x2a387f);}return[..._0x4889ec,..._0x15cef0];}export function buildAutoUpsertItems(_0x5993e2,_0x598a99={}){const _0x5f4815=_0x79fca,_0x1da60c=new Set([...UPSERT_BUILTIN_IGNORE,..._0x598a99[_0x5f4815(0x74)]||[]]),_0x373dc5=[];for(const _0x48af96 of epsColumns(_0x5993e2)){const _0x487b7f=_0x48af96[_0x5f4815(0x80)];if(_0x1da60c['has'](_0x487b7f))continue;const _0x4dc13f=_0x48af96[_0x5f4815(0x9c)]||_0x487b7f,_0x5cf8ec=dictKeyOf(_0x48af96),_0x1ad0e5=_0x48af96[_0x5f4815(0x93)]===![]&&_0x48af96[_0x5f4815(0x92)]!==!![],_0x29c6c4={'prop':_0x487b7f,'label':_0x4dc13f,'span':0xc,..._0x1ad0e5?{'required':!![]}:{}};if(_0x487b7f==='status'){const _0x1c35ea=_0x5cf8ec||_0x5f4815(0x79);isSwitchDict(_0x1c35ea)?_0x373dc5[_0x5f4815(0x83)](switchFormItem(_0x29c6c4,_0x1c35ea,switchDefaultValue(_0x1c35ea))):_0x373dc5[_0x5f4815(0x83)]({..._0x29c6c4,'type':_0x5f4815(0x96),'dict':_0x1c35ea,'value':0x1});continue;}if(_0x5cf8ec){isSwitchDict(_0x5cf8ec)?_0x373dc5[_0x5f4815(0x83)](switchFormItem(_0x29c6c4,_0x5cf8ec,switchDefaultValue(_0x5cf8ec))):_0x373dc5[_0x5f4815(0x83)]({..._0x29c6c4,'type':_0x5f4815(0x96),'dict':_0x5cf8ec,'value':0x0});continue;}if(isTextCol(_0x48af96)){_0x373dc5['push']({..._0x29c6c4,'type':_0x5f4815(0x71),'span':0xc});continue;}if(isBooleanCol(_0x48af96)){_0x373dc5[_0x5f4815(0x83)]({..._0x29c6c4,'type':'switch','value':![],'component':{'props':()=>mapDictOptions(_0x5f4815(0xa4))},'dict':'yes_no_boolean'});continue;}if(isIntegerCol(_0x48af96)||isNumericCol(_0x48af96)){const _0xfb0be6=numberPrecision(_0x48af96);_0x373dc5['push']({..._0x29c6c4,'type':_0x5f4815(0x94),'component':{'props':{'type':_0x5f4815(0x94),'precision':_0xfb0be6,'controls':![]}}});continue;}_0x373dc5[_0x5f4815(0x83)]({..._0x29c6c4,'type':_0x5f4815(0xae)});}return _0x373dc5;}export function buildAutoTableColumns(_0x4ea308,_0x258bef={}){const _0x343f45=_0x79fca,_0x14a743=new Set([...TABLE_BUILTIN_IGNORE,..._0x258bef['ignoreFields']||[]]),_0x4eaed8=[];!_0x14a743[_0x343f45(0x85)](_0x343f45(0xa8))&&_0x4eaed8[_0x343f45(0x83)]({'type':_0x343f45(0xa8),'width':0x32});for(const _0xd9a5fe of epsColumns(_0x4ea308)){const _0x40acc7=_0xd9a5fe[_0x343f45(0x80)];if(_0x14a743[_0x343f45(0x85)](_0x40acc7))continue;const _0x329b5b=_0xd9a5fe[_0x343f45(0x9c)]||_0x40acc7,_0x572987=dictKeyOf(_0xd9a5fe);if(_0x40acc7===_0x343f45(0x79)){const _0x32a7a4=_0x572987||_0x343f45(0x79);isSwitchDict(_0x32a7a4)?_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'width':0x50,'fixed':_0x343f45(0x76),'component':{'name':_0x343f45(0x72),'props':()=>mapDictOptions(_0x32a7a4)}}):_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'width':0x64,'fixed':_0x343f45(0x76),'dict':()=>mapDictOptions(_0x32a7a4)});continue;}if(_0x572987&&isSwitchDict(_0x572987)){_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'width':0x50,'component':{'name':_0x343f45(0x72),'props':()=>mapDictOptions(_0x572987)}});continue;}if(_0x40acc7==='id'){_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'width':0x50});continue;}if(_0x40acc7===_0x343f45(0x98)){_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'width':0xa0});continue;}if(_0x572987){_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'minWidth':0x78,'dict':()=>mapDictOptions(_0x572987)});continue;}if(isTextCol(_0xd9a5fe)){_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'minWidth':0xa0,'showOverflowTooltip':!![]});continue;}_0x4eaed8[_0x343f45(0x83)]({'prop':_0x40acc7,'label':_0x329b5b,'minWidth':0x78});}return!_0x14a743[_0x343f45(0x85)]('op')&&_0x4eaed8[_0x343f45(0x83)]({'type':'op','buttons':[_0x343f45(0xa2),'delete']}),_0x4eaed8;}