py-test-components 1.0.0

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.
@@ -0,0 +1,35 @@
1
+ /*!
2
+ * Vue.js v2.7.16
3
+ * (c) 2014-2023 Evan You
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ /**
8
+ * vue-custom-element v3.3.0
9
+ * (c) 2021 Karol Fabjańczuk
10
+ * @license MIT
11
+ */
12
+
13
+ /**
14
+ * @license
15
+ * Lodash <https://lodash.com/>
16
+ * Copyright JS Foundation and other contributors <https://js.foundation/>
17
+ * Released under MIT license <https://lodash.com/license>
18
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
19
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
20
+ */
21
+
22
+ /**
23
+ * Checks if an event is supported in the current execution environment.
24
+ *
25
+ * NOTE: This will not work correctly for non-generic events such as `change`,
26
+ * `reset`, `load`, `error`, and `select`.
27
+ *
28
+ * Borrows from Modernizr.
29
+ *
30
+ * @param {string} eventNameSuffix Event name, e.g. "click".
31
+ * @param {?boolean} capture Check if the capture phase is supported.
32
+ * @return {boolean} True if the event is supported.
33
+ * @internal
34
+ * @license Modernizr 3.0.0pre (Custom Build) | MIT
35
+ */
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "py-test-components",
3
+ "version": "1.0.0",
4
+ "description": "跨框架组件库 - Vue 2 组件可被 React 使用",
5
+ "main": "dist/py-component.js",
6
+ "module": "dist/py-component.esm.js",
7
+ "files": [
8
+ "dist",
9
+ "src"
10
+ ],
11
+ "scripts": {
12
+ "build": "webpack --mode=production",
13
+ "dev": "webpack --mode=development --watch",
14
+ "clean": "rimraf dist"
15
+ },
16
+ "dependencies": {
17
+ "element-ui": "^2.15.14",
18
+ "vue": "^2.7.16",
19
+ "vue-custom-element": "^3.3.0"
20
+ },
21
+ "devDependencies": {
22
+ "@babel/core": "^7.23.0",
23
+ "@babel/preset-env": "^7.23.0",
24
+ "babel-loader": "^9.1.3",
25
+ "css-loader": "^6.8.1",
26
+ "rimraf": "^5.0.5",
27
+ "style-loader": "^3.3.3",
28
+ "vue-loader": "^15.10.1",
29
+ "vue-template-compiler": "^2.7.16",
30
+ "webpack": "^5.89.0",
31
+ "webpack-cli": "^5.1.4"
32
+ },
33
+ "keywords": [
34
+ "vue",
35
+ "react",
36
+ "web-components",
37
+ "component-library",
38
+ "element-ui"
39
+ ],
40
+ "author": "",
41
+ "license": "MIT"
42
+ }
@@ -0,0 +1,280 @@
1
+ <template>
2
+ <div class="py-table">
3
+ <el-card class="table-card">
4
+ <div slot="header" class="card-header">
5
+ <span class="title">{{ config.title || '数据表格' }}</span>
6
+ <div class="actions">
7
+ <el-button
8
+ v-if="config.showRefresh !== false"
9
+ type="text"
10
+ @click="refreshData"
11
+ icon="el-icon-refresh"
12
+ >
13
+ 刷新
14
+ </el-button>
15
+ </div>
16
+ </div>
17
+
18
+ <el-table
19
+ :data="tableData"
20
+ :stripe="config.stripe !== false"
21
+ :border="config.border === true"
22
+ :height="config.height"
23
+ v-loading="loading"
24
+ @selection-change="handleSelectionChange"
25
+ >
26
+ <!-- 选择列 -->
27
+ <el-table-column
28
+ v-if="config.showSelection"
29
+ type="selection"
30
+ width="55"
31
+ />
32
+
33
+ <!-- 序号列 -->
34
+ <el-table-column
35
+ v-if="config.showIndex !== false"
36
+ type="index"
37
+ label="序号"
38
+ width="60"
39
+ />
40
+
41
+ <!-- 动态列 -->
42
+ <el-table-column
43
+ v-for="column in columns"
44
+ :key="column.prop"
45
+ :prop="column.prop"
46
+ :label="column.label"
47
+ :width="column.width"
48
+ :min-width="column.minWidth"
49
+ :sortable="column.sortable"
50
+ >
51
+ <template slot-scope="scope">
52
+ <!-- 自定义渲染 -->
53
+ <span v-if="column.formatter">
54
+ {{ column.formatter(scope.row[column.prop], scope.row) }}
55
+ </span>
56
+ <span v-else-if="column.type === 'date'">
57
+ {{ formatDate(scope.row[column.prop]) }}
58
+ </span>
59
+ <span v-else-if="column.type === 'status'">
60
+ <el-tag :type="getStatusType(scope.row[column.prop])">
61
+ {{ scope.row[column.prop] }}
62
+ </el-tag>
63
+ </span>
64
+ <span v-else>
65
+ {{ scope.row[column.prop] }}
66
+ </span>
67
+ </template>
68
+ </el-table-column>
69
+
70
+ <!-- 操作列 -->
71
+ <el-table-column
72
+ v-if="config.showActions !== false"
73
+ label="操作"
74
+ width="150"
75
+ fixed="right"
76
+ >
77
+ <template slot-scope="scope">
78
+ <el-button
79
+ type="text"
80
+ size="small"
81
+ @click="handleEdit(scope.row)"
82
+ >
83
+ 编辑
84
+ </el-button>
85
+ <el-button
86
+ type="text"
87
+ size="small"
88
+ @click="handleDelete(scope.row)"
89
+ >
90
+ 删除
91
+ </el-button>
92
+ </template>
93
+ </el-table-column>
94
+ </el-table>
95
+
96
+ <!-- 分页 -->
97
+ <div v-if="config.pagination !== false" class="pagination-wrapper">
98
+ <el-pagination
99
+ :current-page="currentPage"
100
+ :page-size="pageSize"
101
+ :page-sizes="[10, 20, 50, 100]"
102
+ :total="total"
103
+ layout="total, sizes, prev, pager, next, jumper"
104
+ @size-change="handleSizeChange"
105
+ @current-change="handlePageChange"
106
+ />
107
+ </div>
108
+ </el-card>
109
+ </div>
110
+ </template>
111
+
112
+ <script>
113
+ import store from '../store';
114
+ import { tableApi } from '../utils/api';
115
+
116
+ export default {
117
+ name: 'PyTable',
118
+
119
+ props: {
120
+ propData: {
121
+ default: null
122
+ }
123
+ },
124
+
125
+ data() {
126
+ return {
127
+ tableData: [],
128
+ loading: false,
129
+ currentPage: 1,
130
+ pageSize: 10,
131
+ total: 0,
132
+ selectedRows: []
133
+ };
134
+ },
135
+
136
+ computed: {
137
+ config() {
138
+ return this.propData || {};
139
+ },
140
+
141
+ columns() {
142
+ return this.config.columns || [];
143
+ }
144
+ },
145
+
146
+ mounted() {
147
+ this.loadData();
148
+
149
+ // 监听 store 变化(如果需要)
150
+ const baseUrl = store.get('baseUrl');
151
+ if (baseUrl) {
152
+ console.log('[PyTable] baseUrl from store:', baseUrl);
153
+ }
154
+ },
155
+
156
+ methods: {
157
+ // 加载数据
158
+ async loadData() {
159
+ if (this.config.data) {
160
+ // 使用传入的数据
161
+ this.tableData = this.config.data;
162
+ this.total = this.tableData.length;
163
+ return;
164
+ }
165
+
166
+ // 通过 API 获取数据
167
+ if (this.config.api !== false) {
168
+ try {
169
+ this.loading = true;
170
+ const params = {
171
+ page: this.currentPage,
172
+ size: this.pageSize,
173
+ ...this.config.params
174
+ };
175
+
176
+ const res = await tableApi.getData(params);
177
+
178
+ // 支持自定义数据路径
179
+ const dataPath = this.config.dataPath || 'data';
180
+ const totalPath = this.config.totalPath || 'total';
181
+
182
+ this.tableData = this.getPathValue(res, dataPath) || [];
183
+ this.total = this.getPathValue(res, totalPath) || 0;
184
+ } catch (error) {
185
+ console.error('[PyTable] 加载数据失败:', error);
186
+ this.$message.error('加载数据失败');
187
+ } finally {
188
+ this.loading = false;
189
+ }
190
+ }
191
+ },
192
+
193
+ // 获取对象路径值
194
+ getPathValue(obj, path) {
195
+ return path.split('.').reduce((o, p) => o && o[p], obj);
196
+ },
197
+
198
+ // 刷新数据
199
+ refreshData() {
200
+ this.currentPage = 1;
201
+ this.loadData();
202
+ this.$emit('refresh');
203
+ },
204
+
205
+ // 分页大小变化
206
+ handleSizeChange(size) {
207
+ this.pageSize = size;
208
+ this.loadData();
209
+ this.$emit('size-change', size);
210
+ },
211
+
212
+ // 页码变化
213
+ handlePageChange(page) {
214
+ this.currentPage = page;
215
+ this.loadData();
216
+ this.$emit('page-change', page);
217
+ },
218
+
219
+ // 选择变化
220
+ handleSelectionChange(rows) {
221
+ this.selectedRows = rows;
222
+ this.$emit('selection-change', rows);
223
+ },
224
+
225
+ // 编辑
226
+ handleEdit(row) {
227
+ this.$emit('edit', row);
228
+ },
229
+
230
+ // 删除
231
+ handleDelete(row) {
232
+ this.$emit('delete', row);
233
+ },
234
+
235
+ // 格式化日期
236
+ formatDate(value) {
237
+ if (!value) return '';
238
+ const date = new Date(value);
239
+ return date.toLocaleDateString('zh-CN');
240
+ },
241
+
242
+ // 获取状态类型
243
+ getStatusType(status) {
244
+ const statusMap = {
245
+ 'active': 'success',
246
+ 'pending': 'warning',
247
+ 'disabled': 'info',
248
+ 'error': 'danger'
249
+ };
250
+ return statusMap[status] || '';
251
+ }
252
+ }
253
+ };
254
+ </script>
255
+
256
+ <style scoped>
257
+ .py-table {
258
+ width: 100%;
259
+ }
260
+
261
+ .table-card {
262
+ margin-bottom: 20px;
263
+ }
264
+
265
+ .card-header {
266
+ display: flex;
267
+ justify-content: space-between;
268
+ align-items: center;
269
+ }
270
+
271
+ .title {
272
+ font-size: 16px;
273
+ font-weight: 500;
274
+ }
275
+
276
+ .pagination-wrapper {
277
+ margin-top: 20px;
278
+ text-align: right;
279
+ }
280
+ </style>