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.
- package/dist/admin/api/client.js +9 -8
- package/dist/admin/components/ui/avatar/index.js +1 -1
- package/dist/admin/components/ui/badge/index.d.ts +1 -1
- package/dist/admin/components/ui/button/index.d.ts +1 -1
- package/dist/admin/components/ui/checkbox/index.js +1 -1
- package/dist/admin/components/ui/dialog/index.js +1 -1
- package/dist/admin/components/ui/dropdown-menu/index.js +1 -1
- package/dist/admin/components/ui/input/Input.vue +2 -1
- package/dist/admin/components/ui/input/index.js +1 -1
- package/dist/admin/components/ui/label/index.js +1 -1
- package/dist/admin/components/ui/scroll-area/index.js +1 -1
- package/dist/admin/components/ui/select/index.js +1 -1
- package/dist/admin/components/ui/separator/index.js +1 -1
- package/dist/admin/components/ui/sheet/index.js +1 -1
- package/dist/admin/components/ui/sonner/index.js +1 -1
- package/dist/admin/components/ui/table/index.js +1 -1
- package/dist/admin/components/ui/tabs/index.js +1 -1
- package/dist/admin/components/ui/tooltip/index.js +1 -1
- package/dist/admin/components/vm-aside.vue +8 -6
- package/dist/admin/components/vm-auto-perm-dialog.vue +12 -11
- package/dist/admin/components/vm-check-tree.vue +3 -2
- package/dist/admin/components/vm-dept-tree.vue +32 -31
- package/dist/admin/components/vm-empty.vue +16 -2
- package/dist/admin/components/vm-eps-perm-picker.vue +3 -2
- package/dist/admin/components/vm-form-dialog.vue +4 -3
- package/dist/admin/components/vm-group-cascader.vue +5 -4
- package/dist/admin/components/vm-icon-picker.vue +24 -15
- package/dist/admin/components/vm-inline-search.vue +3 -2
- package/dist/admin/components/vm-loading.vue +4 -3
- package/dist/admin/components/vm-markdown.vue +6 -5
- package/dist/admin/components/vm-role-picker.vue +6 -5
- package/dist/admin/components/vm-view-path-picker.vue +3 -2
- package/dist/admin/crud/auto-fields.js +1 -1
- package/dist/admin/crud/components/vm-avatar.vue +2 -1
- package/dist/admin/crud/components/vm-color-picker.vue +8 -8
- package/dist/admin/crud/components/vm-column-custom.vue +6 -5
- package/dist/admin/crud/components/vm-copy-btn.vue +4 -3
- package/dist/admin/crud/components/vm-date-calendar-panel.vue +30 -27
- package/dist/admin/crud/components/vm-date-picker.vue +6 -5
- package/dist/admin/crud/components/vm-date-range.vue +5 -4
- package/dist/admin/crud/components/vm-datetime-field.vue +4 -3
- package/dist/admin/crud/components/vm-json-code.vue +3 -2
- package/dist/admin/crud/components/vm-json-editor.vue +3 -2
- package/dist/admin/crud/components/vm-json-kv-editor.vue +13 -12
- package/dist/admin/crud/components/vm-multi-select.vue +5 -4
- package/dist/admin/crud/components/vm-number-range.vue +5 -4
- package/dist/admin/crud/components/vm-preview-viewer.vue +33 -29
- package/dist/admin/crud/components/vm-richtext-extensions.js +1 -1
- package/dist/admin/crud/components/vm-richtext.vue +33 -30
- package/dist/admin/crud/components/vm-select.vue +4 -3
- package/dist/admin/crud/components/vm-status-tag.vue +2 -1
- package/dist/admin/crud/components/vm-switch.vue +5 -4
- package/dist/admin/crud/components/vm-text-link.vue +3 -2
- package/dist/admin/crud/components/vm-tree-select.vue +3 -2
- package/dist/admin/crud/components/vm-upload-item.vue +6 -4
- package/dist/admin/crud/components/vm-upload.vue +6 -5
- package/dist/admin/crud/config.js +1 -1
- package/dist/admin/crud/confirm.js +1 -1
- package/dist/admin/crud/crud-page-request.js +1 -1
- package/dist/admin/crud/data-i18n.js +1 -1
- package/dist/admin/crud/dict.d.ts +1 -1
- package/dist/admin/crud/dict.js +1 -1
- package/dist/admin/crud/export-fetch.js +1 -1
- package/dist/admin/crud/key.js +1 -1
- package/dist/admin/crud/plugins.js +1 -1
- package/dist/admin/crud/span.js +1 -1
- package/dist/admin/crud/style.js +1 -1
- package/dist/admin/crud/validate.js +1 -1
- package/dist/admin/crud/vm-crud.vue +15 -15
- package/dist/admin/crud/vm-data-i18n-btn.vue +1 -1
- package/dist/admin/crud/vm-export-btn.vue +7 -7
- package/dist/admin/crud/vm-import-btn.vue +33 -27
- package/dist/admin/crud/vm-table.vue +7 -2
- package/dist/admin/crud/vm-upsert.vue +1 -0
- package/dist/admin/directives/perm.js +1 -1
- package/dist/admin/hooks/useUpload.js +1 -1
- package/dist/admin/lib/browser.js +1 -1
- package/dist/admin/lib/cn.js +1 -1
- package/dist/admin/lib/dialog-float.js +1 -1
- package/dist/admin/lib/export-excel.js +1 -1
- package/dist/admin/lib/file-preview.js +8 -6
- package/dist/admin/lib/import-excel.js +1 -1
- package/dist/admin/lib/json.d.ts +0 -1
- package/dist/admin/lib/json.js +1 -1
- package/dist/admin/lib/menu.js +1 -1
- package/dist/admin/lib/micro-locale.js +1 -1
- package/dist/admin/lib/micro-theme.js +1 -1
- package/dist/admin/lib/shell.js +1 -1
- package/dist/admin/lib/theme-color-options.d.ts +1 -2
- package/dist/admin/lib/theme-color-options.js +1 -1
- package/dist/admin/lib/tree.js +1 -1
- package/dist/admin/lib/upload.d.ts +5 -0
- package/dist/admin/lib/upload.js +1 -1
- package/dist/admin/lib/video-frame.js +1 -1
- package/dist/admin/router/create.js +1 -1
- package/dist/admin/router/guards.js +1 -1
- package/dist/ai/index.js +1 -1
- package/dist/client/ai-model-registry.js +1 -1
- package/dist/client/base.js +1 -1
- package/dist/client/configure.js +1 -1
- package/dist/client/dict.js +1 -1
- package/dist/client/eps-payload.js +1 -1
- package/dist/client/eps.js +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/locale-store.js +1 -1
- package/dist/client/service.js +1 -1
- package/dist/client/vite-admin.js +1 -1
- package/dist/client/vite-auto-import.js +1 -1
- package/dist/client/vite-micro-proxy.js +1 -1
- package/dist/client/vite-plugin-eps.js +1 -1
- package/dist/client/vite-resolve.js +1 -1
- package/dist/config/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/shared/datetime-picker.js +1 -1
- package/dist/shared/excel.js +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/locale-json.js +1 -1
- package/dist/shared/tree.js +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
class="vm-preview-viewer__trigger"
|
|
7
7
|
:style="thumbStyle"
|
|
8
8
|
:disabled="!preview"
|
|
9
|
-
:title="preview ? (isVideoKind ? '
|
|
9
|
+
:title="preview ? (isVideoKind ? crudLabel('playVideo') : crudLabel('viewImage')) : undefined"
|
|
10
10
|
@click="openViewer"
|
|
11
11
|
>
|
|
12
12
|
<img
|
|
@@ -75,9 +75,9 @@
|
|
|
75
75
|
:disabled="opening"
|
|
76
76
|
@click="openInNewWindow"
|
|
77
77
|
>
|
|
78
|
-
{{ opening ? '
|
|
78
|
+
{{ opening ? crudLabel('opening') : crudLabel('openNewWindow') }}
|
|
79
79
|
</button>
|
|
80
|
-
<button type="button" class="vm-file-preview-viewer__close" title="
|
|
80
|
+
<button type="button" class="vm-file-preview-viewer__close" :title="crudLabel('dismiss')" @click="closeViewer">
|
|
81
81
|
<i class="ri-close-line" />
|
|
82
82
|
</button>
|
|
83
83
|
</div>
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
class="vm-file-preview-viewer__body vm-scroll"
|
|
88
88
|
:class="{ 'is-media': kind === 'image' || kind === 'video' }"
|
|
89
89
|
>
|
|
90
|
-
<p v-if="loading" class="vm-file-preview-viewer__hint"
|
|
90
|
+
<p v-if="loading" class="vm-file-preview-viewer__hint">{{ crudLabel('loading') }}</p>
|
|
91
91
|
<p v-else-if="error" class="vm-file-preview-viewer__hint is-error">{{ error }}</p>
|
|
92
92
|
|
|
93
93
|
<template v-else-if="kind === 'image'">
|
|
@@ -102,19 +102,19 @@
|
|
|
102
102
|
/>
|
|
103
103
|
</div>
|
|
104
104
|
<div class="vm-file-preview-viewer__toolbar" @click.stop>
|
|
105
|
-
<button type="button" title="
|
|
105
|
+
<button type="button" :title="crudLabel('zoomOut')" @click="zoomOut">
|
|
106
106
|
<i class="ri-subtract-line" />
|
|
107
107
|
</button>
|
|
108
|
-
<button type="button" title="
|
|
108
|
+
<button type="button" :title="crudLabel('zoomIn')" @click="zoomIn">
|
|
109
109
|
<i class="ri-add-line" />
|
|
110
110
|
</button>
|
|
111
|
-
<button type="button" title="
|
|
111
|
+
<button type="button" :title="crudLabel('actualSize')" @click="resetView">
|
|
112
112
|
<i class="ri-aspect-ratio-line" />
|
|
113
113
|
</button>
|
|
114
|
-
<button type="button" title="
|
|
114
|
+
<button type="button" :title="crudLabel('rotateCCW')" @click="rotateLeft">
|
|
115
115
|
<i class="ri-anticlockwise-line" />
|
|
116
116
|
</button>
|
|
117
|
-
<button type="button" title="
|
|
117
|
+
<button type="button" :title="crudLabel('rotateCW')" @click="rotateRight">
|
|
118
118
|
<i class="ri-clockwise-line" />
|
|
119
119
|
</button>
|
|
120
120
|
</div>
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
v-else-if="kind === 'pdf'"
|
|
146
146
|
class="vm-file-preview-viewer__iframe"
|
|
147
147
|
:src="src"
|
|
148
|
-
title="
|
|
148
|
+
:title="crudLabel('pdfPreview')"
|
|
149
149
|
/>
|
|
150
150
|
|
|
151
151
|
<div
|
|
@@ -160,29 +160,29 @@
|
|
|
160
160
|
|
|
161
161
|
<div v-else-if="kind === 'office'" class="vm-file-preview-viewer__fallback">
|
|
162
162
|
<i class="ri-file-3-line" aria-hidden="true" />
|
|
163
|
-
<p>
|
|
164
|
-
<p
|
|
163
|
+
<p>{{ crudLabel('officeNoPreview') }}</p>
|
|
164
|
+
<p>{{ crudLabel('officeDownloadHint') }}</p>
|
|
165
165
|
<button
|
|
166
166
|
type="button"
|
|
167
167
|
class="vm-file-preview-viewer__dl-btn"
|
|
168
168
|
:disabled="downloading"
|
|
169
169
|
@click="downloadFile"
|
|
170
170
|
>
|
|
171
|
-
{{ downloading ? '
|
|
171
|
+
{{ downloading ? crudLabel('downloadingFile') : crudLabel('downloadFile') }}
|
|
172
172
|
</button>
|
|
173
173
|
</div>
|
|
174
174
|
|
|
175
175
|
<div v-else class="vm-file-preview-viewer__fallback">
|
|
176
176
|
<i class="ri-file-3-line" aria-hidden="true" />
|
|
177
|
-
<p
|
|
178
|
-
<p
|
|
177
|
+
<p>{{ crudLabel('typeNoPreview') }}</p>
|
|
178
|
+
<p>{{ crudLabel('downloadHint') }}</p>
|
|
179
179
|
<button
|
|
180
180
|
type="button"
|
|
181
181
|
class="vm-file-preview-viewer__dl-btn"
|
|
182
182
|
:disabled="downloading"
|
|
183
183
|
@click="downloadFile"
|
|
184
184
|
>
|
|
185
|
-
{{ downloading ? '
|
|
185
|
+
{{ downloading ? crudLabel('downloadingFile') : crudLabel('downloadFile') }}
|
|
186
186
|
</button>
|
|
187
187
|
</div>
|
|
188
188
|
</div>
|
|
@@ -191,6 +191,7 @@
|
|
|
191
191
|
</template>
|
|
192
192
|
|
|
193
193
|
<script setup lang="ts">
|
|
194
|
+
import { crudLabel } from '../style'
|
|
194
195
|
import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
|
|
195
196
|
import DOMPurify from 'dompurify'
|
|
196
197
|
import { useVideoFrame } from '../../lib/video-frame'
|
|
@@ -208,14 +209,14 @@ defineOptions({ name: 'vm-preview-viewer', inheritAttrs: false })
|
|
|
208
209
|
const VIDEO_EXT = /\.(mp4|webm|mov|m4v|ogv|ogg)(\?|#|$)/i
|
|
209
210
|
|
|
210
211
|
const KIND_LABEL: Record<MediaPreviewKind, string> = {
|
|
211
|
-
image: '
|
|
212
|
-
video: '
|
|
213
|
-
audio: '
|
|
212
|
+
image: 'typeImage',
|
|
213
|
+
video: 'typeVideo',
|
|
214
|
+
audio: 'typeAudio',
|
|
214
215
|
pdf: 'PDF',
|
|
215
216
|
excel: 'Excel',
|
|
216
|
-
text: '
|
|
217
|
+
text: 'typeText',
|
|
217
218
|
office: 'Office',
|
|
218
|
-
unsupported: '
|
|
219
|
+
unsupported: 'typeFile',
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
const props = withDefaults(
|
|
@@ -250,7 +251,7 @@ const props = withDefaults(
|
|
|
250
251
|
}>(),
|
|
251
252
|
{
|
|
252
253
|
embedded: false,
|
|
253
|
-
label:
|
|
254
|
+
label: undefined,
|
|
254
255
|
trigger: 'auto',
|
|
255
256
|
type: 'auto',
|
|
256
257
|
size: 40,
|
|
@@ -323,9 +324,9 @@ const kind = computed((): MediaPreviewKind => {
|
|
|
323
324
|
})
|
|
324
325
|
|
|
325
326
|
const displayLabel = computed(() => {
|
|
326
|
-
if (props.label !== '
|
|
327
|
-
if (kind.value === 'audio') return '
|
|
328
|
-
return
|
|
327
|
+
if (props.label != null && props.label !== '') return props.label
|
|
328
|
+
if (kind.value === 'audio') return crudLabel('play')
|
|
329
|
+
return crudLabel('view')
|
|
329
330
|
})
|
|
330
331
|
|
|
331
332
|
const triggerIcon = computed(() =>
|
|
@@ -333,13 +334,16 @@ const triggerIcon = computed(() =>
|
|
|
333
334
|
)
|
|
334
335
|
|
|
335
336
|
const triggerTitle = computed(() =>
|
|
336
|
-
kind.value === 'audio' ? '
|
|
337
|
+
kind.value === 'audio' ? crudLabel('playAudio') : crudLabel('viewFile'),
|
|
337
338
|
)
|
|
338
339
|
|
|
339
|
-
const kindLabel = computed(() =>
|
|
340
|
+
const kindLabel = computed(() => {
|
|
341
|
+
const key = KIND_LABEL[kind.value]
|
|
342
|
+
return key.startsWith('type') ? crudLabel(key) : key
|
|
343
|
+
})
|
|
340
344
|
|
|
341
345
|
const displayName = computed(() =>
|
|
342
|
-
fileDisplayName(props.fileName || src.value, '
|
|
346
|
+
fileDisplayName(props.fileName || src.value, crudLabel('unnamedFile')),
|
|
343
347
|
)
|
|
344
348
|
|
|
345
349
|
/** 无法内嵌预览的类型在正文区提供「下载文件」;顶栏统一「新窗口打开」 */
|
|
@@ -463,7 +467,7 @@ async function loadPreview() {
|
|
|
463
467
|
})
|
|
464
468
|
}
|
|
465
469
|
} catch (e) {
|
|
466
|
-
error.value = e instanceof Error ? e.message : '
|
|
470
|
+
error.value = e instanceof Error ? e.message : crudLabel('previewFail')
|
|
467
471
|
} finally {
|
|
468
472
|
loading.value = false
|
|
469
473
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
function _0x1aa3(_0x2e248a,_0x10e119){_0x2e248a=_0x2e248a-0x104;const _0x4bbe12=_0x4bbe();let _0x1aa38e=_0x4bbe12[_0x2e248a];if(_0x1aa3['zIQVwC']===undefined){var _0x59a641=function(_0x1a99b3){const _0x3769da='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x9b7760='',_0x592ea2='';for(let _0x2bcc99=0x0,_0x281fb0,_0x39db77,_0x57af89=0x0;_0x39db77=_0x1a99b3['charAt'](_0x57af89++);~_0x39db77&&(_0x281fb0=_0x2bcc99%0x4?_0x281fb0*0x40+_0x39db77:_0x39db77,_0x2bcc99++%0x4)?_0x9b7760+=String['fromCharCode'](0xff&_0x281fb0>>(-0x2*_0x2bcc99&0x6)):0x0){_0x39db77=_0x3769da['indexOf'](_0x39db77);}for(let _0x199da8=0x0,_0x5abc51=_0x9b7760['length'];_0x199da8<_0x5abc51;_0x199da8++){_0x592ea2+='%'+('00'+_0x9b7760['charCodeAt'](_0x199da8)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x592ea2);};_0x1aa3['uBjRol']=_0x59a641,_0x1aa3['WaYnUS']={},_0x1aa3['zIQVwC']=!![];}const _0x165e16=_0x4bbe12[0x0],_0x2893dd=_0x2e248a+_0x165e16,_0x566b61=_0x1aa3['WaYnUS'][_0x2893dd];return!_0x566b61?(_0x1aa38e=_0x1aa3['uBjRol'](_0x1aa38e),_0x1aa3['WaYnUS'][_0x2893dd]=_0x1aa38e):_0x1aa38e=_0x566b61,_0x1aa38e;}const _0x58ef28=_0x1aa3;(function(_0x318a1e,_0x3761d8){const _0x3cf43d=_0x1aa3,_0x4b2e0a=_0x318a1e();while(!![]){try{const _0x359861=parseInt(_0x3cf43d(0x10b))/0x1+parseInt(_0x3cf43d(0x10a))/0x2*(parseInt(_0x3cf43d(0x110))/0x3)+-parseInt(_0x3cf43d(0x10f))/0x4*(parseInt(_0x3cf43d(0x111))/0x5)+parseInt(_0x3cf43d(0x114))/0x6+parseInt(_0x3cf43d(0x106))/0x7*(-parseInt(_0x3cf43d(0x10d))/0x8)+-parseInt(_0x3cf43d(0x10e))/0x9*(-parseInt(_0x3cf43d(0x10c))/0xa)+-parseInt(_0x3cf43d(0x108))/0xb*(parseInt(_0x3cf43d(0x112))/0xc);if(_0x359861===_0x3761d8)break;else _0x4b2e0a['push'](_0x4b2e0a['shift']());}catch(_0x292f8f){_0x4b2e0a['push'](_0x4b2e0a['shift']());}}}(_0x4bbe,0x74d8b));import{Node,mergeAttributes}from'@tiptap/core';export const VmRichtextVideo=Node['create']({'name':'video','group':_0x58ef28(0x105),'atom':!![],'selectable':!![],'draggable':!![],'addAttributes'(){return{'src':{'default':null},'controls':{'default':!![]}};},'parseHTML'(){return[{'tag':'video[src]'}];},'renderHTML'({HTMLAttributes:_0x9b7760}){const _0x3099ae=_0x58ef28;return['video',mergeAttributes(_0x9b7760,{'controls':!![],'style':_0x3099ae(0x109)})];},'addCommands'(){const _0x47a060=_0x58ef28;return{'setVideo':_0x592ea2=>({commands:_0x2bcc99})=>_0x2bcc99[_0x47a060(0x107)]({'type':this[_0x47a060(0x104)],'attrs':_0x592ea2})};}});function _0x4bbe(){const _0x21e207=['mJa0mtuWrfvQuLD4','nZmWthjkv0Hx','mtm4ngrjyvzMuG','nJiYmZvxu2LzB2u','nJm3nMXOu2zssW','mJqWodK2mxvqyvHcDW','mtm5mhjbyM9yDq','mtjtB1bOt2u','8j+qU+kaJEkDHo+4JW','nte4ntmWoevhEhnqua','BMfTzq','yMXVy2S','mZGYndH1q1rSvNu','Aw5Zzxj0q29UDgvUDa','ntyWmdu3m3ngv1vszG','Bwf4lxDPzhrOoJeWmcu7yM9YzgvYlxjHzgL1CZO4ChG','mKfkr0DoAq'];_0x4bbe=function(){return _0x21e207;};return _0x4bbe();}export const VM_RICHTEXT_EMOJIS=['\uD83D\uDE00','\uD83D\uDE03','\uD83D\uDE04','\uD83D\uDE01','\uD83D\uDE06','\uD83D\uDE05','\uD83E\uDD23','\uD83D\uDE02','\uD83D\uDE42','\uD83D\uDE43','\uD83D\uDE09','\uD83D\uDE0A','\uD83D\uDE07','\uD83E\uDD70','\uD83D\uDE0D','\uD83E\uDD29','\uD83D\uDE18','\uD83D\uDE17','\uD83D\uDE1A','\uD83D\uDE19','\uD83D\uDE0B','\uD83D\uDE1B','\uD83D\uDE1C','\uD83E\uDD2A','\uD83D\uDE1D','\uD83E\uDD11','\uD83E\uDD17','\uD83E\uDD2D','\uD83E\uDD2B','\uD83E\uDD14','\uD83E\uDD10','\uD83E\uDD28','\uD83D\uDE10','\uD83D\uDE11','\uD83D\uDE36','\uD83D\uDE0F','\uD83D\uDE12','\uD83D\uDE44','\uD83D\uDE2C','\uD83E\uDD25','\uD83D\uDE0C','\uD83D\uDE14','\uD83D\uDE2A','\uD83E\uDD24','\uD83D\uDE34','\uD83D\uDE37','\uD83E\uDD12','\uD83E\uDD15','\uD83E\uDD22','\uD83E\uDD2E','\uD83E\uDD75','\uD83E\uDD76','\uD83E\uDD74','\uD83D\uDE35','\uD83E\uDD2F','\uD83E\uDD20','\uD83E\uDD73','\uD83D\uDE0E','\uD83E\uDD13','\uD83E\uDDD0','\uD83D\uDE15','\uD83D\uDE1F','\uD83D\uDE41','☹️','\uD83D\uDE2E','\uD83D\uDE2F','\uD83D\uDE32','\uD83D\uDE33','\uD83E\uDD7A','\uD83D\uDE26','\uD83D\uDE27','\uD83D\uDE28','\uD83D\uDE30','\uD83D\uDE25','\uD83D\uDE22','\uD83D\uDE2D','\uD83D\uDE31','\uD83D\uDE16','\uD83D\uDE23','\uD83D\uDE1E','\uD83D\uDE13','\uD83D\uDE29','\uD83D\uDE2B','\uD83E\uDD71','\uD83D\uDE24','\uD83D\uDE21','\uD83D\uDE20','\uD83E\uDD2C','\uD83D\uDE08','\uD83D\uDC7F','\uD83D\uDC4B','\uD83E\uDD1A','\uD83D\uDD90','✋','\uD83D\uDD96','\uD83D\uDC4C','\uD83E\uDD0C','\uD83E\uDD0F','✌️','\uD83E\uDD1E','\uD83E\uDD1F','\uD83E\uDD18','\uD83E\uDD19','\uD83D\uDC48','\uD83D\uDC49','\uD83D\uDC46','\uD83D\uDD95','\uD83D\uDC47','☝️','\uD83D\uDC4D','\uD83D\uDC4E','✊','\uD83D\uDC4A','\uD83E\uDD1B','\uD83E\uDD1C','\uD83D\uDC4F','\uD83D\uDE4C','\uD83D\uDC50','\uD83E\uDD32','\uD83E\uDD1D','\uD83D\uDE4F','\uD83D\uDCAA','\uD83E\uDDBE','✍️','\uD83D\uDC85','\uD83E\uDD33','❤️','\uD83E\uDDE1','\uD83D\uDC9B','\uD83D\uDC9A','\uD83D\uDC99','\uD83D\uDC9C','\uD83D\uDDA4','\uD83E\uDD0D','\uD83E\uDD0E','\uD83D\uDC94','❣️','\uD83D\uDC95','\uD83D\uDC9E','\uD83D\uDC93','\uD83D\uDC97','\uD83D\uDC96','\uD83D\uDC98','\uD83D\uDC9D','\uD83D\uDC9F','☮️','✝️','☪️','\uD83D\uDD49','☸️','✡️','\uD83D\uDD2F','\uD83D\uDD4E','☯️','☦️','\uD83D\uDED0','⭐','\uD83C\uDF1F','✨','⚡','\uD83D\uDD25','\uD83D\uDCA5','☀️','\uD83C\uDF19','⭐️','\uD83C\uDF08','✅','❌','⭕','❗','❓','‼️','⁉️','\uD83D\uDCAF','\uD83D\uDD14','\uD83D\uDD15','\uD83D\uDCCC','\uD83D\uDCCD','\uD83D\uDCCE','\uD83D\uDD17','\uD83D\uDD12','\uD83D\uDD13','\uD83D\uDD11','\uD83D\uDDDD','\uD83D\uDCA1','\uD83D\uDD26','\uD83D\uDCDD','✏️','✒️','\uD83D\uDD8A','\uD83D\uDD8B','\uD83D\uDD8C','\uD83D\uDD8D','\uD83D\uDCBC','\uD83D\uDCC1','\uD83D\uDCC2','\uD83D\uDCC5','\uD83D\uDCC6','\uD83D\uDDD3','\uD83D\uDCC7','\uD83D\uDCC8','\uD83D\uDCC9','\uD83D\uDCCA','\uD83D\uDCCB','\uD83D\uDCE4','\uD83D\uDCE5','\uD83D\uDCE6','\uD83D\uDCEB','\uD83D\uDCEC','\uD83D\uDCED','\uD83D\uDCEE','\uD83D\uDCEF','\uD83D\uDCDC','\uD83D\uDCC3','\uD83D\uDCC4','\uD83D\uDCD1','☕','\uD83C\uDF75','\uD83E\uDDC3','\uD83E\uDD64','\uD83E\uDDCB','\uD83C\uDF7A','\uD83C\uDF7B','\uD83E\uDD42','\uD83C\uDF77','\uD83C\uDF78','\uD83C\uDF55','\uD83C\uDF54','\uD83C\uDF5F','\uD83C\uDF2D','\uD83C\uDF7F','\uD83C\uDF69','\uD83C\uDF6A','\uD83C\uDF82','\uD83C\uDF70','\uD83E\uDDC1','\uD83C\uDF4E','\uD83C\uDF4A','\uD83C\uDF4B','\uD83C\uDF4C','\uD83C\uDF49','\uD83C\uDF47','\uD83C\uDF53','\uD83E\uDED0','\uD83C\uDF52','\uD83C\uDF51','⚽','\uD83C\uDFC0','\uD83C\uDFC8','⚾','\uD83C\uDFBE','\uD83C\uDFD0','\uD83C\uDFC9','\uD83C\uDFB1','\uD83C\uDFD3','\uD83C\uDFF8','\uD83C\uDFAE','\uD83D\uDD79','\uD83C\uDFB2','\uD83E\uDDE9','\uD83C\uDFAF','\uD83C\uDFB3','\uD83C\uDFB0','\uD83C\uDFB8','\uD83C\uDFB9','\uD83E\uDD41','\uD83C\uDFA4','\uD83C\uDFA7','\uD83C\uDFAC','\uD83C\uDFA5','\uD83D\uDCF7','\uD83D\uDCF8','\uD83D\uDCF9','\uD83D\uDCFA','\uD83D\uDCFB','\uD83C\uDF99','\uD83D\uDE80','✈️','\uD83D\uDEE9','\uD83D\uDEEB','\uD83D\uDEEC','\uD83D\uDEF0','\uD83D\uDCBA','\uD83D\uDEF8','\uD83D\uDE81','\uD83D\uDEF6','\uD83D\uDE97','\uD83D\uDE95','\uD83D\uDE99','\uD83D\uDE8C','\uD83D\uDE8E','\uD83C\uDFCE','\uD83D\uDE93','\uD83D\uDE91','\uD83D\uDE92','\uD83D\uDE90','\uD83C\uDFE0','\uD83C\uDFE1','\uD83C\uDFE2','\uD83C\uDFE3','\uD83C\uDFE4','\uD83C\uDFE5','\uD83C\uDFE6','\uD83C\uDFE8','\uD83C\uDFE9','\uD83C\uDFEA','\uD83D\uDC36','\uD83D\uDC31','\uD83D\uDC2D','\uD83D\uDC39','\uD83D\uDC30','\uD83E\uDD8A','\uD83D\uDC3B','\uD83D\uDC3C',_0x58ef28(0x113),'\uD83D\uDC28','\uD83D\uDC2F','\uD83E\uDD81','\uD83D\uDC2E','\uD83D\uDC37','\uD83D\uDC38','\uD83D\uDC35','\uD83D\uDE48','\uD83D\uDE49','\uD83D\uDE4A','\uD83D\uDC12','\uD83D\uDC14','\uD83D\uDC27','\uD83D\uDC26','\uD83D\uDC24','\uD83D\uDC23','\uD83D\uDC25','\uD83E\uDD86','\uD83E\uDD85','\uD83E\uDD89','\uD83E\uDD87','\uD83C\uDF89','\uD83C\uDF8A','\uD83C\uDF88','\uD83C\uDF81','\uD83C\uDF80','\uD83C\uDF97','\uD83C\uDFAB','\uD83C\uDF9F','\uD83C\uDFC6','\uD83C\uDFC5'];
|
|
@@ -21,38 +21,38 @@
|
|
|
21
21
|
v-if="editor"
|
|
22
22
|
class="vm-richtext__toolbar"
|
|
23
23
|
>
|
|
24
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('bold') }" title="
|
|
25
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('italic') }" title="
|
|
26
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('underline') }" title="
|
|
27
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('strike') }" title="
|
|
28
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('highlight') }" title="
|
|
24
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('bold') }" :title="crudLabel('rtBold')" @click="editor.chain().focus().toggleBold().run()"><i class="ri-bold" /></button>
|
|
25
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('italic') }" :title="crudLabel('rtItalic')" @click="editor.chain().focus().toggleItalic().run()"><i class="ri-italic" /></button>
|
|
26
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('underline') }" :title="crudLabel('rtUnderline')" @click="editor.chain().focus().toggleUnderline().run()"><i class="ri-underline" /></button>
|
|
27
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('strike') }" :title="crudLabel('rtStrike')" @click="editor.chain().focus().toggleStrike().run()"><i class="ri-strikethrough" /></button>
|
|
28
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('highlight') }" :title="crudLabel('rtHighlight')" @click="editor.chain().focus().toggleHighlight().run()"><i class="ri-mark-pen-line" /></button>
|
|
29
29
|
<span class="vm-richtext__sep" />
|
|
30
|
-
<button type="button" class="vm-richtext__btn" title="
|
|
30
|
+
<button type="button" class="vm-richtext__btn" :title="crudLabel('rtTextColor')" @click="pickTextColor"><i class="ri-font-color" /></button>
|
|
31
31
|
<span class="vm-richtext__sep" />
|
|
32
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }" title="
|
|
33
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }" title="
|
|
34
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('paragraph') }" title="
|
|
32
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }" :title="crudLabel('rtH2')" @click="editor.chain().focus().toggleHeading({ level: 2 }).run()">H2</button>
|
|
33
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }" :title="crudLabel('rtH3')" @click="editor.chain().focus().toggleHeading({ level: 3 }).run()">H3</button>
|
|
34
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('paragraph') }" :title="crudLabel('rtParagraph')" @click="editor.chain().focus().setParagraph().run()">P</button>
|
|
35
35
|
<span class="vm-richtext__sep" />
|
|
36
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }" title="
|
|
37
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }" title="
|
|
38
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }" title="
|
|
36
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }" :title="crudLabel('rtAlignLeft')" @click="editor.chain().focus().setTextAlign('left').run()"><i class="ri-align-left" /></button>
|
|
37
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }" :title="crudLabel('rtAlignCenter')" @click="editor.chain().focus().setTextAlign('center').run()"><i class="ri-align-center" /></button>
|
|
38
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }" :title="crudLabel('rtAlignRight')" @click="editor.chain().focus().setTextAlign('right').run()"><i class="ri-align-right" /></button>
|
|
39
39
|
<span class="vm-richtext__sep" />
|
|
40
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('bulletList') }" title="
|
|
41
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('orderedList') }" title="
|
|
42
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('taskList') }" title="
|
|
43
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('blockquote') }" title="
|
|
44
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('codeBlock') }" title="
|
|
45
|
-
<button type="button" class="vm-richtext__btn" title="
|
|
40
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('bulletList') }" :title="crudLabel('rtBulletList')" @click="editor.chain().focus().toggleBulletList().run()"><i class="ri-list-unordered" /></button>
|
|
41
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('orderedList') }" :title="crudLabel('rtOrderedList')" @click="editor.chain().focus().toggleOrderedList().run()"><i class="ri-list-ordered" /></button>
|
|
42
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('taskList') }" :title="crudLabel('rtTaskList')" @click="editor.chain().focus().toggleTaskList().run()"><i class="ri-checkbox-line" /></button>
|
|
43
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('blockquote') }" :title="crudLabel('rtBlockquote')" @click="editor.chain().focus().toggleBlockquote().run()"><i class="ri-double-quotes-l" /></button>
|
|
44
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('codeBlock') }" :title="crudLabel('rtCodeBlock')" @click="editor.chain().focus().toggleCodeBlock().run()"><i class="ri-code-box-line" /></button>
|
|
45
|
+
<button type="button" class="vm-richtext__btn" :title="crudLabel('rtHr')" @click="editor.chain().focus().setHorizontalRule().run()"><i class="ri-separator" /></button>
|
|
46
46
|
<span class="vm-richtext__sep" />
|
|
47
|
-
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('link') }" title="
|
|
48
|
-
<button v-if="uploadEnabled" type="button" class="vm-richtext__btn" title="
|
|
49
|
-
<button v-if="uploadEnabled" type="button" class="vm-richtext__btn" title="
|
|
47
|
+
<button type="button" class="vm-richtext__btn" :class="{ 'is-active': editor.isActive('link') }" :title="crudLabel('rtLink')" @click="toggleLink"><i class="ri-link" /></button>
|
|
48
|
+
<button v-if="uploadEnabled" type="button" class="vm-richtext__btn" :title="crudLabel('rtImage')" @click="pickImage"><i class="ri-image-line" /></button>
|
|
49
|
+
<button v-if="uploadEnabled" type="button" class="vm-richtext__btn" :title="crudLabel('rtVideo')" @click="pickVideo"><i class="ri-video-line" /></button>
|
|
50
50
|
<button
|
|
51
51
|
ref="emojiBtnRef"
|
|
52
52
|
type="button"
|
|
53
53
|
class="vm-richtext__btn"
|
|
54
54
|
:class="{ 'is-active': emojiOpen }"
|
|
55
|
-
title="
|
|
55
|
+
:title="crudLabel('rtEmoji')"
|
|
56
56
|
@click="toggleEmoji"
|
|
57
57
|
>
|
|
58
58
|
<i class="ri-emotion-line" />
|
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
</div>
|
|
79
79
|
</Teleport>
|
|
80
80
|
<span class="vm-richtext__sep" />
|
|
81
|
-
<button type="button" class="vm-richtext__btn" title="
|
|
82
|
-
<button type="button" class="vm-richtext__btn" title="
|
|
83
|
-
<button type="button" class="vm-richtext__btn" title="
|
|
81
|
+
<button type="button" class="vm-richtext__btn" :title="crudLabel('rtTable')" @click="insertTable"><i class="ri-table-line" /></button>
|
|
82
|
+
<button type="button" class="vm-richtext__btn" :title="crudLabel('rtUndo')" :disabled="!editor.can().undo()" @click="editor.chain().focus().undo().run()"><i class="ri-arrow-go-back-line" /></button>
|
|
83
|
+
<button type="button" class="vm-richtext__btn" :title="crudLabel('rtRedo')" :disabled="!editor.can().redo()" @click="editor.chain().focus().redo().run()"><i class="ri-arrow-go-forward-line" /></button>
|
|
84
84
|
</div>
|
|
85
85
|
|
|
86
86
|
<EditorContent class="vm-richtext__content" :editor="editor" />
|
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
</template>
|
|
90
90
|
|
|
91
91
|
<script setup lang="ts">
|
|
92
|
+
import { crudLabel } from '../style'
|
|
92
93
|
import { computed, nextTick, onBeforeUnmount, onMounted, shallowRef, watch } from 'vue'
|
|
93
94
|
import DOMPurify from 'dompurify'
|
|
94
95
|
import { EditorContent, useEditor } from '@tiptap/vue-3'
|
|
@@ -132,7 +133,7 @@ const props = withDefaults(
|
|
|
132
133
|
}>(),
|
|
133
134
|
{
|
|
134
135
|
readonly: false,
|
|
135
|
-
placeholder:
|
|
136
|
+
placeholder: undefined,
|
|
136
137
|
height: 320,
|
|
137
138
|
uploadPrefixPath: 'app/public/richtext',
|
|
138
139
|
autoUpload: true,
|
|
@@ -177,7 +178,7 @@ const safeHtml = computed(() => sanitize(String(props.modelValue || '')))
|
|
|
177
178
|
|
|
178
179
|
async function resolveUpload(file: File): Promise<string> {
|
|
179
180
|
if (props.uploadImage) return props.uploadImage(file)
|
|
180
|
-
if (props.autoUpload === false) throw new Error('
|
|
181
|
+
if (props.autoUpload === false) throw new Error(crudLabel('noUploadImage'))
|
|
181
182
|
const res = await toUpload(file, { prefixPath: props.uploadPrefixPath })
|
|
182
183
|
return res.url
|
|
183
184
|
}
|
|
@@ -286,7 +287,7 @@ function pickTextColor() {
|
|
|
286
287
|
const ed = editor.value
|
|
287
288
|
if (!ed) return
|
|
288
289
|
const current = (ed.getAttributes('textStyle').color as string | undefined) || '#111827'
|
|
289
|
-
const color = window.prompt('
|
|
290
|
+
const color = window.prompt(crudLabel('textColorPrompt'), current)
|
|
290
291
|
if (color == null) return
|
|
291
292
|
const v = color.trim()
|
|
292
293
|
if (!v) {
|
|
@@ -304,7 +305,7 @@ function toggleLink() {
|
|
|
304
305
|
ed.chain().focus().unsetLink().run()
|
|
305
306
|
return
|
|
306
307
|
}
|
|
307
|
-
const url = window.prompt('
|
|
308
|
+
const url = window.prompt(crudLabel('linkUrlPrompt'), prev || 'https://')
|
|
308
309
|
if (url == null) return
|
|
309
310
|
const href = url.trim()
|
|
310
311
|
if (!href) {
|
|
@@ -376,7 +377,9 @@ const editor = useEditor({
|
|
|
376
377
|
TableRow,
|
|
377
378
|
TableHeader,
|
|
378
379
|
TableCell,
|
|
379
|
-
Placeholder.configure({
|
|
380
|
+
Placeholder.configure({
|
|
381
|
+
placeholder: props.placeholder ?? crudLabel('richtextPlaceholder'),
|
|
382
|
+
}),
|
|
380
383
|
],
|
|
381
384
|
editorProps: {
|
|
382
385
|
attributes: { class: 'vm-richtext__prose' },
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
class="vm-select__label"
|
|
18
18
|
:class="{ 'is-placeholder': !displayLabel }"
|
|
19
19
|
>
|
|
20
|
-
{{ displayLabel || placeholder || '
|
|
20
|
+
{{ displayLabel || placeholder || crudLabel('pleaseSelect') }}
|
|
21
21
|
</span>
|
|
22
22
|
<i
|
|
23
23
|
v-if="clearable && hasValue"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
ref="searchRef"
|
|
49
49
|
class="vm-select__search-input"
|
|
50
50
|
:value="search"
|
|
51
|
-
placeholder="
|
|
51
|
+
:placeholder="crudLabel('searchEllipsis')"
|
|
52
52
|
@input="onSearchInput"
|
|
53
53
|
@keydown.esc.stop="closePanel"
|
|
54
54
|
/>
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
mode="footer"
|
|
75
75
|
status="loading"
|
|
76
76
|
/>
|
|
77
|
-
<p v-else-if="!filtered.length" class="vm-select__empty"
|
|
77
|
+
<p v-else-if="!filtered.length" class="vm-select__empty">{{ crudLabel('noMatch') }}</p>
|
|
78
78
|
<vm-loading
|
|
79
79
|
v-else-if="lazy && !hasMore"
|
|
80
80
|
mode="footer"
|
|
@@ -88,6 +88,7 @@
|
|
|
88
88
|
</template>
|
|
89
89
|
|
|
90
90
|
<script setup lang="ts">
|
|
91
|
+
import { crudLabel } from '../style'
|
|
91
92
|
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
|
|
92
93
|
import { FocusScope } from 'reka-ui'
|
|
93
94
|
import { useCrud } from '../useCrud'
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<script setup lang="ts">
|
|
18
|
+
import { crudLabel } from '../style'
|
|
18
19
|
import { computed } from 'vue'
|
|
19
20
|
|
|
20
21
|
defineOptions({ name: 'vm-status-tag' })
|
|
@@ -66,7 +67,7 @@ function resolveQueue(v: unknown): { variant: Variant; label: string } {
|
|
|
66
67
|
|
|
67
68
|
function resolveTask(v: unknown): { variant: Variant; label: string } {
|
|
68
69
|
const on = Number(v) === 1
|
|
69
|
-
const label = props.label ?? (on ? '
|
|
70
|
+
const label = props.label ?? (on ? crudLabel('running') : crudLabel('stopped'))
|
|
70
71
|
return { variant: on ? 'success' : 'neutral', label }
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
</template>
|
|
14
14
|
|
|
15
15
|
<script setup lang="ts">
|
|
16
|
+
import { crudLabel } from '../style'
|
|
16
17
|
import { ref, computed, watch } from 'vue'
|
|
17
18
|
import { toast } from 'vue-sonner'
|
|
18
19
|
import { vmConfirm } from '../confirm'
|
|
@@ -59,7 +60,7 @@ watch(
|
|
|
59
60
|
},
|
|
60
61
|
)
|
|
61
62
|
|
|
62
|
-
/** options 按 value 排序:小=关、大=开(status 0
|
|
63
|
+
/** options 按 value 排序:小=关、大=开(status/yes_no_number 0|1、yes_no_boolean false|true) */
|
|
63
64
|
const pair = computed(() => {
|
|
64
65
|
const opts = props.options
|
|
65
66
|
if (opts && opts.length >= 2) {
|
|
@@ -90,7 +91,7 @@ const on = computed(
|
|
|
90
91
|
async function toggle() {
|
|
91
92
|
if (loading.value || props.disabled) return
|
|
92
93
|
const next = on.value ? pair.value.inactive : pair.value.active
|
|
93
|
-
if (props.check && !(await vmConfirm('
|
|
94
|
+
if (props.check && !(await vmConfirm(crudLabel('switchConfirm')))) return
|
|
94
95
|
|
|
95
96
|
const prev = status.value
|
|
96
97
|
status.value = next
|
|
@@ -104,11 +105,11 @@ async function toggle() {
|
|
|
104
105
|
const params = { id: props.scope.id, [prop]: next }
|
|
105
106
|
if (props.api) await props.api(params)
|
|
106
107
|
else if (crud.service.update) await crud.service.update(params)
|
|
107
|
-
else throw new Error('
|
|
108
|
+
else throw new Error(crudLabel('noUpdateApi'))
|
|
108
109
|
} catch (e) {
|
|
109
110
|
status.value = prev
|
|
110
111
|
emit('update:modelValue', prev as number | string | boolean)
|
|
111
|
-
toast.error(e instanceof Error ? e.message : '
|
|
112
|
+
toast.error(e instanceof Error ? e.message : crudLabel('updateFailed'))
|
|
112
113
|
} finally {
|
|
113
114
|
loading.value = false
|
|
114
115
|
}
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
:disabled="disabled"
|
|
6
6
|
@click="emit('click', $event)"
|
|
7
7
|
>
|
|
8
|
-
<slot>{{ label }}</slot>
|
|
8
|
+
<slot>{{ label ?? crudLabel('view') }}</slot>
|
|
9
9
|
</button>
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
12
|
<script setup lang="ts">
|
|
13
|
+
import { crudLabel } from '../style'
|
|
13
14
|
defineOptions({ name: 'vm-text-link' })
|
|
14
15
|
|
|
15
16
|
withDefaults(
|
|
@@ -18,7 +19,7 @@ withDefaults(
|
|
|
18
19
|
disabled?: boolean
|
|
19
20
|
}>(),
|
|
20
21
|
{
|
|
21
|
-
label:
|
|
22
|
+
label: undefined,
|
|
22
23
|
disabled: false,
|
|
23
24
|
},
|
|
24
25
|
)
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
@click="toggle"
|
|
10
10
|
>
|
|
11
11
|
<span v-if="displayLabel" class="vm-tree-select__value">{{ displayLabel }}</span>
|
|
12
|
-
<span v-else class="vm-tree-select__ph">{{ placeholder || '
|
|
12
|
+
<span v-else class="vm-tree-select__ph">{{ placeholder || crudLabel('pleaseSelect') }}</span>
|
|
13
13
|
<i
|
|
14
14
|
v-if="clearable && hasValue"
|
|
15
15
|
class="ri-close-circle-fill vm-tree-select__clear"
|
|
@@ -46,13 +46,14 @@
|
|
|
46
46
|
{{ row.label }}
|
|
47
47
|
</button>
|
|
48
48
|
</div>
|
|
49
|
-
<p v-if="!visibleRows.length" class="vm-tree-select__empty"
|
|
49
|
+
<p v-if="!visibleRows.length" class="vm-tree-select__empty">{{ crudLabel('empty') }}</p>
|
|
50
50
|
</div>
|
|
51
51
|
</Teleport>
|
|
52
52
|
</div>
|
|
53
53
|
</template>
|
|
54
54
|
|
|
55
55
|
<script setup lang="ts">
|
|
56
|
+
import { crudLabel } from '../style'
|
|
56
57
|
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
|
|
57
58
|
import { POPUP_TRIGGER_GAP } from '../../lib/dialog-float'
|
|
58
59
|
import type { TreeSelectOption } from '../../../../typings/admin/comm/crud'
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
<i class="vm-upload-item__file-icon" :class="fileIcon" aria-hidden="true" />
|
|
36
36
|
<span class="vm-upload-item__name">{{ item.name || item.url }}</span>
|
|
37
37
|
<span v-if="item.error || imgBroken" class="vm-upload-item__error">
|
|
38
|
-
{{ item.error || '
|
|
38
|
+
{{ item.error || crudLabel('loadFailed') }}
|
|
39
39
|
</span>
|
|
40
40
|
</div>
|
|
41
41
|
</template>
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
<div v-if="previewSrc" class="vm-upload-item__actions">
|
|
60
60
|
<button
|
|
61
61
|
type="button"
|
|
62
|
-
title="
|
|
62
|
+
:title="crudLabel('preview')"
|
|
63
63
|
@click.stop="previewOpen = true"
|
|
64
64
|
>
|
|
65
65
|
<i class="ri-zoom-in-line" />
|
|
66
66
|
</button>
|
|
67
|
-
<button v-if="!disabled" type="button" title="
|
|
67
|
+
<button v-if="!disabled" type="button" :title="crudLabel('delete')" @click.stop="emit('remove')">
|
|
68
68
|
<i class="ri-delete-bin-line" />
|
|
69
69
|
</button>
|
|
70
70
|
</div>
|
|
@@ -81,6 +81,8 @@
|
|
|
81
81
|
</template>
|
|
82
82
|
|
|
83
83
|
<script setup lang="ts">
|
|
84
|
+
import { uploadRuleLabel } from '../../lib/upload'
|
|
85
|
+
import { crudLabel } from '../style'
|
|
84
86
|
import { ref, computed, watch } from 'vue'
|
|
85
87
|
import { useVideoFrame } from '../../lib/video-frame'
|
|
86
88
|
import { extname, getUploadRule } from '../../lib/upload'
|
|
@@ -128,7 +130,7 @@ const tag = computed(() => {
|
|
|
128
130
|
const rule = getUploadRule(props.item.type)
|
|
129
131
|
return {
|
|
130
132
|
color: rule.color,
|
|
131
|
-
label: extname(props.item.name || props.item.url) || rule
|
|
133
|
+
label: extname(props.item.name || props.item.url) || uploadRuleLabel(rule),
|
|
132
134
|
}
|
|
133
135
|
})
|
|
134
136
|
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<slot>
|
|
75
75
|
<div v-if="drag" class="vm-upload__drag">
|
|
76
76
|
<i class="ri-upload-cloud-2-line" />
|
|
77
|
-
<span
|
|
77
|
+
<span>{{ crudFormat(crudLabel('uploadHint'), limitSize) }}</span>
|
|
78
78
|
</div>
|
|
79
79
|
<div v-else class="vm-upload__demo">
|
|
80
80
|
<i class="ri-image-add-line" />
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
</template>
|
|
88
88
|
|
|
89
89
|
<script setup lang="ts">
|
|
90
|
+
import { crudFormat, crudLabel } from '../style'
|
|
90
91
|
import { ref, computed, watch, reactive } from 'vue'
|
|
91
92
|
import { toast } from 'vue-sonner'
|
|
92
93
|
import { useUpload } from '../../hooks/useUpload'
|
|
@@ -153,7 +154,7 @@ const acceptValue = computed(() => props.accept ?? '')
|
|
|
153
154
|
|
|
154
155
|
const text = computed(() => {
|
|
155
156
|
if (props.text) return props.text
|
|
156
|
-
return props.type === 'file' ? '
|
|
157
|
+
return props.type === 'file' ? crudLabel('selectFile') : crudLabel('selectImage')
|
|
157
158
|
})
|
|
158
159
|
|
|
159
160
|
const itemStyle = computed(() => {
|
|
@@ -260,7 +261,7 @@ async function onDrop(e: DragEvent) {
|
|
|
260
261
|
async function ingestFiles(files: File[]) {
|
|
261
262
|
for (const file of files) {
|
|
262
263
|
if (!isAdd.value) {
|
|
263
|
-
toast.warning(
|
|
264
|
+
toast.warning(crudFormat(crudLabel('maxUpload'), props.limit))
|
|
264
265
|
break
|
|
265
266
|
}
|
|
266
267
|
await appendFile(file)
|
|
@@ -269,7 +270,7 @@ async function ingestFiles(files: File[]) {
|
|
|
269
270
|
|
|
270
271
|
async function appendFile(raw: File) {
|
|
271
272
|
if (raw.size / 1024 / 1024 >= props.limitSize) {
|
|
272
|
-
toast.error(
|
|
273
|
+
toast.error(crudFormat(crudLabel('fileTooLarge'), props.limitSize))
|
|
273
274
|
return
|
|
274
275
|
}
|
|
275
276
|
if (props.beforeUpload) {
|
|
@@ -330,7 +331,7 @@ async function appendFile(raw: File) {
|
|
|
330
331
|
emitValue()
|
|
331
332
|
} catch (e) {
|
|
332
333
|
item.progress = -1
|
|
333
|
-
item.error = e instanceof Error ? e.message : '
|
|
334
|
+
item.error = e instanceof Error ? e.message : crudLabel('uploadFailed')
|
|
334
335
|
emit('error', item)
|
|
335
336
|
}
|
|
336
337
|
}
|