完成全部页面分页组件的抽取2
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
<view v-if="list.length === 0" class="empty-box">
|
||||
<text class="empty-text">暂无数据</text>
|
||||
</view>
|
||||
<view v-for="(item, index) in list" :key="index" class="table-row">
|
||||
<view v-for="(item, index) in pagedList" :key="index" class="table-row">
|
||||
<text class="td-cell flex-1 color-9">{{ item.id }}</text>
|
||||
<text class="td-cell flex-3">{{ item.name }}</text>
|
||||
<view class="td-cell flex-5">
|
||||
@@ -41,6 +41,23 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<CommonPagination
|
||||
v-if="true"
|
||||
:total="total"
|
||||
:loading="false"
|
||||
:currentPage="currentPage"
|
||||
:pageSize="pageSize"
|
||||
:pageSizeOptionLabels="pageSizeOptionLabels"
|
||||
:pageSizeIndex="pageSizeIndex"
|
||||
:visiblePages="visiblePages"
|
||||
:totalPage="totalPage"
|
||||
:jumpPageInput="jumpPageInput"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
@page-change="handlePageChange"
|
||||
@update:jumpPageInput="(val: string) => { jumpPageInput.value = val }"
|
||||
@jump-page="handleJumpPage"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 添加/编辑参数抽屉 (右侧 50%) -->
|
||||
@@ -101,7 +118,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
interface ParamKV {
|
||||
label: string;
|
||||
@@ -115,10 +133,55 @@ sort: number;
|
||||
params: ParamKV[];
|
||||
}
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 list 为 fetchParamList() 调用
|
||||
const list = reactive<ParamItem[]>([
|
||||
{ id: 1, name: '手机数码', sort: 1, params: [{label: '品牌', value: '华为'}, {label: '型号', value: 'Mate 60'}] as ParamKV[] },
|
||||
{ id: 2, name: '家用电器', sort: 2, params: [{label: '能效等级', value: '一级'}, {label: '产地', value: '中国'}] as ParamKV[] }
|
||||
{ id: 2, name: '家用电器', sort: 2, params: [{label: '能效等级', value: '一级'}, {label: '产地', value: '中国'}] as ParamKV[] },
|
||||
{ id: 3, name: '服装鞋履', sort: 3, params: [{label: '面料', value: '纯棉'}, {label: '适用季节', value: '春夏'}] as ParamKV[] },
|
||||
{ id: 4, name: '食品饮料', sort: 4, params: [{label: '保质期', value: '12个月'}, {label: '常温存储', value: '是'}] as ParamKV[] },
|
||||
{ id: 5, name: '家具家居', sort: 5, params: [{label: '材质', value: '实木'}, {label: '风格', value: '新中式'}] as ParamKV[] },
|
||||
{ id: 6, name: '美妆护肤', sort: 6, params: [{label: '肉质', value: '混合背'}, {label: '容量', value: '50ml'}] as ParamKV[] },
|
||||
{ id: 7, name: '图书文具', sort: 7, params: [{label: '出版社', value: '人民兰山'}, {label: '平装/精装', value: '精装'}] as ParamKV[] },
|
||||
{ id: 8, name: '运动户外', sort: 8, params: [{label: '适用季节', value: '冬季'}, {label: '防水等级', value: 'IPX5'}] as ParamKV[] },
|
||||
{ id: 9, name: '母婴童装', sort: 9, params: [{label: '适用年龄', value: '0-3岁'}, {label: '安全认证', value: 'CCC'}] as ParamKV[] },
|
||||
{ id: 10, name: '創业特惠', sort: 10, params: [{label: '折扣力度', value: '9折'}, {label: '限时时间', value: '7天'}] as ParamKV[] },
|
||||
{ id: 11, name: '山地车辆', sort: 11, params: [{label: '厂家', value: '丰田'}, {label: '排量', value: '2.0T'}] as ParamKV[] },
|
||||
{ id: 12, name: '唨具家电', sort: 12, params: [{label: '功率', value: '1500W'}, {label: '容量', value: '5L'}] as ParamKV[] }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const jumpPageInput = ref('')
|
||||
const pageSizeOptions = [10, 15, 20, 30, 50]
|
||||
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
|
||||
const pageSizeIndex = computed(() => { const idx = pageSizeOptions.indexOf(pageSize.value); return idx >= 0 ? idx : 0 })
|
||||
const total = computed(() => list.length)
|
||||
const totalPage = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
const pagedList = computed(() => {
|
||||
const start = (currentPage.value - 1) * pageSize.value
|
||||
return list.slice(start, start + pageSize.value)
|
||||
})
|
||||
const visiblePages = computed((): number[] => {
|
||||
const t = totalPage.value; const cur = currentPage.value
|
||||
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
|
||||
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
|
||||
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
|
||||
return [1, -1, cur - 1, cur, cur + 1, -1, t]
|
||||
})
|
||||
const handlePageChange = (p: number) => { currentPage.value = p }
|
||||
const handlePageSizeChange = (e: any) => {
|
||||
const idx = Number(e.detail.value)
|
||||
pageSize.value = pageSizeOptions[idx] ?? pageSizeOptions[0]
|
||||
currentPage.value = 1
|
||||
}
|
||||
const handleJumpPage = () => {
|
||||
const p = parseInt(jumpPageInput.value)
|
||||
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
|
||||
}
|
||||
// ========== END PAGINATION STATE ==========
|
||||
|
||||
const showDrawerMask = ref(false)
|
||||
const showDrawer = ref(false)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<view v-if="list.length === 0" class="empty-box">
|
||||
<text class="empty-text">暂无数据</text>
|
||||
</view>
|
||||
<view v-for="(item, index) in list" :key="index" class="table-row-item">
|
||||
<view v-for="(item, index) in pagedList" :key="index" class="table-row-item">
|
||||
<text class="td flex-1 color-9">{{ item.id }}</text>
|
||||
<view class="td flex-2">
|
||||
<image class="protection-icon-img" :src="item.icon" mode="aspectFit"></image>
|
||||
@@ -42,6 +42,22 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="true"
|
||||
:total="total"
|
||||
:loading="false"
|
||||
:currentPage="currentPage"
|
||||
:pageSize="pageSize"
|
||||
:pageSizeOptionLabels="pageSizeOptionLabels"
|
||||
:pageSizeIndex="pageSizeIndex"
|
||||
:visiblePages="visiblePages"
|
||||
:totalPage="totalPage"
|
||||
:jumpPageInput="jumpPageInput"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
@page-change="handlePageChange"
|
||||
@update:jumpPageInput="(val: string) => { jumpPageInput.value = val }"
|
||||
@jump-page="handleJumpPage"
|
||||
/>
|
||||
|
||||
<!-- 添加/编辑弹窗 (居中 Modal) -->
|
||||
<view class="modal-overlay" v-if="showModal" @click="closeModal">
|
||||
@@ -102,8 +118,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import StatusSwitch from '@/components/StatusSwitch.uvue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
interface ProtectionItem {
|
||||
id: number;
|
||||
@@ -114,10 +131,53 @@ interface ProtectionItem {
|
||||
sort: number;
|
||||
}
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 list 为 fetchProtectionList() 调用
|
||||
const list = reactive<ProtectionItem[]>([
|
||||
{ id: 1, name: '正品保障', icon: '/static/logo.png', desc: '该商品由平台认证,保证百分百正品。', status: true, sort: 0 },
|
||||
{ id: 2, name: '七天无理由', icon: '/static/logo.png', desc: '商品在不影响二次销售的情况下,支持7天无理由退换。', status: true, sort: 0 }
|
||||
{ id: 2, name: '七天无理由', icon: '/static/logo.png', desc: '商品在不影响二次销售的情况下,支持 7 天无理由退换。', status: true, sort: 0 },
|
||||
{ id: 3, name: '价格保指', icon: '/static/logo.png', desc: '购买后 30 天内如遇同款低价,即可申请价差补偿。', status: true, sort: 1 },
|
||||
{ id: 4, name: '全程颜料隐形', icon: '/static/logo.png', desc: '顺丰乐丰包装,不露商品信息,注重隐次保护。', status: true, sort: 2 },
|
||||
{ id: 5, name: '隐私保护', icon: '/static/logo.png', desc: '尥尺保护您的个人信息,不向任何第三方泄露。', status: true, sort: 3 },
|
||||
{ id: 6, name: '即时客服', icon: '/static/logo.png', desc: '7×24小时在线客服,随时解决您的问题。', status: true, sort: 4 },
|
||||
{ id: 7, name: '准时发货', icon: '/static/logo.png', desc: '下单后 48 小时内发货,快递全程跟踪。', status: false, sort: 5 },
|
||||
{ id: 8, name: '免费退返运', icon: '/static/logo.png', desc: '指定品类商品支持免费退返运。', status: true, sort: 6 },
|
||||
{ id: 9, name: '官方维修', icon: '/static/logo.png', desc: '各地维修中心 500+,提供上门维修服务。', status: true, sort: 7 },
|
||||
{ id: 10, name: '分期免息', icon: '/static/logo.png', desc: '支持花唉/支付分期,指定商品免息付款。', status: false, sort: 8 }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const jumpPageInput = ref('')
|
||||
const pageSizeOptions = [10, 15, 20, 30, 50]
|
||||
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
|
||||
const pageSizeIndex = computed(() => { const idx = pageSizeOptions.indexOf(pageSize.value); return idx >= 0 ? idx : 0 })
|
||||
const total = computed(() => list.length)
|
||||
const totalPage = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
const pagedList = computed(() => {
|
||||
const start = (currentPage.value - 1) * pageSize.value
|
||||
return list.slice(start, start + pageSize.value)
|
||||
})
|
||||
const visiblePages = computed((): number[] => {
|
||||
const t = totalPage.value; const cur = currentPage.value
|
||||
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
|
||||
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
|
||||
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
|
||||
return [1, -1, cur - 1, cur, cur + 1, -1, t]
|
||||
})
|
||||
const handlePageChange = (p: number) => { currentPage.value = p }
|
||||
const handlePageSizeChange = (e: any) => {
|
||||
const idx = Number(e.detail.value)
|
||||
pageSize.value = pageSizeOptions[idx] ?? pageSizeOptions[0]
|
||||
currentPage.value = 1
|
||||
}
|
||||
const handleJumpPage = () => {
|
||||
const p = parseInt(jumpPageInput.value)
|
||||
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
|
||||
}
|
||||
// ========== END PAGINATION STATE ==========
|
||||
|
||||
const showModal = ref(false)
|
||||
const isEdit = ref(false)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<view class="th col-op"><text>操作</text></view>
|
||||
</view>
|
||||
|
||||
<view v-for="item in replyList" :key="item.id" class="tr-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr-row">
|
||||
<view class="td col-check"><text>□</text></view>
|
||||
<view class="td col-id"><text>{{ item.id }}</text></view>
|
||||
<view class="td col-product">
|
||||
@@ -84,8 +84,8 @@
|
||||
|
||||
<!-- 分页 -->
|
||||
<CommonPagination
|
||||
v-if="replyList.length > 0"
|
||||
:total="replyList.length"
|
||||
v-if="true"
|
||||
:total="total"
|
||||
:loading="false"
|
||||
:currentPage="currentPage"
|
||||
:pageSize="pageSize"
|
||||
@@ -146,24 +146,25 @@ const replyList = ref([
|
||||
}
|
||||
])
|
||||
|
||||
// 分页适配状态
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
let jumpPageInput = ''
|
||||
const jumpPageInput = ref('')
|
||||
const pageSizeOptions = [10, 20, 30, 50]
|
||||
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
|
||||
const pageSizeIndex = computed(() => {
|
||||
const idx = pageSizeOptions.indexOf(pageSize.value)
|
||||
return idx >= 0 ? idx : 0
|
||||
const pageSizeIndex = computed(() => { const idx = pageSizeOptions.indexOf(pageSize.value); return idx >= 0 ? idx : 0 })
|
||||
const total = computed(() => replyList.value.length)
|
||||
const totalPage = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
const pagedList = computed(() => {
|
||||
const start = (currentPage.value - 1) * pageSize.value
|
||||
return replyList.value.slice(start, start + pageSize.value)
|
||||
})
|
||||
const totalPage = computed(() => Math.max(1, Math.ceil(replyList.value.length / pageSize.value)))
|
||||
const visiblePages = computed(() => {
|
||||
const total = totalPage.value
|
||||
const cur = currentPage.value
|
||||
if (total <= 7) return Array.from({ length: total }, (_: any, i: number) => i + 1)
|
||||
if (cur <= 4) return [1, 2, 3, 4, 5, -1, total]
|
||||
if (cur >= total - 3) return [1, -1, total - 4, total - 3, total - 2, total - 1, total]
|
||||
return [1, -1, cur - 1, cur, cur + 1, -1, total]
|
||||
const visiblePages = computed((): number[] => {
|
||||
const t = totalPage.value; const cur = currentPage.value
|
||||
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
|
||||
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
|
||||
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
|
||||
return [1, -1, cur - 1, cur, cur + 1, -1, t]
|
||||
})
|
||||
const handlePageChange = (p: number) => { currentPage.value = p }
|
||||
const handlePageSizeChange = (e: any) => {
|
||||
@@ -172,9 +173,10 @@ const handlePageSizeChange = (e: any) => {
|
||||
currentPage.value = 1
|
||||
}
|
||||
const handleJumpPage = () => {
|
||||
const p = parseInt(jumpPageInput)
|
||||
const p = parseInt(jumpPageInput.value)
|
||||
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
|
||||
}
|
||||
// ========== END PAGINATION STATE ==========
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -274,7 +276,7 @@ const handleJumpPage = () => {
|
||||
.col-reply { flex: 1; }
|
||||
.col-status { width: 100px; }
|
||||
.col-time { width: 160px; }
|
||||
.col-op { width: 180px; }
|
||||
.col-op { width: 180px; display: flex; flex-direction: row; }
|
||||
|
||||
.p-img { width: 40px; height: 40px; border-radius: 4px; }
|
||||
.p-name-txt { font-size: 13px; line-height: 1.4; color: #1890ff; }
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<view v-if="list.length === 0" class="empty-box">
|
||||
<text class="empty-text">暂无数据</text>
|
||||
</view>
|
||||
<view v-for="(item, index) in list" :key="index" class="table-row">
|
||||
<view v-for="(item, index) in pagedList" :key="index" class="table-row">
|
||||
<view class="td-cell flex-1 row-center">
|
||||
<view class="checkbox-mock" :class="item.selected ? 'checked' : ''" @click="item.selected = !item.selected">
|
||||
<text v-if="item.selected" class="check-mark">✓</text>
|
||||
@@ -50,6 +50,22 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="true"
|
||||
:total="total"
|
||||
:loading="false"
|
||||
:currentPage="currentPage"
|
||||
:pageSize="pageSize"
|
||||
:pageSizeOptionLabels="pageSizeOptionLabels"
|
||||
:pageSizeIndex="pageSizeIndex"
|
||||
:visiblePages="visiblePages"
|
||||
:totalPage="totalPage"
|
||||
:jumpPageInput="jumpPageInput"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
@page-change="handlePageChange"
|
||||
@update:jumpPageInput="(val: string) => { jumpPageInput.value = val }"
|
||||
@jump-page="handleJumpPage"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 添加规格弹窗 -->
|
||||
@@ -91,7 +107,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
interface AttrItem {
|
||||
id: number;
|
||||
@@ -101,13 +118,58 @@ interface AttrItem {
|
||||
selected: boolean;
|
||||
}
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 list 为 fetchSpecList() 调用
|
||||
const list = reactive<AttrItem[]>([
|
||||
{ id: 104, name: '颜色', specs: '红色,蓝色,黑色,白色', attrs: '颜色属性', selected: false },
|
||||
{ id: 105, name: '尺寸', specs: 'S,M,L,XL,XXL', attrs: '服装尺寸', selected: false },
|
||||
{ id: 106, name: '材质', specs: '纯棉,涤纶,真丝', attrs: '面料材质', selected: false },
|
||||
{ id: 106, name: '材质', specs: '纯棉,濯纶,真丝', attrs: '面料材质', selected: false },
|
||||
{ id: 107, name: '内存', specs: '8G,16G,32G', attrs: '硬件参数', selected: false },
|
||||
{ id: 108, name: '存储', specs: '128G,256G,512G', attrs: '容量', selected: false }
|
||||
{ id: 108, name: '存储', specs: '128G,256G,512G', attrs: '容量', selected: false },
|
||||
{ id: 109, name: '重量', specs: '100g,200g,500g,1kg', attrs: '包装规格', selected: false },
|
||||
{ id: 110, name: '口味', specs: '原味,辣味,甜味,咋味', attrs: '食品口味', selected: false },
|
||||
{ id: 111, name: '风格', specs: '日系,韩系,欧美,新中式', attrs: '服装风格', selected: false },
|
||||
{ id: 112, name: '屏幕尺寸', specs: '6.1小时,6.7小时,6.9小时', attrs: '手机屏幕', selected: false },
|
||||
{ id: 113, name: '套餐选择', specs: '套餐A,套餐B,套餐C', attrs: '餐飲套餐', selected: false },
|
||||
{ id: 114, name: '独立包装', specs: '独立包装,组合装', attrs: '包装方式', selected: false },
|
||||
{ id: 115, name: '靘刀', specs: '靘刀7天,靘刀14天,靘刀30天', attrs: '服装保洁', selected: false },
|
||||
{ id: 116, name: '宣传图', specs: '带宣传图,不带宣传图', attrs: '商品配送', selected: false },
|
||||
{ id: 117, name: '主题色', specs: '科技蓝,记忆红,森林绿,太空黑', attrs: '设备配色', selected: false },
|
||||
{ id: 118, name: '等级', specs: '普通版,标准版,旗舰版', attrs: '商品等级', selected: false }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const jumpPageInput = ref('')
|
||||
const pageSizeOptions = [10, 15, 20, 30, 50]
|
||||
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
|
||||
const pageSizeIndex = computed(() => { const idx = pageSizeOptions.indexOf(pageSize.value); return idx >= 0 ? idx : 0 })
|
||||
const total = computed(() => list.length)
|
||||
const totalPage = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
const pagedList = computed(() => {
|
||||
const start = (currentPage.value - 1) * pageSize.value
|
||||
return list.slice(start, start + pageSize.value)
|
||||
})
|
||||
const visiblePages = computed((): number[] => {
|
||||
const t = totalPage.value; const cur = currentPage.value
|
||||
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
|
||||
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
|
||||
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
|
||||
return [1, -1, cur - 1, cur, cur + 1, -1, t]
|
||||
})
|
||||
const handlePageChange = (p: number) => { currentPage.value = p }
|
||||
const handlePageSizeChange = (e: any) => {
|
||||
const idx = Number(e.detail.value)
|
||||
pageSize.value = pageSizeOptions[idx] ?? pageSizeOptions[0]
|
||||
currentPage.value = 1
|
||||
}
|
||||
const handleJumpPage = () => {
|
||||
const p = parseInt(jumpPageInput.value)
|
||||
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
|
||||
}
|
||||
// ========== END PAGINATION STATE ==========
|
||||
|
||||
const showModal = ref(false)
|
||||
const form = reactive({
|
||||
|
||||
Reference in New Issue
Block a user