py-test-components 1.0.1 → 1.0.2

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.
@@ -1,387 +1,48 @@
1
- <template>
2
- <div class="py-weather">
3
- <el-card class="weather-card" :body-style="{ padding: '0px' }">
4
- <!-- 加载状态 -->
5
- <div v-if="loading" class="loading-wrapper">
6
- <i class="el-icon-loading"></i>
7
- <span>加载天气数据...</span>
8
- </div>
9
-
10
- <!-- 错误状态 -->
11
- <div v-else-if="error" class="error-wrapper">
12
- <i class="el-icon-warning-outline"></i>
13
- <span>{{ error }}</span>
14
- <el-button type="text" @click="loadWeather">重试</el-button>
15
- </div>
16
-
17
- <!-- 天气内容 -->
18
- <div v-else class="weather-content">
19
- <!-- 头部:城市和日期 -->
20
- <div class="weather-header">
21
- <div class="location">
22
- <i class="el-icon-location"></i>
23
- <span class="city">{{ displayCity }}</span>
24
- </div>
25
- <div class="date">{{ currentDate }}</div>
26
- </div>
27
-
28
- <!-- 主体:温度和天气 -->
29
- <div class="weather-main">
30
- <div class="temperature">
31
- <span class="temp-value">{{ weatherData.temperature }}</span>
32
- <span class="temp-unit">°C</span>
33
- </div>
34
- <div class="weather-desc">
35
- <i :class="weatherIcon"></i>
36
- <span>{{ weatherData.description }}</span>
37
- </div>
38
- </div>
39
-
40
- <!-- 详情:湿度、风速等 -->
41
- <div class="weather-details">
42
- <div class="detail-item">
43
- <i class="el-icon-moisture"></i>
44
- <span class="label">湿度</span>
45
- <span class="value">{{ weatherData.humidity }}%</span>
46
- </div>
47
- <div class="detail-item">
48
- <i class="el-icon-wind-power"></i>
49
- <span class="label">风速</span>
50
- <span class="value">{{ weatherData.windSpeed }} km/h</span>
51
- </div>
52
- <div class="detail-item">
53
- <i class="el-icon-view"></i>
54
- <span class="label">能见度</span>
55
- <span class="value">{{ weatherData.visibility }} km</span>
56
- </div>
57
- </div>
58
-
59
- <!-- 预报 -->
60
- <div v-if="config.showForecast && forecast.length > 0" class="weather-forecast">
61
- <div class="forecast-title">未来预报</div>
62
- <div class="forecast-list">
63
- <div
64
- v-for="(item, index) in forecast"
65
- :key="index"
66
- class="forecast-item"
67
- >
68
- <span class="day">{{ item.day }}</span>
69
- <i :class="getWeatherIcon(item.weather)"></i>
70
- <span class="temp">{{ item.low }}° - {{ item.high }}°</span>
71
- </div>
72
- </div>
73
- </div>
74
- </div>
75
- </el-card>
76
- </div>
77
- </template>
78
-
79
- <script>
80
- import store from '../store';
81
- import { weatherApi } from '../utils/api';
82
-
83
- export default {
84
- name: 'PyWeather',
85
-
86
- props: {
87
- propData: {
88
- default: null
89
- }
90
- },
91
-
92
- data() {
93
- return {
94
- loading: false,
95
- error: '',
96
- weatherData: {
97
- temperature: '--',
98
- description: '--',
99
- humidity: '--',
100
- windSpeed: '--',
101
- visibility: '--'
102
- },
103
- forecast: []
104
- };
105
- },
106
-
107
- computed: {
108
- config() {
109
- return this.propData || {};
110
- },
111
-
112
- displayCity() {
113
- return this.config.city || this.weatherData.city || '北京';
114
- },
115
-
116
- currentDate() {
117
- const date = new Date();
118
- const options = {
119
- year: 'numeric',
120
- month: 'long',
121
- day: 'numeric',
122
- weekday: 'long'
123
- };
124
- return date.toLocaleDateString('zh-CN', options);
125
- },
126
-
127
- weatherIcon() {
128
- const iconMap = {
129
- '晴': 'el-icon-sunny',
130
- '多云': 'el-icon-cloudy-and-sunny',
131
- '阴': 'el-icon-cloudy',
132
- '雨': 'el-icon-heavy-rain',
133
- '雪': 'el-icon-light-snow',
134
- '雾': 'el-icon-foggy',
135
- '霾': 'el-icon-foggy'
136
- };
137
- return iconMap[this.weatherData.description] || 'el-icon-sunny';
138
- }
139
- },
140
-
141
- mounted() {
142
- this.loadWeather();
143
- },
144
-
145
- watch: {
146
- 'config.city': {
147
- handler() {
148
- this.loadWeather();
149
- }
150
- }
151
- },
152
-
153
- methods: {
154
- // 加载天气数据
155
- async loadWeather() {
156
- // 如果有传入的模拟数据,直接使用
157
- if (this.config.mockData) {
158
- this.weatherData = { ...this.config.mockData };
159
- if (this.config.forecast) {
160
- this.forecast = this.config.forecast;
161
- }
162
- return;
163
- }
164
-
165
- try {
166
- this.loading = true;
167
- this.error = '';
168
-
169
- const city = this.config.city || '北京';
170
-
171
- // 获取当前天气
172
- const currentRes = await weatherApi.getWeather(city);
173
- this.weatherData = {
174
- city: city,
175
- temperature: currentRes.temperature || 25,
176
- description: currentRes.weather || '晴',
177
- humidity: currentRes.humidity || 60,
178
- windSpeed: currentRes.windSpeed || 10,
179
- visibility: currentRes.visibility || 10,
180
- ...currentRes
181
- };
182
-
183
- // 获取预报
184
- if (this.config.showForecast) {
185
- const forecastRes = await weatherApi.getForecast(city);
186
- this.forecast = forecastRes.data || this.getDefaultForecast();
187
- }
188
-
189
- // 触发加载完成事件
190
- this.$emit('load', this.weatherData);
191
- } catch (err) {
192
- console.error('[PyWeather] 加载天气失败:', err);
193
- this.error = '获取天气数据失败';
194
- this.$emit('error', err);
195
- } finally {
196
- this.loading = false;
197
- }
198
- },
199
-
200
- // 获取默认预报数据
201
- getDefaultForecast() {
202
- const days = ['明天', '后天', '周三', '周四', '周五'];
203
- return days.map(day => ({
204
- day,
205
- weather: '晴',
206
- high: 28,
207
- low: 18
208
- }));
209
- },
210
-
211
- // 获取天气图标
212
- getWeatherIcon(weather) {
213
- const iconMap = {
214
- '晴': 'el-icon-sunny',
215
- '多云': 'el-icon-cloudy-and-sunny',
216
- '阴': 'el-icon-cloudy',
217
- '雨': 'el-icon-heavy-rain',
218
- '雪': 'el-icon-light-snow'
219
- };
220
- return iconMap[weather] || 'el-icon-sunny';
221
- }
222
- }
223
- };
224
- </script>
225
-
226
- <style scoped>
227
- .py-weather {
228
- width: 100%;
229
- max-width: 400px;
230
- }
231
-
232
- .weather-card {
233
- border-radius: 12px;
234
- overflow: hidden;
235
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
236
- }
237
-
238
- .loading-wrapper,
239
- .error-wrapper {
240
- padding: 40px;
241
- text-align: center;
242
- color: #909399;
243
- }
244
-
245
- .error-wrapper i {
246
- font-size: 48px;
247
- color: #F56C6C;
248
- display: block;
249
- margin-bottom: 16px;
250
- }
251
-
252
- .loading-wrapper i {
253
- font-size: 32px;
254
- margin-right: 8px;
255
- }
256
-
257
- .weather-content {
258
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
259
- color: white;
260
- padding: 24px;
261
- }
262
-
263
- .weather-header {
264
- display: flex;
265
- justify-content: space-between;
266
- align-items: center;
267
- margin-bottom: 24px;
268
- }
269
-
270
- .location {
271
- display: flex;
272
- align-items: center;
273
- font-size: 18px;
274
- }
275
-
276
- .location i {
277
- margin-right: 8px;
278
- }
279
-
280
- .city {
281
- font-weight: 500;
282
- }
283
-
284
- .date {
285
- font-size: 14px;
286
- opacity: 0.9;
287
- }
288
-
289
- .weather-main {
290
- text-align: center;
291
- margin-bottom: 24px;
292
- }
293
-
294
- .temperature {
295
- display: flex;
296
- align-items: flex-start;
297
- justify-content: center;
298
- }
299
-
300
- .temp-value {
301
- font-size: 72px;
302
- font-weight: 300;
303
- line-height: 1;
304
- }
305
-
306
- .temp-unit {
307
- font-size: 24px;
308
- margin-top: 8px;
309
- opacity: 0.8;
310
- }
311
-
312
- .weather-desc {
313
- margin-top: 12px;
314
- font-size: 18px;
315
- opacity: 0.9;
316
- }
317
-
318
- .weather-desc i {
319
- font-size: 24px;
320
- margin-right: 8px;
321
- }
322
-
323
- .weather-details {
324
- display: flex;
325
- justify-content: space-around;
326
- padding: 16px 0;
327
- border-top: 1px solid rgba(255, 255, 255, 0.2);
328
- border-bottom: 1px solid rgba(255, 255, 255, 0.2);
329
- }
330
-
331
- .detail-item {
332
- display: flex;
333
- flex-direction: column;
334
- align-items: center;
335
- gap: 4px;
336
- }
337
-
338
- .detail-item i {
339
- font-size: 20px;
340
- opacity: 0.8;
341
- }
342
-
343
- .detail-item .label {
344
- font-size: 12px;
345
- opacity: 0.7;
346
- }
347
-
348
- .detail-item .value {
349
- font-size: 14px;
350
- font-weight: 500;
351
- }
352
-
353
- .weather-forecast {
354
- margin-top: 16px;
355
- }
356
-
357
- .forecast-title {
358
- font-size: 14px;
359
- margin-bottom: 12px;
360
- opacity: 0.9;
361
- }
362
-
363
- .forecast-list {
364
- display: flex;
365
- justify-content: space-between;
366
- }
367
-
368
- .forecast-item {
369
- display: flex;
370
- flex-direction: column;
371
- align-items: center;
372
- gap: 4px;
373
- font-size: 12px;
374
- }
375
-
376
- .forecast-item .day {
377
- opacity: 0.8;
378
- }
379
-
380
- .forecast-item i {
381
- font-size: 20px;
382
- }
383
-
384
- .forecast-item .temp {
385
- opacity: 0.9;
386
- }
387
- </style>
1
+ <template>
2
+ <div class="py-weather">
3
+ <el-input v-model="city" placeholder="请输入城市" />
4
+ <el-button @click="handleQuery" style="margin-left: 10px">查询天气</el-button>
5
+ <div v-if="weather" class="weather-result" style="margin-top: 20px">
6
+ <p>城市: {{ weather.city }}</p>
7
+ <p>天气: {{ weather.weather }}</p>
8
+ <p>温度: {{ weather.temperature }}°C</p>
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <script>
14
+ import { queryWeather } from '../utils/api';
15
+
16
+ export default {
17
+ name: 'PyWeather',
18
+ props: {
19
+ propData: {
20
+ default: null,
21
+ },
22
+ },
23
+ data() {
24
+ return {
25
+ city: '',
26
+ weather: null,
27
+ };
28
+ },
29
+ methods: {
30
+ async handleQuery() {
31
+ if (!this.city) return;
32
+ try {
33
+ const result = await queryWeather(this.city);
34
+ this.weather = result;
35
+ this.$emit('change', result);
36
+ } catch (e) {
37
+ console.error('查询天气失败', e);
38
+ }
39
+ },
40
+ },
41
+ };
42
+ </script>
43
+
44
+ <style scoped>
45
+ .py-weather {
46
+ padding: 20px;
47
+ }
48
+ </style>
package/src/index.js CHANGED
@@ -1,51 +1,20 @@
1
- import Vue from 'vue';
2
- import VueCustomElement from 'vue-custom-element';
3
- import ElementUI from 'element-ui';
4
- import 'element-ui/lib/theme-chalk/index.css';
5
-
6
- // 引入组件
7
- import PyTable from './components/PyTable.vue';
8
- import PyWeather from './components/PyWeather.vue';
9
-
10
- // 引入 store
11
- import store from './store';
12
-
13
- // 使用插件
14
- Vue.use(ElementUI);
15
- Vue.use(VueCustomElement);
16
-
17
- // 注册 Web Components(必须禁用 Shadow DOM)
18
- Vue.customElement('py-table', PyTable, {
19
- shadow: false
20
- });
21
-
22
- Vue.customElement('py-weather', PyWeather, {
23
- shadow: false
24
- });
25
-
26
- // initStore 函数 - 外部唯一入口
27
- function initStore(config) {
28
- if (!config || typeof config !== 'object') {
29
- console.warn('[PyComponent] initStore 需要传入配置对象');
30
- return;
31
- }
32
-
33
- // 将配置设置到 store 中
34
- Object.keys(config).forEach(key => {
35
- store.set(key, config[key]);
36
- });
37
-
38
- console.log('[PyComponent] Store 已初始化');
39
- }
40
-
41
- // 挂载到 window(浏览器环境)
42
- if (typeof window !== 'undefined') {
43
- window.PyComponent = {
44
- initStore
45
- // 注意:不暴露 store 实例
46
- };
47
- }
48
-
49
- // 默认导出
50
- export { initStore };
51
- export default { initStore };
1
+ import Vue from 'vue';
2
+ import ElementUI from 'element-ui';
3
+ import 'element-ui/lib/theme-chalk/index.css';
4
+
5
+ import PyTable from './components/PyTable.vue';
6
+ import PyWeather from './components/PyWeather.vue';
7
+ import store from './store';
8
+ import { initStore } from './vue/index.js';
9
+
10
+ Vue.use(ElementUI);
11
+
12
+ // 注册 Web Components
13
+ Vue.customElement('py-table', PyTable, { shadow: false });
14
+ Vue.customElement('py-weather', PyWeather, { shadow: false });
15
+
16
+ if (typeof window !== 'undefined') {
17
+ window.PyComponent = {
18
+ initStore,
19
+ };
20
+ }