@agile-team/wl-skills-kit 2.11.0 → 2.11.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.
- package/CHANGELOG.md +47 -9
- package/README.md +41 -23
- package/bin/wl-skills.js +133 -39
- package/docs/agent-pipeline-runbook.md +3 -3
- package/docs//345/205/250/347/233/230/345/210/206/346/236/220/344/270/216/346/231/272/350/203/275/344/275/223/346/220/255/345/273/272/346/214/207/345/215/227.md +4 -4
- package/files/.wl-skills/copilot-instructions-full.md +233 -233
- package/files/.wl-skills/docs/jh-pagination.md +505 -505
- package/files/.wl-skills/docs/page-spec-schema.md +109 -0
- package/files/.wl-skills/docs/request.md +940 -940
- package/files/.wl-skills/guides/architecture.md +1 -1
- package/files/.wl-skills/skills/core/convention-audit/SKILL.md +3 -3
- package/files/.wl-skills/skills/core/page-codegen/SKILL.md +10 -4
- package/files/.wl-skills/skills/core/spec-doc-parse/SKILL.md +332 -332
- package/files/.wl-skills/skills/core/spec-doc-parse/USAGE.md +97 -97
- package/files/.wl-skills/skills/sync/permission-sync/USAGE.md +107 -107
- package/files/.wl-skills/src/components/global/C_ParentView/index.vue +3 -3
- package/files/.wl-skills/src/components/global/C_RightToolbar/index.vue +157 -157
- package/files/.wl-skills/src/components/global/C_SvgIcon/index.vue +31 -31
- package/files/.wl-skills/src/components/global/C_SvgIcon/svgicon.js +10 -10
- package/files/.wl-skills/src/components/global/C_TagStatus/README.md +264 -264
- package/files/.wl-skills/src/components/global/C_TagStatus/config.ts +192 -192
- package/files/.wl-skills/src/components/global/C_TagStatus/index.vue +106 -106
- package/files/.wl-skills/src/components/global/C_TagStatus/types.ts +64 -64
- package/files/.wl-skills/src/components/global/C_Tree/README.md +153 -153
- package/files/.wl-skills/src/components/global/C_Tree/index.scss +42 -42
- package/files/.wl-skills/src/components/global/C_Tree/index.vue +78 -78
- package/files/.wl-skills/src/components/global/C_Tree/types.ts +59 -59
- package/files/.wl-skills/src/components/local/c_formModal/README.md +235 -235
- package/files/.wl-skills/src/components/local/c_formModal/data.ts +95 -95
- package/files/.wl-skills/src/components/local/c_formModal/index.scss +8 -8
- package/files/.wl-skills/src/components/local/c_formModal/index.vue +107 -107
- package/files/.wl-skills/src/components/local/c_formSections/data.ts +175 -175
- package/files/.wl-skills/src/components/local/c_formSections/index.scss +280 -280
- package/files/.wl-skills/src/components/local/c_formSections/index.vue +429 -429
- package/files/.wl-skills/src/components/local/c_listModal/data.ts +41 -41
- package/files/.wl-skills/src/components/local/c_listModal/index.vue +136 -136
- package/files/.wl-skills/src/components/local/c_spliterTitle/index.scss +25 -25
- package/files/.wl-skills/src/components/local/c_spliterTitle/index.vue +21 -21
- package/files/.wl-skills/src/components/remote/AGGrid/README.md +530 -530
- package/files/.wl-skills/src/components/remote/BaseForm/README.md +508 -508
- package/files/.wl-skills/src/components/remote/BaseQuery/README.md +865 -865
- package/files/.wl-skills/src/components/remote/BaseTable/README.md +941 -941
- package/files/.wl-skills/src/components/remote/BaseToolbar/README.md +496 -496
- package/files/.wl-skills/src/types/page.ts +24 -24
- package/files/.wl-skills/standards/04-coding-basics.md +39 -1
- package/files/.wl-skills/standards/09-typescript.md +26 -3
- package/files/.wl-skills/standards/14-layout-containers.md +6 -6
- package/files/.wl-skills/standards/index.md +2 -2
- package/files/.wl-skills/templates/README.md +44 -44
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/api.md +54 -54
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/data.ts +346 -346
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/index.scss +1 -1
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/index.vue +28 -28
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/data.ts +115 -115
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/index.scss +44 -44
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/index.vue +43 -43
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/data.ts +338 -338
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/index.scss +1 -1
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/index.vue +28 -28
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/data.ts +115 -115
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/index.scss +44 -44
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/index.vue +43 -43
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/api.md +88 -88
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/data.ts +601 -601
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/index.scss +1 -1
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/index.vue +64 -64
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/api.md +67 -67
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/data.ts +286 -286
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/index.scss +139 -139
- package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/index.vue +318 -318
- package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/api.md +98 -98
- package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/data.ts +543 -543
- package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/index.scss +1 -1
- package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/index.vue +52 -52
- package/files/.wl-skills/templates/sale/demo/add-demo/data.ts +518 -518
- package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/data.ts +524 -524
- package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/index.scss +154 -154
- package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/index.vue +117 -117
- package/files/.wl-skills/templates/sale/demo/domestic-trade-order/data.ts +308 -308
- package/files/.wl-skills/templates/sale/demo/domestic-trade-order/index.scss +99 -99
- package/files/.wl-skills/templates/sale/demo/domestic-trade-order/index.vue +77 -77
- package/files/.wl-skills/templates/sale/demo/heat-batch-return/data.ts +367 -367
- package/files/.wl-skills/templates/sale/demo/heat-batch-return/index.scss +100 -100
- package/files/.wl-skills/templates/sale/demo/heat-batch-return/index.vue +170 -170
- package/files/.wl-skills/templates/sale/demo/heat-batch-return/meltDialog.vue +320 -320
- package/files/.wl-skills/templates/sale/demo/metallurgical-spec/data.ts +824 -824
- package/lib/ast-rules.js +304 -9
- package/lib/page-spec.js +588 -0
- package/lib/safe-fix.js +115 -0
- package/mcp/config.js +47 -47
- package/mcp/registry.js +6 -1
- package/mcp/tools/projectTools.js +19 -1
- package/package.json +16 -11
- package/files/.wl-skills/src/components/global/C_Splitter/index.scss +0 -61
- package/files/.wl-skills/src/components/global/C_Splitter/index.vue +0 -149
|
@@ -1,505 +1,505 @@
|
|
|
1
|
-
# jh-pagination - 分页组件
|
|
2
|
-
|
|
3
|
-
> 基于 Element Plus Pagination 封装的统一分页组件,提供标准化的分页交互和样式
|
|
4
|
-
|
|
5
|
-
## 📦 组件位置
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// 来自远程 common-core 包
|
|
9
|
-
import "@jhlc/common-core";
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
组件已在全局注册,无需手动导入,直接在模板中使用 `<jh-pagination>`。
|
|
13
|
-
|
|
14
|
-
## 基本用法
|
|
15
|
-
|
|
16
|
-
### 标准分页
|
|
17
|
-
|
|
18
|
-
```vue
|
|
19
|
-
<template>
|
|
20
|
-
<div>
|
|
21
|
-
<!-- 表格数据 -->
|
|
22
|
-
<BaseTable :data="list" :columns="columns" />
|
|
23
|
-
|
|
24
|
-
<!-- 分页组件 -->
|
|
25
|
-
<jh-pagination
|
|
26
|
-
v-show="page.total && page.total > 0"
|
|
27
|
-
:total="page.total || 0"
|
|
28
|
-
v-model:currentPage="page.current"
|
|
29
|
-
v-model:pageSize="page.size"
|
|
30
|
-
@current-change="handlePageChange"
|
|
31
|
-
@size-change="handleSizeChange"
|
|
32
|
-
/>
|
|
33
|
-
</div>
|
|
34
|
-
</template>
|
|
35
|
-
|
|
36
|
-
<script setup lang="ts">
|
|
37
|
-
import { ref } from "vue";
|
|
38
|
-
|
|
39
|
-
const page = ref({
|
|
40
|
-
current: 1,
|
|
41
|
-
size: 10,
|
|
42
|
-
total: 0
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const list = ref([]);
|
|
46
|
-
|
|
47
|
-
// 加载数据
|
|
48
|
-
const loadData = async () => {
|
|
49
|
-
const res = await request({
|
|
50
|
-
url: "/api/list",
|
|
51
|
-
method: "get",
|
|
52
|
-
params: {
|
|
53
|
-
page: page.value.current,
|
|
54
|
-
size: page.value.size
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
list.value = res.data.records;
|
|
59
|
-
page.value.total = res.data.total;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// 页码变化
|
|
63
|
-
const handlePageChange = () => {
|
|
64
|
-
loadData();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// 页大小变化
|
|
68
|
-
const handleSizeChange = () => {
|
|
69
|
-
page.value.current = 1; // 重置到第一页
|
|
70
|
-
loadData();
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// 初始化
|
|
74
|
-
onMounted(() => {
|
|
75
|
-
loadData();
|
|
76
|
-
});
|
|
77
|
-
</script>
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Props 属性
|
|
81
|
-
|
|
82
|
-
| 参数 | 说明 | 类型 | 默认值 |
|
|
83
|
-
| --------------------- | ------------------------ | ---------- | ------------------------------------------- |
|
|
84
|
-
| total | 总条目数 | `number` | `0` |
|
|
85
|
-
| currentPage (v-model) | 当前页码 | `number` | `1` |
|
|
86
|
-
| pageSize (v-model) | 每页显示条数 | `number` | `10` |
|
|
87
|
-
| pageSizes | 每页显示个数选择器的选项 | `number[]` | `[10, 20, 50, 100]` |
|
|
88
|
-
| layout | 组件布局 | `string` | `"total, prev, pager, next, sizes, jumper"` |
|
|
89
|
-
| background | 是否为分页按钮添加背景色 | `boolean` | `true` |
|
|
90
|
-
| disabled | 是否禁用分页 | `boolean` | `false` |
|
|
91
|
-
|
|
92
|
-
## Events 事件
|
|
93
|
-
|
|
94
|
-
| 事件名 | 说明 | 回调参数 |
|
|
95
|
-
| ------------------ | --------------------- | ------------------------ |
|
|
96
|
-
| current-change | 页码改变时触发 | `(page: number) => void` |
|
|
97
|
-
| size-change | 页大小改变时触发 | `(size: number) => void` |
|
|
98
|
-
| update:currentPage | 页码变化(v-model) | `(page: number) => void` |
|
|
99
|
-
| update:pageSize | 页大小变化(v-model) | `(size: number) => void` |
|
|
100
|
-
|
|
101
|
-
## 常见场景
|
|
102
|
-
|
|
103
|
-
### 场景 1:列表页分页(推荐)
|
|
104
|
-
|
|
105
|
-
**适用**: 绝大多数列表页面
|
|
106
|
-
|
|
107
|
-
```vue
|
|
108
|
-
<template>
|
|
109
|
-
<div class="app-container app-page-container">
|
|
110
|
-
<BaseQuery :form="queryParam" :items="queryItems" @select="select" />
|
|
111
|
-
<BaseToolbar :items="toolbars" />
|
|
112
|
-
<BaseTable :data="list" :columns="columns" />
|
|
113
|
-
|
|
114
|
-
<!-- 分页组件 -->
|
|
115
|
-
<jh-pagination
|
|
116
|
-
v-show="page.total && page.total > 0"
|
|
117
|
-
:total="page.total || 0"
|
|
118
|
-
v-model:currentPage="page.current"
|
|
119
|
-
v-model:pageSize="page.size"
|
|
120
|
-
@current-change="select"
|
|
121
|
-
@size-change="select"
|
|
122
|
-
/>
|
|
123
|
-
</div>
|
|
124
|
-
</template>
|
|
125
|
-
|
|
126
|
-
<script setup lang="ts">
|
|
127
|
-
import { createPage } from "./data";
|
|
128
|
-
|
|
129
|
-
const Page = createPage();
|
|
130
|
-
const { page, list, queryParam, queryItems, toolbars, columns, select } = Page;
|
|
131
|
-
|
|
132
|
-
onMounted(() => {
|
|
133
|
-
select();
|
|
134
|
-
});
|
|
135
|
-
</script>
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
**说明**:
|
|
139
|
-
|
|
140
|
-
- ✅ 使用 `v-show` 在无数据时隐藏分页
|
|
141
|
-
- ✅ 使用 `v-model` 双向绑定页码和页大小
|
|
142
|
-
- ✅ 页码/页大小变化时统一调用 `select()` 刷新数据
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
### 场景 2:前端分页(本地数据)
|
|
147
|
-
|
|
148
|
-
**适用**: 数据量小,一次性加载全部数据后在前端分页
|
|
149
|
-
|
|
150
|
-
```vue
|
|
151
|
-
<template>
|
|
152
|
-
<div>
|
|
153
|
-
<!-- 显示分页后的数据 -->
|
|
154
|
-
<BaseTable :data="paginatedData" :columns="columns" />
|
|
155
|
-
|
|
156
|
-
<!-- 分页组件 -->
|
|
157
|
-
<jh-pagination
|
|
158
|
-
v-show="allData.length > 0"
|
|
159
|
-
:total="allData.length"
|
|
160
|
-
v-model:currentPage="currentPage"
|
|
161
|
-
v-model:pageSize="pageSize"
|
|
162
|
-
/>
|
|
163
|
-
</div>
|
|
164
|
-
</template>
|
|
165
|
-
|
|
166
|
-
<script setup lang="ts">
|
|
167
|
-
import { ref, computed } from "vue";
|
|
168
|
-
|
|
169
|
-
const allData = ref([]); // 全部数据
|
|
170
|
-
const currentPage = ref(1);
|
|
171
|
-
const pageSize = ref(10);
|
|
172
|
-
|
|
173
|
-
// 计算属性:分页后的数据
|
|
174
|
-
const paginatedData = computed(() => {
|
|
175
|
-
const start = (currentPage.value - 1) * pageSize.value;
|
|
176
|
-
const end = start + pageSize.value;
|
|
177
|
-
return allData.value.slice(start, end);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// 加载全部数据
|
|
181
|
-
const loadAllData = async () => {
|
|
182
|
-
const res = await request({
|
|
183
|
-
url: "/api/all-data",
|
|
184
|
-
method: "get"
|
|
185
|
-
});
|
|
186
|
-
allData.value = res.data;
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
onMounted(() => {
|
|
190
|
-
loadAllData();
|
|
191
|
-
});
|
|
192
|
-
</script>
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
**说明**:
|
|
196
|
-
|
|
197
|
-
- ✅ `total` 使用全部数据的长度
|
|
198
|
-
- ✅ 使用 `computed` 计算当前页的数据
|
|
199
|
-
- ✅ 不需要监听事件(响应式自动处理)
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
### 场景 3:子表格分页
|
|
204
|
-
|
|
205
|
-
**适用**: 新增编辑页中的项次信息表格
|
|
206
|
-
|
|
207
|
-
```vue
|
|
208
|
-
<template>
|
|
209
|
-
<div>
|
|
210
|
-
<!-- 主表单区域 -->
|
|
211
|
-
<c_formSections :sections="sectionsConfig" :form="form" />
|
|
212
|
-
|
|
213
|
-
<!-- 项次信息表格 -->
|
|
214
|
-
<el-card shadow="never" class="items-card">
|
|
215
|
-
<BaseTable :data="itemData" :columns="itemColumns" />
|
|
216
|
-
|
|
217
|
-
<!-- 项次分页 -->
|
|
218
|
-
<div class="items-pagination">
|
|
219
|
-
<jh-pagination
|
|
220
|
-
v-show="itemTotal && itemTotal > 0"
|
|
221
|
-
:total="itemTotal || 0"
|
|
222
|
-
v-model:currentPage="itemPage"
|
|
223
|
-
v-model:pageSize="itemSize"
|
|
224
|
-
@current-change="loadItemData"
|
|
225
|
-
@size-change="loadItemData"
|
|
226
|
-
/>
|
|
227
|
-
</div>
|
|
228
|
-
</el-card>
|
|
229
|
-
</div>
|
|
230
|
-
</template>
|
|
231
|
-
|
|
232
|
-
<script setup lang="ts">
|
|
233
|
-
const form = ref({});
|
|
234
|
-
const itemData = ref([]);
|
|
235
|
-
const itemTotal = ref(0);
|
|
236
|
-
const itemPage = ref(1);
|
|
237
|
-
const itemSize = ref(10);
|
|
238
|
-
|
|
239
|
-
// 加载项次数据
|
|
240
|
-
const loadItemData = async () => {
|
|
241
|
-
const res = await request({
|
|
242
|
-
url: "/api/items/list",
|
|
243
|
-
method: "get",
|
|
244
|
-
params: {
|
|
245
|
-
page: itemPage.value,
|
|
246
|
-
size: itemSize.value
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
itemData.value = res.data.records;
|
|
250
|
-
itemTotal.value = res.data.total;
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
onMounted(() => {
|
|
254
|
-
loadItemData();
|
|
255
|
-
});
|
|
256
|
-
</script>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
**说明**:
|
|
260
|
-
|
|
261
|
-
- ✅ 子表格使用独立的分页状态
|
|
262
|
-
- ✅ 与主表单数据解耦
|
|
263
|
-
- ✅ 支持独立刷新
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
### 场景 4:无数据时自动隐藏
|
|
268
|
-
|
|
269
|
-
**推荐写法**:
|
|
270
|
-
|
|
271
|
-
```vue
|
|
272
|
-
<!-- ✅ 推荐:无数据时不显示 -->
|
|
273
|
-
<jh-pagination
|
|
274
|
-
v-show="page.total && page.total > 0"
|
|
275
|
-
:total="page.total || 0"
|
|
276
|
-
v-model:currentPage="page.current"
|
|
277
|
-
v-model:pageSize="page.size"
|
|
278
|
-
/>
|
|
279
|
-
|
|
280
|
-
<!-- ❌ 不推荐:始终显示(体验差) -->
|
|
281
|
-
<jh-pagination
|
|
282
|
-
:total="page.total"
|
|
283
|
-
v-model:currentPage="page.current"
|
|
284
|
-
v-model:pageSize="page.size"
|
|
285
|
-
/>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
**说明**:
|
|
289
|
-
|
|
290
|
-
- ✅ 使用 `v-show` 在 `total > 0` 时才显示
|
|
291
|
-
- ✅ 提升用户体验,避免空状态下显示分页
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
### 场景 5:自定义页大小选项
|
|
296
|
-
|
|
297
|
-
```vue
|
|
298
|
-
<jh-pagination
|
|
299
|
-
:total="page.total"
|
|
300
|
-
:page-sizes="[5, 10, 20, 50, 200]"
|
|
301
|
-
v-model:currentPage="page.current"
|
|
302
|
-
v-model:pageSize="page.size"
|
|
303
|
-
/>
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
**说明**:
|
|
307
|
-
|
|
308
|
-
- 根据业务需求自定义每页条数选项
|
|
309
|
-
- 默认为 `[10, 20, 50, 100]`
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
|
-
## 与 el-pagination 对比
|
|
314
|
-
|
|
315
|
-
### 使用 jh-pagination(推荐)
|
|
316
|
-
|
|
317
|
-
```vue
|
|
318
|
-
<jh-pagination
|
|
319
|
-
v-show="page.total && page.total > 0"
|
|
320
|
-
:total="page.total || 0"
|
|
321
|
-
v-model:currentPage="page.current"
|
|
322
|
-
v-model:pageSize="page.size"
|
|
323
|
-
@current-change="select"
|
|
324
|
-
@size-change="select"
|
|
325
|
-
/>
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
**优势**:
|
|
329
|
-
|
|
330
|
-
- ✅ **统一规范** - 全局统一的分页样式和交互
|
|
331
|
-
- ✅ **简化配置** - 无需配置 layout、background 等(内置默认值)
|
|
332
|
-
- ✅ **驼峰命名** - 使用 `currentPage`、`pageSize`(符合 Vue 规范)
|
|
333
|
-
- ✅ **自动样式** - 内置统一的边距、居中、背景色
|
|
334
|
-
|
|
335
|
-
### 使用 el-pagination(不推荐)
|
|
336
|
-
|
|
337
|
-
```vue
|
|
338
|
-
<el-pagination
|
|
339
|
-
v-model:current-page="page.current"
|
|
340
|
-
v-model:page-size="page.size"
|
|
341
|
-
:page-sizes="[10, 20, 50, 100]"
|
|
342
|
-
:total="page.total"
|
|
343
|
-
layout="total, prev, pager, next, sizes, jumper"
|
|
344
|
-
background
|
|
345
|
-
@current-change="select"
|
|
346
|
-
@size-change="select"
|
|
347
|
-
/>
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
**劣势**:
|
|
351
|
-
|
|
352
|
-
- ❌ **配置繁琐** - 需要手动配置 layout、page-sizes、background
|
|
353
|
-
- ❌ **样式不统一** - 每个页面可能配置不同
|
|
354
|
-
- ❌ **命名不一致** - 使用 `current-page`(中划线命名)
|
|
355
|
-
|
|
356
|
-
---
|
|
357
|
-
|
|
358
|
-
## 💡 最佳实践
|
|
359
|
-
|
|
360
|
-
### 1. 统一使用 jh-pagination
|
|
361
|
-
|
|
362
|
-
**推荐**:
|
|
363
|
-
|
|
364
|
-
```vue
|
|
365
|
-
<jh-pagination ... />
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
**不推荐**:
|
|
369
|
-
|
|
370
|
-
```vue
|
|
371
|
-
<el-pagination ... />
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### 2. 始终添加 v-show
|
|
375
|
-
|
|
376
|
-
```vue
|
|
377
|
-
<!-- ✅ 推荐 -->
|
|
378
|
-
<jh-pagination
|
|
379
|
-
v-show="page.total && page.total > 0"
|
|
380
|
-
:total="page.total || 0"
|
|
381
|
-
...
|
|
382
|
-
/>
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### 3. 使用 v-model 双向绑定
|
|
386
|
-
|
|
387
|
-
```vue
|
|
388
|
-
<!-- ✅ 推荐:v-model 双向绑定 -->
|
|
389
|
-
<jh-pagination
|
|
390
|
-
v-model:currentPage="page.current"
|
|
391
|
-
v-model:pageSize="page.size"
|
|
392
|
-
/>
|
|
393
|
-
|
|
394
|
-
<!-- ❌ 不推荐:单向绑定 + 事件手动更新 -->
|
|
395
|
-
<jh-pagination
|
|
396
|
-
:current-page="page.current"
|
|
397
|
-
:page-size="page.size"
|
|
398
|
-
@update:currentPage="page.current = $event"
|
|
399
|
-
@update:pageSize="page.size = $event"
|
|
400
|
-
/>
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
### 4. 页大小变化时重置页码
|
|
404
|
-
|
|
405
|
-
```typescript
|
|
406
|
-
const handleSizeChange = () => {
|
|
407
|
-
page.value.current = 1; // 重置到第一页
|
|
408
|
-
loadData();
|
|
409
|
-
};
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
### 5. 配合 Page Hook 使用
|
|
413
|
-
|
|
414
|
-
```typescript
|
|
415
|
-
// data.ts
|
|
416
|
-
export function createPage() {
|
|
417
|
-
return new (class extends AbstractPageQueryHook {
|
|
418
|
-
// ... Hook 内置分页逻辑
|
|
419
|
-
})();
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
// index.vue
|
|
423
|
-
const Page = createPage();
|
|
424
|
-
const { page, select } = Page;
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
**说明**:
|
|
428
|
-
|
|
429
|
-
- ✅ Page Hook 内置分页状态管理
|
|
430
|
-
- ✅ `select()` 方法自动读取 page 状态
|
|
431
|
-
- ✅ 减少手动管理分页的代码
|
|
432
|
-
|
|
433
|
-
---
|
|
434
|
-
|
|
435
|
-
## 🎯 真实项目示例
|
|
436
|
-
|
|
437
|
-
### 示例 1:内贸订单列表页
|
|
438
|
-
|
|
439
|
-
**路径**: `src/views/sale/.wl-skills/templates/domestic-trade-order/index.vue`
|
|
440
|
-
|
|
441
|
-
```vue
|
|
442
|
-
<jh-pagination
|
|
443
|
-
v-show="page.total && page.total > 0"
|
|
444
|
-
:total="page.total || 0"
|
|
445
|
-
v-model:currentPage="page.current"
|
|
446
|
-
v-model:pageSize="page.size"
|
|
447
|
-
@current-change="select"
|
|
448
|
-
@size-change="select"
|
|
449
|
-
/>
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### 示例 2:新增编辑页项次分页
|
|
453
|
-
|
|
454
|
-
**路径**: `src/views/sale/.wl-skills/templates/add-.wl-skills/templates/index.vue`
|
|
455
|
-
|
|
456
|
-
```vue
|
|
457
|
-
<jh-pagination
|
|
458
|
-
v-show="itemTotal && itemTotal > 0"
|
|
459
|
-
:total="itemTotal || 0"
|
|
460
|
-
v-model:currentPage="currentPage"
|
|
461
|
-
v-model:pageSize="pageSize"
|
|
462
|
-
@current-change="refreshItemData"
|
|
463
|
-
@size-change="refreshItemData"
|
|
464
|
-
/>
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
## ⚠️ 注意事项
|
|
470
|
-
|
|
471
|
-
1. **组件来自远程包**
|
|
472
|
-
|
|
473
|
-
- 组件由 `@jhlc/common-core` 提供
|
|
474
|
-
- 已全局注册,无需手动导入
|
|
475
|
-
- 升级远程包时注意版本兼容性
|
|
476
|
-
|
|
477
|
-
2. **页码从 1 开始**
|
|
478
|
-
|
|
479
|
-
- `currentPage` 最小值为 1
|
|
480
|
-
- 后端接口通常也是从 1 开始
|
|
481
|
-
|
|
482
|
-
3. **total 必须准确**
|
|
483
|
-
|
|
484
|
-
- `total` 应该是数据总数,不是当前页数据量
|
|
485
|
-
- 后端通常返回 `{ records: [], total: 100 }`
|
|
486
|
-
|
|
487
|
-
4. **事件处理**
|
|
488
|
-
|
|
489
|
-
- `current-change` 在页码变化时触发
|
|
490
|
-
- `size-change` 在页大小变化时触发
|
|
491
|
-
- 两个事件通常调用同一个刷新方法
|
|
492
|
-
|
|
493
|
-
5. **样式定制**
|
|
494
|
-
- 如需特殊样式,可通过 CSS 覆盖
|
|
495
|
-
- 不要修改远程组件源码
|
|
496
|
-
|
|
497
|
-
---
|
|
498
|
-
|
|
499
|
-
## 🚀 快速开始
|
|
500
|
-
|
|
501
|
-
1. **在列表页使用**:复制"场景 1"代码
|
|
502
|
-
2. **在详情页使用**:复制"场景 3"代码
|
|
503
|
-
3. **前端分页**:复制"场景 2"代码
|
|
504
|
-
|
|
505
|
-
**推荐作为项目统一的分页组件使用!**
|
|
1
|
+
# jh-pagination - 分页组件
|
|
2
|
+
|
|
3
|
+
> 基于 Element Plus Pagination 封装的统一分页组件,提供标准化的分页交互和样式
|
|
4
|
+
|
|
5
|
+
## 📦 组件位置
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// 来自远程 common-core 包
|
|
9
|
+
import "@jhlc/common-core";
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
组件已在全局注册,无需手动导入,直接在模板中使用 `<jh-pagination>`。
|
|
13
|
+
|
|
14
|
+
## 基本用法
|
|
15
|
+
|
|
16
|
+
### 标准分页
|
|
17
|
+
|
|
18
|
+
```vue
|
|
19
|
+
<template>
|
|
20
|
+
<div>
|
|
21
|
+
<!-- 表格数据 -->
|
|
22
|
+
<BaseTable :data="list" :columns="columns" />
|
|
23
|
+
|
|
24
|
+
<!-- 分页组件 -->
|
|
25
|
+
<jh-pagination
|
|
26
|
+
v-show="page.total && page.total > 0"
|
|
27
|
+
:total="page.total || 0"
|
|
28
|
+
v-model:currentPage="page.current"
|
|
29
|
+
v-model:pageSize="page.size"
|
|
30
|
+
@current-change="handlePageChange"
|
|
31
|
+
@size-change="handleSizeChange"
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import { ref } from "vue";
|
|
38
|
+
|
|
39
|
+
const page = ref({
|
|
40
|
+
current: 1,
|
|
41
|
+
size: 10,
|
|
42
|
+
total: 0
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const list = ref([]);
|
|
46
|
+
|
|
47
|
+
// 加载数据
|
|
48
|
+
const loadData = async () => {
|
|
49
|
+
const res = await request({
|
|
50
|
+
url: "/api/list",
|
|
51
|
+
method: "get",
|
|
52
|
+
params: {
|
|
53
|
+
page: page.value.current,
|
|
54
|
+
size: page.value.size
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
list.value = res.data.records;
|
|
59
|
+
page.value.total = res.data.total;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// 页码变化
|
|
63
|
+
const handlePageChange = () => {
|
|
64
|
+
loadData();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// 页大小变化
|
|
68
|
+
const handleSizeChange = () => {
|
|
69
|
+
page.value.current = 1; // 重置到第一页
|
|
70
|
+
loadData();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// 初始化
|
|
74
|
+
onMounted(() => {
|
|
75
|
+
loadData();
|
|
76
|
+
});
|
|
77
|
+
</script>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Props 属性
|
|
81
|
+
|
|
82
|
+
| 参数 | 说明 | 类型 | 默认值 |
|
|
83
|
+
| --------------------- | ------------------------ | ---------- | ------------------------------------------- |
|
|
84
|
+
| total | 总条目数 | `number` | `0` |
|
|
85
|
+
| currentPage (v-model) | 当前页码 | `number` | `1` |
|
|
86
|
+
| pageSize (v-model) | 每页显示条数 | `number` | `10` |
|
|
87
|
+
| pageSizes | 每页显示个数选择器的选项 | `number[]` | `[10, 20, 50, 100]` |
|
|
88
|
+
| layout | 组件布局 | `string` | `"total, prev, pager, next, sizes, jumper"` |
|
|
89
|
+
| background | 是否为分页按钮添加背景色 | `boolean` | `true` |
|
|
90
|
+
| disabled | 是否禁用分页 | `boolean` | `false` |
|
|
91
|
+
|
|
92
|
+
## Events 事件
|
|
93
|
+
|
|
94
|
+
| 事件名 | 说明 | 回调参数 |
|
|
95
|
+
| ------------------ | --------------------- | ------------------------ |
|
|
96
|
+
| current-change | 页码改变时触发 | `(page: number) => void` |
|
|
97
|
+
| size-change | 页大小改变时触发 | `(size: number) => void` |
|
|
98
|
+
| update:currentPage | 页码变化(v-model) | `(page: number) => void` |
|
|
99
|
+
| update:pageSize | 页大小变化(v-model) | `(size: number) => void` |
|
|
100
|
+
|
|
101
|
+
## 常见场景
|
|
102
|
+
|
|
103
|
+
### 场景 1:列表页分页(推荐)
|
|
104
|
+
|
|
105
|
+
**适用**: 绝大多数列表页面
|
|
106
|
+
|
|
107
|
+
```vue
|
|
108
|
+
<template>
|
|
109
|
+
<div class="app-container app-page-container">
|
|
110
|
+
<BaseQuery :form="queryParam" :items="queryItems" @select="select" />
|
|
111
|
+
<BaseToolbar :items="toolbars" />
|
|
112
|
+
<BaseTable :data="list" :columns="columns" />
|
|
113
|
+
|
|
114
|
+
<!-- 分页组件 -->
|
|
115
|
+
<jh-pagination
|
|
116
|
+
v-show="page.total && page.total > 0"
|
|
117
|
+
:total="page.total || 0"
|
|
118
|
+
v-model:currentPage="page.current"
|
|
119
|
+
v-model:pageSize="page.size"
|
|
120
|
+
@current-change="select"
|
|
121
|
+
@size-change="select"
|
|
122
|
+
/>
|
|
123
|
+
</div>
|
|
124
|
+
</template>
|
|
125
|
+
|
|
126
|
+
<script setup lang="ts">
|
|
127
|
+
import { createPage } from "./data";
|
|
128
|
+
|
|
129
|
+
const Page = createPage();
|
|
130
|
+
const { page, list, queryParam, queryItems, toolbars, columns, select } = Page;
|
|
131
|
+
|
|
132
|
+
onMounted(() => {
|
|
133
|
+
select();
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**说明**:
|
|
139
|
+
|
|
140
|
+
- ✅ 使用 `v-show` 在无数据时隐藏分页
|
|
141
|
+
- ✅ 使用 `v-model` 双向绑定页码和页大小
|
|
142
|
+
- ✅ 页码/页大小变化时统一调用 `select()` 刷新数据
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### 场景 2:前端分页(本地数据)
|
|
147
|
+
|
|
148
|
+
**适用**: 数据量小,一次性加载全部数据后在前端分页
|
|
149
|
+
|
|
150
|
+
```vue
|
|
151
|
+
<template>
|
|
152
|
+
<div>
|
|
153
|
+
<!-- 显示分页后的数据 -->
|
|
154
|
+
<BaseTable :data="paginatedData" :columns="columns" />
|
|
155
|
+
|
|
156
|
+
<!-- 分页组件 -->
|
|
157
|
+
<jh-pagination
|
|
158
|
+
v-show="allData.length > 0"
|
|
159
|
+
:total="allData.length"
|
|
160
|
+
v-model:currentPage="currentPage"
|
|
161
|
+
v-model:pageSize="pageSize"
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
164
|
+
</template>
|
|
165
|
+
|
|
166
|
+
<script setup lang="ts">
|
|
167
|
+
import { ref, computed } from "vue";
|
|
168
|
+
|
|
169
|
+
const allData = ref([]); // 全部数据
|
|
170
|
+
const currentPage = ref(1);
|
|
171
|
+
const pageSize = ref(10);
|
|
172
|
+
|
|
173
|
+
// 计算属性:分页后的数据
|
|
174
|
+
const paginatedData = computed(() => {
|
|
175
|
+
const start = (currentPage.value - 1) * pageSize.value;
|
|
176
|
+
const end = start + pageSize.value;
|
|
177
|
+
return allData.value.slice(start, end);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// 加载全部数据
|
|
181
|
+
const loadAllData = async () => {
|
|
182
|
+
const res = await request({
|
|
183
|
+
url: "/api/all-data",
|
|
184
|
+
method: "get"
|
|
185
|
+
});
|
|
186
|
+
allData.value = res.data;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
onMounted(() => {
|
|
190
|
+
loadAllData();
|
|
191
|
+
});
|
|
192
|
+
</script>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**说明**:
|
|
196
|
+
|
|
197
|
+
- ✅ `total` 使用全部数据的长度
|
|
198
|
+
- ✅ 使用 `computed` 计算当前页的数据
|
|
199
|
+
- ✅ 不需要监听事件(响应式自动处理)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### 场景 3:子表格分页
|
|
204
|
+
|
|
205
|
+
**适用**: 新增编辑页中的项次信息表格
|
|
206
|
+
|
|
207
|
+
```vue
|
|
208
|
+
<template>
|
|
209
|
+
<div>
|
|
210
|
+
<!-- 主表单区域 -->
|
|
211
|
+
<c_formSections :sections="sectionsConfig" :form="form" />
|
|
212
|
+
|
|
213
|
+
<!-- 项次信息表格 -->
|
|
214
|
+
<el-card shadow="never" class="items-card">
|
|
215
|
+
<BaseTable :data="itemData" :columns="itemColumns" />
|
|
216
|
+
|
|
217
|
+
<!-- 项次分页 -->
|
|
218
|
+
<div class="items-pagination">
|
|
219
|
+
<jh-pagination
|
|
220
|
+
v-show="itemTotal && itemTotal > 0"
|
|
221
|
+
:total="itemTotal || 0"
|
|
222
|
+
v-model:currentPage="itemPage"
|
|
223
|
+
v-model:pageSize="itemSize"
|
|
224
|
+
@current-change="loadItemData"
|
|
225
|
+
@size-change="loadItemData"
|
|
226
|
+
/>
|
|
227
|
+
</div>
|
|
228
|
+
</el-card>
|
|
229
|
+
</div>
|
|
230
|
+
</template>
|
|
231
|
+
|
|
232
|
+
<script setup lang="ts">
|
|
233
|
+
const form = ref({});
|
|
234
|
+
const itemData = ref([]);
|
|
235
|
+
const itemTotal = ref(0);
|
|
236
|
+
const itemPage = ref(1);
|
|
237
|
+
const itemSize = ref(10);
|
|
238
|
+
|
|
239
|
+
// 加载项次数据
|
|
240
|
+
const loadItemData = async () => {
|
|
241
|
+
const res = await request({
|
|
242
|
+
url: "/api/items/list",
|
|
243
|
+
method: "get",
|
|
244
|
+
params: {
|
|
245
|
+
page: itemPage.value,
|
|
246
|
+
size: itemSize.value
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
itemData.value = res.data.records;
|
|
250
|
+
itemTotal.value = res.data.total;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
onMounted(() => {
|
|
254
|
+
loadItemData();
|
|
255
|
+
});
|
|
256
|
+
</script>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**说明**:
|
|
260
|
+
|
|
261
|
+
- ✅ 子表格使用独立的分页状态
|
|
262
|
+
- ✅ 与主表单数据解耦
|
|
263
|
+
- ✅ 支持独立刷新
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### 场景 4:无数据时自动隐藏
|
|
268
|
+
|
|
269
|
+
**推荐写法**:
|
|
270
|
+
|
|
271
|
+
```vue
|
|
272
|
+
<!-- ✅ 推荐:无数据时不显示 -->
|
|
273
|
+
<jh-pagination
|
|
274
|
+
v-show="page.total && page.total > 0"
|
|
275
|
+
:total="page.total || 0"
|
|
276
|
+
v-model:currentPage="page.current"
|
|
277
|
+
v-model:pageSize="page.size"
|
|
278
|
+
/>
|
|
279
|
+
|
|
280
|
+
<!-- ❌ 不推荐:始终显示(体验差) -->
|
|
281
|
+
<jh-pagination
|
|
282
|
+
:total="page.total"
|
|
283
|
+
v-model:currentPage="page.current"
|
|
284
|
+
v-model:pageSize="page.size"
|
|
285
|
+
/>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**说明**:
|
|
289
|
+
|
|
290
|
+
- ✅ 使用 `v-show` 在 `total > 0` 时才显示
|
|
291
|
+
- ✅ 提升用户体验,避免空状态下显示分页
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
### 场景 5:自定义页大小选项
|
|
296
|
+
|
|
297
|
+
```vue
|
|
298
|
+
<jh-pagination
|
|
299
|
+
:total="page.total"
|
|
300
|
+
:page-sizes="[5, 10, 20, 50, 200]"
|
|
301
|
+
v-model:currentPage="page.current"
|
|
302
|
+
v-model:pageSize="page.size"
|
|
303
|
+
/>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**说明**:
|
|
307
|
+
|
|
308
|
+
- 根据业务需求自定义每页条数选项
|
|
309
|
+
- 默认为 `[10, 20, 50, 100]`
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## 与 el-pagination 对比
|
|
314
|
+
|
|
315
|
+
### 使用 jh-pagination(推荐)
|
|
316
|
+
|
|
317
|
+
```vue
|
|
318
|
+
<jh-pagination
|
|
319
|
+
v-show="page.total && page.total > 0"
|
|
320
|
+
:total="page.total || 0"
|
|
321
|
+
v-model:currentPage="page.current"
|
|
322
|
+
v-model:pageSize="page.size"
|
|
323
|
+
@current-change="select"
|
|
324
|
+
@size-change="select"
|
|
325
|
+
/>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**优势**:
|
|
329
|
+
|
|
330
|
+
- ✅ **统一规范** - 全局统一的分页样式和交互
|
|
331
|
+
- ✅ **简化配置** - 无需配置 layout、background 等(内置默认值)
|
|
332
|
+
- ✅ **驼峰命名** - 使用 `currentPage`、`pageSize`(符合 Vue 规范)
|
|
333
|
+
- ✅ **自动样式** - 内置统一的边距、居中、背景色
|
|
334
|
+
|
|
335
|
+
### 使用 el-pagination(不推荐)
|
|
336
|
+
|
|
337
|
+
```vue
|
|
338
|
+
<el-pagination
|
|
339
|
+
v-model:current-page="page.current"
|
|
340
|
+
v-model:page-size="page.size"
|
|
341
|
+
:page-sizes="[10, 20, 50, 100]"
|
|
342
|
+
:total="page.total"
|
|
343
|
+
layout="total, prev, pager, next, sizes, jumper"
|
|
344
|
+
background
|
|
345
|
+
@current-change="select"
|
|
346
|
+
@size-change="select"
|
|
347
|
+
/>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**劣势**:
|
|
351
|
+
|
|
352
|
+
- ❌ **配置繁琐** - 需要手动配置 layout、page-sizes、background
|
|
353
|
+
- ❌ **样式不统一** - 每个页面可能配置不同
|
|
354
|
+
- ❌ **命名不一致** - 使用 `current-page`(中划线命名)
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## 💡 最佳实践
|
|
359
|
+
|
|
360
|
+
### 1. 统一使用 jh-pagination
|
|
361
|
+
|
|
362
|
+
**推荐**:
|
|
363
|
+
|
|
364
|
+
```vue
|
|
365
|
+
<jh-pagination ... />
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**不推荐**:
|
|
369
|
+
|
|
370
|
+
```vue
|
|
371
|
+
<el-pagination ... />
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### 2. 始终添加 v-show
|
|
375
|
+
|
|
376
|
+
```vue
|
|
377
|
+
<!-- ✅ 推荐 -->
|
|
378
|
+
<jh-pagination
|
|
379
|
+
v-show="page.total && page.total > 0"
|
|
380
|
+
:total="page.total || 0"
|
|
381
|
+
...
|
|
382
|
+
/>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 3. 使用 v-model 双向绑定
|
|
386
|
+
|
|
387
|
+
```vue
|
|
388
|
+
<!-- ✅ 推荐:v-model 双向绑定 -->
|
|
389
|
+
<jh-pagination
|
|
390
|
+
v-model:currentPage="page.current"
|
|
391
|
+
v-model:pageSize="page.size"
|
|
392
|
+
/>
|
|
393
|
+
|
|
394
|
+
<!-- ❌ 不推荐:单向绑定 + 事件手动更新 -->
|
|
395
|
+
<jh-pagination
|
|
396
|
+
:current-page="page.current"
|
|
397
|
+
:page-size="page.size"
|
|
398
|
+
@update:currentPage="page.current = $event"
|
|
399
|
+
@update:pageSize="page.size = $event"
|
|
400
|
+
/>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### 4. 页大小变化时重置页码
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
const handleSizeChange = () => {
|
|
407
|
+
page.value.current = 1; // 重置到第一页
|
|
408
|
+
loadData();
|
|
409
|
+
};
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### 5. 配合 Page Hook 使用
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
// data.ts
|
|
416
|
+
export function createPage() {
|
|
417
|
+
return new (class extends AbstractPageQueryHook {
|
|
418
|
+
// ... Hook 内置分页逻辑
|
|
419
|
+
})();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// index.vue
|
|
423
|
+
const Page = createPage();
|
|
424
|
+
const { page, select } = Page;
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**说明**:
|
|
428
|
+
|
|
429
|
+
- ✅ Page Hook 内置分页状态管理
|
|
430
|
+
- ✅ `select()` 方法自动读取 page 状态
|
|
431
|
+
- ✅ 减少手动管理分页的代码
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## 🎯 真实项目示例
|
|
436
|
+
|
|
437
|
+
### 示例 1:内贸订单列表页
|
|
438
|
+
|
|
439
|
+
**路径**: `src/views/sale/.wl-skills/templates/domestic-trade-order/index.vue`
|
|
440
|
+
|
|
441
|
+
```vue
|
|
442
|
+
<jh-pagination
|
|
443
|
+
v-show="page.total && page.total > 0"
|
|
444
|
+
:total="page.total || 0"
|
|
445
|
+
v-model:currentPage="page.current"
|
|
446
|
+
v-model:pageSize="page.size"
|
|
447
|
+
@current-change="select"
|
|
448
|
+
@size-change="select"
|
|
449
|
+
/>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### 示例 2:新增编辑页项次分页
|
|
453
|
+
|
|
454
|
+
**路径**: `src/views/sale/.wl-skills/templates/add-.wl-skills/templates/index.vue`
|
|
455
|
+
|
|
456
|
+
```vue
|
|
457
|
+
<jh-pagination
|
|
458
|
+
v-show="itemTotal && itemTotal > 0"
|
|
459
|
+
:total="itemTotal || 0"
|
|
460
|
+
v-model:currentPage="currentPage"
|
|
461
|
+
v-model:pageSize="pageSize"
|
|
462
|
+
@current-change="refreshItemData"
|
|
463
|
+
@size-change="refreshItemData"
|
|
464
|
+
/>
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## ⚠️ 注意事项
|
|
470
|
+
|
|
471
|
+
1. **组件来自远程包**
|
|
472
|
+
|
|
473
|
+
- 组件由 `@jhlc/common-core` 提供
|
|
474
|
+
- 已全局注册,无需手动导入
|
|
475
|
+
- 升级远程包时注意版本兼容性
|
|
476
|
+
|
|
477
|
+
2. **页码从 1 开始**
|
|
478
|
+
|
|
479
|
+
- `currentPage` 最小值为 1
|
|
480
|
+
- 后端接口通常也是从 1 开始
|
|
481
|
+
|
|
482
|
+
3. **total 必须准确**
|
|
483
|
+
|
|
484
|
+
- `total` 应该是数据总数,不是当前页数据量
|
|
485
|
+
- 后端通常返回 `{ records: [], total: 100 }`
|
|
486
|
+
|
|
487
|
+
4. **事件处理**
|
|
488
|
+
|
|
489
|
+
- `current-change` 在页码变化时触发
|
|
490
|
+
- `size-change` 在页大小变化时触发
|
|
491
|
+
- 两个事件通常调用同一个刷新方法
|
|
492
|
+
|
|
493
|
+
5. **样式定制**
|
|
494
|
+
- 如需特殊样式,可通过 CSS 覆盖
|
|
495
|
+
- 不要修改远程组件源码
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## 🚀 快速开始
|
|
500
|
+
|
|
501
|
+
1. **在列表页使用**:复制"场景 1"代码
|
|
502
|
+
2. **在详情页使用**:复制"场景 3"代码
|
|
503
|
+
3. **前端分页**:复制"场景 2"代码
|
|
504
|
+
|
|
505
|
+
**推荐作为项目统一的分页组件使用!**
|