@coffic/cosy-ui 0.8.17 → 0.8.19
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/app.css +1 -1
- package/dist/index-vue.ts +2 -2
- package/dist/src-astro/code-container/CodeContainer.astro +1 -1
- package/dist/src-astro/hero/Hero.astro +15 -17
- package/dist/src-vue/iPhone/StatusBarContent.vue +121 -0
- package/dist/src-vue/iPhone/iPhoneWindow.vue +177 -190
- package/dist/src-vue/iPhone/index.ts +1 -30
- package/dist/src-vue/icons/IPhoneBatteryIcon.vue +7 -0
- package/dist/src-vue/icons/IPhoneSignalIcon.vue +6 -0
- package/dist/src-vue/icons/IPhoneWifiIcon.vue +6 -0
- package/dist/src-vue/icons/index.ts +3 -0
- package/dist/src-vue/mac-window/MacWindow.vue +138 -159
- package/dist/src-vue/mac-window/index.ts +0 -34
- package/package.json +1 -1
- package/dist/src-vue/iPhone/Basic.vue +0 -33
- package/dist/src-vue/iPhone/CustomBackground.vue +0 -35
- package/dist/src-vue/iPhone/NoFrame.vue +0 -33
- package/dist/src-vue/iPhone/WeatherApp.vue +0 -143
- package/dist/src-vue/mac-window/Basic.vue +0 -9
- package/dist/src-vue/mac-window/CustomHeight.vue +0 -13
- package/dist/src-vue/mac-window/WithEvents.vue +0 -40
- package/dist/src-vue/mac-window/WithSidebar.vue +0 -31
- package/dist/src-vue/mac-window/WithTabs.vue +0 -26
- package/dist/src-vue/mac-window/WithToolbar.vue +0 -44
package/dist/index-vue.ts
CHANGED
@@ -29,8 +29,8 @@ export * from './src-vue/icons/index';
|
|
29
29
|
export * from './src-vue/list/index';
|
30
30
|
|
31
31
|
// Windows
|
32
|
-
|
33
|
-
|
32
|
+
export * from './src-vue/mac-window/index';
|
33
|
+
export * from './src-vue/iPhone/index';
|
34
34
|
|
35
35
|
// SmartLink
|
36
36
|
// export { default as SmartLink } from './vue/SmartLink.vue';
|
@@ -116,7 +116,7 @@ const {
|
|
116
116
|
</p>
|
117
117
|
)}
|
118
118
|
|
119
|
-
<div class="cosy:relative cosy:p-4 cosy:bg-gradient-to-br cosy:from-red-100 cosy:to-green-300 cosy:rounded-b">
|
119
|
+
<div class="cosy:relative cosy:p-4 cosy:bg-gradient-to-br cosy:from-red-100 cosy:to-green-300 cosy:dark:from-red-900/20 cosy:dark:to-green-900/20 cosy:rounded-b">
|
120
120
|
<div class="cosy:block cosy:code-example-panel" data-panel="preview">
|
121
121
|
<div
|
122
122
|
class={`cosy:code-preview-area ${resetStyles ? 'cosy:reset-styles' : ''}`}
|
@@ -142,6 +142,7 @@
|
|
142
142
|
* @prop {Array<Link>} links - 链接按钮数组
|
143
143
|
* @prop {string} links[].text - 链接按钮的文本
|
144
144
|
* @prop {string} links[].href - 链接按钮的目标地址
|
145
|
+
* @prop {string} links[].variant - 链接按钮的变体,可选值:"primary", "secondary", "accent", "info", "success", "warning", "error"
|
145
146
|
* @prop {string} [background="gradient"] - 背景样式,可选值:"gradient", "plain"
|
146
147
|
* @prop {string} [align="center"] - 内容对齐方式,可选值:"center", "left", "right"
|
147
148
|
* @prop {string} [imagePosition="right"] - 图片位置,可选值:"right", "left", "top", "bottom"
|
@@ -151,11 +152,19 @@
|
|
151
152
|
*/
|
152
153
|
|
153
154
|
import '../../style.ts';
|
154
|
-
import {
|
155
|
+
import { Button } from '../../index-astro';
|
155
156
|
|
156
157
|
interface Link {
|
157
158
|
text: string;
|
158
159
|
href: string;
|
160
|
+
variant:
|
161
|
+
| 'primary'
|
162
|
+
| 'secondary'
|
163
|
+
| 'accent'
|
164
|
+
| 'info'
|
165
|
+
| 'success'
|
166
|
+
| 'warning'
|
167
|
+
| 'error';
|
159
168
|
}
|
160
169
|
|
161
170
|
interface Props {
|
@@ -263,12 +272,12 @@ const titleClasses = [
|
|
263
272
|
].join(' ');
|
264
273
|
|
265
274
|
const descriptionClasses = [
|
266
|
-
'cosy:text-xl',
|
275
|
+
'cosy:text-xl cosy:prose',
|
267
276
|
'cosy:max-w-3xl',
|
268
277
|
'cosy:mb-8',
|
269
278
|
backgroundImage &&
|
270
279
|
(backgroundOverlay === 'dark' || backgroundOverlay === 'gradient')
|
271
|
-
? 'cosy:
|
280
|
+
? 'cosy:opacity-90'
|
272
281
|
: 'cosy:opacity-80',
|
273
282
|
].join(' ');
|
274
283
|
|
@@ -339,7 +348,7 @@ const contentOrder = {
|
|
339
348
|
|
340
349
|
<div
|
341
350
|
class={contentOrder[imagePosition] +
|
342
|
-
' cosy:flex cosy:flex-col cosy:w-full ' +
|
351
|
+
' cosy:flex cosy:flex-col cosy:w-full not-prose cosy:not-prose' +
|
343
352
|
(align === 'center' ? 'cosy:text-center cosy:items-center' : '') +
|
344
353
|
(align === 'left' ? 'cosy:text-left cosy:items-start' : '') +
|
345
354
|
(align === 'right' ? 'cosy:text-right cosy:items-end' : '')}>
|
@@ -359,20 +368,9 @@ const contentOrder = {
|
|
359
368
|
<div class={linksContainerClasses}>
|
360
369
|
{
|
361
370
|
links.map((link: Link) => (
|
362
|
-
<
|
363
|
-
href={link.href}
|
364
|
-
external
|
365
|
-
variant={
|
366
|
-
backgroundImage &&
|
367
|
-
(backgroundOverlay === 'dark' ||
|
368
|
-
backgroundOverlay === 'gradient')
|
369
|
-
? 'light'
|
370
|
-
: 'cta'
|
371
|
-
}
|
372
|
-
animation="hover-lift"
|
373
|
-
size="lg">
|
371
|
+
<Button href={link.href} variant={link.variant} size="lg">
|
374
372
|
{link.text}
|
375
|
-
</
|
373
|
+
</Button>
|
376
374
|
))
|
377
375
|
}
|
378
376
|
</div>
|
@@ -0,0 +1,121 @@
|
|
1
|
+
<!--
|
2
|
+
@component StatusBarContent
|
3
|
+
|
4
|
+
@description
|
5
|
+
StatusBarContent 组件显示 iPhone 状态栏的内容,包括时间、信号、WiFi 和电池图标。
|
6
|
+
组件会自动更新时间显示,并支持根据设备大小进行缩放。
|
7
|
+
|
8
|
+
@usage
|
9
|
+
基本用法:
|
10
|
+
```vue
|
11
|
+
<StatusBarContent />
|
12
|
+
```
|
13
|
+
|
14
|
+
带缩放比例:
|
15
|
+
```vue
|
16
|
+
<StatusBarContent :scaleRatio="1.5" />
|
17
|
+
```
|
18
|
+
|
19
|
+
@props
|
20
|
+
@prop {Number} [scaleRatio=1] - 缩放比例,用于根据设备大小调整文字和图标大小
|
21
|
+
@slots
|
22
|
+
@emits
|
23
|
+
-->
|
24
|
+
<script lang="ts">
|
25
|
+
import { defineComponent, ref, onMounted, onUnmounted, computed } from 'vue';
|
26
|
+
import { IPhoneSignalIcon, IPhoneWifiIcon, IPhoneBatteryIcon } from '../icons';
|
27
|
+
import '../../style.ts';
|
28
|
+
|
29
|
+
export default defineComponent({
|
30
|
+
name: 'StatusBarContent',
|
31
|
+
components: {
|
32
|
+
IPhoneSignalIcon,
|
33
|
+
IPhoneWifiIcon,
|
34
|
+
IPhoneBatteryIcon,
|
35
|
+
},
|
36
|
+
props: {
|
37
|
+
scaleRatio: {
|
38
|
+
type: Number,
|
39
|
+
default: 1,
|
40
|
+
},
|
41
|
+
},
|
42
|
+
setup(props) {
|
43
|
+
const currentTime = ref('12:00');
|
44
|
+
|
45
|
+
// 更新时间的函数
|
46
|
+
const updateTime = () => {
|
47
|
+
const now = new Date();
|
48
|
+
const hours = now.getHours().toString().padStart(2, '0');
|
49
|
+
const minutes = now.getMinutes().toString().padStart(2, '0');
|
50
|
+
currentTime.value = `${hours}:${minutes}`;
|
51
|
+
};
|
52
|
+
|
53
|
+
// 计算缩放后的字体大小
|
54
|
+
const scaledFontSize = computed(() => {
|
55
|
+
const baseFontSize = 14; // 基础字体大小
|
56
|
+
return `${baseFontSize * props.scaleRatio}px`;
|
57
|
+
});
|
58
|
+
|
59
|
+
// 计算缩放后的图标尺寸
|
60
|
+
const scaledIconSize = computed(() => {
|
61
|
+
const baseIconSize = 15; // 基础图标宽度
|
62
|
+
return `${baseIconSize * props.scaleRatio}px`;
|
63
|
+
});
|
64
|
+
|
65
|
+
// 计算缩放后的图标高度百分比
|
66
|
+
const scaledIconHeight = computed(() => {
|
67
|
+
const baseHeight = 60; // 基础高度百分比
|
68
|
+
return `${baseHeight * props.scaleRatio}%`;
|
69
|
+
});
|
70
|
+
|
71
|
+
// 设置定时器更新时间
|
72
|
+
let timeInterval: number;
|
73
|
+
onMounted(() => {
|
74
|
+
updateTime();
|
75
|
+
timeInterval = window.setInterval(updateTime, 60000); // 每分钟更新一次
|
76
|
+
});
|
77
|
+
|
78
|
+
onUnmounted(() => {
|
79
|
+
if (timeInterval) {
|
80
|
+
clearInterval(timeInterval);
|
81
|
+
}
|
82
|
+
});
|
83
|
+
|
84
|
+
return {
|
85
|
+
currentTime,
|
86
|
+
scaledFontSize,
|
87
|
+
scaledIconSize,
|
88
|
+
scaledIconHeight,
|
89
|
+
};
|
90
|
+
},
|
91
|
+
});
|
92
|
+
</script>
|
93
|
+
|
94
|
+
<template>
|
95
|
+
<div class="cosy:flex cosy:items-center cosy:h-full cosy:justify-between">
|
96
|
+
<!-- 左侧时间 -->
|
97
|
+
<span class="cosy:font-medium time-text" :style="{ fontSize: scaledFontSize }">
|
98
|
+
{{ currentTime }}
|
99
|
+
</span>
|
100
|
+
|
101
|
+
<!-- 右侧状态图标 -->
|
102
|
+
<div class="cosy:flex cosy:flex-row cosy:items-center cosy:space-x-1 cosy:h-full">
|
103
|
+
<div :style="{ width: scaledIconSize, height: scaledIconHeight, minWidth: 0, minHeight: 0 }">
|
104
|
+
<IPhoneBatteryIcon />
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
</div>
|
108
|
+
</template>
|
109
|
+
|
110
|
+
<style scoped>
|
111
|
+
/* 确保图标渲染更平滑 */
|
112
|
+
svg {
|
113
|
+
shape-rendering: geometricPrecision;
|
114
|
+
}
|
115
|
+
|
116
|
+
/* 时间文字基础样式 */
|
117
|
+
.time-text {
|
118
|
+
line-height: 1;
|
119
|
+
transition: font-size 0.2s ease;
|
120
|
+
}
|
121
|
+
</style>
|
@@ -27,8 +27,30 @@ iPhoneWindow 组件模拟 iPhone 设备的外观,包含状态栏、时间显
|
|
27
27
|
</iPhoneWindow>
|
28
28
|
```
|
29
29
|
|
30
|
+
自定义高度:
|
31
|
+
```vue
|
32
|
+
<iPhoneWindow height="md">
|
33
|
+
<div>应用内容</div>
|
34
|
+
</iPhoneWindow>
|
35
|
+
```
|
36
|
+
|
37
|
+
使用较大高度:
|
38
|
+
```vue
|
39
|
+
<iPhoneWindow height="2xl">
|
40
|
+
<div>应用内容</div>
|
41
|
+
</iPhoneWindow>
|
42
|
+
```
|
43
|
+
|
30
44
|
@props
|
31
|
-
@prop {
|
45
|
+
@prop {'sm'|'md'|'lg'|'xl'|'2xl'|'3xl'|'4xl'|'5xl'} [height='lg'] - 窗口高度选项
|
46
|
+
- sm: 256px (h-64)
|
47
|
+
- md: 320px (h-80)
|
48
|
+
- lg: 384px (h-96) - 默认值
|
49
|
+
- xl: 480px
|
50
|
+
- 2xl: 560px
|
51
|
+
- 3xl: 640px
|
52
|
+
- 4xl: 720px
|
53
|
+
- 5xl: 800px
|
32
54
|
@prop {String} [title=''] - 窗口标题
|
33
55
|
@prop {Array} [statusBarButtons=[]] - 状态栏按钮数组
|
34
56
|
@prop {Boolean} [withShadow=true] - 是否显示阴影效果
|
@@ -43,205 +65,170 @@ iPhoneWindow 组件模拟 iPhone 设备的外观,包含状态栏、时间显
|
|
43
65
|
<script lang="ts">
|
44
66
|
import '../../style.ts';
|
45
67
|
import { AlertDialog } from '../../index-vue.ts';
|
46
|
-
import { ref,
|
47
|
-
// 导入内部图片资源
|
68
|
+
import { ref, defineComponent } from 'vue';
|
48
69
|
import iphoneFrame from './assets/iPhone 14 Pro - Deep Purple - Portrait.png';
|
70
|
+
import StatusBarContent from './StatusBarContent.vue';
|
71
|
+
|
72
|
+
// iPhone边框图片-宽度
|
73
|
+
const iphoneFrameWidth = 1339;
|
74
|
+
// iPhone边框图片-高度
|
75
|
+
const iphoneFrameHeight = 2716;
|
76
|
+
// iPhone边框图片-状态栏离上边框的距离
|
77
|
+
const iphoneFrameStatusBarTop = 115;
|
78
|
+
// iPhone边框图片-状态栏高度
|
79
|
+
const iphoneFrameStatusBarHeight = 110;
|
80
|
+
|
81
|
+
// 比例-总宽度
|
82
|
+
const mainContentWidthAspectRatio = 1179 / iphoneFrameWidth;
|
83
|
+
// 比例-总高度
|
84
|
+
const mainContentHeightAspectRatio = 2556 / iphoneFrameHeight;
|
85
|
+
// 比例-状态栏高度
|
86
|
+
const iphoneFrameStatusBarHeightAspectRatio = iphoneFrameStatusBarHeight / iphoneFrameHeight;
|
87
|
+
// 比例-状态栏离上边框的距离
|
88
|
+
const iphoneFrameStatusBarTopAspectRatio = iphoneFrameStatusBarTop / iphoneFrameHeight;
|
89
|
+
|
90
|
+
// 预定义的高度选项
|
91
|
+
type HeightOption = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl';
|
92
|
+
|
93
|
+
const heightClasses: Record<HeightOption, string> = {
|
94
|
+
sm: 'cosy:h-64', // 256px
|
95
|
+
md: 'cosy:h-80', // 320px
|
96
|
+
lg: 'cosy:h-96', // 384px
|
97
|
+
xl: 'cosy:h-[480px]', // 480px
|
98
|
+
'2xl': 'cosy:h-[560px]', // 560px
|
99
|
+
'3xl': 'cosy:h-[640px]', // 640px
|
100
|
+
'4xl': 'cosy:h-[720px]', // 720px
|
101
|
+
'5xl': 'cosy:h-[800px]', // 800px
|
102
|
+
};
|
49
103
|
|
50
104
|
export default defineComponent({
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
props: {
|
56
|
-
height: {
|
57
|
-
type: String,
|
58
|
-
default: 'h-96',
|
59
|
-
},
|
60
|
-
title: {
|
61
|
-
type: String,
|
62
|
-
default: '',
|
63
|
-
},
|
64
|
-
statusBarButtons: {
|
65
|
-
type: Array,
|
66
|
-
default: () => [],
|
105
|
+
name: 'iPhoneWindow',
|
106
|
+
components: {
|
107
|
+
AlertDialog,
|
108
|
+
StatusBarContent,
|
67
109
|
},
|
68
|
-
|
69
|
-
|
70
|
-
|
110
|
+
props: {
|
111
|
+
height: {
|
112
|
+
type: String as () => HeightOption,
|
113
|
+
default: 'lg',
|
114
|
+
validator: (value: string) => {
|
115
|
+
return Object.keys(heightClasses).includes(value);
|
116
|
+
},
|
117
|
+
},
|
118
|
+
debug: {
|
119
|
+
type: Boolean,
|
120
|
+
default: false,
|
121
|
+
},
|
122
|
+
title: {
|
123
|
+
type: String,
|
124
|
+
default: '',
|
125
|
+
},
|
126
|
+
statusBarButtons: {
|
127
|
+
type: Array,
|
128
|
+
default: () => [],
|
129
|
+
},
|
130
|
+
withShadow: {
|
131
|
+
type: Boolean,
|
132
|
+
default: true,
|
133
|
+
},
|
134
|
+
showFrame: {
|
135
|
+
type: Boolean,
|
136
|
+
default: true,
|
137
|
+
},
|
138
|
+
backgroundColor: {
|
139
|
+
type: String,
|
140
|
+
default: '',
|
141
|
+
},
|
71
142
|
},
|
72
|
-
|
73
|
-
|
74
|
-
|
143
|
+
setup(props) {
|
144
|
+
const showAlertDialog = ref(false);
|
145
|
+
const alertMessage = ref('');
|
146
|
+
|
147
|
+
// 获取图片URL
|
148
|
+
const frameSrc =
|
149
|
+
typeof iphoneFrame === 'string' ? iphoneFrame : iphoneFrame.src;
|
150
|
+
|
151
|
+
// 计算当前高度的缩放比例
|
152
|
+
const getScaleRatio = () => {
|
153
|
+
const heightValues = {
|
154
|
+
sm: 256,
|
155
|
+
md: 320,
|
156
|
+
lg: 384,
|
157
|
+
xl: 480,
|
158
|
+
'2xl': 560,
|
159
|
+
'3xl': 640,
|
160
|
+
'4xl': 720,
|
161
|
+
'5xl': 800,
|
162
|
+
};
|
163
|
+
const currentHeight = heightValues[props.height];
|
164
|
+
// 基于特定高度计算缩放比例
|
165
|
+
return currentHeight / 500;
|
166
|
+
};
|
167
|
+
|
168
|
+
return {
|
169
|
+
showAlertDialog,
|
170
|
+
alertMessage,
|
171
|
+
frameSrc,
|
172
|
+
heightClasses,
|
173
|
+
mainContentWidthAspectRatio,
|
174
|
+
mainContentHeightAspectRatio,
|
175
|
+
iphoneFrameWidth,
|
176
|
+
iphoneFrameHeight,
|
177
|
+
iphoneFrameStatusBarTop,
|
178
|
+
iphoneFrameStatusBarHeight,
|
179
|
+
iphoneFrameStatusBarHeightAspectRatio,
|
180
|
+
iphoneFrameStatusBarTopAspectRatio,
|
181
|
+
getScaleRatio,
|
182
|
+
};
|
75
183
|
},
|
76
|
-
backgroundColor: {
|
77
|
-
type: String,
|
78
|
-
default: '',
|
79
|
-
},
|
80
|
-
},
|
81
|
-
setup() {
|
82
|
-
const showAlertDialog = ref(false);
|
83
|
-
const alertMessage = ref('');
|
84
|
-
const currentTime = ref('12:00');
|
85
|
-
|
86
|
-
// 获取图片URL
|
87
|
-
const frameSrc =
|
88
|
-
typeof iphoneFrame === 'string' ? iphoneFrame : iphoneFrame.src;
|
89
|
-
|
90
|
-
// 更新时间的函数
|
91
|
-
const updateTime = () => {
|
92
|
-
const now = new Date();
|
93
|
-
const hours = now.getHours().toString().padStart(2, '0');
|
94
|
-
const minutes = now.getMinutes().toString().padStart(2, '0');
|
95
|
-
currentTime.value = `${hours}:${minutes}`;
|
96
|
-
};
|
97
|
-
|
98
|
-
// 设置定时器更新时间
|
99
|
-
let timeInterval: number;
|
100
|
-
onMounted(() => {
|
101
|
-
updateTime();
|
102
|
-
timeInterval = window.setInterval(updateTime, 60000); // 每分钟更新一次
|
103
|
-
});
|
104
|
-
|
105
|
-
onUnmounted(() => {
|
106
|
-
if (timeInterval) {
|
107
|
-
clearInterval(timeInterval);
|
108
|
-
}
|
109
|
-
});
|
110
|
-
|
111
|
-
return {
|
112
|
-
showAlertDialog,
|
113
|
-
alertMessage,
|
114
|
-
currentTime,
|
115
|
-
frameSrc,
|
116
|
-
};
|
117
|
-
},
|
118
184
|
});
|
119
185
|
</script>
|
120
186
|
|
121
187
|
<template>
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
alt="iPhone frame"
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
<div class="cosy:flex cosy:items-center cosy:space-x-1.5">
|
164
|
-
<!-- 信号图标 -->
|
165
|
-
<svg
|
166
|
-
class="cosy:w-5 cosy:h-3.5 cosy:text-gray-700 cosy:dark:text-gray-200"
|
167
|
-
viewBox="0 0 20 12"
|
168
|
-
fill="none"
|
169
|
-
stroke="currentColor"
|
170
|
-
>
|
171
|
-
<path
|
172
|
-
d="M1 11h2V6H1v5zm4 0h2V4H5v7zm4 0h2V2H9v9zm4 0h2V0h-2v11z"
|
173
|
-
fill="currentColor"
|
174
|
-
/>
|
175
|
-
<path
|
176
|
-
d="M17 11h2V0h-2v11z"
|
177
|
-
fill="currentColor"
|
178
|
-
opacity="0.4"
|
179
|
-
/>
|
180
|
-
</svg>
|
181
|
-
<!-- Wi-Fi图标 -->
|
182
|
-
<svg
|
183
|
-
class="cosy:w-5 cosy:h-4 cosy:text-gray-700 cosy:dark:text-gray-200"
|
184
|
-
viewBox="0 0 16 12"
|
185
|
-
fill="currentColor"
|
186
|
-
>
|
187
|
-
<path
|
188
|
-
d="M8 10.5a1 1 0 100-2 1 1 0 000 2zM4.25 7.25a5 5 0 017.5 0l-1.06 1.06a3.5 3.5 0 00-5.38 0L4.25 7.25z"
|
189
|
-
/>
|
190
|
-
<path
|
191
|
-
d="M1.75 4.75a8.5 8.5 0 0112.5 0l-1.06 1.06a7 7 0 00-10.38 0L1.75 4.75z"
|
192
|
-
/>
|
193
|
-
</svg>
|
194
|
-
<!-- 电池图标 -->
|
195
|
-
<div class="cosy:flex cosy:items-center cosy:space-x-0.5">
|
196
|
-
<svg
|
197
|
-
class="cosy:w-6 cosy:h-3.5 cosy:text-gray-700 cosy:dark:text-gray-200"
|
198
|
-
viewBox="0 0 25 12"
|
199
|
-
fill="none"
|
200
|
-
stroke="currentColor"
|
201
|
-
>
|
202
|
-
<rect
|
203
|
-
x="0.5"
|
204
|
-
y="0.5"
|
205
|
-
width="21"
|
206
|
-
height="11"
|
207
|
-
rx="2.5"
|
208
|
-
stroke-width="1"
|
209
|
-
/>
|
210
|
-
<rect
|
211
|
-
x="2"
|
212
|
-
y="2"
|
213
|
-
width="18"
|
214
|
-
height="8"
|
215
|
-
rx="1"
|
216
|
-
fill="currentColor"
|
217
|
-
/>
|
218
|
-
<path
|
219
|
-
d="M23 4h1a1 1 0 011 1v2a1 1 0 01-1 1h-1V4z"
|
220
|
-
fill="currentColor"
|
221
|
-
/>
|
222
|
-
</svg>
|
223
|
-
</div>
|
224
|
-
</div>
|
188
|
+
<div :class="['cosy:relative', heightClasses[height]]" :style="{
|
189
|
+
aspectRatio: `${iphoneFrameWidth}/${iphoneFrameHeight}`,
|
190
|
+
// 调试模式,背景色为半透明的黄色
|
191
|
+
backgroundColor: debug ? 'rgba(255, 255, 0, 0.3)' : 'transparent',
|
192
|
+
}">
|
193
|
+
<!-- iPhone 边框 -->
|
194
|
+
<img v-if="showFrame" style="max-width: 100%; max-height: 100%;" :src="frameSrc" alt="iPhone frame" />
|
195
|
+
|
196
|
+
<!-- 顶部状态栏 -->
|
197
|
+
<div :style="{
|
198
|
+
position: 'absolute',
|
199
|
+
top: iphoneFrameStatusBarTopAspectRatio * 100 + '%',
|
200
|
+
height: iphoneFrameStatusBarHeightAspectRatio * 100 + '%',
|
201
|
+
width: mainContentWidthAspectRatio * 100 + '%',
|
202
|
+
left: '50%',
|
203
|
+
transform: 'translate(-50%, 0)',
|
204
|
+
paddingLeft: '5%',
|
205
|
+
paddingRight: '5%',
|
206
|
+
// 调试模式,背景色为半透明的红色
|
207
|
+
backgroundColor: debug ? 'rgba(255, 0, 0, 0.3)' : 'transparent',
|
208
|
+
zIndex: 10,
|
209
|
+
}">
|
210
|
+
<StatusBarContent :scaleRatio="getScaleRatio()" />
|
211
|
+
</div>
|
212
|
+
|
213
|
+
<!-- 内容区域 -->
|
214
|
+
<div class="cosy:inset-0 cosy:h-full" :style="{
|
215
|
+
width: mainContentWidthAspectRatio * 100 + '%',
|
216
|
+
height: mainContentHeightAspectRatio * 100 + '%',
|
217
|
+
// 水平居中
|
218
|
+
left: '50%',
|
219
|
+
// 垂直居中
|
220
|
+
top: '50%',
|
221
|
+
transform: 'translate(-50%, -50%)',
|
222
|
+
position: 'absolute',
|
223
|
+
// 调试模式,背景色为半透明的蓝色
|
224
|
+
backgroundColor: debug ? 'rgba(0, 0, 255, 0.3)' : 'transparent',
|
225
|
+
zIndex: 10,
|
226
|
+
}">
|
227
|
+
<div :class="[debug ? 'cosy:bg-green-300/50' : '', 'cosy:h-full cosy:w-full cosy:overflow-hidden']">
|
228
|
+
<slot />
|
225
229
|
</div>
|
226
|
-
</div>
|
227
|
-
|
228
|
-
<!-- 主要内容区域 -->
|
229
|
-
<div
|
230
|
-
class="cosy:flex-1 cosy:flex cosy:flex-col cosy:overflow-hidden cosy:relative"
|
231
|
-
>
|
232
|
-
<slot />
|
233
|
-
</div>
|
234
230
|
</div>
|
235
|
-
</div>
|
236
231
|
</div>
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
</template>
|
241
|
-
|
242
|
-
<style scoped>
|
243
|
-
/* 确保图标渲染更平滑 */
|
244
|
-
svg {
|
245
|
-
shape-rendering: geometricPrecision;
|
246
|
-
}
|
247
|
-
</style>
|
232
|
+
|
233
|
+
<AlertDialog v-model="showAlertDialog" :message="alertMessage" />
|
234
|
+
</template>
|
@@ -1,31 +1,2 @@
|
|
1
|
-
import Basic from './Basic.vue';
|
2
|
-
import WeatherApp from './WeatherApp.vue';
|
3
|
-
import NoFrame from './NoFrame.vue';
|
4
|
-
import CustomBackground from './CustomBackground.vue';
|
5
|
-
import BasicSource from './Basic.vue?raw';
|
6
|
-
import NoFrameSource from './NoFrame.vue?raw';
|
7
|
-
import CustomBackgroundSource from './CustomBackground.vue?raw';
|
8
|
-
import WeatherAppSource from './WeatherApp.vue?raw';
|
9
|
-
import { extractSimpleExample } from '../../utils/component';
|
10
|
-
|
11
1
|
// 导出主组件
|
12
|
-
export { default as iPhoneWindow } from './iPhoneWindow.vue';
|
13
|
-
|
14
|
-
// 将示例组件整合为一个对象导出
|
15
|
-
export const iPhoneWindowExamples = {
|
16
|
-
Basic,
|
17
|
-
WeatherApp,
|
18
|
-
NoFrame,
|
19
|
-
CustomBackground,
|
20
|
-
};
|
21
|
-
|
22
|
-
// 导出示例组件的源代码(简化版本)
|
23
|
-
export const iPhoneWindowExampleCodes = {
|
24
|
-
Basic: extractSimpleExample(BasicSource, 'iPhoneWindow'),
|
25
|
-
NoFrame: extractSimpleExample(NoFrameSource, 'iPhoneWindow'),
|
26
|
-
CustomBackground: extractSimpleExample(
|
27
|
-
CustomBackgroundSource,
|
28
|
-
'iPhoneWindow'
|
29
|
-
),
|
30
|
-
WeatherApp: extractSimpleExample(WeatherAppSource, 'iPhoneWindow'),
|
31
|
-
};
|
2
|
+
export { default as iPhoneWindow } from './iPhoneWindow.vue';
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<template>
|
2
|
+
<svg width="100%" height="100%" viewBox="0 0 25 12" fill="none" stroke="currentColor" style="display: block;">
|
3
|
+
<rect x="0.5" y="0.5" width="21" height="11" rx="2.5" stroke-width="1" />
|
4
|
+
<rect x="2" y="2" width="18" height="8" rx="1" fill="currentColor" />
|
5
|
+
<path d="M23 4h1a1 1 0 011 1v2a1 1 0 01-1 1h-1V4z" fill="currentColor" />
|
6
|
+
</svg>
|
7
|
+
</template>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<template>
|
2
|
+
<svg width="100%" height="100%" viewBox="0 0 20 12" fill="none" stroke="currentColor" style="display: block;">
|
3
|
+
<path d="M1 11h2V6H1v5zm4 0h2V4H5v7zm4 0h2V2H9v9zm4 0h2V0h-2v11z" fill="currentColor" />
|
4
|
+
<path d="M17 11h2V0h-2v11z" fill="currentColor" opacity="0.4" />
|
5
|
+
</svg>
|
6
|
+
</template>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<template>
|
2
|
+
<svg width="100%" height="100%" viewBox="0 0 16 12" fill="currentColor" style="display: block;">
|
3
|
+
<path d="M8 10.5a1 1 0 100-2 1 1 0 000 2zM4.25 7.25a5 5 0 017.5 0l-1.06 1.06a3.5 3.5 0 00-5.38 0L4.25 7.25z" />
|
4
|
+
<path d="M1.75 4.75a8.5 8.5 0 0112.5 0l-1.06 1.06a7 7 0 00-10.38 0L1.75 4.75z" />
|
5
|
+
</svg>
|
6
|
+
</template>
|
@@ -17,3 +17,6 @@ export { default as SuccessIcon } from './SuccessIcon.vue';
|
|
17
17
|
export { default as UserIcon } from './UserIcon.vue';
|
18
18
|
export { default as WarningIcon } from './WarningIcon.vue';
|
19
19
|
export { default as XCircleIcon } from './XCircleIcon.vue';
|
20
|
+
export { default as IPhoneSignalIcon } from './IPhoneSignalIcon.vue';
|
21
|
+
export { default as IPhoneWifiIcon } from './IPhoneWifiIcon.vue';
|
22
|
+
export { default as IPhoneBatteryIcon } from './IPhoneBatteryIcon.vue';
|