Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions src/renderer/src/components/artifacts/ArtifactDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,97 @@
</button>
</div>

<!-- 设备尺寸切换按钮组 (仅在HTML预览时显示) -->
<div
v-if="isPreview && artifactStore.currentArtifact?.type === 'text/html'"
class="bg-border p-0.5 rounded-lg flex items-center"
>
<button
class="px-2 py-1 text-xs rounded-md transition-colors"
:class="
viewportSize === 'desktop'
? 'bg-background shadow-sm'
: 'text-muted-foreground hover:bg-background/50'
"
@click="setViewportSize('desktop')"
:title="t('artifacts.desktop')"
>
<Icon icon="lucide:monitor" class="w-3 h-3" />
</button>
<button
class="px-2 py-1 text-xs rounded-md transition-colors"
:class="
viewportSize === 'tablet'
? 'bg-background shadow-sm'
: 'text-muted-foreground hover:bg-background/50'
"
@click="setViewportSize('tablet')"
:title="t('artifacts.tablet')"
>
<Icon icon="lucide:tablet" class="w-3 h-3" />
</button>
<button
class="px-2 py-1 text-xs rounded-md transition-colors"
:class="
viewportSize === 'mobile'
? 'bg-background shadow-sm'
: 'text-muted-foreground hover:bg-background/50'
"
@click="setViewportSize('mobile')"
:title="t('artifacts.mobile')"
>
<Icon icon="lucide:smartphone" class="w-3 h-3" />
</button>
</div>

<!-- 尺寸微调输入框 (仅在平板和手机模式下显示) -->
<div
v-if="
isPreview &&
artifactStore.currentArtifact?.type === 'text/html' &&
viewportSize !== 'desktop'
"
class="flex items-center gap-2 bg-border p-1 rounded-lg"
>
<span class="text-xs text-muted-foreground whitespace-nowrap"
>{{ t('artifacts.width') }}:</span
>
<input
v-if="viewportSize === 'tablet'"
v-model.number="tabletWidth"
type="number"
min="320"
max="1200"
class="w-16 px-2 py-1 text-xs rounded border-0 bg-background focus:ring-1 focus:ring-blue-500 focus:outline-none text-center"
/>
<input
v-else-if="viewportSize === 'mobile'"
v-model.number="mobileWidth"
type="number"
min="320"
max="480"
class="w-16 px-2 py-1 text-xs rounded border-0 bg-background focus:ring-1 focus:ring-blue-500 focus:outline-none text-center"
/>
<span class="text-xs text-muted-foreground">×</span>
<input
v-if="viewportSize === 'tablet'"
v-model.number="tabletHeight"
type="number"
min="426"
max="1400"
class="w-16 px-2 py-1 text-xs rounded border-0 bg-background focus:ring-1 focus:ring-blue-500 focus:outline-none text-center"
/>
<input
v-else-if="viewportSize === 'mobile'"
v-model.number="mobileHeight"
type="number"
min="426"
max="1000"
class="w-16 px-2 py-1 text-xs rounded border-0 bg-background focus:ring-1 focus:ring-blue-500 focus:outline-none text-center"
/>
<span class="text-xs text-muted-foreground">px</span>
</div>

<!-- 导出按钮 -->
<div class="flex items-center gap-1">
<Button
Expand Down Expand Up @@ -116,6 +207,11 @@
}
}"
:is-preview="isPreview"
:viewport-size="viewportSize"
v-model:tablet-width="tabletWidth"
v-model:mobile-width="mobileWidth"
v-model:tablet-height="tabletHeight"
v-model:mobile-height="mobileHeight"
class="artifact-dialog-content"
/>
</template>
Expand Down Expand Up @@ -154,6 +250,11 @@ import { useMonaco, detectLanguage } from 'vue-use-monaco'
const artifactStore = useArtifactStore()
const componentKey = ref(0)
const isPreview = ref(false)
const viewportSize = ref<'desktop' | 'tablet' | 'mobile'>('desktop')
const tabletWidth = ref(768)
const mobileWidth = ref(375)
const tabletHeight = ref(1024) // 4:3 比例
const mobileHeight = ref(667) // 16:9 比例
const t = useI18n().t
const { toast } = useToast()
const themeStore = useThemeStore()
Expand Down Expand Up @@ -242,6 +343,10 @@ const setPreview = (value: boolean) => {
isPreview.value = value
}

const setViewportSize = (size: 'desktop' | 'tablet' | 'mobile') => {
viewportSize.value = size
}

// 监听 artifact 变化,强制重新渲染组件
watch(
() => artifactStore.currentArtifact,
Expand Down
Loading