index.vue
4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!--
* @Date: 2025-11-18 16:17:40
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-11-26 17:17:14
* @FilePath: /data-table/src/components/PaginationField/index.vue
* @Description: 分页组件
-->
<template>
<div class="pagination-field">
<div class="indicator">第{{ current + 1 }}页 / 共{{ total }}页</div>
<div class="actions">
<div class="actionsLeft">
<van-button
v-if="showPrev"
:disabled="prev_disabled_effective || current === 0"
round
type="primary"
:color="prevBtnColor"
class="btn"
@click="onPrev"
>
<span :style="{ color: prevTextColor }">{{ prevLabel }}</span>
</van-button>
</div>
<div class="actionsCenter">
<van-button v-if="showSubmit" round type="primary" :color="submitButton.btn_color" class="btn" @click="onSubmit">
<span :style="{ color: submitButton.text_color }">{{ submitButton.text }}</span>
</van-button>
</div>
<div class="actionsRight">
<van-button v-if="showNext" round type="primary" :color="nextBtnColor" class="btn" @click="onNext">
<span :style="{ color: nextTextColor }">{{ nextLabel }}</span>
</van-button>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { styleColor } from "@/constant.js";
const props = defineProps({
current: { type: Number, default: 0 },
total: { type: Number, default: 1 },
isLast: { type: Boolean, default: false },
prevLabel: { type: String, default: '上一页' },
nextLabel: { type: String, default: '下一页' },
prevBtnColor: { type: String, default: styleColor.baseColor },
nextBtnColor: { type: String, default: styleColor.baseColor },
prevTextColor: { type: String, default: '#fff' },
nextTextColor: { type: String, default: '#fff' },
submitButton: { type: Object, default: { text: '提交', back_title: '上一页', is_back: false, btn_color: styleColor.baseColor, text_color: '#fff' } },
prevDisabled: { type: Boolean, default: false },
})
const emit = defineEmits(['prev', 'next', 'submit'])
/**
* @description 是否显示上一页按钮(最后一页且 is_back 为 false 时不显示)
* @returns {import('vue').ComputedRef<boolean>}
*/
const showPrev = computed(() => {
// 非最后一页按原逻辑显示;最后一页由 submitButton.is_back 控制显示与否
if (!showSubmit.value) return props.current > 0
return props.current > 0 && props.submitButton?.is_back !== false
})
const showNext = computed(() => props.current < props.total - 1)
const showSubmit = computed(() => props.current === props.total - 1)
/**
* @description 计算上一页按钮文案(最后一页用提交按钮配置的返回文案)
* @returns {import('vue').ComputedRef<string>}
*/
const prev_label_effective = computed(() => {
// 最后一页使用 submitButton.back_title,否则使用外部传入的 prevLabel
return showSubmit.value ? (props.submitButton?.back_title || props.prevLabel) : props.prevLabel
})
/**
* @description 计算上一页按钮禁用状态(最后一页用提交按钮配置的 is_back)
* @returns {import('vue').ComputedRef<boolean>}
*/
const prev_disabled_effective = computed(() => {
// 最后一页直接使用 submitButton.is_back 替换 prevDisabled;否则使用外部传入的 prevDisabled
return showSubmit.value ? (!props.submitButton?.is_back ?? props.prevDisabled) : props.prevDisabled
})
const onPrev = () => emit('prev')
const onNext = () => emit('next')
const onSubmit = () => emit('submit')
</script>
<style lang="less" scoped>
.pagination-field {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
padding: 0.75rem 1rem;
border-top: 1px solid #eaeaea;
display: flex;
flex-direction: column;
align-items: center;
z-index: 10;
.indicator {
font-size: 0.85rem;
color: #666;
margin-bottom: 0.5rem;
}
.actions {
// 三列栅格:左列起始(上一页),中列居中(提交),右列末尾(下一页)
display: grid;
width: 100%;
grid-template-columns: 1fr auto 1fr;
align-items: start; // 垂直方向顶对齐
min-height: 44px; // 保障容器高度,按钮靠顶部
.actionsLeft {
justify-self: start; // 左对齐到边
}
.actionsCenter {
justify-self: center; // 中间居中
}
.actionsRight {
justify-self: end; // 右对齐到边
}
.btn {
min-width: 6rem;
}
}
}
</style>