Skip to content

Commit 49882c9

Browse files
authored
fix: optimization and Modification of SaaS Official Website (#3848)
* fix: optimization and Modification of SaaS Official Website * fix: delete invalid styles
1 parent 358d767 commit 49882c9

File tree

12 files changed

+309
-13
lines changed

12 files changed

+309
-13
lines changed

examples/sites/demos/mobile-first/app/button/webdoc/button.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ export default {
99
'en-US': 'basic usage'
1010
},
1111
desc: {
12-
'zh-CN': '<p></p>',
13-
'en-US': '<p></p>'
12+
'zh-CN': '通过<code>type</code> 设置按钮类型, <code>plain</code> 设置是否为朴素按钮。',
13+
'en-US': 'Use <code>type</code> to set the button type, <code>plain</code> to set whether it is a plain button.'
1414
},
1515
codeFiles: ['basic-usage.vue']
1616
},

examples/sites/demos/mobile-first/app/file-upload/show-title.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
</template>
44

55
<script>
6-
import { TinyFileUpload, TinyButton } from '@opentiny/vue'
6+
import { TinyFileUpload } from '@opentiny/vue'
77
88
export default {
99
components: {
10-
TinyFileUpload,
11-
TinyButton
10+
TinyFileUpload
1211
},
1312
data() {
1413
return {

examples/sites/public/static/css/design-common.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@
767767
.tinyui-design-footer .footer-content .links .link-item div {
768768
width: 100%;
769769
text-align: left;
770+
display: flex;
770771
}
771772
.tinyui-design-footer .footer-content .contact {
772773
width: 100%;

examples/sites/saas.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<link rel="stylesheet" href="/saas/style.css" />
7+
<title>多端演示</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/saas/main.ts"></script>
12+
</body>
13+
</html>

examples/sites/saas/App.vue

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<template>
2+
<div class="mobile-preview">
3+
<component :is="showComponent" />
4+
</div>
5+
</template>
6+
7+
<script setup lang="tsx">
8+
import { shallowRef, onMounted, onBeforeUnmount } from 'vue'
9+
import { TinyLoading } from '@opentiny/vue'
10+
import { getMobileFirstDemo } from '@/views/components-doc/cmp-config'
11+
12+
const showComponent = shallowRef(null)
13+
const notFoundDemo = (demoPath) => <div>{`${demoPath}示例资源不存在,请检查文件名是否正确?`}</div>
14+
const getComponent = async (demoPath) => {
15+
const mobileFirstDemo = getMobileFirstDemo()
16+
try {
17+
const cmp = (await mobileFirstDemo[`mobile-first/${demoPath}`]()).default
18+
return cmp
19+
} catch (e) {
20+
return notFoundDemo(demoPath)
21+
}
22+
}
23+
24+
let loadingService
25+
const showLoading = () => {
26+
if (!loadingService) {
27+
loadingService = TinyLoading.service({
28+
lock: true
29+
})
30+
}
31+
}
32+
const closeLoading = () => {
33+
if (loadingService) {
34+
loadingService.close()
35+
loadingService = null
36+
}
37+
}
38+
39+
const receiveMessage = ({ data }) => {
40+
const { from, component, demo } = data || {}
41+
if (!['tiny-vue-site'].includes(from)) {
42+
return
43+
}
44+
const demoPath = `${component}/${demo}`
45+
getComponent(demoPath).then((cmp) => {
46+
showComponent.value = cmp
47+
})
48+
}
49+
50+
onMounted(() => {
51+
const searchObj = new URLSearchParams(location.search)
52+
const component = searchObj.get('component')
53+
const demo = searchObj.get('demo')
54+
window.addEventListener('message', receiveMessage, false)
55+
if (component && demo) {
56+
showLoading()
57+
const demoPath = `${component}/${demo}`
58+
getComponent(demoPath).then((cmp) => {
59+
showComponent.value = cmp
60+
closeLoading()
61+
})
62+
}
63+
})
64+
65+
onBeforeUnmount(() => {
66+
window.removeEventListener('message', receiveMessage)
67+
})
68+
</script>
69+
70+
<style lang="less">
71+
html,
72+
body {
73+
margin: 0;
74+
padding: 0;
75+
}
76+
77+
html,
78+
body,
79+
#app {
80+
height: 100%;
81+
::-webkit-scrollbar {
82+
width: var(--tvm-size-scrollbar-width);
83+
height: var(--tvm-size-scrollbar-height);
84+
}
85+
86+
::-webkit-scrollbar-track-piece {
87+
background: var(--tvm-color-bg-scrollbar-track);
88+
}
89+
90+
::-webkit-scrollbar-thumb {
91+
background: var(--tvm-color-bg-scrollbar-thumb);
92+
border-radius: var(--tvm-border-radius-scrollbar-thumb);
93+
}
94+
95+
::-webkit-scrollbar-thumb:hover {
96+
background: var(--tvm-color-bg-scrollbar-thumb-hover);
97+
}
98+
99+
::-webkit-scrollbar-thumb:active {
100+
background: var(--tvm-color-bg-scrollbar-thumb-active);
101+
}
102+
}
103+
</style>

examples/sites/saas/main.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import '../../../packages/theme-saas/src/index.less'
2+
import '../../../packages/theme-saas/theme/theme.json'
3+
4+
import { createApp } from 'vue'
5+
import App from './App.vue'
6+
7+
const app = createApp(App)
8+
app.config.globalProperties.tiny_mode = 'mobile-first'
9+
app.mount('#app')

examples/sites/saas/style.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/* 右侧固定面板样式 */
2+
.right-side-panel {
3+
width: 100%;
4+
height: 375px;
5+
background-color: #ffffff;
6+
display: flex;
7+
flex-direction: column;
8+
overflow: auto;
9+
margin-bottom: 12px;
10+
}
11+
12+
/* 顶部标题栏 - 修改为 flex 布局 */
13+
.panel-header {
14+
background-color: #f5f5f5;
15+
padding: 16px 24px;
16+
flex-shrink: 0;
17+
border: 1px solid #dbdbdb;
18+
border-bottom: none;
19+
border-radius: 6px 6px 0 0;
20+
display: flex;
21+
justify-content: space-between;
22+
align-items: center;
23+
color: #595959;
24+
}
25+
26+
.panel-title {
27+
margin: 0;
28+
font-size: 14px;
29+
font-weight: 400;
30+
color: #595959;
31+
line-height: 1.5;
32+
white-space: nowrap; /* 防止文本换行 */
33+
overflow: hidden; /* 隐藏溢出内容 */
34+
text-overflow: ellipsis; /* 添加省略号 */
35+
max-width: 100%; /* 确保标题宽度不超过父容器 */
36+
}
37+
38+
/* Switch 容器样式 */
39+
.screen-switch-wrapper {
40+
display: flex;
41+
align-items: center;
42+
gap: 8px;
43+
}
44+
45+
.switch-label {
46+
font-size: 14px;
47+
color: #666;
48+
white-space: nowrap;
49+
}
50+
51+
/* 内容区域 */
52+
.panel-body {
53+
flex: 1;
54+
padding: 12px;
55+
overflow-y: auto;
56+
color: #666;
57+
border: 1px solid #dbdbdb;
58+
border-top: none;
59+
border-radius: 0 0 6px 6px;
60+
}
61+
62+
.panel-cmp-box {
63+
width: 100%;
64+
height: 100%;
65+
}

examples/sites/src/components/demo.vue

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
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 -->
@@ -43,6 +47,37 @@
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'
83118
import { i18nByKey, getWord } from '@/i18n'
84119
import { $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'
86121
import { AutoTip as vAutoTip } from '@opentiny/vue-directive'
87122
import { languageMap, vueComponents, getWebdocPath, staticDemoPath } from '../views/components-doc/cmp-config'
88123
import { router } from '@/router.js'
89124
import demoConfig from '@demos/config.js'
90125
import { useApiMode, useTemplateMode } from '@/tools'
126+
import { useBreakpoint } from '@opentiny/vue-common'
91127
import useTheme from '@/tools/useTheme'
92128
import AsyncHighlight from './async-highlight.vue'
129+
import '../assets/right-panel.less'
93130
94131
const props = defineProps({
95132
demo: {
@@ -109,9 +146,10 @@ const props = defineProps({
109146
default: false
110147
}
111148
})
112-
113149
const emit = defineEmits(['mounted', 'get-iframe-demo'])
114-
150+
const iframeRef = ref()
151+
const isSmallScreen = computed(() => useBreakpoint().current.value === 'default')
152+
let screenFlag = ref(false)
115153
const { apiModeState, apiModeFn } = useApiMode()
116154
117155
defineOptions({
@@ -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+
140186
watch(
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

Comments
 (0)