完成90%页面分页组件的抽取
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in articleList" :key="item.id">
|
||||
<view class="table-row" v-for="item in pagedList" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-img">
|
||||
<view class="img-box"><text class="img-placeholder">🖼️</text></view>
|
||||
@@ -65,11 +65,22 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="pagination-bar">
|
||||
<view class="page-info">
|
||||
<text class="page-total">共 {{ articleList.length }} 条</text>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
|
||||
@@ -217,14 +228,68 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const filterCategory = ref('全部')
|
||||
const filterKeyword = ref('')
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 articleList 为 fetchArticleList() 调用
|
||||
const articleList = ref([
|
||||
{ id: '240', name: '赋能消费 | 卷狗优选迈向文化消费新时代', categoryName:'消费文化', linkedProduct: '', views: '3349', time: '2025-04-01 16:34' },
|
||||
{ id: '237', name: '把重要的日子放在桌面', categoryName:'品牌资讯', linkedProduct: '2024新款吹风机...', views: '260', time: '2025-04-01 16:32' }
|
||||
{ id: '260', name: '赋能消费 | 卷狗优选迈向文化消费新时代', categoryName: '消费文化', linkedProduct: '', views: '3349', time: '2025-04-01 16:34' },
|
||||
{ id: '259', name: '把重要的日子放在桌面', categoryName: '品牌资讯', linkedProduct: '2024新款吹风机...', views: '260', time: '2025-04-01 16:32' },
|
||||
{ id: '258', name: '春季家居好物推荐', categoryName: '购物心得', linkedProduct: '', views: '1820', time: '2025-03-28 10:00' },
|
||||
{ id: '257', name: '如何挑选适合自己的护肤品', categoryName: '消费文化', linkedProduct: '', views: '2100', time: '2025-03-25 14:20' },
|
||||
{ id: '256', name: '品牌创始人专访:坚守初心', categoryName: '品牌资讯', linkedProduct: '', views: '980', time: '2025-03-20 09:15' },
|
||||
{ id: '255', name: '高效厨房整理术', categoryName: '购物心得', linkedProduct: '多功能收纳盒...', views: '3456', time: '2025-03-18 11:30' },
|
||||
{ id: '254', name: '2025年度流行色解析', categoryName: '消费文化', linkedProduct: '', views: '4120', time: '2025-03-15 16:00' },
|
||||
{ id: '253', name: '新品发布:智能水杯上市', categoryName: '品牌资讯', linkedProduct: '智能水杯Pro', views: '5230', time: '2025-03-10 10:00' },
|
||||
{ id: '252', name: '宠物用品选购指南', categoryName: '购物心得', linkedProduct: '宠物牵引绳', views: '770', time: '2025-03-08 12:00' },
|
||||
{ id: '251', name: '极简生活方式的艺术', categoryName: '消费文化', linkedProduct: '', views: '6100', time: '2025-03-05 08:30' },
|
||||
{ id: '250', name: '环保购物袋全测评', categoryName: '购物心得', linkedProduct: '帆布购物袋', views: '1430', time: '2025-03-01 14:00' },
|
||||
{ id: '249', name: '春节营销实战复盘', categoryName: '品牌资讯', linkedProduct: '', views: '2210', time: '2025-02-20 09:00' },
|
||||
{ id: '248', name: '提升生活品质的10个妙招', categoryName: '消费文化', linkedProduct: '', views: '8900', time: '2025-02-15 10:00' },
|
||||
{ id: '247', name: '运动装备选购攻略', categoryName: '购物心得', linkedProduct: '跑步鞋推荐款', views: '3310', time: '2025-02-10 11:00' },
|
||||
{ id: '246', name: '年货节好物大盘点', categoryName: '品牌资讯', linkedProduct: '', views: '7640', time: '2025-02-05 14:00' },
|
||||
{ id: '245', name: '居家健身的正确打开方式', categoryName: '消费文化', linkedProduct: '哑铃套装', views: '4450', time: '2025-01-28 09:30' },
|
||||
{ id: '244', name: '厨房小家电测评合集', categoryName: '购物心得', linkedProduct: '空气炸锅推荐', views: '5560', time: '2025-01-20 10:00' },
|
||||
{ id: '243', name: '品牌十周年回顾', categoryName: '品牌资讯', linkedProduct: '', views: '3120', time: '2025-01-15 16:00' },
|
||||
{ id: '242', name: '冬季护肤必备清单', categoryName: '消费文化', linkedProduct: '', views: '6780', time: '2025-01-10 14:00' },
|
||||
{ id: '241', name: '新年礼物推荐:让 Ta 惊喜', categoryName: '购物心得', linkedProduct: '礼品套装', views: '9900', time: '2025-01-01 00:00' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => articleList.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 articleList.value.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 categoryList = ref(['购物心得', '消费文化', '品牌资讯', '全部']) // Mock data mirroring categories
|
||||
const dropdownVisible = ref(false)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in categoryList" :key="item.id">
|
||||
<view class="table-row" v-for="item in pagedList" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-name"><text class="td-txt">{{ item.name }}</text></view>
|
||||
<view class="td col-img">
|
||||
@@ -57,6 +57,22 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
|
||||
@@ -135,15 +151,68 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import StatusSwitch from '@/components/StatusSwitch.uvue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const filterKeyword = ref('')
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 categoryList 为 fetchCategoryList() 调用
|
||||
const categoryList = ref([
|
||||
{ id: '181', name: '购物心得', status: true },
|
||||
{ id: '180', name: '消费文化', status: true },
|
||||
{ id: '179', name: '品牌资讯', status: true }
|
||||
{ id: '200', name: '购物心得', status: true },
|
||||
{ id: '199', name: '消费文化', status: true },
|
||||
{ id: '198', name: '品牌资讯', status: true },
|
||||
{ id: '197', name: '新品上市', status: true },
|
||||
{ id: '196', name: '生活方式', status: false },
|
||||
{ id: '195', name: '健康养生', status: true },
|
||||
{ id: '194', name: '科技数码', status: true },
|
||||
{ id: '193', name: '家居家装', status: false },
|
||||
{ id: '192', name: '美食美味', status: true },
|
||||
{ id: '191', name: '旅行户外', status: true },
|
||||
{ id: '190', name: '时尚穿搭', status: true },
|
||||
{ id: '189', name: '亲子活动', status: false },
|
||||
{ id: '188', name: '身心健康', status: true },
|
||||
{ id: '187', name: '财经商业', status: true },
|
||||
{ id: '186', name: '文化艺术', status: true },
|
||||
{ id: '185', name: '社交情感', status: false },
|
||||
{ id: '184', name: '工具技能', status: true },
|
||||
{ id: '183', name: '玩具游戏', status: true },
|
||||
{ id: '182', name: '守护联盟', status: true },
|
||||
{ id: '181', name: '全部分类', status: true }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => categoryList.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 categoryList.value.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 showDrawer = ref(false)
|
||||
const isClosing = ref(false)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<view class="col col-ops"><text>操作</text></view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in agentList" :key="item.uid" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.uid" class="table-row">
|
||||
<view class="col col-uid"><text>{{ item.uid }}</text></view>
|
||||
<view class="col col-avatar">
|
||||
<image class="avatar-img" src="/static/logo.png" mode="aspectFill" />
|
||||
@@ -51,14 +51,87 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 agentList 为 fetchAgentList() 调用
|
||||
const agentList = ref([
|
||||
{ uid: '60569', name: 'cs2020', ratio: 50, staffCount: 1, endTime: '2026-01-01', status: true },
|
||||
{ uid: '60570', name: '张伟', ratio: 45, staffCount: 3, endTime: '2026-06-30', status: true },
|
||||
{ uid: '60571', name: '李华', ratio: 40, staffCount: 5, endTime: '2026-12-31', status: true },
|
||||
{ uid: '60572', name: '王芳', ratio: 38, staffCount: 2, endTime: '2027-03-01', status: false },
|
||||
{ uid: '60573', name: '赵磊', ratio: 42, staffCount: 7, endTime: '2026-09-30', status: true },
|
||||
{ uid: '60574', name: '陈浩', ratio: 35, staffCount: 0, endTime: '2026-04-15', status: true },
|
||||
{ uid: '60575', name: '刘娜', ratio: 48, staffCount: 4, endTime: '2026-08-01', status: true },
|
||||
{ uid: '60576', name: '黄明', ratio: 33, staffCount: 6, endTime: '2027-01-31', status: false },
|
||||
{ uid: '60577', name: '周静', ratio: 52, staffCount: 1, endTime: '2026-11-30', status: true },
|
||||
{ uid: '60578', name: '吴强', ratio: 30, staffCount: 9, endTime: '2026-07-15', status: true },
|
||||
{ uid: '60579', name: '郑丽', ratio: 55, staffCount: 2, endTime: '2026-03-31', status: true },
|
||||
{ uid: '60580', name: '孙勇', ratio: 28, staffCount: 11, endTime: '2027-06-30', status: true },
|
||||
{ uid: '60581', name: '朱婷', ratio: 46, staffCount: 3, endTime: '2026-10-31', status: false },
|
||||
{ uid: '60582', name: '马林', ratio: 37, staffCount: 0, endTime: '2026-05-01', status: true },
|
||||
{ uid: '60583', name: '胡倩', ratio: 41, staffCount: 8, endTime: '2026-02-28', status: true },
|
||||
{ uid: '60584', name: '高峰', ratio: 36, staffCount: 4, endTime: '2027-09-30', status: true },
|
||||
{ uid: '60585', name: '梁雪', ratio: 49, staffCount: 2, endTime: '2026-06-15', status: false },
|
||||
{ uid: '60586', name: '邓超', ratio: 32, staffCount: 6, endTime: '2027-02-01', status: true },
|
||||
{ uid: '60587', name: '彭宇', ratio: 44, staffCount: 5, endTime: '2026-08-30', status: true },
|
||||
{ uid: '60588', name: '曹芸', ratio: 39, staffCount: 1, endTime: '2026-12-01', status: true },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => agentList.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 agentList.value.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 ==========
|
||||
|
||||
function onSearch() { uni.showToast({ title: '查询中...', icon: 'none' }) }
|
||||
function onAdd() { uni.showToast({ title: '添加中...', icon: 'none' }) }
|
||||
</script>
|
||||
@@ -76,7 +149,8 @@ function onAdd() { uni.showToast({ title: '添加中...', icon: 'none' }) }
|
||||
.table-header { display: flex; flex-direction: row; background: #f8faff; border-bottom: 1px solid #f0f0f0; padding: 12px 0; }
|
||||
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #f0f0f0; padding: 12px 0; align-items: center; &:hover { background: #fafafa; } }
|
||||
.col { padding: 0 8px; font-size: 14px; color: #333; display: flex; align-items: center; }
|
||||
.col-uid { width: 80px; } .col-avatar { width: 80px; justify-content: center; } .col-name { width: 120px; } .col-ratio { width: 100px; justify-content: center; } .col-count { width: 100px; justify-content: center; } .col-time { width: 120px; justify-content: center; } .col-status { width: 80px; justify-content: center; } .col-ops { flex: 1; justify-content: flex-end; }
|
||||
.col-uid { width: 80px; } .col-avatar { width: 80px; justify-content: center; } .col-name { width: 120px; } .col-ratio { width: 100px; justify-content: center; } .col-count { width: 100px; justify-content: center; } .col-time { width: 120px; justify-content: center; } .col-status { width: 80px; justify-content: center; }
|
||||
.col-ops { flex: 1; justify-content: flex-end; display: flex; flex-direction: row; }
|
||||
.avatar-img { width: 32px; height: 32px; border-radius: 2px; }
|
||||
.op-link { color: #1890ff; cursor: pointer; }
|
||||
.op-divider { color: #e8e8e8; margin: 0 8px; }
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<view class="col col-ops"><text>操作</text></view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in applyList" :key="item.uid" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.uid" class="table-row">
|
||||
<view class="col col-uid"><text>{{ item.uid }}</text></view>
|
||||
<view class="col col-name"><text>{{ item.name }}</text></view>
|
||||
<view class="col col-phone"><text>{{ item.phone }}</text></view>
|
||||
@@ -53,16 +53,90 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const activeTab = ref(0)
|
||||
const tabs = ['全部', '申请中', '已同意', '已拒绝']
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 applyList 为 fetchApplyList() 调用
|
||||
const applyList = ref([
|
||||
{ uid: '81806', name: '测试测试', phone: '19910205954', deptName: '26991', time: '2026-01-08 15:30:39', statusText: '申请中', code: '70623142' },
|
||||
{ uid: '81807', name: '张三', phone: '13812345678', deptName: '北京事业部', time: '2026-01-10 09:20:15', statusText: '已同意', code: '80731253' },
|
||||
{ uid: '81808', name: '李四', phone: '13987654321', deptName: '上海事业部', time: '2026-01-12 14:05:33', statusText: '已拒绝', code: '90842364' },
|
||||
{ uid: '81809', name: '王五', phone: '15012341234', deptName: '广州事业部', time: '2026-01-15 11:45:20', statusText: '申请中', code: '10953475' },
|
||||
{ uid: '81810', name: '赵六', phone: '18600001111', deptName: '深圳事业部', time: '2026-01-18 08:30:00', statusText: '已同意', code: '21064586' },
|
||||
{ uid: '81811', name: '孙七', phone: '17712349876', deptName: '成都事业部', time: '2026-01-20 16:15:44', statusText: '已同意', code: '32175697' },
|
||||
{ uid: '81812', name: '周八', phone: '13300002222', deptName: '杭州事业部', time: '2026-01-22 10:55:30', statusText: '申请中', code: '43286708' },
|
||||
{ uid: '81813', name: '吴九', phone: '15566667777', deptName: '武汉事业部', time: '2026-01-25 13:40:18', statusText: '已拒绝', code: '54397819' },
|
||||
{ uid: '81814', name: '郑十', phone: '18899998888', deptName: '南京事业部', time: '2026-01-28 09:00:05', statusText: '申请中', code: '65408920' },
|
||||
{ uid: '81815', name: '冯云', phone: '13712348765', deptName: '西安事业部', time: '2026-02-01 15:20:33', statusText: '已同意', code: '76519031' },
|
||||
{ uid: '81816', name: '陈霞', phone: '15087651234', deptName: '重庆事业部', time: '2026-02-05 11:10:22', statusText: '申请中', code: '87620142' },
|
||||
{ uid: '81817', name: '蒋峰', phone: '13500004444', deptName: '郑州事业部', time: '2026-02-08 14:35:49', statusText: '已同意', code: '98731253' },
|
||||
{ uid: '81818', name: '卫林', phone: '17656785678', deptName: '长沙事业部', time: '2026-02-10 08:45:11', statusText: '已拒绝', code: '09842364' },
|
||||
{ uid: '81819', name: '蒋彪', phone: '18211112222', deptName: '合肥事业部', time: '2026-02-12 17:00:00', statusText: '申请中', code: '10953476' },
|
||||
{ uid: '81820', name: '沈辉', phone: '13655554444', deptName: '天津事业部', time: '2026-02-15 12:30:40', statusText: '已同意', code: '21064587' },
|
||||
{ uid: '81821', name: '韩磊', phone: '15999990000', deptName: '苏州事业部', time: '2026-02-18 09:55:28', statusText: '已同意', code: '32175698' },
|
||||
{ uid: '81822', name: '杨红', phone: '17811122233', deptName: '宁波事业部', time: '2026-02-20 16:40:15', statusText: '申请中', code: '43286709' },
|
||||
{ uid: '81823', name: '秦波', phone: '13234561234', deptName: '厦门事业部', time: '2026-02-22 11:20:06', statusText: '已拒绝', code: '54397820' },
|
||||
{ uid: '81824', name: '许丹', phone: '18777776666', deptName: '青岛事业部', time: '2026-02-25 14:05:50', statusText: '已同意', code: '65408921' },
|
||||
{ uid: '81825', name: '何强', phone: '15344443333', deptName: '福州事业部', time: '2026-02-28 08:15:38', statusText: '申请中', code: '76519032' },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => applyList.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 applyList.value.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 ==========
|
||||
|
||||
function onSearch() { uni.showToast({ title: '查询中...', icon: 'none' }) }
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@@ -80,7 +154,8 @@ function onSearch() { uni.showToast({ title: '查询中...', icon: 'none' }) }
|
||||
.table-header { display: flex; flex-direction: row; background: #f8faff; border-bottom: 1px solid #f0f0f0; padding: 12px 0; }
|
||||
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #f0f0f0; padding: 12px 0; align-items: center; &:hover { background: #fafafa; } }
|
||||
.col { padding: 0 8px; font-size: 14px; color: #333; display: flex; align-items: center; }
|
||||
.col-uid { width: 80px; } .col-name { width: 120px; } .col-phone { width: 120px; } .col-dept { width: 120px; } .col-img { width: 80px; justify-content: center; } .col-time { width: 160px; justify-content: center; } .col-status { width: 100px; justify-content: center; } .col-code { width: 100px; justify-content: center; } .col-ops { flex: 1; justify-content: flex-end; }
|
||||
.col-uid { width: 80px; } .col-name { width: 120px; } .col-phone { width: 120px; } .col-dept { width: 120px; } .col-img { width: 80px; justify-content: center; } .col-time { width: 160px; justify-content: center; } .col-status { width: 100px; justify-content: center; } .col-code { width: 100px; justify-content: center; }
|
||||
.col-ops { flex: 1; justify-content: flex-end; display: flex; flex-direction: row; }
|
||||
.table-img { width: 32px; height: 32px; border-radius: 2px; }
|
||||
.status-tag { border: 1px solid #1890ff; color: #1890ff; padding: 2px 8px; border-radius: 4px; font-size: 12px; }
|
||||
.code-box { border: 1px solid #d9d9d9; padding: 2px 8px; border-radius: 4px; font-size: 12px; background: #fafafa; }
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<view class="col col-ops"><text>操作</text></view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in divisionList" :key="item.uid" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.uid" class="table-row">
|
||||
<view class="col col-uid"><text>{{ item.uid }}</text></view>
|
||||
<view class="col col-avatar">
|
||||
<image class="avatar-img" src="/static/logo.png" mode="aspectFill" />
|
||||
@@ -51,14 +51,87 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 divisionList 为 fetchDivisionList() 调用
|
||||
const divisionList = ref([
|
||||
{ uid: '26991', name: '26991', code: '70623142', ratio: 40, agentCount: 1, endTime: '2026-12-31', status: true },
|
||||
{ uid: '26991', name: '北京事业部', code: '70623142', ratio: 40, agentCount: 5, endTime: '2026-12-31', status: true },
|
||||
{ uid: '26992', name: '上海事业部', code: '80731253', ratio: 35, agentCount: 8, endTime: '2026-06-30', status: true },
|
||||
{ uid: '26993', name: '广州事业部', code: '90842364', ratio: 38, agentCount: 3, endTime: '2027-03-01', status: true },
|
||||
{ uid: '26994', name: '深圳事业部', code: '10953475', ratio: 42, agentCount: 12, endTime: '2026-09-30', status: false },
|
||||
{ uid: '26995', name: '成都事业部', code: '21064586', ratio: 30, agentCount: 2, endTime: '2026-08-15', status: true },
|
||||
{ uid: '26996', name: '杭州事业部', code: '32175697', ratio: 45, agentCount: 7, endTime: '2026-12-01', status: true },
|
||||
{ uid: '26997', name: '武汉事业部', code: '43286708', ratio: 33, agentCount: 4, endTime: '2027-01-01', status: true },
|
||||
{ uid: '26998', name: '南京事业部', code: '54397819', ratio: 36, agentCount: 6, endTime: '2026-11-30', status: false },
|
||||
{ uid: '26999', name: '西安事业部', code: '65408920', ratio: 40, agentCount: 1, endTime: '2026-07-31', status: true },
|
||||
{ uid: '27000', name: '重庆事业部', code: '76519031', ratio: 28, agentCount: 9, endTime: '2026-10-01', status: true },
|
||||
{ uid: '27001', name: '郑州事业部', code: '87620142', ratio: 32, agentCount: 3, endTime: '2026-05-31', status: true },
|
||||
{ uid: '27002', name: '长沙事业部', code: '98731253', ratio: 37, agentCount: 5, endTime: '2027-02-28', status: false },
|
||||
{ uid: '27003', name: '合肥事业部', code: '09842364', ratio: 41, agentCount: 2, endTime: '2026-04-30', status: true },
|
||||
{ uid: '27004', name: '天津事业部', code: '10953476', ratio: 39, agentCount: 10, endTime: '2026-12-31', status: true },
|
||||
{ uid: '27005', name: '苏州事业部', code: '21064587', ratio: 34, agentCount: 4, endTime: '2026-03-31', status: true },
|
||||
{ uid: '27006', name: '宁波事业部', code: '32175698', ratio: 43, agentCount: 6, endTime: '2027-06-30', status: true },
|
||||
{ uid: '27007', name: '厦门事业部', code: '43286709', ratio: 31, agentCount: 1, endTime: '2026-08-31', status: false },
|
||||
{ uid: '27008', name: '青岛事业部', code: '54397820', ratio: 44, agentCount: 7, endTime: '2026-02-28', status: true },
|
||||
{ uid: '27009', name: '福州事业部', code: '65408921', ratio: 29, agentCount: 3, endTime: '2027-04-30', status: true },
|
||||
{ uid: '27010', name: '昆明事业部', code: '76519032', ratio: 46, agentCount: 8, endTime: '2026-01-31', status: true },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => divisionList.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 divisionList.value.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 ==========
|
||||
|
||||
function onSearch() { uni.showToast({ title: '查询中...', icon: 'none' }) }
|
||||
function onAdd() { uni.showToast({ title: '添加中...', icon: 'none' }) }
|
||||
</script>
|
||||
@@ -76,7 +149,8 @@ function onAdd() { uni.showToast({ title: '添加中...', icon: 'none' }) }
|
||||
.table-header { display: flex; flex-direction: row; background: #f8faff; border-bottom: 1px solid #f0f0f0; padding: 12px 0; }
|
||||
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #f0f0f0; padding: 12px 0; align-items: center; &:hover { background: #fafafa; } }
|
||||
.col { padding: 0 8px; font-size: 14px; color: #333; display: flex; align-items: center; }
|
||||
.col-uid { width: 80px; } .col-avatar { width: 80px; justify-content: center; } .col-name { width: 120px; } .col-code { width: 100px; justify-content: center; } .col-ratio { width: 100px; justify-content: center; } .col-count { width: 100px; justify-content: center; } .col-time { width: 120px; justify-content: center; } .col-status { width: 80px; justify-content: center; } .col-ops { flex: 1; justify-content: flex-end; }
|
||||
.col-uid { width: 80px; } .col-avatar { width: 80px; justify-content: center; } .col-name { width: 120px; } .col-code { width: 100px; justify-content: center; } .col-ratio { width: 100px; justify-content: center; } .col-count { width: 100px; justify-content: center; } .col-time { width: 120px; justify-content: center; } .col-status { width: 80px; justify-content: center; }
|
||||
.col-ops { flex: 1; justify-content: flex-end; display: flex; flex-direction: row; }
|
||||
.avatar-img { width: 32px; height: 32px; border-radius: 2px; }
|
||||
.op-link { color: #1890ff; cursor: pointer; }
|
||||
.op-divider { color: #e8e8e8; margin: 0 8px; }
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<view class="col col-ops"><text>操作</text></view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in levelList" :key="item.id" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="table-row">
|
||||
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||
<view class="col col-img">
|
||||
<image class="table-img" src="/static/logo.png" mode="aspectFill" />
|
||||
@@ -57,17 +57,87 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pagination">
|
||||
<text class="page-info">共 {{ levelList.length }} 条</text>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 levelList 为 fetchLevelList() 调用
|
||||
const levelList = ref([
|
||||
{ id: '1', name: '一级分销员', level: 1, percent1: 0.00, percent2: 0.00, taskTotal: 0, taskFinish: 0, show: true },
|
||||
{ id: '1', name: '一级分销员', level: 1, percent1: 20.00, percent2: 10.00, taskTotal: 5, taskFinish: 3, show: true },
|
||||
{ id: '2', name: '二级分销员', level: 2, percent1: 15.00, percent2: 8.00, taskTotal: 3, taskFinish: 2, show: true },
|
||||
{ id: '3', name: '三级分销员', level: 3, percent1: 10.00, percent2: 5.00, taskTotal: 2, taskFinish: 1, show: true },
|
||||
{ id: '4', name: '铂金分销员', level: 4, percent1: 25.00, percent2: 12.00, taskTotal: 8, taskFinish: 6, show: true },
|
||||
{ id: '5', name: '钻石分销员', level: 5, percent1: 30.00, percent2: 15.00, taskTotal: 10, taskFinish: 8, show: false },
|
||||
{ id: '6', name: '精英分销员', level: 6, percent1: 18.00, percent2: 9.00, taskTotal: 4, taskFinish: 4, show: true },
|
||||
{ id: '7', name: '超级分销员', level: 7, percent1: 35.00, percent2: 18.00, taskTotal: 12, taskFinish: 10, show: true },
|
||||
{ id: '8', name: '黄金分销员', level: 8, percent1: 22.00, percent2: 11.00, taskTotal: 6, taskFinish: 5, show: true },
|
||||
{ id: '9', name: '白银分销员', level: 9, percent1: 12.00, percent2: 6.00, taskTotal: 3, taskFinish: 1, show: false },
|
||||
{ id: '10', name: '青铜分销员', level: 10, percent1: 8.00, percent2: 4.00, taskTotal: 2, taskFinish: 0, show: true },
|
||||
{ id: '11', name: '新人分销员', level: 11, percent1: 5.00, percent2: 2.00, taskTotal: 1, taskFinish: 0, show: true },
|
||||
{ id: '12', name: 'VIP分销员', level: 12, percent1: 28.00, percent2: 14.00, taskTotal: 7, taskFinish: 7, show: true },
|
||||
{ id: '13', name: '明星分销员', level: 13, percent1: 32.00, percent2: 16.00, taskTotal: 9, taskFinish: 8, show: true },
|
||||
{ id: '14', name: '王者分销员', level: 14, percent1: 40.00, percent2: 20.00, taskTotal: 15, taskFinish: 12, show: false },
|
||||
{ id: '15', name: '传奇分销员', level: 15, percent1: 45.00, percent2: 22.00, taskTotal: 20, taskFinish: 18, show: true },
|
||||
{ id: '16', name: '荣耀分销员', level: 16, percent1: 38.00, percent2: 19.00, taskTotal: 11, taskFinish: 9, show: true },
|
||||
{ id: '17', name: '至尊分销员', level: 17, percent1: 42.00, percent2: 21.00, taskTotal: 14, taskFinish: 11, show: true },
|
||||
{ id: '18', name: '神话分销员', level: 18, percent1: 48.00, percent2: 24.00, taskTotal: 18, taskFinish: 15, show: false },
|
||||
{ id: '19', name: '无双分销员', level: 19, percent1: 50.00, percent2: 25.00, taskTotal: 20, taskFinish: 20, show: true },
|
||||
{ id: '20', name: '巅峰分销员', level: 20, percent1: 55.00, percent2: 28.00, taskTotal: 25, taskFinish: 22, show: true },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => levelList.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 levelList.value.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 ==========
|
||||
|
||||
function onSearch() { uni.showToast({ title: '查询中...', icon: 'none' }) }
|
||||
function onAdd() { uni.showToast({ title: '添加中...', icon: 'none' }) }
|
||||
</script>
|
||||
@@ -86,7 +156,8 @@ function onAdd() { uni.showToast({ title: '添加中...', icon: 'none' }) }
|
||||
.table-header { display: flex; flex-direction: row; background: #f8faff; border-bottom: 1px solid #f0f0f0; padding: 12px 0; }
|
||||
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #f0f0f0; padding: 12px 0; align-items: center; &:hover { background: #fafafa; } }
|
||||
.col { padding: 0 8px; display: flex; align-items: center; font-size: 14px; color: #333; }
|
||||
.col-id { width: 50px; } .col-img { width: 80px; justify-content: center; } .col-name { width: 120px; } .col-level { width: 80px; justify-content: center; } .col-percent { width: 120px; justify-content: center; } .col-stat { width: 100px; justify-content: center; } .col-status { width: 100px; justify-content: center; } .col-ops { flex: 1; justify-content: flex-end; padding-right: 16px; }
|
||||
.col-id { width: 50px; } .col-img { width: 80px; justify-content: center; } .col-name { width: 120px; } .col-level { width: 80px; justify-content: center; } .col-percent { width: 120px; justify-content: center; } .col-stat { width: 100px; justify-content: center; } .col-status { width: 100px; justify-content: center; }
|
||||
.col-ops { flex: 1; justify-content: flex-end; padding-right: 16px; display: flex; flex-direction: row; }
|
||||
.table-img { width: 32px; height: 32px; border-radius: 2px; }
|
||||
.op-link { color: #1890ff; cursor: pointer; }
|
||||
.op-divider { color: #e8e8e8; margin: 0 8px; }
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<view class="col col-ops"><text>操作</text></view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in promoterList" :key="item.id" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="table-row">
|
||||
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||
<view class="col col-img">
|
||||
<image class="table-img" src="/static/logo.png" mode="aspectFill" />
|
||||
@@ -67,18 +67,88 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pagination">
|
||||
<text class="page-info">共 {{ promoterList.length }} 条</text>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 promoterList 为 fetchPromoterList() 调用
|
||||
const promoterList = ref([
|
||||
{ id: '82764', nickname: '183****5762', name: '-', phone: '183****5762', level: '--', userCount: 0, orderCount: 0, orderAmount: '0.00', commissionTotal: '0.00', withdrawnAmount: 0, withdrawCount: 0, unwithdrawnAmount: 0 },
|
||||
{ id: '82765', nickname: '张小明', name: '张小明', phone: '138****1234', level: '一级', userCount: 12, orderCount: 8, orderAmount: '2560.00', commissionTotal: '256.00', withdrawnAmount: 200, withdrawCount: 2, unwithdrawnAmount: 56 },
|
||||
{ id: '82766', nickname: '李美丽', name: '李美丽', phone: '139****5678', level: '二级', userCount: 5, orderCount: 3, orderAmount: '980.00', commissionTotal: '98.00', withdrawnAmount: 50, withdrawCount: 1, unwithdrawnAmount: 48 },
|
||||
{ id: '82767', nickname: '王大力', name: '王大力', phone: '150****9876', level: '一级', userCount: 28, orderCount: 20, orderAmount: '8800.00', commissionTotal: '880.00', withdrawnAmount: 800, withdrawCount: 5, unwithdrawnAmount: 80 },
|
||||
{ id: '82768', nickname: '赵小红', name: '赵小红', phone: '186****1111', level: '三级', userCount: 3, orderCount: 2, orderAmount: '450.00', commissionTotal: '22.50', withdrawnAmount: 0, withdrawCount: 0, unwithdrawnAmount: 22.5 },
|
||||
{ id: '82769', nickname: '陈风', name: '陈风', phone: '177****2222', level: '二级', userCount: 15, orderCount: 10, orderAmount: '3200.00', commissionTotal: '320.00', withdrawnAmount: 300, withdrawCount: 3, unwithdrawnAmount: 20 },
|
||||
{ id: '82770', nickname: '刘明亮', name: '刘明亮', phone: '133****3333', level: '一级', userCount: 42, orderCount: 35, orderAmount: '15600.00', commissionTotal: '1560.00', withdrawnAmount: 1500, withdrawCount: 8, unwithdrawnAmount: 60 },
|
||||
{ id: '82771', nickname: '黄小花', name: '黄小花', phone: '155****4444', level: '--', userCount: 1, orderCount: 0, orderAmount: '0.00', commissionTotal: '0.00', withdrawnAmount: 0, withdrawCount: 0, unwithdrawnAmount: 0 },
|
||||
{ id: '82772', nickname: '周建国', name: '周建国', phone: '188****5555', level: '二级', userCount: 9, orderCount: 6, orderAmount: '2100.00', commissionTotal: '210.00', withdrawnAmount: 200, withdrawCount: 2, unwithdrawnAmount: 10 },
|
||||
{ id: '82773', nickname: '吴晓燕', name: '吴晓燕', phone: '137****6666', level: '一级', userCount: 20, orderCount: 15, orderAmount: '6300.00', commissionTotal: '630.00', withdrawnAmount: 600, withdrawCount: 4, unwithdrawnAmount: 30 },
|
||||
{ id: '82774', nickname: '郑强', name: '郑强', phone: '150****7777', level: '三级', userCount: 2, orderCount: 1, orderAmount: '320.00', commissionTotal: '16.00', withdrawnAmount: 0, withdrawCount: 0, unwithdrawnAmount: 16 },
|
||||
{ id: '82775', nickname: '孙月', name: '孙月', phone: '182****8888', level: '一级', userCount: 35, orderCount: 28, orderAmount: '11200.00', commissionTotal: '1120.00', withdrawnAmount: 1000, withdrawCount: 6, unwithdrawnAmount: 120 },
|
||||
{ id: '82776', nickname: '冯磊', name: '冯磊', phone: '136****9999', level: '二级', userCount: 8, orderCount: 5, orderAmount: '1800.00', commissionTotal: '180.00', withdrawnAmount: 150, withdrawCount: 2, unwithdrawnAmount: 30 },
|
||||
{ id: '82777', nickname: '陈小丽', name: '陈小丽', phone: '159****0000', level: '--', userCount: 0, orderCount: 0, orderAmount: '0.00', commissionTotal: '0.00', withdrawnAmount: 0, withdrawCount: 0, unwithdrawnAmount: 0 },
|
||||
{ id: '82778', nickname: '蒋涛', name: '蒋涛', phone: '178****1234', level: '一级', userCount: 18, orderCount: 12, orderAmount: '4500.00', commissionTotal: '450.00', withdrawnAmount: 400, withdrawCount: 3, unwithdrawnAmount: 50 },
|
||||
{ id: '82779', nickname: '卫芳', name: '卫芳', phone: '132****5678', level: '三级', userCount: 4, orderCount: 3, orderAmount: '750.00', commissionTotal: '37.50', withdrawnAmount: 30, withdrawCount: 1, unwithdrawnAmount: 7.5 },
|
||||
{ id: '82780', nickname: '韩超', name: '韩超', phone: '156****9876', level: '二级', userCount: 11, orderCount: 8, orderAmount: '2800.00', commissionTotal: '280.00', withdrawnAmount: 250, withdrawCount: 3, unwithdrawnAmount: 30 },
|
||||
{ id: '82781', nickname: '杨静', name: '杨静', phone: '199****1111', level: '一级', userCount: 25, orderCount: 18, orderAmount: '7200.00', commissionTotal: '720.00', withdrawnAmount: 700, withdrawCount: 5, unwithdrawnAmount: 20 },
|
||||
{ id: '82782', nickname: '秦刚', name: '秦刚', phone: '135****2222', level: '--', userCount: 0, orderCount: 0, orderAmount: '0.00', commissionTotal: '0.00', withdrawnAmount: 0, withdrawCount: 0, unwithdrawnAmount: 0 },
|
||||
{ id: '82783', nickname: '许丽华', name: '许丽华', phone: '180****3333', level: '二级', userCount: 7, orderCount: 4, orderAmount: '1400.00', commissionTotal: '140.00', withdrawnAmount: 100, withdrawCount: 1, unwithdrawnAmount: 40 },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => promoterList.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 promoterList.value.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 ==========
|
||||
|
||||
function onSearch() { uni.showToast({ title: '查询中...', icon: 'none' }) }
|
||||
function onExport() { uni.showToast({ title: '开始导出', icon: 'none' }) }
|
||||
function onPromoter(item: any) { uni.showToast({ title: '推广人: ' + item.id, icon: 'none' }) }
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</view>
|
||||
|
||||
<scroll-view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.id">
|
||||
<view class="table-row" v-for="item in pagedList" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-order text-left"><text class="td-txt">{{ item.order }}</text></view>
|
||||
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
|
||||
@@ -49,12 +49,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
interface BalanceRecord {
|
||||
id: string
|
||||
@@ -66,71 +83,63 @@ interface BalanceRecord {
|
||||
remark: string
|
||||
}
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 tableData 为 fetchBalanceRecordList() 调用
|
||||
const tableData = ref<BalanceRecord[]>([
|
||||
{
|
||||
id: '31216',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 10:30:11',
|
||||
amount: '+ 88888.00',
|
||||
user: '1',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31215',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 10:19:52',
|
||||
amount: '+ 88888.00',
|
||||
user: 'circus',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31214',
|
||||
order: 'cp541560738494283776',
|
||||
time: '2026-02-03 10:09:07',
|
||||
amount: '- 999.00',
|
||||
user: '1岁上班22岁退休',
|
||||
type: '余额支付购买商品',
|
||||
remark: '余额支付999.00元购买商品'
|
||||
},
|
||||
{
|
||||
id: '31213',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 10:07:59',
|
||||
amount: '+ 88888.00',
|
||||
user: '1岁上班22岁退休',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31212',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 02:17:24',
|
||||
amount: '+ 88888.00',
|
||||
user: '136****0434',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31211',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 02:04:17',
|
||||
amount: '+ 88888.00',
|
||||
user: '灵境',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31210',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 00:58:21',
|
||||
amount: '+ 88888.00',
|
||||
user: 'J.',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
}
|
||||
{ id: '31216', order: '新用户注册赠送余额', time: '2026-02-03 10:30:11', amount: '+ 88888.00', user: '1', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31215', order: '新用户注册赠送余额', time: '2026-02-03 10:19:52', amount: '+ 88888.00', user: 'circus', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31214', order: 'cp541560738494283776', time: '2026-02-03 10:09:07', amount: '- 999.00', user: '1岁上班22岁退休', type: '余额支付购买商品', remark: '余额支付999.00元购买商品' },
|
||||
{ id: '31213', order: '新用户注册赠送余额', time: '2026-02-03 10:07:59', amount: '+ 88888.00', user: '1岁上班22岁退休', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31212', order: '新用户注册赠送余额', time: '2026-02-03 02:17:24', amount: '+ 88888.00', user: '136****0434', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31211', order: '新用户注册赠送余额', time: '2026-02-03 02:04:17', amount: '+ 88888.00', user: '灵境', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31210', order: '新用户注册赠送余额', time: '2026-02-03 00:58:21', amount: '+ 88888.00', user: 'J.', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31209', order: 'cp540123456789012345', time: '2026-02-02 18:30:00', amount: '- 288.00', user: '张小明', type: '余额支付购买商品', remark: '余额支付288.00元购买商品' },
|
||||
{ id: '31208', order: '管理员手动充值', time: '2026-02-02 16:00:00', amount: '+ 500.00', user: '李大力', type: '管理员手动充值', remark: '管理员充值500元' },
|
||||
{ id: '31207', order: 'cp539876543210987654', time: '2026-02-02 14:20:00', amount: '- 99.00', user: '王芳', type: '余额支付购买商品', remark: '余额支付99.00元购买商品' },
|
||||
{ id: '31206', order: '退款退回余额', time: '2026-02-02 11:45:00', amount: '+ 150.00', user: '赵明', type: '退款退回余额', remark: '订单退款150元返还余额' },
|
||||
{ id: '31205', order: 'cp538765432109876543', time: '2026-02-02 09:00:00', amount: '- 1280.00', user: '陈小燕', type: '余额支付购买商品', remark: '余额支付1280.00元购买商品' },
|
||||
{ id: '31204', order: '签到赠送余额', time: '2026-02-01 23:59:00', amount: '+ 10.00', user: '刘建国', type: '签到赠送余额', remark: '每日签到赠送10元余额' },
|
||||
{ id: '31203', order: 'cp537654321098765432', time: '2026-02-01 20:30:00', amount: '- 450.00', user: '黄晓兰', type: '余额支付购买商品', remark: '余额支付450.00元购买商品' },
|
||||
{ id: '31202', order: '新用户注册赠送余额', time: '2026-02-01 18:00:00', amount: '+ 88888.00', user: '周大卫', type: '新用户注册赠送余额', remark: '新用户注册赠送88888余额' },
|
||||
{ id: '31201', order: '管理员手动充值', time: '2026-02-01 15:30:00', amount: '+ 1000.00', user: '吴玲玲', type: '管理员手动充值', remark: '管理员充值1000元' },
|
||||
{ id: '31200', order: 'cp536543210987654321', time: '2026-02-01 12:00:00', amount: '- 680.00', user: '郑明亮', type: '余额支付购买商品', remark: '余额支付680.00元购买商品' },
|
||||
{ id: '31199', order: '活动赠送余额', time: '2026-02-01 10:00:00', amount: '+ 200.00', user: '孙小丽', type: '活动赠送余额', remark: '新春活动赠送200元余额' },
|
||||
{ id: '31198', order: 'cp535432109876543210', time: '2026-01-31 16:30:00', amount: '- 320.00', user: '冯浩', type: '余额支付购买商品', remark: '余额支付320.00元购买商品' },
|
||||
{ id: '31197', order: '退款退回余额', time: '2026-01-31 14:00:00', amount: '+ 99.00', user: '陈建国', type: '退款退回余额', remark: '订单退款99元返还余额' },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => tableData.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 tableData.value.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 ==========
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.uid">
|
||||
<view class="table-row" v-for="item in pagedList" :key="item.uid">
|
||||
<view class="td col-user">
|
||||
<text class="td-txt">{{ item.userInfo }}</text>
|
||||
</view>
|
||||
@@ -46,12 +46,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
interface CommissionSummary {
|
||||
uid: string
|
||||
@@ -61,64 +78,63 @@ interface CommissionSummary {
|
||||
withdrawAmount: string
|
||||
}
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 tableData 为 fetchCommissionList() 调用
|
||||
const tableData = ref<CommissionSummary[]>([
|
||||
{
|
||||
uid: '77418',
|
||||
userInfo: '张迪 | 155****5525 | 77418',
|
||||
totalAmount: '11.00',
|
||||
accountAmount: '11.00',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '69696',
|
||||
userInfo: "I'm yours - | 69696",
|
||||
totalAmount: '0.40',
|
||||
accountAmount: '0.40',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '68582',
|
||||
userInfo: 'guan | 68582',
|
||||
totalAmount: '140.80',
|
||||
accountAmount: '140.80',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '65258',
|
||||
userInfo: '纯爱战神别名王富贵儿 | 158****4881 | 65258',
|
||||
totalAmount: '11.00',
|
||||
accountAmount: '11.00',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '66265',
|
||||
userInfo: '王伟兴 | 66265',
|
||||
totalAmount: '11.99',
|
||||
accountAmount: '11.99',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '65270',
|
||||
userInfo: '199****1781 | 199****1781 | 65270',
|
||||
totalAmount: '31.60',
|
||||
accountAmount: '31.60',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '64572',
|
||||
userInfo: '洒笾菂艸 | 188****2434 | 64572',
|
||||
totalAmount: '0.20',
|
||||
accountAmount: '0.20',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '47952',
|
||||
userInfo: '那小子 | 134****3573 | 47952',
|
||||
totalAmount: '19.80',
|
||||
accountAmount: '19.80',
|
||||
withdrawAmount: '0'
|
||||
}
|
||||
{ uid: '77418', userInfo: '张迪 | 155****5525 | 77418', totalAmount: '11.00', accountAmount: '11.00', withdrawAmount: '0' },
|
||||
{ uid: '69696', userInfo: "I'm yours - | 69696", totalAmount: '0.40', accountAmount: '0.40', withdrawAmount: '0' },
|
||||
{ uid: '68582', userInfo: 'guan | 68582', totalAmount: '140.80', accountAmount: '140.80', withdrawAmount: '0' },
|
||||
{ uid: '65258', userInfo: '纯爱战神别名王富贵儿 | 158****4881 | 65258', totalAmount: '11.00', accountAmount: '11.00', withdrawAmount: '0' },
|
||||
{ uid: '66265', userInfo: '王伟兴 | 66265', totalAmount: '11.99', accountAmount: '11.99', withdrawAmount: '0' },
|
||||
{ uid: '65270', userInfo: '199****1781 | 199****1781 | 65270', totalAmount: '31.60', accountAmount: '31.60', withdrawAmount: '0' },
|
||||
{ uid: '64572', userInfo: '洒笾菂艸 | 188****2434 | 64572', totalAmount: '0.20', accountAmount: '0.20', withdrawAmount: '0' },
|
||||
{ uid: '47952', userInfo: '那小子 | 134****3573 | 47952', totalAmount: '19.80', accountAmount: '19.80', withdrawAmount: '0' },
|
||||
{ uid: '43210', userInfo: '小花猫 | 132****0011 | 43210', totalAmount: '56.00', accountAmount: '30.00', withdrawAmount: '26.00' },
|
||||
{ uid: '39876', userInfo: '蓝色天空 | 136****5566 | 39876', totalAmount: '88.50', accountAmount: '50.00', withdrawAmount: '38.50' },
|
||||
{ uid: '35432', userInfo: '星星之火 | 159****7788 | 35432', totalAmount: '200.00', accountAmount: '100.00', withdrawAmount: '100.00' },
|
||||
{ uid: '31098', userInfo: '夜行者 | 177****9900 | 31098', totalAmount: '15.60', accountAmount: '15.60', withdrawAmount: '0' },
|
||||
{ uid: '26754', userInfo: '晨曦 | 138****1122 | 26754', totalAmount: '320.00', accountAmount: '200.00', withdrawAmount: '120.00' },
|
||||
{ uid: '22410', userInfo: '落叶归根 | 152****3344 | 22410', totalAmount: '45.80', accountAmount: '45.80', withdrawAmount: '0' },
|
||||
{ uid: '18066', userInfo: '风中漫步 | 189****5566 | 18066', totalAmount: '800.00', accountAmount: '500.00', withdrawAmount: '300.00' },
|
||||
{ uid: '13722', userInfo: '快乐小屋 | 133****7788 | 13722', totalAmount: '12.00', accountAmount: '12.00', withdrawAmount: '0' },
|
||||
{ uid: '9378', userInfo: '云端漫步 | 176****9900 | 9378', totalAmount: '650.00', accountAmount: '400.00', withdrawAmount: '250.00' },
|
||||
{ uid: '5034', userInfo: '绿草如茵 | 156****0011 | 5034', totalAmount: '28.40', accountAmount: '28.40', withdrawAmount: '0' },
|
||||
{ uid: '88901', userInfo: '阳光路上 | 139****2233 | 88901', totalAmount: '1200.00', accountAmount: '800.00', withdrawAmount: '400.00' },
|
||||
{ uid: '84557', userInfo: '繁花似锦 | 173****4455 | 84557', totalAmount: '76.60', accountAmount: '76.60', withdrawAmount: '0' },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => tableData.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 tableData.value.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 ==========
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.orderNo">
|
||||
<view class="table-row" v-for="item in pagedList" :key="item.orderNo">
|
||||
<view class="td col-order text-left"><text class="td-txt">{{ item.orderNo }}</text></view>
|
||||
<view class="td col-amount"><text class="td-txt">¥ {{ item.amount }}</text></view>
|
||||
<view class="td col-type"><text class="td-txt">{{ item.invoiceType }}</text></view>
|
||||
@@ -72,11 +72,28 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const activeTab = ref(0)
|
||||
|
||||
@@ -87,80 +104,63 @@ const tabs = ref([
|
||||
{ name: '退款发票', count: 33 }
|
||||
])
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 tableData 为 fetchInvoiceList() 调用
|
||||
const tableData = ref([
|
||||
{
|
||||
orderNo: 'cp538981381384962048',
|
||||
amount: '999.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2026-01-27 07:19:35',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp523490058603331584',
|
||||
amount: '9.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-15 13:22:35',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp524967077409193984',
|
||||
amount: '9.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-19 15:11:44',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp521126678106210304',
|
||||
amount: '11890.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-09 00:51:22',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp521126166883467264',
|
||||
amount: '11800.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-09 00:49:20',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp517015093888679936',
|
||||
amount: '142.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-11-27 16:33:24',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp313601579989073920',
|
||||
amount: '0.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2024-05-15 08:59:56',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '待评价'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp503871643047690240',
|
||||
amount: '999.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-10-22 10:06:01',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
}
|
||||
{ orderNo: 'cp538981381384962048', amount: '999.00', invoiceType: '电子普通发票', headerType: '个人', time: '2026-01-27 07:19:35', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp523490058603331584', amount: '9.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-12-15 13:22:35', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp524967077409193984', amount: '9.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-12-19 15:11:44', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp521126678106210304', amount: '11890.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-12-09 00:51:22', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp521126166883467264', amount: '11800.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-12-09 00:49:20', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp517015093888679936', amount: '142.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-11-27 16:33:24', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp313601579989073920', amount: '0.00', invoiceType: '电子普通发票', headerType: '个人', time: '2024-05-15 08:59:56', invStatus: '未开票', orderStatus: '待评价' },
|
||||
{ orderNo: 'cp503871643047690240', amount: '999.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-10-22 10:06:01', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp510234567890123456', amount: '288.00', invoiceType: '电子增值税发票', headerType: '企业', time: '2025-11-05 09:30:00', invStatus: '已开票', orderStatus: '已发货' },
|
||||
{ orderNo: 'cp511234567890123456', amount: '1580.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-11-10 14:20:00', invStatus: '退款发票', orderStatus: '已退款' },
|
||||
{ orderNo: 'cp512234567890123456', amount: '680.00', invoiceType: '电子增值税发票', headerType: '企业', time: '2025-11-12 16:45:00', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp513234567890123456', amount: '99.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-11-15 11:00:00', invStatus: '已开票', orderStatus: '已签收' },
|
||||
{ orderNo: 'cp514234567890123456', amount: '350.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-11-18 08:30:00', invStatus: '未开票', orderStatus: '配送中' },
|
||||
{ orderNo: 'cp515234567890123456', amount: '2500.00', invoiceType: '电子增值税发票', headerType: '企业', time: '2025-11-20 10:15:00', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp516234567890123456', amount: '120.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-11-22 13:40:00', invStatus: '已开票', orderStatus: '待评价' },
|
||||
{ orderNo: 'cp518234567890123456', amount: '799.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-11-28 09:50:00', invStatus: '未开票', orderStatus: '未发货' },
|
||||
{ orderNo: 'cp519234567890123456', amount: '3200.00', invoiceType: '电子增值税发票', headerType: '企业', time: '2025-12-01 14:30:00', invStatus: '退款发票', orderStatus: '已退款' },
|
||||
{ orderNo: 'cp520234567890123456', amount: '450.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-12-05 10:00:00', invStatus: '未开票', orderStatus: '已发货' },
|
||||
{ orderNo: 'cp522234567890123456', amount: '980.00', invoiceType: '电子增值税发票', headerType: '企业', time: '2025-12-12 15:20:00', invStatus: '已开票', orderStatus: '已签收' },
|
||||
{ orderNo: 'cp525234567890123456', amount: '199.00', invoiceType: '电子普通发票', headerType: '个人', time: '2025-12-25 12:00:00', invStatus: '未开票', orderStatus: '未发货' },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => tableData.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 tableData.value.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 ==========
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="(item, index) in tableData" :key="item.id">
|
||||
<view class="table-row" v-for="(item, index) in pagedList" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-user">
|
||||
<view class="user-info-box">
|
||||
@@ -113,11 +113,28 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const timeRange = ref([])
|
||||
const timeRangeText = ref('')
|
||||
@@ -156,35 +173,63 @@ const stats = ref([
|
||||
{ label: '未提现金额', value: '607930.00', icon: '¥', colorClass: 'pink' }
|
||||
])
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 tableData 为 fetchWithdrawalList() 调用
|
||||
const tableData = ref([
|
||||
{
|
||||
id: 57,
|
||||
nickname: '用户昵称: 177****766',
|
||||
userId: '58837',
|
||||
amount: '20.00',
|
||||
fee: '0.00',
|
||||
netAmount: '20.00',
|
||||
name: '接口',
|
||||
type: '支付宝',
|
||||
account: '1195953899',
|
||||
time: '2025-10-24 16:04',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
id: 56,
|
||||
nickname: '用户昵称: 测试员的',
|
||||
userId: '20695',
|
||||
amount: '1.00',
|
||||
fee: '0.00',
|
||||
netAmount: '1.00',
|
||||
name: '123',
|
||||
type: '银行卡',
|
||||
account: '4001231221',
|
||||
bank: '中国银行',
|
||||
time: '2025-07-04 15:11',
|
||||
remark: ''
|
||||
}
|
||||
{ id: 57, nickname: '用户昵称: 177****766', userId: '58837', amount: '20.00', fee: '0.00', netAmount: '20.00', name: '接口', type: '支付宝', account: '1195953899', time: '2025-10-24 16:04', remark: '' },
|
||||
{ id: 56, nickname: '用户昵称: 测试员的', userId: '20695', amount: '1.00', fee: '0.00', netAmount: '1.00', name: '123', type: '银行卡', account: '4001231221', bank: '中国银行', time: '2025-07-04 15:11', remark: '' },
|
||||
{ id: 55, nickname: '张小红', userId: '18340', amount: '50.00', fee: '0.50', netAmount: '49.50', name: '张小红', type: '微信', account: 'wx_zhangxh', time: '2025-06-20 10:22', remark: '' },
|
||||
{ id: 54, nickname: '李大明', userId: '29501', amount: '200.00', fee: '2.00', netAmount: '198.00', name: '李大明', type: '支付宝', account: 'lidaming@qq.com', time: '2025-06-15 09:30', remark: '' },
|
||||
{ id: 53, nickname: '王芳芳', userId: '32110', amount: '80.00', fee: '0.00', netAmount: '80.00', name: '王芳芳', type: '银行卡', account: '6200123456789', bank: '建设银行', time: '2025-06-10 14:55', remark: '' },
|
||||
{ id: 52, nickname: '赵刚', userId: '44422', amount: '150.00', fee: '1.50', netAmount: '148.50', name: '赵刚', type: '支付宝', account: 'zhaogang@163.com', time: '2025-06-05 16:40', remark: '请尽快处理' },
|
||||
{ id: 51, nickname: '陈小燕', userId: '55631', amount: '30.00', fee: '0.00', netAmount: '30.00', name: '陈小燕', type: '微信', account: 'wx_chenxy', time: '2025-05-28 11:15', remark: '' },
|
||||
{ id: 50, nickname: '刘建军', userId: '61204', amount: '500.00', fee: '5.00', netAmount: '495.00', name: '刘建军', type: '银行卡', account: '6228480012345678', bank: '农业银行', time: '2025-05-20 08:00', remark: '' },
|
||||
{ id: 49, nickname: '黄小兰', userId: '72890', amount: '25.00', fee: '0.00', netAmount: '25.00', name: '黄小兰', type: '支付宝', account: 'huangxl@sina.com', time: '2025-05-15 13:22', remark: '' },
|
||||
{ id: 48, nickname: '周大伟', userId: '83456', amount: '100.00', fee: '1.00', netAmount: '99.00', name: '周大伟', type: '支付宝', account: 'zhoudw@gmail.com', time: '2025-05-10 17:30', remark: '' },
|
||||
{ id: 47, nickname: '吴玲玲', userId: '91223', amount: '60.00', fee: '0.00', netAmount: '60.00', name: '吴玲玲', type: '微信', account: 'wx_wull', time: '2025-05-05 10:45', remark: '' },
|
||||
{ id: 46, nickname: '郑明亮', userId: '10234', amount: '300.00', fee: '3.00', netAmount: '297.00', name: '郑明亮', type: '银行卡', account: '6217000012345', bank: '工商银行', time: '2025-04-28 09:00', remark: '' },
|
||||
{ id: 45, nickname: '孙小丽', userId: '21345', amount: '45.00', fee: '0.00', netAmount: '45.00', name: '孙小丽', type: '支付宝', account: 'sunxl@aliyun.com', time: '2025-04-20 15:10', remark: '' },
|
||||
{ id: 44, nickname: '冯浩', userId: '32456', amount: '88.00', fee: '0.88', netAmount: '87.12', name: '冯浩', type: '微信', account: 'wx_fenghao', time: '2025-04-15 11:30', remark: '' },
|
||||
{ id: 43, nickname: '陈建国', userId: '43567', amount: '120.00', fee: '1.20', netAmount: '118.80', name: '陈建国', type: '支付宝', account: 'chenjg@hotmail.com', time: '2025-04-10 14:00', remark: '' },
|
||||
{ id: 42, nickname: '蒋小娟', userId: '54678', amount: '75.00', fee: '0.00', netAmount: '75.00', name: '蒋小娟', type: '银行卡', account: '6225880099887766', bank: '招商银行', time: '2025-04-05 08:45', remark: '' },
|
||||
{ id: 41, nickname: '卫东', userId: '65789', amount: '40.00', fee: '0.40', netAmount: '39.60', name: '卫东', type: '支付宝', account: 'weidong@126.com', time: '2025-03-28 16:20', remark: '' },
|
||||
{ id: 40, nickname: '韩美丽', userId: '76890', amount: '250.00', fee: '2.50', netAmount: '247.50', name: '韩美丽', type: '微信', account: 'wx_hanml', time: '2025-03-20 10:00', remark: '' },
|
||||
{ id: 39, nickname: '杨志远', userId: '87901', amount: '16.00', fee: '0.00', netAmount: '16.00', name: '杨志远', type: '银行卡', account: '6228001234567890', bank: '中国银行', time: '2025-03-15 12:35', remark: '' },
|
||||
{ id: 38, nickname: '秦晓', userId: '98012', amount: '180.00', fee: '1.80', netAmount: '178.20', name: '秦晓', type: '支付宝', account: 'qinxiao@vip.qq.com', time: '2025-03-10 09:50', remark: '' },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => tableData.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 tableData.value.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 statusChange = (e: any) => {
|
||||
statusValue.value = statusOptions.value[e.detail.value].value
|
||||
|
||||
@@ -1,21 +1,154 @@
|
||||
<template>
|
||||
<AdminLayout currentPage="data-logistics-company">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">物流公司</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="tip">TODO: 物流公司</text>
|
||||
<view class="admin-page-container">
|
||||
<view class="page-card">
|
||||
<view class="search-wrap">
|
||||
<view class="search-item">
|
||||
<text class="label">公司名称:</text>
|
||||
<input class="input" placeholder="请输入物流公司名称" v-model="searchKey" />
|
||||
</view>
|
||||
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||
</view>
|
||||
<view class="action-wrap">
|
||||
<button class="btn btn-primary" @click="onAdd">添加物流公司</button>
|
||||
</view>
|
||||
<view class="table-wrap">
|
||||
<view class="table-header">
|
||||
<view class="th" style="flex: 0 0 60px;">ID</view>
|
||||
<view class="th" style="flex: 2;">公司名称</view>
|
||||
<view class="th" style="flex: 2;">编码</view>
|
||||
<view class="th" style="flex: 1;">是否显示</view>
|
||||
<view class="th" style="flex: 1;">排序</view>
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.code }}</view>
|
||||
<view class="td" style="flex: 1;">
|
||||
<switch :checked="item.isshow" color="#1890ff" style="transform: scale(0.7);" />
|
||||
</view>
|
||||
<view class="td" style="flex: 1;">{{ item.sort }}</view>
|
||||
<view class="td" style="flex: 2;">
|
||||
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
</script>
|
||||
<style scoped>
|
||||
.page { padding: 0; }
|
||||
.title { font-size: 18px; font-weight: 600; }
|
||||
.tip { color: #999; margin-top: 8px; display: block; }
|
||||
</style>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchKey = ref('')
|
||||
|
||||
type LogisticsItem = { id: number; name: string; code: string; isshow: boolean; sort: number }
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 logisticsList 为 fetchLogisticsList() 调用
|
||||
const logisticsList = ref<LogisticsItem[]>([
|
||||
{ id: 20, name: '顺丰速递', code: 'SF', isshow: true, sort: 1 },
|
||||
{ id: 19, name: '圆通速递', code: 'YTO', isshow: true, sort: 2 },
|
||||
{ id: 18, name: '申通快递', code: 'STO', isshow: true, sort: 3 },
|
||||
{ id: 17, name: '中通快递', code: 'ZTO', isshow: true, sort: 4 },
|
||||
{ id: 16, name: '韵达速递', code: 'YUNDA', isshow: true, sort: 5 },
|
||||
{ id: 15, name: '百世快递', code: 'BEST', isshow: true, sort: 6 },
|
||||
{ id: 14, name: '极兔速递', code: 'JTEX', isshow: true, sort: 7 },
|
||||
{ id: 13, name: '菜鸟快递', code: 'CAINIAO', isshow: true, sort: 8 },
|
||||
{ id: 12, name: '京东快递', code: 'JD', isshow: true, sort: 9 },
|
||||
{ id: 11, name: '丰网速运', code: 'FENGWANG', isshow: false, sort: 10 },
|
||||
{ id: 10, name: '邮政快递包裹', code: 'YZPY', isshow: true, sort: 11 },
|
||||
{ id: 9, name: 'EMS', code: 'EMS', isshow: true, sort: 12 },
|
||||
{ id: 8, name: '德邦快递', code: 'DEPPON', isshow: true, sort: 13 },
|
||||
{ id: 7, name: '壹米滴答', code: 'YMDD', isshow: false, sort: 14 },
|
||||
{ id: 6, name: '安能快运', code: 'ANE', isshow: true, sort: 15 },
|
||||
{ id: 5, name: '中远快运', code: 'COSCO', isshow: false, sort: 16 },
|
||||
{ id: 4, name: '宅急送', code: 'ZJS', isshow: true, sort: 17 },
|
||||
{ id: 3, name: '国通快递', code: 'GTO', isshow: true, sort: 18 },
|
||||
{ id: 2, name: '明亮(品骏)', code: 'PINJUN', isshow: false, sort: 19 },
|
||||
{ id: 1, name: '速尔快递', code: 'SURE', isshow: true, sort: 20 }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => logisticsList.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 logisticsList.value.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 ==========
|
||||
|
||||
function onSearch() { console.log('Search:', searchKey.value) }
|
||||
function onAdd() { uni.showToast({ title: '添加物流公司', icon: 'none' }) }
|
||||
function onEdit(item: LogisticsItem) { uni.showToast({ title: '编辑: ' + item.name, icon: 'none' }) }
|
||||
function onDel(item: LogisticsItem) {
|
||||
uni.showModal({ title: '提示', content: '确定删除该物流公司吗?', success: (res) => {
|
||||
if (res.confirm) uni.showToast({ title: '已删除', icon: 'success' })
|
||||
}})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-page-container { padding: 0; background-color: transparent; min-height: auto; }
|
||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; }
|
||||
.search-wrap { display: flex; flex-direction: row; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #f0f0f0; margin-bottom: 20px; }
|
||||
.search-item { display: flex; flex-direction: row; align-items: center; margin-right: 20px; }
|
||||
.label { font-size: 14px; color: #606266; margin-right: 8px; }
|
||||
.input { width: 220px; height: 32px; padding: 0 10px; border: 1px solid #dcdfe6; border-radius: 4px; font-size: 14px; }
|
||||
.btn { height: 32px; padding: 0 15px; font-size: 14px; border-radius: 4px; border: none; }
|
||||
.btn-primary { background-color: #1890ff; color: #fff; }
|
||||
.action-wrap { margin-bottom: 20px; }
|
||||
.table-wrap { width: 100%; border: 1px solid #f0f0f0; }
|
||||
.table-header { display: flex; flex-direction: row; background-color: #f8f8f9; }
|
||||
.th { padding: 12px 10px; font-size: 13px; font-weight: bold; color: #515a6e; border-bottom: 1px solid #f0f0f0; text-align: center; }
|
||||
.tr { display: flex; flex-direction: row; align-items: center; border-bottom: 1px solid #f0f0f0; min-height: 50px; }
|
||||
.td { padding: 10px; font-size: 13px; color: #515a6e; text-align: center; }
|
||||
.action-btn { font-size: 13px; color: #1890ff; margin-right: 8px; cursor: pointer; }
|
||||
.action-btn-del { font-size: 13px; color: #ed4014; cursor: pointer; }
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="table-row">
|
||||
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||
<view class="col col-key"><text>{{ item.key }}</text></view>
|
||||
<view class="col col-name"><text>{{ item.name }}</text></view>
|
||||
@@ -45,13 +45,30 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const dataList = ref([
|
||||
{ id: 49, key: 'routine_seckill_time', name: '秒杀时间段', desc: '秒杀时间段' },
|
||||
@@ -66,8 +83,48 @@ const dataList = ref([
|
||||
{ id: 65, key: 'admin_login_slide', name: '后台登录页面幻灯片', desc: '后台登录页面幻灯片' },
|
||||
{ id: 66, key: 'uni_app_link', name: '前端页面链接', desc: '前端页面链接' },
|
||||
{ id: 67, key: 'combination_banner', name: '拼团列表轮播图', desc: '拼团列表轮播图' },
|
||||
{ id: 68, key: 'integral_shop_banner', name: '积分商城轮播图', desc: '积分商城轮播图' }
|
||||
{ id: 68, key: 'integral_shop_banner', name: '积分商城轮播图', desc: '积分商城轮播图' },
|
||||
{ id: 70, key: 'live_share_img', name: '直播分享图片', desc: '直播分享图片' },
|
||||
{ id: 71, key: 'live_home_banner', name: '直播首页轮播图', desc: '直播首页轮播图' },
|
||||
{ id: 72, key: 'user_welfare', name: '会员权益配置', desc: '会员权益配置' },
|
||||
{ id: 73, key: 'presale_banner', name: '预售轮播图配置', desc: '预售轮播图配置' },
|
||||
{ id: 74, key: 'share_image', name: '分享海报图片', desc: '分享海报图片' },
|
||||
{ id: 75, key: 'coupon_banner', name: '优惠券列表轮播图', desc: '优惠券列表轮播图' },
|
||||
{ id: 76, key: 'vip_privilege', name: 'VIP特权配置', desc: 'VIP特权配置' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => dataList.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 dataList.value.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 ==========
|
||||
|
||||
function onSearch() {
|
||||
uni.showToast({ title: '查询中...', icon: 'none' })
|
||||
@@ -203,7 +260,7 @@ function onDelete(item: any) {
|
||||
.col-key { flex: 2; }
|
||||
.col-name { flex: 2; }
|
||||
.col-desc { flex: 2; }
|
||||
.col-ops { flex: 2; justify-content: flex-end; }
|
||||
.col-ops { flex: 2; justify-content: flex-end; flex-direction: row;}
|
||||
|
||||
.op-link {
|
||||
color: #1890ff;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="table-row">
|
||||
<view class="col col-title"><text>{{ item.title }}</text></view>
|
||||
<view class="col col-desc"><text>{{ item.desc }}</text></view>
|
||||
<view class="col col-cycle"><text>{{ item.cycle }}</text></view>
|
||||
@@ -42,17 +42,30 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页 -->
|
||||
<view class="pagination">
|
||||
<text class="page-info">共 10 条 15条/页</text>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const dataList = ref([
|
||||
{ id: 1, title: '自动开具/冲红电子发票', desc: '每隔10分钟执行自动开具/冲红电子发票', cycle: '每隔10分钟执行一次', status: true },
|
||||
@@ -64,8 +77,51 @@ const dataList = ref([
|
||||
{ id: 7, title: '自动更新直播商品状态', desc: '每隔3分钟执行更新直播商品状态', cycle: '每隔3分钟执行一次', status: true },
|
||||
{ id: 8, title: '到期自动解绑上级', desc: '每隔1分钟执行到期的绑定关系的解除', cycle: '每隔1分钟执行一次', status: true },
|
||||
{ id: 9, title: '拼团到期订单处理', desc: '每隔1分钟拼团到期后的操作', cycle: '每隔1分钟执行一次', status: true },
|
||||
{ id: 10, title: '未支付自动取消订单', desc: '每隔30秒执行自动取消到期未支付的订单', cycle: '每隔30秒执行一次', status: true }
|
||||
{ id: 10, title: '未支付自动取消订单', desc: '每隆30秒执行自动取消到期未支付的订单', cycle: '每隆30秒执行一次', status: true },
|
||||
{ id: 11, title: '积分过期处理', desc: '每天凅晑59分0秒执行清除已过期积分', cycle: '每天凅晑59分执行一次', status: true },
|
||||
{ id: 12, title: '余额到期处理', desc: '每天中午1时执行一次余额到期检查', cycle: '每天中午1时执行一次', status: false },
|
||||
{ id: 13, title: '优惠券过期处理', desc: '每隔1小时检查并更新过期优惠券状态', cycle: '每隔1小时执行一次', status: true },
|
||||
{ id: 14, title: '会员等级更新', desc: '每天凅昹3时执行会员等级自动更新', cycle: '每天凅昹3时执行一次', status: true },
|
||||
{ id: 15, title: '统计数据更新', desc: '每天凅昹4时执行一次经营数据汇总', cycle: '每天凅昹4时执行一次', status: true },
|
||||
{ id: 16, title: '清理缓存数据', desc: '每天凅晑30分执行一次过期缓存清除', cycle: '每天凅晑30分执行一次', status: true },
|
||||
{ id: 17, title: '商品库存预警', desc: '每隆15分钟检查库存不足预警商品', cycle: '每隆15分钟执行一次', status: false },
|
||||
{ id: 18, title: '短信队列发送', desc: '每隔1分钟处理短信队列', cycle: '每隔1分钟执行一次', status: true },
|
||||
{ id: 19, title: '邮件队列发送', desc: '每隔2分钟处理邮件发送队列', cycle: '每隔2分钟执行一次', status: true },
|
||||
{ id: 20, title: '每日对账任务', desc: '每天凅晑22时执行一次财务对账', cycle: '每天凅晑22时执行一次', status: true }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => dataList.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 dataList.value.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 ==========
|
||||
|
||||
function onEdit(item: any) {
|
||||
uni.showToast({ title: '编辑: ' + item.title, icon: 'none' })
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<view class="table-cell action-cell" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="(item, index) in dictionaryList" :key="index">
|
||||
<view class="table-row" v-for="(item, index) in pagedList" :key="index">
|
||||
<view class="table-cell" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="table-cell" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="table-cell" style="flex: 2;">{{ item.tag }}</view>
|
||||
@@ -38,10 +38,27 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view></template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchQuery = ref('')
|
||||
const dictionaryList = ref([
|
||||
@@ -54,8 +71,50 @@ const dictionaryList = ref([
|
||||
{ id: 16, name: '用户管理模块', tag: '123', type: '多级', add_time: '2024-10-22 09:30:46' },
|
||||
{ id: 18, name: '类型', tag: '1', type: '多级', add_time: '2024-12-11 13:48:01' },
|
||||
{ id: 19, name: '店铺', tag: 'shop', type: '多级', add_time: '2024-12-11 22:23:07' },
|
||||
{ id: 20, name: 'ce', tag: 'zzz', type: '一级', add_time: '2024-12-14 12:19:17' }
|
||||
{ id: 20, name: 'ce', tag: 'zzz', type: '一级', add_time: '2024-12-14 12:19:17' },
|
||||
{ id: 21, name: '语言', tag: 'language', type: '多级', add_time: '2025-01-05 10:00:00' },
|
||||
{ id: 22, name: '地区', tag: 'region', type: '多级', add_time: '2025-01-10 11:30:00' },
|
||||
{ id: 23, name: '货币类型', tag: 'currency', type: '一级', add_time: '2025-01-15 09:00:00' },
|
||||
{ id: 24, name: '支付方式', tag: 'payment_type', type: '一级', add_time: '2025-01-20 14:00:00' },
|
||||
{ id: 25, name: '订单状态', tag: 'order_status', type: '一级', add_time: '2025-01-25 10:30:00' },
|
||||
{ id: 26, name: '物流公司', tag: 'express_company', type: '一级', add_time: '2025-02-01 08:00:00' },
|
||||
{ id: 27, name: '售后类型', tag: 'after_sale_type', type: '多级', add_time: '2025-02-05 15:00:00' },
|
||||
{ id: 28, name: '套餐类型', tag: 'package_type', type: '多级', add_time: '2025-02-10 09:30:00' },
|
||||
{ id: 29, name: '签到规则', tag: 'sign_rule', type: '一级', add_time: '2025-02-15 11:00:00' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => dictionaryList.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 dictionaryList.value.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 ==========
|
||||
|
||||
function handleSearch() {
|
||||
uni.showToast({ title: '搜索: ' + searchQuery.value, icon: 'none' })
|
||||
|
||||
163
pages/mall/admin/maintain/external/account.uvue
vendored
163
pages/mall/admin/maintain/external/account.uvue
vendored
@@ -1,13 +1,154 @@
|
||||
<template>
|
||||
<AdminLayout currentPage="external-account">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">账号管理</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="tip">TODO: 账号管理</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
|
||||
<view class="admin-page-container">
|
||||
<view class="page-card">
|
||||
<view class="search-wrap">
|
||||
<view class="search-item">
|
||||
<text class="label">平台类型:</text>
|
||||
<input class="input" placeholder="请输入平台名称" v-model="searchKey" />
|
||||
</view>
|
||||
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||
</view>
|
||||
<view class="action-wrap">
|
||||
<button class="btn btn-primary" @click="onAdd">添加账号</button>
|
||||
</view>
|
||||
<view class="table-wrap">
|
||||
<view class="table-header">
|
||||
<view class="th" style="flex: 0 0 60px;">ID</view>
|
||||
<view class="th" style="flex: 2;">账号名称</view>
|
||||
<view class="th" style="flex: 2;">平台类型</view>
|
||||
<view class="th" style="flex: 2;">AppID/账号</view>
|
||||
<view class="th" style="flex: 1;">状态</view>
|
||||
<view class="th" style="flex: 2;">创建时间</view>
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.platform }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.appId }}</view>
|
||||
<view class="td" style="flex: 1;">
|
||||
<switch :checked="item.status" color="#1890ff" style="transform: scale(0.7);" />
|
||||
</view>
|
||||
<view class="td" style="flex: 2;">{{ item.createTime }}</view>
|
||||
<view class="td" style="flex: 2;">
|
||||
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchKey = ref('')
|
||||
|
||||
type AccountItem = { id: number; name: string; platform: string; appId: string; status: boolean; createTime: string }
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 accountList 为 fetchExternalAccountList() 调用
|
||||
const accountList = ref<AccountItem[]>([
|
||||
{ id: 20, name: '微信公众号', platform: '微信', appId: 'wx_public_001', status: true, createTime: '2025-01-01 10:00:00' },
|
||||
{ id: 19, name: '微信小程序', platform: '微信', appId: 'wx_mini_001', status: true, createTime: '2025-01-02 10:00:00' },
|
||||
{ id: 18, name: '支付宝商家版', platform: '支付宝', appId: 'alipay_shop_001', status: true, createTime: '2025-01-03 10:00:00' },
|
||||
{ id: 17, name: '微信支付', platform: '微信支付', appId: 'wxpay_mch_001', status: true, createTime: '2025-01-04 10:00:00' },
|
||||
{ id: 16, name: '百度小程序', platform: '百度', appId: 'baidu_mini_001', status: false, createTime: '2025-01-05 10:00:00' },
|
||||
{ id: 15, name: '字节跳动小程序', platform: '字节跳动', appId: 'douyin_mini_001', status: true, createTime: '2025-01-06 10:00:00' },
|
||||
{ id: 14, name: '阿里云短信', platform: '阿里云', appId: 'aliyun_sms_001', status: true, createTime: '2025-01-07 10:00:00' },
|
||||
{ id: 13, name: '腾讯云短信', platform: '腾讯云', appId: 'tencent_sms_001', status: true, createTime: '2025-01-08 10:00:00' },
|
||||
{ id: 12, name: '七牛云存储', platform: '七牛云', appId: 'qiniu_oss_001', status: false, createTime: '2025-01-09 10:00:00' },
|
||||
{ id: 11, name: '阿里云OSS', platform: '阿里云', appId: 'aliyun_oss_001', status: true, createTime: '2025-01-10 10:00:00' },
|
||||
{ id: 10, name: '腾讯云COS', platform: '腾讯云', appId: 'tencent_cos_001', status: true, createTime: '2025-01-11 10:00:00' },
|
||||
{ id: 9, name: 'Apple登录', platform: 'Apple', appId: 'apple_signin_001', status: false, createTime: '2025-01-12 10:00:00' },
|
||||
{ id: 8, name: '高德地图', platform: '高德地图', appId: 'amap_key_001', status: true, createTime: '2025-01-13 10:00:00' },
|
||||
{ id: 7, name: '百度地图', platform: '百度', appId: 'bmap_key_001', status: true, createTime: '2025-01-14 10:00:00' },
|
||||
{ id: 6, name: '联通支付', platform: '联通', appId: 'union_pay_001', status: false, createTime: '2025-01-15 10:00:00' },
|
||||
{ id: 5, name: 'H5微信登录', platform: '微信', appId: 'wx_h5_001', status: true, createTime: '2025-01-16 10:00:00' },
|
||||
{ id: 4, name: 'App微信登录', platform: '微信', appId: 'wx_app_001', status: true, createTime: '2025-01-17 10:00:00' },
|
||||
{ id: 3, name: 'QQ登录', platform: 'QQ', appId: 'qq_login_001', status: false, createTime: '2025-01-18 10:00:00' },
|
||||
{ id: 2, name: '微博登录', platform: '微博', appId: 'weibo_login_001', status: false, createTime: '2025-01-19 10:00:00' },
|
||||
{ id: 1, name: '易联云打印', platform: '易联云', appId: 'yly_key_001', status: true, createTime: '2025-01-20 10:00:00' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => accountList.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 accountList.value.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 ==========
|
||||
|
||||
function onSearch() { console.log('Search:', searchKey.value) }
|
||||
function onAdd() { uni.showToast({ title: '添加账号', icon: 'none' }) }
|
||||
function onEdit(item: AccountItem) { uni.showToast({ title: '编辑: ' + item.name, icon: 'none' }) }
|
||||
function onDel(item: AccountItem) {
|
||||
uni.showModal({ title: '提示', content: '确定删除该账号吗?', success: (res) => {
|
||||
if (res.confirm) uni.showToast({ title: '已删除', icon: 'success' })
|
||||
}})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-page-container { padding: 0; background-color: transparent; min-height: auto; }
|
||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; }
|
||||
.search-wrap { display: flex; flex-direction: row; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #f0f0f0; margin-bottom: 20px; }
|
||||
.search-item { display: flex; flex-direction: row; align-items: center; margin-right: 20px; }
|
||||
.label { font-size: 14px; color: #606266; margin-right: 8px; }
|
||||
.input { width: 220px; height: 32px; padding: 0 10px; border: 1px solid #dcdfe6; border-radius: 4px; font-size: 14px; }
|
||||
.btn { height: 32px; padding: 0 15px; font-size: 14px; border-radius: 4px; border: none; }
|
||||
.btn-primary { background-color: #1890ff; color: #fff; }
|
||||
.action-wrap { margin-bottom: 20px; }
|
||||
.table-wrap { width: 100%; border: 1px solid #f0f0f0; }
|
||||
.table-header { display: flex; flex-direction: row; background-color: #f8f8f9; }
|
||||
.th { padding: 12px 10px; font-size: 13px; font-weight: bold; color: #515a6e; border-bottom: 1px solid #f0f0f0; text-align: center; }
|
||||
.tr { display: flex; flex-direction: row; align-items: center; border-bottom: 1px solid #f0f0f0; min-height: 50px; }
|
||||
.td { padding: 10px; font-size: 13px; color: #515a6e; text-align: center; }
|
||||
.action-btn { font-size: 13px; color: #1890ff; margin-right: 8px; cursor: pointer; }
|
||||
.action-btn-del { font-size: 13px; color: #ed4014; cursor: pointer; }
|
||||
</style>
|
||||
@@ -1,12 +1,140 @@
|
||||
<template>
|
||||
<AdminLayout currentPage="i18n-language-detail">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">语言详情</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="tip">TODO: 语言详情</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
<view class="admin-page-container">
|
||||
<view class="page-card">
|
||||
<view class="search-wrap">
|
||||
<view class="search-item">
|
||||
<text class="label">翻译key:</text>
|
||||
<input class="input" placeholder="请输入翻译键" v-model="searchKey" />
|
||||
</view>
|
||||
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||
</view>
|
||||
<view class="action-wrap">
|
||||
<button class="btn btn-primary" @click="onAdd">添加翻译</button>
|
||||
</view>
|
||||
<view class="table-wrap">
|
||||
<view class="table-header">
|
||||
<view class="th" style="flex: 0 0 60px;">ID</view>
|
||||
<view class="th" style="flex: 2;">翻译键(key)</view>
|
||||
<view class="th" style="flex: 3;">中文原文</view>
|
||||
<view class="th" style="flex: 3;">翻译内容</view>
|
||||
<view class="th" style="flex: 1.5;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.key }}</view>
|
||||
<view class="td" style="flex: 3;">{{ item.original }}</view>
|
||||
<view class="td" style="flex: 3;">{{ item.translation }}</view>
|
||||
<view class="td" style="flex: 1.5;">
|
||||
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchKey = ref('')
|
||||
|
||||
type TranslationItem = { id: number; key: string; original: string; translation: string }
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
const translationList = ref<TranslationItem[]>([
|
||||
{ id: 1, key: 'common.confirm', original: '确定', translation: 'Confirm' },
|
||||
{ id: 2, key: 'common.cancel', original: '取消', translation: 'Cancel' },
|
||||
{ id: 3, key: 'common.save', original: '保存', translation: 'Save' },
|
||||
{ id: 4, key: 'common.delete', original: '删除', translation: 'Delete' },
|
||||
{ id: 5, key: 'common.edit', original: '编辑', translation: 'Edit' },
|
||||
{ id: 6, key: 'common.add', original: '添加', translation: 'Add' },
|
||||
{ id: 7, key: 'common.search', original: '搜索', translation: 'Search' },
|
||||
{ id: 8, key: 'common.reset', original: '重置', translation: 'Reset' },
|
||||
{ id: 9, key: 'common.loading', original: '加载中...', translation: 'Loading...' },
|
||||
{ id: 10, key: 'common.no_data', original: '暂无数据', translation: 'No Data' },
|
||||
{ id: 11, key: 'order.status.pending', original: '待支付', translation: 'Pending' },
|
||||
{ id: 12, key: 'order.status.paid', original: '已支付', translation: 'Paid' },
|
||||
{ id: 13, key: 'order.status.shipped', original: '已发货', translation: 'Shipped' },
|
||||
{ id: 14, key: 'order.status.received', original: '已收货', translation: 'Received' },
|
||||
{ id: 15, key: 'order.status.cancelled', original: '已取消', translation: 'Cancelled' },
|
||||
{ id: 16, key: 'product.out_of_stock', original: '已售罄', translation: 'Out of Stock' },
|
||||
{ id: 17, key: 'user.login', original: '登录', translation: 'Login' },
|
||||
{ id: 18, key: 'user.logout', original: '登出', translation: 'Logout' },
|
||||
{ id: 19, key: 'user.register', original: '注册', translation: 'Register' },
|
||||
{ id: 20, key: 'user.profile', original: '个人中心', translation: 'Profile' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => translationList.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 translationList.value.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 ==========
|
||||
|
||||
function onSearch() { console.log('Search:', searchKey.value) }
|
||||
function onAdd() { uni.showToast({ title: '添加翻译', icon: 'none' }) }
|
||||
function onEdit(item: TranslationItem) { uni.showToast({ title: '编辑: ' + item.key, icon: 'none' }) }
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-page-container { padding: 0; background-color: transparent; min-height: auto; }
|
||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; }
|
||||
.search-wrap { display: flex; flex-direction: row; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #f0f0f0; margin-bottom: 20px; }
|
||||
.search-item { display: flex; flex-direction: row; align-items: center; margin-right: 20px; }
|
||||
.label { font-size: 14px; color: #606266; margin-right: 8px; }
|
||||
.input { width: 220px; height: 32px; padding: 0 10px; border: 1px solid #dcdfe6; border-radius: 4px; font-size: 14px; }
|
||||
.btn { height: 32px; padding: 0 15px; font-size: 14px; border-radius: 4px; border: none; }
|
||||
.btn-primary { background-color: #1890ff; color: #fff; }
|
||||
.action-wrap { margin-bottom: 20px; }
|
||||
.table-wrap { width: 100%; border: 1px solid #f0f0f0; }
|
||||
.table-header { display: flex; flex-direction: row; background-color: #f8f8f9; }
|
||||
.th { padding: 12px 10px; font-size: 13px; font-weight: bold; color: #515a6e; border-bottom: 1px solid #f0f0f0; text-align: center; }
|
||||
.tr { display: flex; flex-direction: row; align-items: center; border-bottom: 1px solid #f0f0f0; min-height: 50px; }
|
||||
.td { padding: 10px; font-size: 13px; color: #515a6e; text-align: center; }
|
||||
.action-btn { font-size: 13px; color: #1890ff; margin-right: 8px; cursor: pointer; }
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,137 @@
|
||||
<template>
|
||||
<AdminLayout currentPage="i18n-language-list">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">语言列表</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="tip">TODO: 语言列表</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
<view class="admin-page-container">
|
||||
<view class="page-card">
|
||||
<view class="action-wrap">
|
||||
<button class="btn btn-primary" @click="onAdd">添加语言</button>
|
||||
</view>
|
||||
<view class="table-wrap">
|
||||
<view class="table-header">
|
||||
<view class="th" style="flex: 0 0 60px;">ID</view>
|
||||
<view class="th" style="flex: 2;">语言名称</view>
|
||||
<view class="th" style="flex: 1;">简称</view>
|
||||
<view class="th" style="flex: 1;">是否启用</view>
|
||||
<view class="th" style="flex: 1;">排序</view>
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="td" style="flex: 1;">{{ item.code }}</view>
|
||||
<view class="td" style="flex: 1;">
|
||||
<switch :checked="item.status" color="#1890ff" style="transform: scale(0.7);" />
|
||||
</view>
|
||||
<view class="td" style="flex: 1;">{{ item.sort }}</view>
|
||||
<view class="td" style="flex: 2;">
|
||||
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||
<text class="action-btn" @click="onTranslate(item)">翻译管理</text>
|
||||
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
type LangItem = { id: number; name: string; code: string; status: boolean; sort: number }
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
const languageList = ref<LangItem[]>([
|
||||
{ id: 1, name: '中文简体', code: 'zh-CN', status: true, sort: 1 },
|
||||
{ id: 2, name: '中文繁体', code: 'zh-TW', status: true, sort: 2 },
|
||||
{ id: 3, name: '英语', code: 'en-US', status: true, sort: 3 },
|
||||
{ id: 4, name: '日语', code: 'ja-JP', status: true, sort: 4 },
|
||||
{ id: 5, name: '韩语', code: 'ko-KR', status: true, sort: 5 },
|
||||
{ id: 6, name: '法语', code: 'fr-FR', status: false, sort: 6 },
|
||||
{ id: 7, name: '德语', code: 'de-DE', status: false, sort: 7 },
|
||||
{ id: 8, name: '西班牙语', code: 'es-ES', status: false, sort: 8 },
|
||||
{ id: 9, name: '葡萄牙语', code: 'pt-PT', status: false, sort: 9 },
|
||||
{ id: 10, name: '阿拉伯语', code: 'ar-SA', status: false, sort: 10 },
|
||||
{ id: 11, name: '俄语', code: 'ru-RU', status: false, sort: 11 },
|
||||
{ id: 12, name: '意大利语', code: 'it-IT', status: false, sort: 12 },
|
||||
{ id: 13, name: '泰语', code: 'th-TH', status: true, sort: 13 },
|
||||
{ id: 14, name: '越南语', code: 'vi-VN', status: true, sort: 14 },
|
||||
{ id: 15, name: '印尼语', code: 'id-ID', status: false, sort: 15 },
|
||||
{ id: 16, name: '马来语', code: 'ms-MY', status: false, sort: 16 },
|
||||
{ id: 17, name: '印地语', code: 'hi-IN', status: false, sort: 17 },
|
||||
{ id: 18, name: '土耳其语', code: 'tr-TR', status: false, sort: 18 },
|
||||
{ id: 19, name: '波兰语', code: 'pl-PL', status: false, sort: 19 },
|
||||
{ id: 20, name: '荷兰语', code: 'nl-NL', status: false, sort: 20 }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => languageList.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 languageList.value.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 ==========
|
||||
|
||||
function onAdd() { uni.showToast({ title: '添加语言', icon: 'none' }) }
|
||||
function onEdit(item: LangItem) { uni.showToast({ title: '编辑: ' + item.name, icon: 'none' }) }
|
||||
function onTranslate(item: LangItem) { uni.showToast({ title: '翻译管理: ' + item.name, icon: 'none' }) }
|
||||
function onDel(item: LangItem) {
|
||||
uni.showModal({ title: '提示', content: '确定删除该语言吗?', success: (res) => {
|
||||
if (res.confirm) uni.showToast({ title: '已删除', icon: 'success' })
|
||||
}})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-page-container { padding: 0; background-color: transparent; min-height: auto; }
|
||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; }
|
||||
.action-wrap { margin-bottom: 20px; }
|
||||
.table-wrap { width: 100%; border: 1px solid #f0f0f0; }
|
||||
.table-header { display: flex; flex-direction: row; background-color: #f8f8f9; }
|
||||
.th { padding: 12px 10px; font-size: 13px; font-weight: bold; color: #515a6e; border-bottom: 1px solid #f0f0f0; text-align: center; }
|
||||
.tr { display: flex; flex-direction: row; align-items: center; border-bottom: 1px solid #f0f0f0; min-height: 50px; }
|
||||
.td { padding: 10px; font-size: 13px; color: #515a6e; text-align: center; }
|
||||
.action-btn { font-size: 13px; color: #1890ff; margin-right: 8px; cursor: pointer; }
|
||||
.action-btn-del { font-size: 13px; color: #ed4014; cursor: pointer; }
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,144 @@
|
||||
<template>
|
||||
<AdminLayout currentPage="i18n-region-list">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">地区列表</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="tip">TODO: 地区列表</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
<view class="admin-page-container">
|
||||
<view class="page-card">
|
||||
<view class="search-wrap">
|
||||
<view class="search-item">
|
||||
<text class="label">地区名称:</text>
|
||||
<input class="input" placeholder="请输入地区名称" v-model="searchKey" />
|
||||
</view>
|
||||
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||
</view>
|
||||
<view class="table-wrap">
|
||||
<view class="table-header">
|
||||
<view class="th" style="flex: 0 0 60px;">ID</view>
|
||||
<view class="th" style="flex: 2;">地区名称</view>
|
||||
<view class="th" style="flex: 2;">父级地区</view>
|
||||
<view class="th" style="flex: 1.5;">地区代码</view>
|
||||
<view class="th" style="flex: 1;">层级</view>
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.parentName }}</view>
|
||||
<view class="td" style="flex: 1.5;">{{ item.code }}</view>
|
||||
<view class="td" style="flex: 1;">第{{ item.level }}级</view>
|
||||
<view class="td" style="flex: 2;">
|
||||
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchKey = ref('')
|
||||
|
||||
type RegionItem = { id: number; name: string; parentName: string; code: string; level: number }
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
const regionList = ref<RegionItem[]>([
|
||||
{ id: 1, name: '北京市', parentName: '中国', code: '110000', level: 1 },
|
||||
{ id: 2, name: '天津市', parentName: '中国', code: '120000', level: 1 },
|
||||
{ id: 3, name: '河北省', parentName: '中国', code: '130000', level: 1 },
|
||||
{ id: 4, name: '山西省', parentName: '中国', code: '140000', level: 1 },
|
||||
{ id: 5, name: '内蒙古自治区', parentName: '中国', code: '150000', level: 1 },
|
||||
{ id: 6, name: '辽宁省', parentName: '中国', code: '210000', level: 1 },
|
||||
{ id: 7, name: '吉林省', parentName: '中国', code: '220000', level: 1 },
|
||||
{ id: 8, name: '黑龙江省', parentName: '中国', code: '230000', level: 1 },
|
||||
{ id: 9, name: '上海市', parentName: '中国', code: '310000', level: 1 },
|
||||
{ id: 10, name: '江苏省', parentName: '中国', code: '320000', level: 1 },
|
||||
{ id: 11, name: '浙江省', parentName: '中国', code: '330000', level: 1 },
|
||||
{ id: 12, name: '安徽省', parentName: '中国', code: '340000', level: 1 },
|
||||
{ id: 13, name: '福建省', parentName: '中国', code: '350000', level: 1 },
|
||||
{ id: 14, name: '江西省', parentName: '中国', code: '360000', level: 1 },
|
||||
{ id: 15, name: '山东省', parentName: '中国', code: '370000', level: 1 },
|
||||
{ id: 16, name: '河南省', parentName: '中国', code: '410000', level: 1 },
|
||||
{ id: 17, name: '湖北省', parentName: '中国', code: '420000', level: 1 },
|
||||
{ id: 18, name: '湖南省', parentName: '中国', code: '430000', level: 1 },
|
||||
{ id: 19, name: '广东省', parentName: '中国', code: '440000', level: 1 },
|
||||
{ id: 20, name: '广西壮族自治区', parentName: '中国', code: '450000', level: 1 }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => regionList.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 regionList.value.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 ==========
|
||||
|
||||
function onSearch() { console.log('Search:', searchKey.value) }
|
||||
function onEdit(item: RegionItem) { uni.showToast({ title: '编辑: ' + item.name, icon: 'none' }) }
|
||||
function onDel(item: RegionItem) {
|
||||
uni.showModal({ title: '提示', content: '确定删除该地区吗?', success: (res) => {
|
||||
if (res.confirm) uni.showToast({ title: '已删除', icon: 'success' })
|
||||
}})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-page-container { padding: 0; background-color: transparent; min-height: auto; }
|
||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; }
|
||||
.search-wrap { display: flex; flex-direction: row; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #f0f0f0; margin-bottom: 20px; }
|
||||
.search-item { display: flex; flex-direction: row; align-items: center; margin-right: 20px; }
|
||||
.label { font-size: 14px; color: #606266; margin-right: 8px; }
|
||||
.input { width: 220px; height: 32px; padding: 0 10px; border: 1px solid #dcdfe6; border-radius: 4px; font-size: 14px; }
|
||||
.btn { height: 32px; padding: 0 15px; font-size: 14px; border-radius: 4px; border: none; }
|
||||
.btn-primary { background-color: #1890ff; color: #fff; }
|
||||
.table-wrap { width: 100%; border: 1px solid #f0f0f0; }
|
||||
.table-header { display: flex; flex-direction: row; background-color: #f8f8f9; }
|
||||
.th { padding: 12px 10px; font-size: 13px; font-weight: bold; color: #515a6e; border-bottom: 1px solid #f0f0f0; text-align: center; }
|
||||
.tr { display: flex; flex-direction: row; align-items: center; border-bottom: 1px solid #f0f0f0; min-height: 50px; }
|
||||
.td { padding: 10px; font-size: 13px; color: #515a6e; text-align: center; }
|
||||
.action-btn { font-size: 13px; color: #1890ff; margin-right: 8px; cursor: pointer; }
|
||||
.action-btn-del { font-size: 13px; color: #ed4014; cursor: pointer; }
|
||||
</style>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="table-row">
|
||||
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||
<view class="col col-user"><text>{{ item.user }}</text></view>
|
||||
<view class="col col-action"><text>{{ item.action }}</text></view>
|
||||
@@ -58,17 +58,30 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页 -->
|
||||
<view class="pagination">
|
||||
<text class="page-info">共 583387 条 15条/页</text>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const dataList = ref([
|
||||
{ id: 585387, user: '5 / demo', action: '系统日志', link: 'system/log', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:49' },
|
||||
@@ -81,8 +94,49 @@ const dataList = ref([
|
||||
{ id: 585380, user: '5 / demo', action: '定时任务类型', link: 'system/crontab/mark', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||
{ id: 585379, user: '5 / demo', action: '定时任务列表', link: 'system/crontab/list', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||
{ id: 585378, user: '5 / demo', action: '保存组合数据', link: 'setting/group', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||
{ id: 585377, user: '5 / demo', action: '保存系统配置分类', link: 'setting/config_class', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' }
|
||||
{ id: 585377, user: '5 / demo', action: '保存系统配置分类', link: 'setting/config_class', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||
{ id: 585376, user: '5 / demo', action: '神识别相册管理', link: 'system/gallery', ip: '115.29.168.1', type: 'system', time: '2026-02-11 18:45' },
|
||||
{ id: 585375, user: '3 / admin', action: '订单列表', link: 'order/list', ip: '116.228.88.5', type: 'system', time: '2026-02-11 18:43' },
|
||||
{ id: 585374, user: '3 / admin', action: '商品列表', link: 'product/list', ip: '116.228.88.5', type: 'system', time: '2026-02-11 18:42' },
|
||||
{ id: 585373, user: '3 / admin', action: '用户列表', link: 'user/list', ip: '116.228.88.5', type: 'system', time: '2026-02-11 18:41' },
|
||||
{ id: 585372, user: '5 / demo', action: '分销分红记录', link: 'distribution/brokerage', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:40' },
|
||||
{ id: 585371, user: '5 / demo', action: '财务提现列表', link: 'finance/withdraw', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:39' },
|
||||
{ id: 585370, user: '3 / admin', action: '商品分类列表', link: 'product/category', ip: '116.228.88.5', type: 'system', time: '2026-02-11 18:38' },
|
||||
{ id: 585369, user: '1 / 超级管理员', action: '系统监控', link: 'system/monitor', ip: '127.0.0.1', type: 'system', time: '2026-02-11 18:37' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => dataList.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 dataList.value.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 ==========
|
||||
|
||||
function onSearch() {
|
||||
uni.showToast({ title: '搜索中...', icon: 'none' })
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<template>
|
||||
<AdminLayout currentPage="marketing">
|
||||
<view class="admin-page">
|
||||
<view class="admin-sections">
|
||||
<view class="admin-card Header">
|
||||
<text class="Title">营销管理</text>
|
||||
<text class="SubTitle">marketing-management</text>
|
||||
</view>
|
||||
|
||||
<view class="admin-card Card">
|
||||
<text class="Label">页面参数(query)</text>
|
||||
<text class="Mono">{{ params }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
|
||||
const params = ref('')
|
||||
|
||||
onLoad((options) => {
|
||||
// options: Record<string, any>
|
||||
params.value = JSON.stringify(options ?? {})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.Header {
|
||||
}
|
||||
.Title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
.SubTitle {
|
||||
margin-top: 8rpx;
|
||||
font-size: 24rpx;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.Card {
|
||||
}
|
||||
.Label {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.Mono {
|
||||
font-size: 24rpx;
|
||||
font-family: monospace;
|
||||
line-height: 36rpx;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
@@ -226,7 +226,7 @@ const handleSubmit = () => {
|
||||
.cell-days { width: 120px; }
|
||||
.cell-reward { flex: 1; }
|
||||
.cell-status { width: 100px; text-align: center; }
|
||||
.cell-op { width: 150px; text-align: right; }
|
||||
.cell-op { width: 150px; text-align: right; display: flex; flex-direction: row; }
|
||||
|
||||
.op-link { color: #1890ff; font-size: 13px; cursor: pointer; }
|
||||
.op-link.del { color: #ff4d4f; }
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view v-for="item in configList" :key="item.id" class="table-row">
|
||||
<view v-for="item in pagedList" :key="item.id" class="table-row">
|
||||
<view class="td cell-id">
|
||||
<text class="td-txt">{{ item.id }}</text>
|
||||
</view>
|
||||
@@ -60,17 +60,22 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="pagination-footer">
|
||||
<view class="page-total">
|
||||
<text class="total-txt">共 {{ configList.length }} 条</text>
|
||||
</view>
|
||||
<view class="page-select">
|
||||
<view class="select-mock mini">
|
||||
<text class="select-val">20条/页</text>
|
||||
<text class="arrow">▼</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
|
||||
<!-- Drawer Overlay -->
|
||||
@@ -116,8 +121,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import StatusSwitch from '@/components/StatusSwitch.uvue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const showDrawer = ref(false)
|
||||
const isAnimating = ref(false)
|
||||
@@ -131,16 +137,63 @@ const formData = ref({
|
||||
status: true
|
||||
})
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 configList 为 fetchConfigList() 调用
|
||||
const configList = ref([
|
||||
{
|
||||
id: 2268,
|
||||
start_hour: 6,
|
||||
duration: 18,
|
||||
image: '',
|
||||
sort: 1,
|
||||
status: true
|
||||
}
|
||||
{ id: 2268, start_hour: 0, duration: 2, image: '', sort: 1, status: true },
|
||||
{ id: 2269, start_hour: 2, duration: 2, image: '', sort: 2, status: true },
|
||||
{ id: 2270, start_hour: 4, duration: 2, image: '', sort: 3, status: true },
|
||||
{ id: 2271, start_hour: 6, duration: 3, image: '', sort: 4, status: true },
|
||||
{ id: 2272, start_hour: 9, duration: 3, image: '', sort: 5, status: true },
|
||||
{ id: 2273, start_hour: 12, duration: 3, image: '', sort: 6, status: false },
|
||||
{ id: 2274, start_hour: 15, duration: 3, image: '', sort: 7, status: true },
|
||||
{ id: 2275, start_hour: 18, duration: 2, image: '', sort: 8, status: true },
|
||||
{ id: 2276, start_hour: 20, duration: 2, image: '', sort: 9, status: true },
|
||||
{ id: 2277, start_hour: 22, duration: 2, image: '', sort: 10, status: false },
|
||||
{ id: 2278, start_hour: 8, duration: 4, image: '', sort: 11, status: true },
|
||||
{ id: 2279, start_hour: 10, duration: 2, image: '', sort: 12, status: true },
|
||||
{ id: 2280, start_hour: 13, duration: 2, image: '', sort: 13, status: true },
|
||||
{ id: 2281, start_hour: 16, duration: 3, image: '', sort: 14, status: false },
|
||||
{ id: 2282, start_hour: 19, duration: 1, image: '', sort: 15, status: true },
|
||||
{ id: 2283, start_hour: 21, duration: 2, image: '', sort: 16, status: true },
|
||||
{ id: 2284, start_hour: 7, duration: 3, image: '', sort: 17, status: true },
|
||||
{ id: 2285, start_hour: 11, duration: 2, image: '', sort: 18, status: false },
|
||||
{ id: 2286, start_hour: 14, duration: 4, image: '', sort: 19, status: true },
|
||||
{ id: 2287, start_hour: 17, duration: 2, image: '', sort: 20, status: true },
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => configList.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 configList.value.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 handleEdit = (item: any) => {
|
||||
formData.value = { ...item }
|
||||
@@ -313,16 +366,7 @@ const closeDrawer = () => {
|
||||
.op-link { color: #1890ff; font-size: 13px; cursor: pointer; }
|
||||
.op-split { color: #e8eaec; margin: 0 8px; }
|
||||
|
||||
/* 分页 */
|
||||
.pagination-footer {
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
.total-txt { font-size: 13px; color: #606266; }
|
||||
/* 分页区域已迁至 CommonPagination 组件 */
|
||||
|
||||
/* Drawer Styles */
|
||||
.drawer-mask {
|
||||
|
||||
@@ -32,23 +32,119 @@
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view class="no-data">
|
||||
<text class="no-data-text">暂无数据</text>
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.account }}</view>
|
||||
<view class="td" style="flex: 2;">{{ item.role }}</view>
|
||||
<view class="td" style="flex: 3;">{{ item.lastLoginTime }}</view>
|
||||
<view class="td" style="flex: 3;">{{ item.lastLoginIp }}</view>
|
||||
<view class="td" style="flex: 1;">
|
||||
<switch :checked="item.status" color="#1890ff" style="transform: scale(0.7);" />
|
||||
</view>
|
||||
<view class="td" style="flex: 2;">
|
||||
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||
<text class="action-btn-del" @click="onDelete(item)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchKey = ref('')
|
||||
const statusRange = ['所有', '启用', '禁用']
|
||||
const statusIndex = ref(0)
|
||||
const statusText = ref('请选择')
|
||||
|
||||
type AdminItem = {
|
||||
id: number
|
||||
name: string
|
||||
account: string
|
||||
role: string
|
||||
lastLoginTime: string
|
||||
lastLoginIp: string
|
||||
status: boolean
|
||||
}
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 adminList 为 fetchAdminList() 调用
|
||||
const adminList = ref<AdminItem[]>([
|
||||
{ id: 20, name: '张三', account: 'zhangsan', role: '超级管理员', lastLoginTime: '2025-06-28 10:30:00', lastLoginIp: '192.168.1.1', status: true },
|
||||
{ id: 19, name: '李四', account: 'lisi', role: '运营管理员', lastLoginTime: '2025-06-27 09:15:00', lastLoginIp: '192.168.1.2', status: true },
|
||||
{ id: 18, name: '王五', account: 'wangwu', role: '财务管理员', lastLoginTime: '2025-06-26 14:20:00', lastLoginIp: '10.0.0.5', status: true },
|
||||
{ id: 17, name: '赵六', account: 'zhaoliu', role: '客服专员', lastLoginTime: '2025-06-25 11:00:00', lastLoginIp: '10.0.0.6', status: false },
|
||||
{ id: 16, name: '陈七', account: 'chenqi', role: '商品管理员', lastLoginTime: '2025-06-24 16:45:00', lastLoginIp: '172.16.0.1', status: true },
|
||||
{ id: 15, name: '周八', account: 'zhouba', role: '订单管理员', lastLoginTime: '2025-06-23 08:30:00', lastLoginIp: '172.16.0.2', status: true },
|
||||
{ id: 14, name: '吴九', account: 'wujiu', role: '营销专员', lastLoginTime: '2025-06-22 13:00:00', lastLoginIp: '192.168.2.1', status: true },
|
||||
{ id: 13, name: '郑十', account: 'zhengshi', role: '内容管理员', lastLoginTime: '2025-06-21 10:00:00', lastLoginIp: '192.168.2.2', status: false },
|
||||
{ id: 12, name: '马一一', account: 'mayiyi', role: '数据分析师', lastLoginTime: '2025-06-20 15:20:00', lastLoginIp: '10.0.1.1', status: true },
|
||||
{ id: 11, name: '刘二二', account: 'liuerer', role: '技术支持', lastLoginTime: '2025-06-19 09:40:00', lastLoginIp: '10.0.1.2', status: true },
|
||||
{ id: 10, name: '张三三', account: 'zhangsansan', role: '分销管理员', lastLoginTime: '2025-06-18 11:30:00', lastLoginIp: '172.16.1.1', status: true },
|
||||
{ id: 9, name: '李四四', account: 'lisisi', role: '仓库管理员', lastLoginTime: '2025-06-17 14:00:00', lastLoginIp: '172.16.1.2', status: false },
|
||||
{ id: 8, name: '王五五', account: 'wangwuwu', role: '客服小组长', lastLoginTime: '2025-06-16 10:10:00', lastLoginIp: '192.168.3.1', status: true },
|
||||
{ id: 7, name: '赵六六', account: 'zhaoliuliu', role: '运营小组长', lastLoginTime: '2025-06-15 09:00:00', lastLoginIp: '192.168.3.2', status: true },
|
||||
{ id: 6, name: '陈七七', account: 'chenqiqi', role: '商品小组长', lastLoginTime: '2025-06-14 16:00:00', lastLoginIp: '10.0.2.1', status: true },
|
||||
{ id: 5, name: '周八八', account: 'zhoubaba', role: '订单小组长', lastLoginTime: '2025-06-13 15:00:00', lastLoginIp: '10.0.2.2', status: false },
|
||||
{ id: 4, name: '吴九九', account: 'wujiujiu', role: '营销小组长', lastLoginTime: '2025-06-12 11:00:00', lastLoginIp: '172.16.2.1', status: true },
|
||||
{ id: 3, name: '马小明', account: 'maxiaoming', role: '普通管理员', lastLoginTime: '2025-06-11 10:20:00', lastLoginIp: '172.16.2.2', status: true },
|
||||
{ id: 2, name: '李小花', account: 'lixiaohua', role: '普通管理员', lastLoginTime: '2025-06-10 08:50:00', lastLoginIp: '192.168.4.1', status: true },
|
||||
{ id: 1, name: 'admin', account: 'admin', role: '超级管理员', lastLoginTime: '2025-06-29 22:00:00', lastLoginIp: '127.0.0.1', status: true }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => adminList.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 adminList.value.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 ==========
|
||||
|
||||
function onStatusChange(e: any) {
|
||||
statusIndex.value = parseInt(e.detail.value.toString())
|
||||
statusText.value = statusRange[statusIndex.value]
|
||||
@@ -61,6 +157,22 @@ function onSearch() {
|
||||
function onAdd() {
|
||||
console.log('Add admin')
|
||||
}
|
||||
|
||||
function onEdit(item: AdminItem) {
|
||||
console.log('Edit admin:', item.account)
|
||||
}
|
||||
|
||||
function onDelete(item: AdminItem) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定删除该管理员吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showToast({ title: '已删除', icon: 'success' })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -166,13 +278,31 @@ function onAdd() {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
padding: 40px 0;
|
||||
.tr {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
min-height: 54px;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
color: #515a6e;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-data-text {
|
||||
font-size: 14px;
|
||||
color: #c5c8ce;
|
||||
.action-btn {
|
||||
font-size: 13px;
|
||||
color: #1890ff;
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-btn-del {
|
||||
font-size: 13px;
|
||||
color: #ed4014;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in courierList" :key="item.id" class="tr">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 1.5;">
|
||||
<image class="avatar" :src="item.avatar" mode="aspectFill" />
|
||||
@@ -35,12 +35,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
type CourierItem = {
|
||||
id: number
|
||||
@@ -51,11 +68,63 @@ type CourierItem = {
|
||||
addTime: string
|
||||
}
|
||||
|
||||
const courierList = reactive<CourierItem[]>([
|
||||
{ id: 106, avatar: '/static/logo.png', name: 'cheshi', phone: '18943652356', isshow: true, addTime: '2025-06-29 21:45:19' },
|
||||
{ id: 105, avatar: '/static/logo.png', name: 'dl', phone: '15648569914', isshow: true, addTime: '2025-06-28 18:40:26' },
|
||||
{ id: 102, avatar: '/static/logo.png', name: '小牛马', phone: '13548652258', isshow: true, addTime: '2025-06-26 15:14:40' }
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 courierList 为 fetchCourierList() 调用
|
||||
const courierList = ref<CourierItem[]>([
|
||||
{ id: 120, avatar: '/static/logo.png', name: '王明', phone: '13812345678', isshow: true, addTime: '2025-06-29 21:45:19' },
|
||||
{ id: 119, avatar: '/static/logo.png', name: '李红', phone: '13987654321', isshow: true, addTime: '2025-06-28 18:40:26' },
|
||||
{ id: 118, avatar: '/static/logo.png', name: '张伟', phone: '15800001111', isshow: true, addTime: '2025-06-27 09:00:00' },
|
||||
{ id: 117, avatar: '/static/logo.png', name: '刘洋', phone: '15900002222', isshow: false, addTime: '2025-06-26 15:14:40' },
|
||||
{ id: 116, avatar: '/static/logo.png', name: '陈娟', phone: '13600003333', isshow: true, addTime: '2025-06-25 10:00:00' },
|
||||
{ id: 115, avatar: '/static/logo.png', name: '杨帆', phone: '13700004444', isshow: true, addTime: '2025-06-24 08:30:00' },
|
||||
{ id: 114, avatar: '/static/logo.png', name: '赵雷', phone: '18900005555', isshow: false, addTime: '2025-06-23 11:20:00' },
|
||||
{ id: 113, avatar: '/static/logo.png', name: '周芳', phone: '13500006666', isshow: true, addTime: '2025-06-22 14:50:00' },
|
||||
{ id: 112, avatar: '/static/logo.png', name: '吴勇', phone: '15600007777', isshow: true, addTime: '2025-06-21 16:10:00' },
|
||||
{ id: 111, avatar: '/static/logo.png', name: '郑山', phone: '18700008888', isshow: true, addTime: '2025-06-20 09:40:00' },
|
||||
{ id: 110, avatar: '/static/logo.png', name: '孙海', phone: '13900009999', isshow: false, addTime: '2025-06-19 13:00:00' },
|
||||
{ id: 109, avatar: '/static/logo.png', name: '马琳', phone: '15300010101', isshow: true, addTime: '2025-06-18 07:50:00' },
|
||||
{ id: 108, avatar: '/static/logo.png', name: '胡兴', phone: '18600011111', isshow: true, addTime: '2025-06-17 12:00:00' },
|
||||
{ id: 107, avatar: '/static/logo.png', name: '高雪', phone: '13200012222', isshow: true, addTime: '2025-06-16 15:30:00' },
|
||||
{ id: 106, avatar: '/static/logo.png', name: 'cheshi', phone: '18943652356', isshow: true, addTime: '2025-06-15 21:45:19' },
|
||||
{ id: 105, avatar: '/static/logo.png', name: 'dl', phone: '15648569914', isshow: true, addTime: '2025-06-14 18:40:26' },
|
||||
{ id: 104, avatar: '/static/logo.png', name: '小牛马', phone: '13548652258', isshow: true, addTime: '2025-06-13 15:14:40' },
|
||||
{ id: 103, avatar: '/static/logo.png', name: '小李', phone: '13200013333', isshow: false, addTime: '2025-06-12 10:00:00' },
|
||||
{ id: 102, avatar: '/static/logo.png', name: '小刘', phone: '15000014444', isshow: true, addTime: '2025-06-11 09:00:00' },
|
||||
{ id: 101, avatar: '/static/logo.png', name: '小王', phone: '13300015555', isshow: true, addTime: '2025-06-10 08:00:00' }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => courierList.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 courierList.value.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 ==========
|
||||
|
||||
function onAdd() {
|
||||
console.log('Add courier')
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in stationList" :key="item.id" class="tr">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 2;">
|
||||
<image class="station-img" :src="item.image" mode="aspectFill" />
|
||||
@@ -53,12 +53,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchKey = ref('')
|
||||
|
||||
@@ -72,10 +89,63 @@ type StationItem = {
|
||||
isshow: boolean
|
||||
}
|
||||
|
||||
const stationList = reactive<StationItem[]>([
|
||||
{ id: 46, image: '/static/logo.png', name: '提货点222', phone: '13769102384', address: '能看见你的困难', hours: '00:00:00 - 23:00:00', isshow: true },
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 stationList 为 fetchStationList() 调用
|
||||
const stationList = ref<StationItem[]>([
|
||||
{ id: 65, image: '/static/logo.png', name: '北京朝阳门提货点', phone: '13012340001', address: '北京市朝阳区建国路1号', hours: '09:00 - 21:00', isshow: true },
|
||||
{ id: 64, image: '/static/logo.png', name: '北京海淨区提货点', phone: '13012340002', address: '北京市海淨区中关村大腃4号', hours: '08:30 - 20:30', isshow: true },
|
||||
{ id: 63, image: '/static/logo.png', name: '上海浦东新区提货点', phone: '13012340003', address: '上海市浦东新区张江高科2号', hours: '09:00 - 22:00', isshow: true },
|
||||
{ id: 62, image: '/static/logo.png', name: '上海徐汇提货点', phone: '13012340004', address: '上海市徐汇区淮海中路100号', hours: '10:00 - 21:00', isshow: false },
|
||||
{ id: 61, image: '/static/logo.png', name: '广州天河提货点', phone: '13012340005', address: '广州市天河区天河北路55号', hours: '09:00 - 21:00', isshow: true },
|
||||
{ id: 60, image: '/static/logo.png', name: '广州越秀提货点', phone: '13012340006', address: '广州市越秀区环市东路18号', hours: '08:00 - 20:00', isshow: true },
|
||||
{ id: 59, image: '/static/logo.png', name: '深圳南山提货点', phone: '13012340007', address: '深圳市南山区松白路7号', hours: '09:00 - 22:00', isshow: true },
|
||||
{ id: 58, image: '/static/logo.png', name: '深圳福田提货点', phone: '13012340008', address: '深圳市福田区深南大道青年公指1号', hours: '09:00 - 21:00', isshow: false },
|
||||
{ id: 57, image: '/static/logo.png', name: '成都武侯提货点', phone: '13012340009', address: '成都市武侯区為最居东路3号', hours: '09:00 - 21:00', isshow: true },
|
||||
{ id: 56, image: '/static/logo.png', name: '成都高新提货点', phone: '13012340010', address: '成都市高新区天府大道三段501号', hours: '08:30 - 20:30', isshow: true },
|
||||
{ id: 55, image: '/static/logo.png', name: '杭州西湖提货点', phone: '13012340011', address: '杭州市西湖区建途路21号', hours: '09:00 - 22:00', isshow: true },
|
||||
{ id: 54, image: '/static/logo.png', name: '杭州滨江提货点', phone: '13012340012', address: '杭州市拱墅区餓山镇中路', hours: '10:00 - 21:00', isshow: false },
|
||||
{ id: 53, image: '/static/logo.png', name: '武汉江汉提货点', phone: '13012340013', address: '武汉市江汉区建设大道100号', hours: '09:00 - 20:00', isshow: true },
|
||||
{ id: 52, image: '/static/logo.png', name: '武汉武昌提货点', phone: '13012340014', address: '武汉市武昌区紫菓路58号', hours: '08:30 - 21:00', isshow: true },
|
||||
{ id: 51, image: '/static/logo.png', name: '南京中山提货点', phone: '13012340015', address: '南京市中山区阳山路123号', hours: '09:00 - 21:00', isshow: true },
|
||||
{ id: 50, image: '/static/logo.png', name: '南京冿淮提货点', phone: '13012340016', address: '南京市冿淮区广州路9号', hours: '09:00 - 20:30', isshow: true },
|
||||
{ id: 49, image: '/static/logo.png', name: '苏州工业园提货点', phone: '13012340017', address: '苏州工业园区现代大道168号', hours: '09:00 - 21:00', isshow: false },
|
||||
{ id: 48, image: '/static/logo.png', name: '苏州姑苏提货点', phone: '13012340018', address: '苏州市姑苏区干将东路66号', hours: '07:30 - 22:00', isshow: true },
|
||||
{ id: 47, image: '/static/logo.png', name: '提货点222', phone: '13769102384', address: '能看见你的困难', hours: '00:00:00 - 23:00:00', isshow: true },
|
||||
{ id: 44, image: '/static/logo.png', name: '美东科技', phone: '15912341234', address: '襄阳火车站', hours: '08:00:00 - 22:00:00', isshow: true }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => stationList.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 stationList.value.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 ==========
|
||||
|
||||
function onSearch() {
|
||||
console.log('Search:', searchKey.value)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<view class="th" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="item in verifierList" :key="item.id" class="tr">
|
||||
<view v-for="item in pagedList" :key="item.id" class="tr">
|
||||
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||
<view class="td" style="flex: 1.5;">
|
||||
<image class="avatar" :src="item.avatar" mode="aspectFill" />
|
||||
@@ -48,12 +48,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const stationRange = ['所有', '提货点222', '美东科技']
|
||||
const stationText = ref('请选择')
|
||||
@@ -68,9 +85,63 @@ type VerifierItem = {
|
||||
status: boolean
|
||||
}
|
||||
|
||||
const verifierList = reactive<VerifierItem[]>([
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 verifierList 为 fetchVerifierList() 调用
|
||||
const verifierList = ref<VerifierItem[]>([
|
||||
{ id: 113, avatar: '/static/logo.png', wechatName: '林小星', name: '13800000001', station: '提货点222', addTime: '2025-11-01 09:00:00', status: true },
|
||||
{ id: 112, avatar: '/static/logo.png', wechatName: '吴明', name: '13800000002', station: '美东科技', addTime: '2025-10-30 10:20:00', status: true },
|
||||
{ id: 111, avatar: '/static/logo.png', wechatName: '赵姐', name: '13800000003', station: '提货点222', addTime: '2025-10-29 11:40:00', status: false },
|
||||
{ id: 110, avatar: '/static/logo.png', wechatName: '高先', name: '13800000004', station: '美东科技', addTime: '2025-10-28 08:30:00', status: true },
|
||||
{ id: 109, avatar: '/static/logo.png', wechatName: '孙明', name: '13800000005', station: '提货点222', addTime: '2025-10-27 14:00:00', status: true },
|
||||
{ id: 108, avatar: '/static/logo.png', wechatName: '周波', name: '13800000006', station: '美东科技', addTime: '2025-10-26 16:10:00', status: true },
|
||||
{ id: 107, avatar: '/static/logo.png', wechatName: '郑军', name: '13800000007', station: '提货点222', addTime: '2025-10-25 09:50:00', status: false },
|
||||
{ id: 106, avatar: '/static/logo.png', wechatName: '谢婷', name: '13800000008', station: '美东科技', addTime: '2025-10-24 13:20:00', status: true },
|
||||
{ id: 105, avatar: '/static/logo.png', wechatName: '谢军', name: '13800000009', station: '提货点222', addTime: '2025-10-23 11:00:00', status: true },
|
||||
{ id: 104, avatar: '/static/logo.png', wechatName: '马芳', name: '13800000010', station: '美东科技', addTime: '2025-10-22 12:30:00', status: true },
|
||||
{ id: 103, avatar: '/static/logo.png', wechatName: '李迪', name: '13800000011', station: '提货点222', addTime: '2025-10-21 10:00:00', status: false },
|
||||
{ id: 102, avatar: '/static/logo.png', wechatName: '张玉', name: '13800000012', station: '美东科技', addTime: '2025-10-20 15:40:00', status: true },
|
||||
{ id: 101, avatar: '/static/logo.png', wechatName: '王海', name: '13800000013', station: '提货点222', addTime: '2025-10-19 08:20:00', status: true },
|
||||
{ id: 100, avatar: '/static/logo.png', wechatName: '刘云', name: '13800000014', station: '美东科技', addTime: '2025-10-18 09:10:00', status: true },
|
||||
{ id: 99, avatar: '/static/logo.png', wechatName: '陈山', name: '13800000015', station: '提货点222', addTime: '2025-10-17 11:30:00', status: false },
|
||||
{ id: 98, avatar: '/static/logo.png', wechatName: '吴州', name: '13800000016', station: '美东科技', addTime: '2025-10-16 14:50:00', status: true },
|
||||
{ id: 97, avatar: '/static/logo.png', wechatName: '魏桂', name: '13800000017', station: '提货点222', addTime: '2025-10-15 10:20:00', status: true },
|
||||
{ id: 96, avatar: '/static/logo.png', wechatName: '彭冬', name: '13800000018', station: '美东科技', addTime: '2025-10-14 16:00:00', status: true },
|
||||
{ id: 95, avatar: '/static/logo.png', wechatName: '夏迪', name: '13800000019', station: '提货点222', addTime: '2025-10-23 10:45:07', status: true },
|
||||
{ id: 94, avatar: '/static/logo.png', wechatName: '地球人', name: '15920014197', station: '美东科技', addTime: '2025-10-22 10:33:07', status: true }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => verifierList.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 verifierList.value.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 ==========
|
||||
|
||||
function onStationChange(e: any) {
|
||||
const index = parseInt(e.detail.value.toString())
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<view class="table-cell action-cell" style="flex: 2;">操作</view>
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="(item, index) in printerList" :key="index">
|
||||
<view class="table-row" v-for="(item, index) in pagedList" :key="index">
|
||||
<view class="table-cell" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||
<view class="table-cell" style="flex: 2;">{{ item.name }}</view>
|
||||
<view class="table-cell" style="flex: 1.5;">{{ item.platform }}</view>
|
||||
@@ -52,26 +52,90 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页 (模拟) -->
|
||||
<view class="pagination">
|
||||
<text class="total">共 1 条</text>
|
||||
<picker :range="['15条/页', '30条/页']">
|
||||
<view class="page-size">15条/页</view>
|
||||
</picker>
|
||||
</view>
|
||||
<CommonPagination
|
||||
v-if="total > 0"
|
||||
: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>
|
||||
</view>
|
||||
</view></template>
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
|
||||
|
||||
const searchQuery = ref({ name: '' })
|
||||
const platforms = ['全部', '易联云', '飞鹅打印机']
|
||||
const selectedPlatform = ref(0)
|
||||
|
||||
// ========== MOCK DATA START ==========
|
||||
// TODO: 接真实接口时替换此处 printerList 为 fetchPrinterList() 调用
|
||||
const printerList = ref([
|
||||
{ id: 20, name: '总部底层打印机', platform: '易联云', account: 'hq_admin', copies: 2, add_time: '2025-02-01 10:00:00', status: true },
|
||||
{ id: 19, name: '广州仓库打印机', platform: '飞鹅打印机', account: 'gz_wh01', copies: 1, add_time: '2025-02-03 11:00:00', status: true },
|
||||
{ id: 18, name: '上海分拨打印机', platform: '易联云', account: 'sh_fp01', copies: 1, add_time: '2025-02-05 09:30:00', status: false },
|
||||
{ id: 17, name: '北京主打印机', platform: '易联云', account: 'bj_main', copies: 2, add_time: '2025-02-08 14:00:00', status: true },
|
||||
{ id: 16, name: '北京备打印机', platform: '飞鹅打印机', account: 'bj_bak01', copies: 1, add_time: '2025-02-10 08:30:00', status: true },
|
||||
{ id: 15, name: '化妙打印机', platform: '易联云', account: 'hm_pr01', copies: 3, add_time: '2025-02-12 10:20:00', status: true },
|
||||
{ id: 14, name: '客服部打印机', platform: '飞鹅打印机', account: 'cs_pr01', copies: 1, add_time: '2025-02-15 15:00:00', status: true },
|
||||
{ id: 13, name: '采购部打印机', platform: '易联云', account: 'cg_pr01', copies: 1, add_time: '2025-02-18 12:00:00', status: false },
|
||||
{ id: 12, name: '财务部打印机', platform: '飞鹅打印机', account: 'cw_pr01', copies: 2, add_time: '2025-02-20 09:00:00', status: true },
|
||||
{ id: 11, name: '运营部打印机', platform: '易联云', account: 'yy_pr01', copies: 1, add_time: '2025-02-22 11:30:00', status: true },
|
||||
{ id: 10, name: '成都网点打印机', platform: '飞鹅打印机', account: 'cd_np01', copies: 1, add_time: '2025-02-25 10:00:00', status: true },
|
||||
{ id: 9, name: '武汉网点打印机', platform: '易联云', account: 'wh_np01', copies: 2, add_time: '2025-03-01 14:00:00', status: false },
|
||||
{ id: 8, name: '深圳网点打印机', platform: '飞鹅打印机', account: 'sz_np01', copies: 1, add_time: '2025-03-05 09:00:00', status: true },
|
||||
{ id: 7, name: '杭州网点打印机', platform: '易联云', account: 'hz_np01', copies: 1, add_time: '2025-03-08 11:00:00', status: true },
|
||||
{ id: 6, name: '南京网点打印机', platform: '飞鹅打印机', account: 'nj_np01', copies: 2, add_time: '2025-03-10 12:00:00', status: true },
|
||||
{ id: 5, name: '苏州网点打印机', platform: '易联云', account: 'sz2_np01', copies: 1, add_time: '2025-03-12 15:00:00', status: false },
|
||||
{ id: 4, name: '小类目打印机', platform: '飞鹅打印机', account: 'xl_pr01', copies: 1, add_time: '2025-03-15 10:30:00', status: true },
|
||||
{ id: 3, name: '大档打印机', platform: '易联云', account: 'dd_pr01', copies: 3, add_time: '2025-03-18 09:00:00', status: true },
|
||||
{ id: 2, name: '二号打印', platform: '飞鹅打印机', account: '333', copies: 1, add_time: '2025-01-01 12:00:00', status: false },
|
||||
{ id: 1, name: '一号打印', platform: '易联云', account: '222', copies: 1, add_time: '2024-12-11 15:12:58', status: true }
|
||||
])
|
||||
// ========== MOCK DATA END ==========
|
||||
|
||||
// ========== PAGINATION STATE ==========
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
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(() => printerList.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 printerList.value.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 ==========
|
||||
|
||||
function onPlatformChange(e: any) {
|
||||
selectedPlatform.value = e.detail.value
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GET http://localhost:5173/uni_modules/ak-req/ak-req.uts?t=1773363160904&import net::ERR_ABORTED 500 (Internal Server Error)
|
||||
main.uts:16 [Vue warn]: Unhandled error during execution of async component loader
|
||||
withdrawal.uvue:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error)
|
||||
uni-h5.es.js:19975 [Vue warn]: Unhandled error during execution of async component loader
|
||||
at <AsyncComponentWrapper>
|
||||
at <PageBody>
|
||||
at <Page>
|
||||
@@ -17,85 +17,32 @@ callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||
handleError @ vue.runtime.esm.js:1421
|
||||
onError @ vue.runtime.esm.js:3724
|
||||
(anonymous) @ vue.runtime.esm.js:3767
|
||||
Promise.catch
|
||||
setup @ vue.runtime.esm.js:3766
|
||||
vue.runtime.esm.js:1443 TypeError: Failed to fetch dynamically imported module: http://localhost:5173/pages/mall/admin/homePage/index.uvue?t=1773707553790&import
|
||||
logError @ vue.runtime.esm.js:1443
|
||||
errorHandler @ uni-h5.es.js:19600
|
||||
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||
setupComponent @ vue.runtime.esm.js:8946
|
||||
mountComponent @ vue.runtime.esm.js:7262
|
||||
processComponent @ vue.runtime.esm.js:7228
|
||||
patch @ vue.runtime.esm.js:6694
|
||||
mountChildren @ vue.runtime.esm.js:6942
|
||||
processFragment @ vue.runtime.esm.js:7158
|
||||
patch @ vue.runtime.esm.js:6668
|
||||
mountChildren @ vue.runtime.esm.js:6942
|
||||
processFragment @ vue.runtime.esm.js:7158
|
||||
patch @ vue.runtime.esm.js:6668
|
||||
mountChildren @ vue.runtime.esm.js:6942
|
||||
mountElement @ vue.runtime.esm.js:6849
|
||||
processElement @ vue.runtime.esm.js:6814
|
||||
patch @ vue.runtime.esm.js:6682
|
||||
mountChildren @ vue.runtime.esm.js:6942
|
||||
mountElement @ vue.runtime.esm.js:6849
|
||||
processElement @ vue.runtime.esm.js:6814
|
||||
patch @ vue.runtime.esm.js:6682
|
||||
mountChildren @ vue.runtime.esm.js:6942
|
||||
processFragment @ vue.runtime.esm.js:7158
|
||||
patch @ vue.runtime.esm.js:6668
|
||||
componentUpdateFn @ vue.runtime.esm.js:7372
|
||||
run @ vue.runtime.esm.js:153
|
||||
instance.update @ vue.runtime.esm.js:7497
|
||||
setupRenderEffect @ vue.runtime.esm.js:7507
|
||||
mountComponent @ vue.runtime.esm.js:7274
|
||||
processComponent @ vue.runtime.esm.js:7228
|
||||
patch @ vue.runtime.esm.js:6694
|
||||
mountChildren @ vue.runtime.esm.js:6942
|
||||
mountElement @ vue.runtime.esm.js:6849
|
||||
processElement @ vue.runtime.esm.js:6814
|
||||
patch @ vue.runtime.esm.js:6682
|
||||
componentUpdateFn @ vue.runtime.esm.js:7372
|
||||
run @ vue.runtime.esm.js:153
|
||||
instance.update @ vue.runtime.esm.js:7497
|
||||
setupRenderEffect @ vue.runtime.esm.js:7507
|
||||
mountComponent @ vue.runtime.esm.js:7274
|
||||
processComponent @ vue.runtime.esm.js:7228
|
||||
patch @ vue.runtime.esm.js:6694
|
||||
componentUpdateFn @ vue.runtime.esm.js:7372
|
||||
run @ vue.runtime.esm.js:153
|
||||
instance.update @ vue.runtime.esm.js:7497
|
||||
setupRenderEffect @ vue.runtime.esm.js:7507
|
||||
mountComponent @ vue.runtime.esm.js:7274
|
||||
processComponent @ vue.runtime.esm.js:7228
|
||||
patch @ vue.runtime.esm.js:6694
|
||||
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||
run @ vue.runtime.esm.js:153
|
||||
instance.update @ vue.runtime.esm.js:7497
|
||||
updateComponent @ vue.runtime.esm.js:7305
|
||||
processComponent @ vue.runtime.esm.js:7239
|
||||
patch @ vue.runtime.esm.js:6694
|
||||
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||
run @ vue.runtime.esm.js:153
|
||||
instance.update @ vue.runtime.esm.js:7497
|
||||
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||
flushJobs @ vue.runtime.esm.js:1585
|
||||
handleError @ vue.runtime.esm.js:1421
|
||||
onError @ vue.runtime.esm.js:3724
|
||||
(anonymous) @ vue.runtime.esm.js:3767
|
||||
ak-req.uts:164 GET http://119.146.131.237:9126/auth/v1/user 403 (Forbidden)
|
||||
(anonymous) @ uni-h5.es.js:23666
|
||||
(anonymous) @ uni-h5.es.js:4125
|
||||
invokeApi @ uni-h5.es.js:3971
|
||||
(anonymous) @ uni-h5.es.js:3989
|
||||
(anonymous) @ ak-req.uts:164
|
||||
doOnce @ ak-req.uts:163
|
||||
(anonymous) @ ak-req.uts:233
|
||||
fulfilled @ tslib.es6.js:73
|
||||
Promise.then
|
||||
queueFlush @ vue.runtime.esm.js:1494
|
||||
queueJob @ vue.runtime.esm.js:1488
|
||||
scheduler @ vue.runtime.esm.js:3179
|
||||
resetScheduling @ vue.runtime.esm.js:236
|
||||
triggerEffects @ vue.runtime.esm.js:280
|
||||
triggerRefValue @ vue.runtime.esm.js:1033
|
||||
set value @ vue.runtime.esm.js:1078
|
||||
finalizeNavigation @ vue-router.mjs?v=ed041164:2474
|
||||
(anonymous) @ vue-router.mjs?v=ed041164:2384
|
||||
Promise.then
|
||||
pushWithRedirect @ vue-router.mjs?v=ed041164:2352
|
||||
push @ vue-router.mjs?v=ed041164:2278
|
||||
install @ vue-router.mjs?v=ed041164:2631
|
||||
use @ vue.runtime.esm.js:5190
|
||||
initRouter @ uni-h5.es.js:19886
|
||||
install @ uni-h5.es.js:19955
|
||||
use @ vue.runtime.esm.js:5190
|
||||
(anonymous) @ main.uts:16
|
||||
main.uts:16 TypeError: Failed to fetch dynamically imported module: http://localhost:5173/pages/mall/admin/homePage/index.uvue?t=1773363235472&import》
|
||||
|
||||
step @ tslib.es6.js:75
|
||||
(anonymous) @ tslib.es6.js:76
|
||||
__awaiter @ tslib.es6.js:72
|
||||
request @ ak-req.uts:127
|
||||
(anonymous) @ aksupa.uts:733
|
||||
(anonymous) @ tslib.es6.js:76
|
||||
__awaiter @ tslib.es6.js:72
|
||||
hydrateSessionFromStorage @ aksupa.uts:729
|
||||
AkSupa @ aksupa.uts:655
|
||||
createClient @ aksupa.uts:1254
|
||||
(anonymous) @ aksupainstance.uts:7
|
||||
ak-req.uts:164 GET http://119.146.131.237:9126/auth/v1/user 403 (Forbidden)
|
||||
Reference in New Issue
Block a user