@arronqzy/vue-view 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -7
- package/src/panel/VueViewOnlinePreview.vue +15 -7
- package/src/panel/VueViewPanel.vue +81 -55
- package/src/panel/components/ConfigHintIcon.vue +4 -2
- package/src/panel/components/ElementsLayer.vue +15 -0
- package/src/panel/components/MaterialPreview.vue +19 -1
- package/src/panel/components/MaterialSidebar.vue +35 -31
- package/src/panel/components/MaterialSidebarTreeNode.vue +27 -26
- package/src/panel/components/MoveableLayer.vue +7 -4
- package/src/panel/components/PanelConfigSidebar.vue +57 -39
- package/src/panel/components/ViewElementScopePanel.vue +6 -4
- package/src/panel/components/WorkspaceConfigSidebar.vue +7 -1
- package/src/panel/components/WorkspaceProjectNav.vue +23 -16
- package/src/panel/components/WorkspaceStageSplit.vue +10 -7
- package/src/panel/components/config/ConfigColorField.vue +3 -1
- package/src/panel/components/config/PanelConfigAudioSection.vue +44 -43
- package/src/panel/components/config/PanelConfigChartSection.vue +79 -76
- package/src/panel/components/config/PanelConfigGeometrySection.vue +21 -19
- package/src/panel/components/config/PanelConfigGridChildSpan.vue +7 -5
- package/src/panel/components/config/PanelConfigGridSection.vue +10 -8
- package/src/panel/components/config/PanelConfigImageSection.vue +22 -21
- package/src/panel/components/config/PanelConfigMultiSelect.vue +42 -40
- package/src/panel/components/config/PanelConfigNodeInfo.vue +19 -16
- package/src/panel/components/config/PanelConfigReferenceSection.vue +11 -9
- package/src/panel/components/config/PanelConfigStyleSections.vue +27 -26
- package/src/panel/components/config/PanelConfigTextSection.vue +20 -17
- package/src/panel/components/config/PanelConfigVideoSection.vue +15 -14
- package/src/panel/components/config/shared.ts +0 -3
- package/src/panel/components/elementsLayerNodes.ts +37 -18
- package/src/panel/components/materialSidebarData.ts +73 -54
- package/src/panel/components/scope-config/ScopeTemplatePreviewHost.vue +7 -2
- package/src/panel/components/scope-config/ScopeTemplatePreviewPanel.vue +6 -3
- package/src/panel/components/scope-config/ScopeTemplateUsageHint.vue +7 -16
- package/src/panel/components/scope-config/ScopeTemplateWarningsPanel.vue +4 -2
- package/src/panel/components/table/ConditionEditor.vue +181 -0
- package/src/panel/components/table/JsonCodeEditor.vue +148 -0
- package/src/panel/components/table/PanelConfigTableSection.vue +2033 -0
- package/src/panel/components/table/TableNodeContent.vue +557 -0
- package/src/panel/constants/messages.ts +76 -34
- package/src/panel/hooks/usePanelElements.ts +54 -41
- package/src/panel/hooks/useWorkspaceProjects.ts +8 -5
- package/src/panel/types.ts +4 -0
- package/src/panel/utils/panelElementDefaults.ts +73 -39
- package/src/panel/utils/scope-field-labels.ts +53 -39
- package/src/panel/utils/scope-template-spread.ts +57 -24
- package/src/panel/utils/scope-template-warnings.ts +23 -22
- package/src/panel/utils/scope-template.ts +80 -0
- package/src/tailwind.css +18 -10
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import { InputNumber } from "ant-design-vue";
|
|
3
4
|
import type { PanelElement } from "../../types";
|
|
4
5
|
import ConfigFieldGroup from "./ConfigFieldGroup.vue";
|
|
5
6
|
import ConfigSection from "./ConfigSection.vue";
|
|
6
7
|
|
|
8
|
+
const { t, locale } = useI18n();
|
|
7
9
|
const props = defineProps<{
|
|
8
10
|
element: PanelElement;
|
|
9
11
|
isEditable: boolean;
|
|
@@ -28,18 +30,18 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
28
30
|
<template>
|
|
29
31
|
<ConfigSection
|
|
30
32
|
v-if="element.parentGridId"
|
|
31
|
-
title="
|
|
33
|
+
:title="t('panel.config.sectionGridChildSpan')"
|
|
32
34
|
:open="open"
|
|
33
35
|
:force-open="forceOpen"
|
|
34
36
|
@update:open="emit('update:open', $event)"
|
|
35
37
|
>
|
|
36
38
|
<template #hint>
|
|
37
|
-
|
|
39
|
+
{{ t("panel.config.gridChildHint") }}
|
|
38
40
|
</template>
|
|
39
|
-
<ConfigFieldGroup title="
|
|
41
|
+
<ConfigFieldGroup :title="t('panel.config.groupCrossSlots')">
|
|
40
42
|
<div class="grid grid-cols-2 gap-2">
|
|
41
43
|
<label class="block space-y-1">
|
|
42
|
-
<div
|
|
44
|
+
<div>{{ t("panel.config.colSpan") }}</div>
|
|
43
45
|
<InputNumber
|
|
44
46
|
size="small"
|
|
45
47
|
class="w-full"
|
|
@@ -51,7 +53,7 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
51
53
|
/>
|
|
52
54
|
</label>
|
|
53
55
|
<label class="block space-y-1">
|
|
54
|
-
<div
|
|
56
|
+
<div>{{ t("panel.config.rowSpan") }}</div>
|
|
55
57
|
<InputNumber
|
|
56
58
|
size="small"
|
|
57
59
|
class="w-full"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import { InputNumber } from "ant-design-vue";
|
|
3
4
|
import type { PanelElement } from "../../types";
|
|
4
5
|
import ConfigFieldGroup from "./ConfigFieldGroup.vue";
|
|
5
6
|
import ConfigSection from "./ConfigSection.vue";
|
|
6
7
|
|
|
8
|
+
const { t, locale } = useI18n();
|
|
7
9
|
const props = defineProps<{
|
|
8
10
|
element: PanelElement;
|
|
9
11
|
isEditable: boolean;
|
|
@@ -27,18 +29,18 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
27
29
|
|
|
28
30
|
<template>
|
|
29
31
|
<ConfigSection
|
|
30
|
-
title="
|
|
32
|
+
:title="t('panel.config.sectionGrid')"
|
|
31
33
|
:open="open"
|
|
32
34
|
:force-open="forceOpen"
|
|
33
35
|
@update:open="emit('update:open', $event)"
|
|
34
36
|
>
|
|
35
37
|
<template #hint>
|
|
36
|
-
|
|
38
|
+
{{ t("panel.config.gridHint") }}
|
|
37
39
|
</template>
|
|
38
|
-
<ConfigFieldGroup title="
|
|
40
|
+
<ConfigFieldGroup :title="t('panel.config.groupGridParams')">
|
|
39
41
|
<div class="grid grid-cols-2 gap-2">
|
|
40
42
|
<label class="block space-y-1">
|
|
41
|
-
<div
|
|
43
|
+
<div>{{ t("panel.config.rowCount") }}</div>
|
|
42
44
|
<InputNumber
|
|
43
45
|
size="small"
|
|
44
46
|
class="w-full"
|
|
@@ -50,7 +52,7 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
50
52
|
/>
|
|
51
53
|
</label>
|
|
52
54
|
<label class="block space-y-1">
|
|
53
|
-
<div
|
|
55
|
+
<div>{{ t("panel.config.colCount") }}</div>
|
|
54
56
|
<InputNumber
|
|
55
57
|
size="small"
|
|
56
58
|
class="w-full"
|
|
@@ -62,7 +64,7 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
62
64
|
/>
|
|
63
65
|
</label>
|
|
64
66
|
<label class="block space-y-1">
|
|
65
|
-
<div
|
|
67
|
+
<div>{{ t("panel.config.gapPx") }}</div>
|
|
66
68
|
<InputNumber
|
|
67
69
|
size="small"
|
|
68
70
|
class="w-full"
|
|
@@ -74,7 +76,7 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
74
76
|
/>
|
|
75
77
|
</label>
|
|
76
78
|
<label class="block space-y-1">
|
|
77
|
-
<div
|
|
79
|
+
<div>{{ t("panel.config.paddingPx") }}</div>
|
|
78
80
|
<InputNumber
|
|
79
81
|
size="small"
|
|
80
82
|
class="w-full"
|
|
@@ -86,7 +88,7 @@ function patch(patch: Partial<PanelElement>) {
|
|
|
86
88
|
/>
|
|
87
89
|
</label>
|
|
88
90
|
<label class="block space-y-1">
|
|
89
|
-
<div
|
|
91
|
+
<div>{{ t("panel.config.snapThresholdPx") }}</div>
|
|
90
92
|
<InputNumber
|
|
91
93
|
size="small"
|
|
92
94
|
class="w-full"
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import { ref } from "vue";
|
|
3
4
|
import { Input, Select } from "ant-design-vue";
|
|
4
5
|
import type { PanelElement } from "../../types";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
readFileAsDataUrl,
|
|
8
|
-
uploadFileToRemote,
|
|
9
|
-
} from "./shared";
|
|
6
|
+
import { readFileAsDataUrl, uploadFileToRemote } from "./shared";
|
|
7
|
+
import { getPanelMessages } from "../../constants/messages";
|
|
10
8
|
import ConfigFieldGroup from "./ConfigFieldGroup.vue";
|
|
11
9
|
import ConfigSection from "./ConfigSection.vue";
|
|
12
10
|
import ConfigHintIcon from "../ConfigHintIcon.vue";
|
|
13
11
|
|
|
12
|
+
const { t, locale } = useI18n();
|
|
13
|
+
const msgs = () => getPanelMessages(t);
|
|
14
|
+
|
|
14
15
|
const props = defineProps<{
|
|
15
16
|
element: PanelElement;
|
|
16
17
|
isEditable: boolean;
|
|
@@ -36,15 +37,15 @@ function patchStyle(patch: Record<string, string | undefined>) {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
async function handleUploadImage(file: File) {
|
|
39
|
-
const base64 = await readFileAsDataUrl(file,
|
|
40
|
+
const base64 = await readFileAsDataUrl(file, msgs().readImageFailed);
|
|
40
41
|
patchStyle({ backgroundImage: `url("${base64}")` });
|
|
41
|
-
uploadStatus.value = "
|
|
42
|
+
uploadStatus.value = t("panel.config.uploadWrittenBase64");
|
|
42
43
|
const url = await uploadFileToRemote(file);
|
|
43
44
|
if (url) {
|
|
44
45
|
patchStyle({ backgroundImageRemoteUrl: url });
|
|
45
|
-
uploadStatus.value = "
|
|
46
|
+
uploadStatus.value = t("panel.config.uploadServerAndBase64");
|
|
46
47
|
} else {
|
|
47
|
-
uploadStatus.value = "
|
|
48
|
+
uploadStatus.value = t("panel.config.uploadServerFailedKeepBase64");
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -58,17 +59,17 @@ function onFileChange(e: Event) {
|
|
|
58
59
|
|
|
59
60
|
<template>
|
|
60
61
|
<ConfigSection
|
|
61
|
-
title="
|
|
62
|
+
:title="t('panel.config.sectionImage')"
|
|
62
63
|
:open="open"
|
|
63
64
|
:force-open="forceOpen"
|
|
64
65
|
@update:open="emit('update:open', $event)"
|
|
65
66
|
>
|
|
66
|
-
<ConfigFieldGroup title="
|
|
67
|
+
<ConfigFieldGroup :title="t('panel.config.groupImageSource')">
|
|
67
68
|
<label class="block space-y-1">
|
|
68
69
|
<div class="flex items-center gap-1">
|
|
69
|
-
<span
|
|
70
|
-
<ConfigHintIcon label="
|
|
71
|
-
|
|
70
|
+
<span>{{ t("panel.config.imageUrlCss") }}</span>
|
|
71
|
+
<ConfigHintIcon :label="t('panel.config.imageUrlHintLabel')">
|
|
72
|
+
{{ t("panel.config.imageUrlHint") }}
|
|
72
73
|
</ConfigHintIcon>
|
|
73
74
|
</div>
|
|
74
75
|
<Input
|
|
@@ -93,15 +94,15 @@ function onFileChange(e: Event) {
|
|
|
93
94
|
class="inline-flex cursor-pointer items-center rounded border border-gray-200 px-2 py-1 text-[11px] hover:bg-gray-50"
|
|
94
95
|
:class="{ 'pointer-events-none opacity-50': !isEditable }"
|
|
95
96
|
>
|
|
96
|
-
|
|
97
|
+
{{ t("panel.config.uploadImage") }}
|
|
97
98
|
<input type="file" accept="image/*" class="hidden" :disabled="!isEditable" @change="onFileChange" />
|
|
98
99
|
</label>
|
|
99
100
|
<span v-if="uploadStatus" class="text-[11px] text-gray-500">{{ uploadStatus }}</span>
|
|
100
101
|
</div>
|
|
101
102
|
</ConfigFieldGroup>
|
|
102
|
-
<ConfigFieldGroup title="
|
|
103
|
+
<ConfigFieldGroup :title="t('panel.config.groupDisplayMode')">
|
|
103
104
|
<label class="block space-y-1">
|
|
104
|
-
<div
|
|
105
|
+
<div>{{ t("panel.config.objectFitFull") }}</div>
|
|
105
106
|
<Select
|
|
106
107
|
size="small"
|
|
107
108
|
class="w-full"
|
|
@@ -109,14 +110,14 @@ function onFileChange(e: Event) {
|
|
|
109
110
|
:disabled="!isEditable"
|
|
110
111
|
@update:value="(v) => patchStyle({ backgroundSize: String(v) })"
|
|
111
112
|
>
|
|
112
|
-
<Select.Option value="cover">
|
|
113
|
-
<Select.Option value="contain">
|
|
114
|
-
<Select.Option value="100% 100%">
|
|
113
|
+
<Select.Option value="cover">{{ t("panel.config.fitCover") }}</Select.Option>
|
|
114
|
+
<Select.Option value="contain">{{ t("panel.config.fitContain") }}</Select.Option>
|
|
115
|
+
<Select.Option value="100% 100%">{{ t("panel.config.fitFill") }}</Select.Option>
|
|
115
116
|
<Select.Option value="auto">auto</Select.Option>
|
|
116
117
|
</Select>
|
|
117
118
|
</label>
|
|
118
119
|
<label class="block space-y-1">
|
|
119
|
-
<div
|
|
120
|
+
<div>{{ t("panel.config.alignPosition") }}</div>
|
|
120
121
|
<Select
|
|
121
122
|
size="small"
|
|
122
123
|
class="w-full"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import { computed, ref } from "vue";
|
|
3
4
|
import { Card, Checkbox, Input, InputNumber, Select } from "ant-design-vue";
|
|
4
5
|
import type { PanelElement, PanelLayer, ReferenceCopyMode } from "../../types";
|
|
5
6
|
import { CHART_TYPES } from "../../utils/chartOptionBuilder";
|
|
6
7
|
|
|
8
|
+
const { t, locale } = useI18n();
|
|
7
9
|
const props = defineProps<{
|
|
8
10
|
elements: PanelElement[];
|
|
9
11
|
layers: PanelLayer[];
|
|
@@ -52,9 +54,9 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
52
54
|
|
|
53
55
|
<template>
|
|
54
56
|
<div class="space-y-3">
|
|
55
|
-
<Card size="small" title="
|
|
57
|
+
<Card size="small" :title="t('panel.config.batchTitle')">
|
|
56
58
|
<template #title>
|
|
57
|
-
<span class="text-xs"
|
|
59
|
+
<span class="text-xs">{{ t("panel.config.batchTitleWithCount", { count: elements.length }) }}</span>
|
|
58
60
|
</template>
|
|
59
61
|
<div class="grid grid-cols-2 gap-2 text-xs">
|
|
60
62
|
<button
|
|
@@ -62,14 +64,14 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
62
64
|
class="rounded border border-gray-200 bg-white px-2 py-1 hover:bg-gray-50"
|
|
63
65
|
@click="elements.forEach((el) => updateElement(el.id, { locked: true }))"
|
|
64
66
|
>
|
|
65
|
-
|
|
67
|
+
{{ t("panel.config.lockAll") }}
|
|
66
68
|
</button>
|
|
67
69
|
<button
|
|
68
70
|
type="button"
|
|
69
71
|
class="rounded border border-gray-200 bg-white px-2 py-1 hover:bg-gray-50"
|
|
70
72
|
@click="elements.forEach((el) => updateElement(el.id, { locked: false }))"
|
|
71
73
|
>
|
|
72
|
-
|
|
74
|
+
{{ t("panel.config.unlockAll") }}
|
|
73
75
|
</button>
|
|
74
76
|
<button
|
|
75
77
|
v-if="onAdjustNodeZOrder"
|
|
@@ -77,7 +79,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
77
79
|
class="rounded border border-gray-200 bg-white px-2 py-1 hover:bg-gray-50"
|
|
78
80
|
@click="elements.forEach((el) => onAdjustNodeZOrder?.(el.id, 'bringForward'))"
|
|
79
81
|
>
|
|
80
|
-
|
|
82
|
+
{{ t("panel.config.bringAllForward") }}
|
|
81
83
|
</button>
|
|
82
84
|
<button
|
|
83
85
|
v-if="onAdjustNodeZOrder"
|
|
@@ -85,14 +87,14 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
85
87
|
class="rounded border border-gray-200 bg-white px-2 py-1 hover:bg-gray-50"
|
|
86
88
|
@click="elements.forEach((el) => onAdjustNodeZOrder?.(el.id, 'sendBackward'))"
|
|
87
89
|
>
|
|
88
|
-
|
|
90
|
+
{{ t("panel.config.sendAllBackward") }}
|
|
89
91
|
</button>
|
|
90
92
|
<button
|
|
91
93
|
type="button"
|
|
92
94
|
class="rounded border border-gray-200 bg-white px-2 py-1 hover:bg-gray-50"
|
|
93
95
|
@click="elements.forEach((el) => updateElement(el.id, { zIndex: 1 }))"
|
|
94
96
|
>
|
|
95
|
-
|
|
97
|
+
{{ t("panel.config.setAllZIndex1") }}
|
|
96
98
|
</button>
|
|
97
99
|
<button
|
|
98
100
|
type="button"
|
|
@@ -105,7 +107,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
105
107
|
)
|
|
106
108
|
"
|
|
107
109
|
>
|
|
108
|
-
|
|
110
|
+
{{ t("panel.config.setAllBgBlue") }}
|
|
109
111
|
</button>
|
|
110
112
|
</div>
|
|
111
113
|
</Card>
|
|
@@ -126,7 +128,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
126
128
|
{{ isNodeCardExpanded(el.id) ? "▾" : "▸" }}
|
|
127
129
|
</button>
|
|
128
130
|
<span class="min-w-0 flex-1 truncate text-xs">
|
|
129
|
-
{{ el.name?.trim() || el.materialType || "
|
|
131
|
+
{{ el.name?.trim() || el.materialType || t("common.node") }} · {{ el.id }}
|
|
130
132
|
</span>
|
|
131
133
|
<button
|
|
132
134
|
v-if="onExcludeSelectedNode"
|
|
@@ -134,7 +136,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
134
136
|
class="inline-flex h-6 items-center rounded border border-gray-200 px-2 text-[11px] text-gray-500 hover:bg-gray-50"
|
|
135
137
|
@click="onExcludeSelectedNode(el.id)"
|
|
136
138
|
>
|
|
137
|
-
|
|
139
|
+
{{ t("panel.config.removeFromSelection") }}
|
|
138
140
|
</button>
|
|
139
141
|
</div>
|
|
140
142
|
</template>
|
|
@@ -144,18 +146,18 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
144
146
|
:checked="el.locked === true"
|
|
145
147
|
@update:checked="(v) => updateElement(el.id, { locked: v === true })"
|
|
146
148
|
/>
|
|
147
|
-
<span
|
|
149
|
+
<span>{{ t("panel.config.lockedNode") }}</span>
|
|
148
150
|
</label>
|
|
149
151
|
<div
|
|
150
152
|
v-if="el.locked"
|
|
151
153
|
class="rounded border border-amber-500/40 bg-amber-500/10 px-2 py-1.5 text-[11px] text-amber-700"
|
|
152
154
|
>
|
|
153
|
-
|
|
155
|
+
{{ t("panel.config.lockedNodeHint") }}
|
|
154
156
|
</div>
|
|
155
157
|
<fieldset :disabled="el.locked" :class="el.locked ? 'opacity-60' : ''">
|
|
156
158
|
<div class="space-y-2">
|
|
157
159
|
<label class="block space-y-1">
|
|
158
|
-
<div
|
|
160
|
+
<div>{{ t("panel.config.name") }}</div>
|
|
159
161
|
<Input
|
|
160
162
|
size="small"
|
|
161
163
|
:value="el.name ?? ''"
|
|
@@ -173,7 +175,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
173
175
|
/>
|
|
174
176
|
</label>
|
|
175
177
|
<label class="block space-y-1">
|
|
176
|
-
<div
|
|
178
|
+
<div>{{ t("panel.config.layer") }}</div>
|
|
177
179
|
<Select
|
|
178
180
|
size="small"
|
|
179
181
|
class="w-full"
|
|
@@ -196,21 +198,21 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
196
198
|
<InputNumber size="small" class="w-full" :value="el.y" @update:value="(v) => updateElement(el.id, { y: Number(v) || 0 })" />
|
|
197
199
|
</label>
|
|
198
200
|
<label class="block space-y-1">
|
|
199
|
-
<div
|
|
201
|
+
<div>{{ t("panel.config.rotate") }}</div>
|
|
200
202
|
<InputNumber size="small" class="w-full" :value="el.rotate ?? 0" @update:value="(v) => updateElement(el.id, { rotate: Number(v) || 0 })" />
|
|
201
203
|
</label>
|
|
202
204
|
<label class="block space-y-1">
|
|
203
|
-
<div
|
|
205
|
+
<div>{{ t("panel.config.width") }}</div>
|
|
204
206
|
<InputNumber size="small" class="w-full" :min="1" :value="el.width" @update:value="(v) => updateElement(el.id, { width: Math.max(1, Number(v) || 1) })" />
|
|
205
207
|
</label>
|
|
206
208
|
<label class="block space-y-1">
|
|
207
|
-
<div
|
|
209
|
+
<div>{{ t("panel.config.height") }}</div>
|
|
208
210
|
<InputNumber size="small" class="w-full" :min="1" :value="el.height" @update:value="(v) => updateElement(el.id, { height: Math.max(1, Number(v) || 1) })" />
|
|
209
211
|
</label>
|
|
210
212
|
</div>
|
|
211
213
|
<div class="grid grid-cols-2 gap-2">
|
|
212
214
|
<label class="block space-y-1">
|
|
213
|
-
<div
|
|
215
|
+
<div>{{ t("panel.scope.fieldStyleBackgroundColor") }}</div>
|
|
214
216
|
<Input
|
|
215
217
|
size="small"
|
|
216
218
|
:value="el.style?.backgroundColor ?? ''"
|
|
@@ -218,7 +220,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
218
220
|
/>
|
|
219
221
|
</label>
|
|
220
222
|
<label class="block space-y-1">
|
|
221
|
-
<div
|
|
223
|
+
<div>{{ t("panel.config.borderColorShort") }}</div>
|
|
222
224
|
<Input
|
|
223
225
|
size="small"
|
|
224
226
|
:value="el.style?.borderColor ?? ''"
|
|
@@ -230,7 +232,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
230
232
|
<template v-if="CHART_TYPES.has(el.materialType ?? '')">
|
|
231
233
|
<div class="grid grid-cols-2 gap-2">
|
|
232
234
|
<label class="col-span-2 block space-y-1">
|
|
233
|
-
<div
|
|
235
|
+
<div>{{ t("panel.scope.fieldChartTitle") }}</div>
|
|
234
236
|
<Input
|
|
235
237
|
size="small"
|
|
236
238
|
:value="el.chart?.title ?? ''"
|
|
@@ -238,7 +240,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
238
240
|
/>
|
|
239
241
|
</label>
|
|
240
242
|
<label class="block space-y-1">
|
|
241
|
-
<div
|
|
243
|
+
<div>{{ t("panel.config.primaryColor") }}</div>
|
|
242
244
|
<Input
|
|
243
245
|
size="small"
|
|
244
246
|
:value="el.chart?.color ?? ''"
|
|
@@ -251,7 +253,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
251
253
|
<template v-if="el.materialType === 'text'">
|
|
252
254
|
<div class="grid grid-cols-2 gap-2">
|
|
253
255
|
<label class="col-span-2 block space-y-1">
|
|
254
|
-
<div
|
|
256
|
+
<div>{{ t("panel.config.textHtml") }}</div>
|
|
255
257
|
<Input.TextArea
|
|
256
258
|
:value="el.textHtml ?? ''"
|
|
257
259
|
:rows="3"
|
|
@@ -259,7 +261,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
259
261
|
/>
|
|
260
262
|
</label>
|
|
261
263
|
<label class="block space-y-1">
|
|
262
|
-
<div
|
|
264
|
+
<div>{{ t("panel.config.fontSize") }}</div>
|
|
263
265
|
<InputNumber
|
|
264
266
|
size="small"
|
|
265
267
|
class="w-full"
|
|
@@ -269,7 +271,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
269
271
|
/>
|
|
270
272
|
</label>
|
|
271
273
|
<label class="block space-y-1">
|
|
272
|
-
<div
|
|
274
|
+
<div>{{ t("panel.config.textColor") }}</div>
|
|
273
275
|
<Input
|
|
274
276
|
size="small"
|
|
275
277
|
:value="el.textColor ?? ''"
|
|
@@ -282,7 +284,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
282
284
|
<template v-if="el.materialType === 'audio'">
|
|
283
285
|
<div class="grid grid-cols-2 gap-2">
|
|
284
286
|
<label class="col-span-2 block space-y-1">
|
|
285
|
-
<div
|
|
287
|
+
<div>{{ t("panel.config.audioUrl") }}</div>
|
|
286
288
|
<Input
|
|
287
289
|
size="small"
|
|
288
290
|
:value="el.audioRemoteUrl ?? ''"
|
|
@@ -290,7 +292,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
290
292
|
/>
|
|
291
293
|
</label>
|
|
292
294
|
<label class="block space-y-1">
|
|
293
|
-
<div
|
|
295
|
+
<div>{{ t("panel.config.effect") }}</div>
|
|
294
296
|
<Select
|
|
295
297
|
size="small"
|
|
296
298
|
class="w-full"
|
|
@@ -307,7 +309,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
307
309
|
|
|
308
310
|
<template v-if="el.materialType === 'video'">
|
|
309
311
|
<label class="block space-y-1">
|
|
310
|
-
<div
|
|
312
|
+
<div>{{ t("panel.config.videoUrl") }}</div>
|
|
311
313
|
<Input
|
|
312
314
|
size="small"
|
|
313
315
|
:value="el.videoRemoteUrl ?? ''"
|
|
@@ -319,11 +321,11 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
319
321
|
<template v-if="el.materialType === 'grid'">
|
|
320
322
|
<div class="grid grid-cols-2 gap-2 rounded-lg border border-gray-200/60 bg-gray-50/50 p-3">
|
|
321
323
|
<label class="block space-y-1">
|
|
322
|
-
<div
|
|
324
|
+
<div>{{ t("panel.config.rowsShort") }}</div>
|
|
323
325
|
<InputNumber size="small" class="w-full" :min="1" :value="el.gridRows ?? 2" @update:value="(v) => updateElement(el.id, { gridRows: Math.max(1, Number(v) || 2) })" />
|
|
324
326
|
</label>
|
|
325
327
|
<label class="block space-y-1">
|
|
326
|
-
<div
|
|
328
|
+
<div>{{ t("panel.config.colsShort") }}</div>
|
|
327
329
|
<InputNumber size="small" class="w-full" :min="1" :value="el.gridCols ?? 3" @update:value="(v) => updateElement(el.id, { gridCols: Math.max(1, Number(v) || 3) })" />
|
|
328
330
|
</label>
|
|
329
331
|
</div>
|
|
@@ -332,20 +334,20 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
332
334
|
<template v-if="el.materialType === 'geometry'">
|
|
333
335
|
<div class="grid grid-cols-2 gap-2 rounded-lg border border-gray-200/60 bg-gray-50/50 p-3">
|
|
334
336
|
<label class="block space-y-1">
|
|
335
|
-
<div
|
|
337
|
+
<div>{{ t("panel.config.shape") }}</div>
|
|
336
338
|
<Select
|
|
337
339
|
size="small"
|
|
338
340
|
class="w-full"
|
|
339
341
|
:value="el.geometryShape ?? 'rect'"
|
|
340
342
|
@update:value="(v) => updateElement(el.id, { geometryShape: v as PanelElement['geometryShape'] })"
|
|
341
343
|
>
|
|
342
|
-
<Select.Option value="rect"
|
|
343
|
-
<Select.Option value="circle"
|
|
344
|
-
<Select.Option value="triangle"
|
|
344
|
+
<Select.Option value="rect">{{ t("panel.config.shapeRect") }}</Select.Option>
|
|
345
|
+
<Select.Option value="circle">{{ t("panel.config.shapeCircle") }}</Select.Option>
|
|
346
|
+
<Select.Option value="triangle">{{ t("panel.config.shapeTriangle") }}</Select.Option>
|
|
345
347
|
</Select>
|
|
346
348
|
</label>
|
|
347
349
|
<label class="block space-y-1">
|
|
348
|
-
<div
|
|
350
|
+
<div>{{ t("panel.config.color") }}</div>
|
|
349
351
|
<Input
|
|
350
352
|
size="small"
|
|
351
353
|
:value="el.geometryColor ?? '#3b82f6'"
|
|
@@ -358,14 +360,14 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
358
360
|
<template v-if="el.materialType === 'reference'">
|
|
359
361
|
<div class="grid grid-cols-2 gap-2">
|
|
360
362
|
<label class="block space-y-1">
|
|
361
|
-
<div
|
|
363
|
+
<div>{{ t("panel.config.refLayer") }}</div>
|
|
362
364
|
<Select
|
|
363
365
|
size="small"
|
|
364
366
|
class="w-full"
|
|
365
367
|
:value="el.refLayerId ?? '__none__'"
|
|
366
368
|
@update:value="(v) => updateElement(el.id, { refLayerId: v === '__none__' ? undefined : String(v) })"
|
|
367
369
|
>
|
|
368
|
-
<Select.Option value="__none__"
|
|
370
|
+
<Select.Option value="__none__">{{ t("common.none") }}</Select.Option>
|
|
369
371
|
<Select.Option
|
|
370
372
|
v-for="layer in layers.filter((l) => l.id !== el.layerId)"
|
|
371
373
|
:key="layer.id"
|
|
@@ -376,7 +378,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
376
378
|
</Select>
|
|
377
379
|
</label>
|
|
378
380
|
<label class="block space-y-1">
|
|
379
|
-
<div
|
|
381
|
+
<div>{{ t("panel.config.copy") }}</div>
|
|
380
382
|
<Select
|
|
381
383
|
size="small"
|
|
382
384
|
class="w-full"
|
|
@@ -392,7 +394,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
392
394
|
|
|
393
395
|
<template v-if="el.materialType === 'image'">
|
|
394
396
|
<label class="block space-y-1">
|
|
395
|
-
<div
|
|
397
|
+
<div>{{ t("panel.config.backgroundImageUrl") }}</div>
|
|
396
398
|
<Input
|
|
397
399
|
size="small"
|
|
398
400
|
:value="el.style?.backgroundImageRemoteUrl ?? el.style?.backgroundImage ?? ''"
|
|
@@ -406,7 +408,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
406
408
|
/>
|
|
407
409
|
</label>
|
|
408
410
|
<label class="block space-y-1">
|
|
409
|
-
<div
|
|
411
|
+
<div>{{ t("panel.config.objectFit") }}</div>
|
|
410
412
|
<Select
|
|
411
413
|
size="small"
|
|
412
414
|
class="w-full"
|
|
@@ -428,7 +430,7 @@ function setNodeCardExpanded(id: string, open: boolean) {
|
|
|
428
430
|
v-if="noSearchMatch"
|
|
429
431
|
class="rounded border border-gray-200/60 bg-white px-2 py-1.5 text-[11px] text-gray-500"
|
|
430
432
|
>
|
|
431
|
-
|
|
433
|
+
{{ t("panel.config.noEditableMatch") }}
|
|
432
434
|
</div>
|
|
433
435
|
</div>
|
|
434
436
|
</template>
|