11<template >
2- <div ref =" demoContainer" :id =" demo.demoId" class =" demo-container" >
2+ <div ref =" demoContainer" :id =" demo.demoId" : class =" !isMobileFirst ? ' demo-container' : 'demo-mobile-first-container' " >
33 <div
44 v-if =" isIntersecting"
55 class =" ti-br-sm ti-wp100"
6- :class =" currDemoId === demo.demoId ? 'b-a-success is-current' : ''"
6+ :class =" {
7+ 'b-a-success': currDemoId === demo.demoId,
8+ 'is-current': currDemoId === demo.demoId,
9+ 'is-mobile-first': isMobileFirst
10+ }"
711 >
812 <div class =" demo-content" >
913 <!-- DEMO 的标题 + 说明desc + 示例wcTag -->
4347 <tiny-button @click =" openIframe(demo)" >{{ i18nByKey('yan-shi') }}</tiny-button >
4448 </div >
4549 </div >
50+ <div v-else-if =" isMobileFirst" class =" mobile-first-demo-container" >
51+ <div class =" right-side-panel" >
52+ <div class =" panel-header" >
53+ <h3 class =" panel-title" >{{ demo.name[state.langKey] }}</h3 >
54+ <div class =" screen-switch-wrapper" v-if =" !isSmallScreen" >
55+ <!-- 添加 Switch 控件 -->
56+ <span class =" switch-label" >{{ screenFlag ? '小屏' : '大屏' }}</span >
57+ <tiny-switch v-model =" screenFlag" size =" small" > </tiny-switch >
58+ </div >
59+ </div >
60+ <div class =" panel-body" >
61+ <div class =" panel-cmp-box" >
62+ <!-- 小屏幕 -->
63+ <div v-if =" screenFlag && !isSmallScreen" key =" mobile-iframe-wrapper" >
64+ <iframe
65+ ref =" iframeRef"
66+ style =" height : 300px ; max-width : 639px "
67+ sandbox =" allow-scripts allow-same-origin"
68+ :src =" `/saas.html?component=${router.currentRoute.value.params.cmpId}&demo=${demo.codeFiles[0]}`"
69+ frameborder =" 0"
70+ importance =" high"
71+ loading =" lazy"
72+ >
73+ </iframe >
74+ </div >
75+ <!-- 大屏 -->
76+ <component v-else :is =" cmp" />
77+ </div >
78+ </div >
79+ </div >
80+ </div >
4681 <div v-else class =" pc-demo-container" >
4782 <div class =" pc-demo" >
4883 <component :is =" cmp" />
@@ -82,14 +117,16 @@ import {
82117} from ' vue'
83118import { i18nByKey , getWord } from ' @/i18n'
84119import { $split , fetchDemosFile } from ' @/tools'
85- import { Tabs as TinyTabs , TabItem as TinyTabItem , Button as TinyButton } from ' @opentiny/vue'
120+ import { Tabs as TinyTabs , TabItem as TinyTabItem , Button as TinyButton , Switch as TinySwitch } from ' @opentiny/vue'
86121import { AutoTip as vAutoTip } from ' @opentiny/vue-directive'
87122import { languageMap , vueComponents , getWebdocPath , staticDemoPath } from ' ../views/components-doc/cmp-config'
88123import { router } from ' @/router.js'
89124import demoConfig from ' @demos/config.js'
90125import { useApiMode , useTemplateMode } from ' @/tools'
126+ import { useBreakpoint } from ' @opentiny/vue-common'
91127import useTheme from ' @/tools/useTheme'
92128import AsyncHighlight from ' ./async-highlight.vue'
129+ import ' ../assets/right-panel.less'
93130
94131const props = defineProps ({
95132 demo: {
@@ -109,9 +146,10 @@ const props = defineProps({
109146 default: false
110147 }
111148})
112-
113149const emit = defineEmits ([' mounted' , ' get-iframe-demo' ])
114-
150+ const iframeRef = ref ()
151+ const isSmallScreen = computed (() => useBreakpoint ().current .value === ' default' )
152+ let screenFlag = ref (false )
115153const { apiModeState, apiModeFn } = useApiMode ()
116154
117155defineOptions ({
@@ -137,6 +175,14 @@ const state = reactive({
137175 copyIcon: ' i-ti-copy'
138176})
139177
178+ watch (
179+ isSmallScreen ,
180+ (val ) => {
181+ if (val ) screenFlag .value = true
182+ },
183+ { immediate: true }
184+ )
185+
140186watch (
141187 () => props .isIntersecting ,
142188 async () => {
@@ -253,7 +299,7 @@ const openPlayground = (demo, open = true) => {
253299 const tinyTheme = templateModeState .isSaas ? ' saas' : currentThemeKey .value .split (' -' )[0 ]
254300 const openModeQuery = open ? ' ' : ' &openMode=preview'
255301 // TODO: 目前mf只有Options写法,后续再放开compositon
256- const url = ` ${import .meta .env .VITE_PLAYGROUND_URL }?cmpId=${cmpId }&fileName=${demo .codeFiles [0 ]}&apiMode=${
302+ const url = ` ${import .meta .env .VITE_PLAYGROUND_URL }?cmpId=${cmpId }&fileName=${props . demo .codeFiles [0 ]}&apiMode=${
257303 isMobileFirst .value ? ' Options' : apiModeState .apiMode
258304 }&mode=${templateModeState .mode }&theme=${tinyTheme }${openModeQuery } `
259305
@@ -296,6 +342,11 @@ onBeforeUnmount(() => {
296342 padding : 20px 24px ;
297343}
298344
345+ .is-mobile-first {
346+ padding : 20px ;
347+ border : 1px solid #dcdfe6 ;
348+ }
349+
299350.demo-desc {
300351 font-size : 16px ;
301352 line-height : 1.7em ;
@@ -348,6 +399,23 @@ onBeforeUnmount(() => {
348399 .pc-demo-container {
349400 overflow : auto ;
350401 }
402+ .demo-mobile-first-container {
403+ cursor : pointer ;
404+ width : 100% ;
405+ .is-mobile-first {
406+ .demo-title {
407+ width : 200px ;
408+ font-size : 18px ;
409+ white-space : nowrap ;
410+ overflow : hidden ;
411+ text-overflow : ellipsis ;
412+ }
413+ .demo-options {
414+ top : 0px ;
415+ right : 0px ;
416+ }
417+ }
418+ }
351419}
352420
353421.pc-demo-container {
0 commit comments