feat(需求): ①全站列表/卡片分页统一为共享 OldPagination(共N条+10/20/50/100条数可选+跳页) ②创建用户菜单权限改左右布局(后台|桌面端并排) ③修复角色筛选失效(normalizeUserPageParams 白名单丢 role 字段)
This commit is contained in:
@@ -61,6 +61,7 @@ export function normalizeUserPageParams(raw: Partial<UserListParams>): UserListP
|
||||
keyword,
|
||||
createdById: typeof raw.createdById === 'number' ? raw.createdById : null,
|
||||
adminId: typeof raw.adminId === 'number' ? raw.adminId : null,
|
||||
role: typeof raw.role === 'string' ? raw.role.trim() || undefined : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
<script setup lang="ts">
|
||||
/** 旧版风格分页(像素复刻 admin.html .pagination)+ 每页条数下拉(10/20/50/100)。
|
||||
* props: total / page / pageSize / sizes(默认 10/20/50/100) / showTotal(默认 true) / jump(默认 true)。 */
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
sizes?: number[]
|
||||
showTotal?: boolean
|
||||
jump?: boolean
|
||||
}>(),
|
||||
{ sizes: () => [10, 20, 50, 100], showTotal: true, jump: true },
|
||||
)
|
||||
const emit = defineEmits<{
|
||||
(e: 'change', page: number): void
|
||||
(e: 'size-change', size: number): void
|
||||
}>()
|
||||
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(props.total / props.pageSize)))
|
||||
|
||||
function go(next: number) {
|
||||
if (next < 1 || next > totalPages.value || next === props.page) return
|
||||
emit('change', next)
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) return
|
||||
jumpPage.value = ''
|
||||
go(Math.min(Math.max(n, 1), totalPages.value))
|
||||
}
|
||||
|
||||
function onSizeChange(event: Event) {
|
||||
const value = Number((event.target as HTMLSelectElement).value)
|
||||
if (Number.isFinite(value) && value > 0) emit('size-change', value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="old-pagination">
|
||||
<span v-if="showTotal" class="page-total">共 {{ total }} 条</span>
|
||||
<select class="page-size-select" :value="pageSize" @change="onSizeChange">
|
||||
<option v-for="size in sizes" :key="size" :value="size">{{ size }}条/页</option>
|
||||
</select>
|
||||
<button type="button" :disabled="page <= 1" @click="go(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="go(page + 1)">下一页</button>
|
||||
<span v-if="jump" class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.old-pagination {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-top: 18px;
|
||||
color: #5b6f83;
|
||||
font-size: 13px;
|
||||
}
|
||||
.old-pagination button {
|
||||
min-height: 30px;
|
||||
padding: 4px 12px;
|
||||
border: 1px solid #c7d7e5;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
color: #5b6f83;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.old-pagination button:hover:not(:disabled) {
|
||||
background: #edf5fb;
|
||||
border-color: #95b1cb;
|
||||
color: #2f5d8b;
|
||||
}
|
||||
.old-pagination button:disabled {
|
||||
background: #eef3f7;
|
||||
color: #9baaba;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.page-total {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.page-size-select {
|
||||
min-height: 30px;
|
||||
padding: 3px 8px;
|
||||
border: 1px solid #cbd9e6;
|
||||
border-radius: 8px;
|
||||
background: #f8fbfd;
|
||||
color: #24384d;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
}
|
||||
.page-jump {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.page-jump input {
|
||||
width: 56px;
|
||||
min-height: 30px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #cbd9e6;
|
||||
border-radius: 8px;
|
||||
background: #f8fbfd;
|
||||
color: #24384d;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
}
|
||||
</style>
|
||||
@@ -59,31 +59,33 @@ watch(
|
||||
<template>
|
||||
<el-scrollbar max-height="300px" class="user-menu-tree-scroll">
|
||||
<template v-if="adminNodes.length || appNodes.length">
|
||||
<div v-if="adminNodes.length" class="menu-group-block">
|
||||
<div class="menu-group-title">后台</div>
|
||||
<el-tree
|
||||
ref="adminTree"
|
||||
:data="adminNodes"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
default-expand-all
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
@check="onCheck"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="appNodes.length" class="menu-group-block">
|
||||
<div class="menu-group-title">桌面端</div>
|
||||
<el-tree
|
||||
ref="appTree"
|
||||
:data="appNodes"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
default-expand-all
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
@check="onCheck"
|
||||
/>
|
||||
<div class="menu-group-columns">
|
||||
<div v-if="adminNodes.length" class="menu-group-block">
|
||||
<div class="menu-group-title">后台</div>
|
||||
<el-tree
|
||||
ref="adminTree"
|
||||
:data="adminNodes"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
default-expand-all
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
@check="onCheck"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="appNodes.length" class="menu-group-block">
|
||||
<div class="menu-group-title">桌面端</div>
|
||||
<el-tree
|
||||
ref="appTree"
|
||||
:data="appNodes"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
default-expand-all
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
@check="onCheck"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<p v-else class="menu-group-empty">暂无可用菜单</p>
|
||||
@@ -91,8 +93,20 @@ watch(
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.menu-group-block + .menu-group-block {
|
||||
margin-top: 10px;
|
||||
.menu-group-columns {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
.menu-group-block {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
padding: 0 10px 8px 0;
|
||||
}
|
||||
.menu-group-block:last-child {
|
||||
padding-right: 0;
|
||||
border-left: 1px solid #e6edf4;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.menu-group-title {
|
||||
padding: 4px 0 6px;
|
||||
|
||||
@@ -15,6 +15,7 @@ import { listPhaseOf, userListEmptyHint } from './user-list-state'
|
||||
import { isEditableUser } from './user-edit-model'
|
||||
import CreateUserDialog from './CreateUserDialog.vue'
|
||||
import EditUserDialog from './EditUserDialog.vue'
|
||||
import OldPagination from '@/components/OldPagination.vue'
|
||||
|
||||
const session = useAdminSessionStore()
|
||||
const loading = ref(false)
|
||||
@@ -211,24 +212,7 @@ onMounted(loadUsers)
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<select v-model="filters.pageSize" class="page-size-select" @change="changeSize(Number(filters.pageSize))">
|
||||
<option :value="10">10条/页</option>
|
||||
<option :value="20">20条/页</option>
|
||||
<option :value="50">50条/页</option>
|
||||
<option :value="100">100条/页</option>
|
||||
</select>
|
||||
<button type="button" :disabled="filters.page <= 1" @click="changePage(filters.page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ filters.page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="filters.page >= totalPages" @click="changePage(filters.page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="filters.page" :page-size="filters.pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<CreateUserDialog v-model="createVisible" :operator-super="isSuperAdmin" :admin-options="admins" @created="loadUsers" />
|
||||
|
||||
@@ -17,10 +17,10 @@ const loading = ref(false)
|
||||
const rows = ref<InvalidAsinItem[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const groups = ref<ShopGroupOption[]>([])
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
|
||||
const filter = reactive({ dataValue: '', brand: '', groupId: null as number | null })
|
||||
|
||||
@@ -58,7 +58,7 @@ async function load() {
|
||||
try {
|
||||
const result = await fetchInvalidAsinPage({
|
||||
page: page.value,
|
||||
pageSize,
|
||||
pageSize: pageSize.value,
|
||||
dataValue: filter.dataValue.trim() || undefined,
|
||||
brand: filter.brand.trim() || undefined,
|
||||
groupId: filter.groupId,
|
||||
@@ -84,6 +84,13 @@ function changePage(next: number) {
|
||||
load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -225,19 +232,7 @@ onMounted(() => {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="dialogVisible" :title="editingId == null ? '新增不符合ASIN' : '编辑不符合ASIN'" width="520px">
|
||||
|
||||
@@ -23,17 +23,18 @@ import {
|
||||
import { importOutcomeText, importTaskFinished, isAllowedImportFile } from './dedupe-import-model.ts'
|
||||
import type { DedupeImportProgress } from './dedupe-import-model.ts'
|
||||
import { toExportUrl } from './dedupe-total-export.ts'
|
||||
import OldPagination from '@/components/OldPagination.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
const rows = ref<DedupeTotalItem[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const filter = reactive(createDedupeTotalFilterState())
|
||||
const groups = ref<DedupeGroupOption[]>([])
|
||||
const jumpPage = ref('')
|
||||
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
|
||||
const editVisible = ref(false)
|
||||
const editSaving = ref(false)
|
||||
@@ -74,7 +75,7 @@ function stopExportWait(): void {
|
||||
async function load(): Promise<void> {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchDedupeTotalList(toDedupeListParams(filter, page.value, pageSize))
|
||||
const result = await fetchDedupeTotalList(toDedupeListParams(filter, page.value, pageSize.value))
|
||||
rows.value = result.items
|
||||
total.value = result.total
|
||||
if (result.page >= 1) page.value = result.page
|
||||
@@ -102,7 +103,13 @@ function goJump(): void {
|
||||
ElMessage.warning('请输入页码')
|
||||
return
|
||||
}
|
||||
changePage(n)
|
||||
changePage(Math.min(Math.max(n, 1), totalPages.value))
|
||||
}
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
void load()
|
||||
}
|
||||
|
||||
function openEdit(row: DedupeTotalItem): void {
|
||||
@@ -371,18 +378,7 @@ onMounted(() => {
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<div v-if="editVisible" class="modal-mask" @click.self="editVisible = false">
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
} from './product-category-model.ts'
|
||||
import { categoryDraftError, createProductCategoryDraft, toCategorySaveRequest, type ProductCategoryDraft } from './product-category-editor-model.ts'
|
||||
import { buildProductCategoryExportUrl } from './product-category-export.ts'
|
||||
import OldPagination from '@/components/OldPagination.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
const tree = ref<ProductCategoryNode[]>([])
|
||||
@@ -23,6 +24,7 @@ const selected = ref<ProductCategoryNode | null>(null)
|
||||
|
||||
const searchLoading = ref(false)
|
||||
const searchRows = ref<ProductCategoryNode[]>([])
|
||||
const searchPageSize = ref(PRODUCT_CATEGORY_DEFAULT_PAGE_SIZE)
|
||||
const searchTotal = ref(0)
|
||||
const searchPage = ref(1)
|
||||
const searchHasMore = ref(false)
|
||||
@@ -54,7 +56,7 @@ function flatten(nodes: ProductCategoryNode[]): ProductCategoryNode[] {
|
||||
const allNodes = computed(() => flatten(tree.value))
|
||||
const searching = computed(() => (keyword.value || '').trim().length > 0)
|
||||
const dialogTitle = computed(() => (editingId.value == null ? '新增商品类目' : '编辑商品类目'))
|
||||
const searchTotalPages = computed(() => Math.max(1, Math.ceil(searchTotal.value / PRODUCT_CATEGORY_DEFAULT_PAGE_SIZE)))
|
||||
const searchTotalPages = computed(() => Math.max(1, Math.ceil(searchTotal.value / searchPageSize.value)))
|
||||
|
||||
/** 拉取根级第一页(对齐 admin.js loadProductCategoryChildren(null) 懒加载根)。 */
|
||||
async function loadTree(): Promise<void> {
|
||||
@@ -168,10 +170,15 @@ function moreLoading(more: ProductCategoryNode): boolean {
|
||||
return isCategoryLoadMoreNode(more) && (childrenState.get(stateKeyOf(more.parentId))?.loading ?? false)
|
||||
}
|
||||
|
||||
function changeSearchSize(size: number) {
|
||||
searchPageSize.value = size
|
||||
void runSearch(1)
|
||||
}
|
||||
|
||||
async function runSearch(page: number): Promise<void> {
|
||||
searchLoading.value = true
|
||||
try {
|
||||
const result = await searchProductCategories(keyword.value, page, PRODUCT_CATEGORY_DEFAULT_PAGE_SIZE)
|
||||
const result = await searchProductCategories(keyword.value, page, searchPageSize.value)
|
||||
searchRows.value = result.items
|
||||
searchTotal.value = result.total
|
||||
searchPage.value = result.page
|
||||
@@ -412,12 +419,7 @@ onMounted(loadTree)
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div v-if="searching" class="pagination">
|
||||
<span class="page-total">共 {{ searchTotal }} 条 · 搜索结果</span>
|
||||
<button type="button" :disabled="searchPage <= 1" @click="runSearch(searchPage - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ searchPage }} / {{ searchTotalPages }} 页</span>
|
||||
<button type="button" :disabled="searchPage >= searchTotalPages" @click="runSearch(searchPage + 1)">下一页</button>
|
||||
</div>
|
||||
<OldPagination v-if="searching" :total="searchTotal" :page="searchPage" :page-size="searchPageSize" @change="runSearch" @size-change="changeSearchSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="560px">
|
||||
|
||||
@@ -19,14 +19,14 @@ const loading = ref(false)
|
||||
const rows = ref<QueryAsinItem[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const groups = ref<ShopGroupOption[]>([])
|
||||
const filter = reactive<QueryAsinFilterState>(createQueryAsinFilterState())
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
|
||||
/** 纵向展示行:分组/店铺/操作 按 rowspan 合并,逐国一行(对齐 admin.js renderQueryAsinRows)。 */
|
||||
const displayRows = computed(() => queryAsinDisplayRows(rows.value, (page.value - 1) * pageSize + 1))
|
||||
const displayRows = computed(() => queryAsinDisplayRows(rows.value, (page.value - 1) * pageSize.value + 1))
|
||||
|
||||
function asinOf(row: QueryAsinItem, country: string): string {
|
||||
const map: Record<string, string> = { DE: row.asinDe, UK: row.asinUk, FR: row.asinFr, IT: row.asinIt, ES: row.asinEs }
|
||||
@@ -268,7 +268,7 @@ async function load() {
|
||||
try {
|
||||
const result = await fetchQueryAsinList({
|
||||
page: page.value,
|
||||
pageSize,
|
||||
pageSize: pageSize.value,
|
||||
groupId: filter.groupId,
|
||||
shopName: filter.shopName.trim() || undefined,
|
||||
asin: filter.asin.trim() || undefined,
|
||||
@@ -295,6 +295,13 @@ function changePage(next: number) {
|
||||
void load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -391,19 +398,7 @@ onMounted(() => {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="createVisible" title="新增查询 ASIN" width="560px" :close-on-click-modal="false">
|
||||
|
||||
@@ -19,11 +19,11 @@ const loading = ref(false)
|
||||
const rows = ref<SkipPriceItem[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const groups = ref<ShopGroupOption[]>([])
|
||||
const filter = reactive<SkipPriceFilterState>(createSkipPriceFilterState())
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
|
||||
const COUNTRIES = ['DE', 'UK', 'FR', 'IT', 'ES'] as const
|
||||
const ASIN_MAP: Record<string, keyof SkipPriceItem> = { DE: 'asinDe', UK: 'asinUk', FR: 'asinFr', IT: 'asinIt', ES: 'asinEs' }
|
||||
@@ -39,7 +39,7 @@ function priceOf(row: SkipPriceItem, code: string): number | null {
|
||||
}
|
||||
|
||||
/** 纵向展示行:分组/店铺/操作 按 rowspan 合并,逐国一行(对齐 admin.js renderSkipPriceAsinRows)。 */
|
||||
const displayRows = computed(() => skipPriceDisplayRows(rows.value, (page.value - 1) * pageSize + 1))
|
||||
const displayRows = computed(() => skipPriceDisplayRows(rows.value, (page.value - 1) * pageSize.value + 1))
|
||||
|
||||
// ---- 新增 ASIN 弹窗(对齐 admin.js btnOpenCreateSkipPriceAsin/btnCreateSkipPriceAsin) ----
|
||||
const createVisible = ref(false)
|
||||
@@ -310,7 +310,7 @@ async function loadGroups() {
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchSkipPriceList(toSkipPriceParams(filter, page.value, pageSize))
|
||||
const result = await fetchSkipPriceList(toSkipPriceParams(filter, page.value, pageSize.value))
|
||||
rows.value = result.items
|
||||
total.value = result.total
|
||||
page.value = result.page
|
||||
@@ -332,6 +332,13 @@ function changePage(next: number) {
|
||||
void load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -438,19 +445,7 @@ onMounted(() => {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="createVisible" title="新增 ASIN" width="560px" :close-on-click-modal="false">
|
||||
|
||||
@@ -21,13 +21,14 @@ import {
|
||||
import { validateDigitalHumanUpload } from './digitalhuman-upload-model.ts'
|
||||
import { canReleaseDigitalHumanVersion, releaseDigitalHumanConfirmText } from './digitalhuman-release.ts'
|
||||
import { canSetLatestDigitalHumanVersion, setLatestDigitalHumanConfirmText } from './digitalhuman-latest.ts'
|
||||
import OldPagination from '@/components/OldPagination.vue'
|
||||
import { digitalHumanStatusDisplay } from './digitalhuman-status-display.ts'
|
||||
|
||||
const loading = ref(false)
|
||||
const items = ref<DigitalHumanVersion[]>([])
|
||||
|
||||
/** 分页(对齐 admin.js:6311 pageSize=20 + 数字页码 + 跳转;Java 列表接口不分页,前端分页呈现)。 */
|
||||
const pageSize = 20
|
||||
const pageSize = ref(20)
|
||||
const page = ref(1)
|
||||
/** 版本号搜索(客户端过滤)。 */
|
||||
const versionKeyword = ref('')
|
||||
@@ -37,10 +38,10 @@ const filteredItems = computed(() => {
|
||||
return items.value.filter((item) => `${item.version}`.toLowerCase().includes(kw))
|
||||
})
|
||||
const pagedItems = computed(() => {
|
||||
const start = (page.value - 1) * pageSize
|
||||
return filteredItems.value.slice(start, start + pageSize)
|
||||
const start = (page.value - 1) * pageSize.value
|
||||
return filteredItems.value.slice(start, start + pageSize.value)
|
||||
})
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(filteredItems.value.length / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(filteredItems.value.length / pageSize.value)))
|
||||
const jumpPage = ref('')
|
||||
|
||||
const uploadVisible = ref(false)
|
||||
@@ -56,7 +57,7 @@ async function load() {
|
||||
try {
|
||||
items.value = (await fetchDigitalHumanVersions()).items
|
||||
// 数据收缩后页码越界回钳。
|
||||
const last = Math.max(Math.ceil(items.value.length / pageSize), 1)
|
||||
const last = Math.max(Math.ceil(items.value.length / pageSize.value), 1)
|
||||
if (page.value > last) page.value = last
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '版本列表加载失败')
|
||||
@@ -70,6 +71,11 @@ function changePage(next: number): void {
|
||||
page.value = next
|
||||
}
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
}
|
||||
|
||||
function goJump(): void {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -259,19 +265,7 @@ onMounted(load)
|
||||
</div>
|
||||
|
||||
<div v-if="filteredItems.length > pageSize" class="pagination">
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-nums">
|
||||
<template v-for="n in totalPages" :key="n">
|
||||
<button type="button" class="num-page" :class="{ 'is-active': n === page }" @click="changePage(n)">{{ n }}</button>
|
||||
</template>
|
||||
</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
<OldPagination :total="filteredItems.length" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const userLoading = ref(false)
|
||||
const rows = ref<HistoryRecordItem[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const userOptions = ref<HistoryUserOption[]>([])
|
||||
const errorText = ref('')
|
||||
const filter = reactive({ userId: '', timeStart: '', timeEnd: '' })
|
||||
@@ -26,7 +26,7 @@ const jumpPage = ref('')
|
||||
|
||||
const hasFilter = computed(() => Boolean(filter.userId || filter.timeStart || filter.timeEnd))
|
||||
const emptyText = computed(() => historyEmptyText({ hasFilter: hasFilter.value, total: total.value }))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
|
||||
/** datetime-local 原生值(YYYY-MM-DDTHH:mm) 转后端兼容格式。 */
|
||||
function toApiTime(value: string): string | undefined {
|
||||
@@ -56,7 +56,7 @@ async function load() {
|
||||
try {
|
||||
const result = await fetchHistoryList({
|
||||
page: page.value,
|
||||
pageSize,
|
||||
pageSize: pageSize.value,
|
||||
userId: filter.userId ? Number(filter.userId) : undefined,
|
||||
timeStart: toApiTime(filter.timeStart),
|
||||
timeEnd: toApiTime(filter.timeEnd),
|
||||
@@ -97,6 +97,13 @@ function changePage(next: number) {
|
||||
load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -192,19 +199,7 @@ onMounted(() => {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<div v-if="previewVisible" class="modal-mask" @click.self="previewVisible = false">
|
||||
|
||||
@@ -13,9 +13,9 @@ const loading = ref(false)
|
||||
const rows = ref<ShopKeyItem[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
/** 筛选:备注名/紫鸟账号(用户要求店铺密钥列表补筛选)。 */
|
||||
const filterKeyword = ref('')
|
||||
const filteredRows = computed(() => {
|
||||
@@ -52,7 +52,7 @@ function whitelistTooltip(row: ShopKeyItem): string {
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchShopKeyList({ page: page.value, pageSize })
|
||||
const result = await fetchShopKeyList({ page: page.value, pageSize: pageSize.value })
|
||||
rows.value = result.items
|
||||
total.value = result.total
|
||||
page.value = result.page
|
||||
@@ -126,6 +126,13 @@ function changePage(next: number) {
|
||||
load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -206,19 +213,7 @@ onMounted(load)
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="dialogVisible" :title="editingId == null ? '新增密钥' : '编辑密钥'" width="560px">
|
||||
|
||||
@@ -21,9 +21,9 @@ const loading = ref(false)
|
||||
const rows = ref<ShopSummary[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
const pageSize = ref(15)
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
|
||||
|
||||
const groups = ref<ShopGroupOption[]>([])
|
||||
const filter = reactive({ shopName: '', groupId: null as number | null })
|
||||
@@ -78,7 +78,7 @@ async function load() {
|
||||
try {
|
||||
const result = await fetchShopManageList({
|
||||
page: page.value,
|
||||
pageSize,
|
||||
pageSize: pageSize.value,
|
||||
groupId: filter.groupId,
|
||||
shopName: filter.shopName.trim() || undefined,
|
||||
})
|
||||
@@ -103,6 +103,13 @@ function changePage(next: number) {
|
||||
void load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -273,19 +280,7 @@ onMounted(() => {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="total" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="dialogVisible" :title="editingId == null ? '新增店铺' : '编辑店铺'" width="600px">
|
||||
|
||||
@@ -24,9 +24,9 @@ const loading = ref(false)
|
||||
const tasks = ref<ImageVideoRow[]>([])
|
||||
const totalTasks = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 20
|
||||
const pageSize = ref(20)
|
||||
const jumpPage = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(totalTasks.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(totalTasks.value / pageSize.value)))
|
||||
|
||||
const filter = reactive<ImageVideoFilter & { dateRange: string[] }>({ ...createImageVideoFilter(), dateRange: [] })
|
||||
const selection = ref<Set<string>>(new Set())
|
||||
@@ -103,7 +103,7 @@ function toFilter(): ImageVideoFilter {
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchImageVideoTasks(toFilter(), page.value, pageSize)
|
||||
const result = await fetchImageVideoTasks(toFilter(), page.value, pageSize.value)
|
||||
tasks.value = result.items
|
||||
totalTasks.value = result.total
|
||||
page.value = result.page
|
||||
@@ -133,6 +133,13 @@ function changePage(next: number) {
|
||||
void load()
|
||||
}
|
||||
|
||||
|
||||
function changeSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function goJump() {
|
||||
const n = Number.parseInt(jumpPage.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -356,19 +363,7 @@ onMounted(load)
|
||||
</template>
|
||||
<div v-else-if="!loading" class="empty-tip">暂无符合条件的视频任务</div>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">共 {{ totalTasks }} 条</span>
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="jumpPage" type="text" inputmode="numeric" @keyup.enter="goJump" />
|
||||
页
|
||||
<button type="button" @click="goJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination :total="totalTasks" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeSize" />
|
||||
</section>
|
||||
|
||||
<el-drawer v-model="detailVisible" title="任务明细" size="720px">
|
||||
|
||||
@@ -25,20 +25,21 @@ import {
|
||||
toggleShopDataSelection,
|
||||
} from './shop-data-selection.ts'
|
||||
import { useAdminSessionStore } from '@/stores/admin-session'
|
||||
import OldPagination from '@/components/OldPagination.vue'
|
||||
|
||||
const session = useAdminSessionStore()
|
||||
const loading = ref(false)
|
||||
const groups = ref<ShopDataTaskGroup[]>([])
|
||||
const totalShops = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 20
|
||||
const pageSize = ref(20)
|
||||
const pageJump = ref('')
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(totalShops.value / pageSize)))
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(totalShops.value / pageSize.value)))
|
||||
// 卡片宫格分页:一行 3 个、一页 9 张卡片(在店铺分页的结果文件内翻页)。
|
||||
const cardPage = ref(1)
|
||||
const cardPageSize = 9
|
||||
const cardPageSize = ref(10)
|
||||
const cardJump = ref('')
|
||||
const cardTotalPages = computed(() => Math.max(1, Math.ceil(allResultRows.value.length / cardPageSize)))
|
||||
const cardTotalPages = computed(() => Math.max(1, Math.ceil(allResultRows.value.length / cardPageSize.value)))
|
||||
|
||||
const filter = reactive<ShopDataFilter & { dateRange: string[] }>({ ...createShopDataFilter(), dateRange: [] })
|
||||
const selection = ref<Set<string>>(new Set())
|
||||
@@ -91,7 +92,7 @@ function toFilter(): ShopDataFilter {
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchShopDataTaskList(toFilter(), page.value, pageSize)
|
||||
const result = await fetchShopDataTaskList(toFilter(), page.value, pageSize.value)
|
||||
groups.value = result.items
|
||||
totalShops.value = result.total
|
||||
page.value = result.page
|
||||
@@ -122,6 +123,13 @@ function changePage(next: number) {
|
||||
void load()
|
||||
}
|
||||
|
||||
function changeShopSize(size: number) {
|
||||
pageSize.value = size
|
||||
page.value = 1
|
||||
cardPage.value = 1
|
||||
void load()
|
||||
}
|
||||
|
||||
function goPageJump() {
|
||||
const n = Number.parseInt(pageJump.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -133,7 +141,7 @@ function goPageJump() {
|
||||
|
||||
const allResultRows = computed(() => groups.value.flatMap((group) => group.results))
|
||||
const pagedResultRows = computed(() =>
|
||||
allResultRows.value.slice((cardPage.value - 1) * cardPageSize, cardPage.value * cardPageSize),
|
||||
allResultRows.value.slice((cardPage.value - 1) * cardPageSize.value, cardPage.value * cardPageSize.value),
|
||||
)
|
||||
const selectionCount = computed(() => countShopDataSelection(selection.value))
|
||||
|
||||
@@ -141,6 +149,11 @@ function changeCardPage(p: number) {
|
||||
cardPage.value = p
|
||||
}
|
||||
|
||||
function changeCardSize(size: number) {
|
||||
cardPageSize.value = size
|
||||
cardPage.value = 1
|
||||
}
|
||||
|
||||
function goCardJump() {
|
||||
const n = Number.parseInt(cardJump.value, 10)
|
||||
if (Number.isNaN(n)) {
|
||||
@@ -325,13 +338,7 @@ onMounted(load)
|
||||
</div>
|
||||
<div class="sd-toolbar-side">
|
||||
<span class="sd-summary">共 {{ totalShops }} 家店铺 · 本页 {{ resultFileCount() }} 个结果文件</span>
|
||||
<span class="sd-shop-pager">
|
||||
<button type="button" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ page }} / {{ totalPages }} 页</span>
|
||||
<button type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
|
||||
<input v-model="pageJump" type="text" inputmode="numeric" placeholder="页" @keyup.enter="goPageJump" />
|
||||
<button type="button" class="jump-btn" @click="goPageJump">跳转</button>
|
||||
</span>
|
||||
<OldPagination v-if="totalShops > 0" :total="totalShops" :page="page" :page-size="pageSize" @change="changePage" @size-change="changeShopSize" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -393,18 +400,7 @@ onMounted(load)
|
||||
<div v-else-if="!loading" class="empty-tip">暂无符合条件的店铺数据记录</div>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="page-total">本页数据 · 共 {{ allResultRows.length }} 个结果文件</span>
|
||||
<button type="button" :disabled="cardPage <= 1" @click="changeCardPage(cardPage - 1)">上一页</button>
|
||||
<span class="page-cur">第 {{ cardPage }} / {{ cardTotalPages }} 页</span>
|
||||
<button type="button" :disabled="cardPage >= cardTotalPages" @click="changeCardPage(cardPage + 1)">下一页</button>
|
||||
<span class="page-jump">
|
||||
跳至
|
||||
<input v-model="cardJump" type="text" inputmode="numeric" @keyup.enter="goCardJump" />
|
||||
页
|
||||
<button type="button" @click="goCardJump">跳转</button>
|
||||
</span>
|
||||
</div>
|
||||
<OldPagination v-if="allResultRows.length > 0" :total="allResultRows.length" :page="cardPage" :page-size="cardPageSize" @change="changeCardPage" @size-change="changeCardSize" />
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="permissionVisible" title="店铺数据记录数据范围授权" width="620px">
|
||||
|
||||
@@ -13,10 +13,13 @@ test('align_pagination_normal_primary_path', () => {
|
||||
})
|
||||
|
||||
test('align_pagination_normal_variant_input', () => {
|
||||
// 数字人版本数字页码含上一页/下一页。
|
||||
// 数字人版本分页升级为共享 OldPagination(含上一页/下一页/条数选择)。
|
||||
const dh = readSource('src/pages/records/RecordsDigitalHumanVersionPage.vue')
|
||||
assert.match(dh, />上一页<\/button>/, '数字人分页含上一页')
|
||||
assert.match(dh, />下一页<\/button>/, '数字人分页含下一页')
|
||||
assert.match(dh, /OldPagination/, '数字人分页用共享组件')
|
||||
const comp = readSource('src/components/OldPagination.vue')
|
||||
assert.match(comp, />上一页<\/button>/, '共享分页含上一页')
|
||||
assert.match(comp, />下一页<\/button>/, '共享分页含下一页')
|
||||
assert.match(comp, /10, 20, 50, 100|sizes/, '共享分页默认 10/20/50/100')
|
||||
})
|
||||
|
||||
test('align_pagination_boundary_empty_input', () => {
|
||||
@@ -35,19 +38,19 @@ test('align_pagination_boundary_single_item', () => {
|
||||
|
||||
test('align_pagination_repeated_operation_is_idempotent', () => {
|
||||
// 已像素复刻(自绘旧式分页/原生表格)的页单独断言。
|
||||
const users = readSource('src/pages/account/UsersPage.vue')
|
||||
assert.match(users, /class="pagination"/, '用户页已像素复刻,用旧式分页容器')
|
||||
assert.doesNotMatch(users, /el-pagination/, '用户页不再用 EP 分页')
|
||||
for (const page of [
|
||||
'src/pages/account/UsersPage.vue',
|
||||
'src/pages/asin/AsinInvalidPage.vue',
|
||||
'src/pages/asin/DedupeRegistryPage.vue',
|
||||
'src/pages/shop/ShopManagePage.vue',
|
||||
'src/pages/shop/ShopKeysPage.vue',
|
||||
'src/pages/tasks/ImageVideoTasksPage.vue',
|
||||
]) {
|
||||
const src = readSource(page)
|
||||
assert.match(src, /OldPagination/, `${page} 用共享旧式分页`)
|
||||
assert.doesNotMatch(src, /el-pagination/, `${page} 不再用 EP 分页`)
|
||||
}
|
||||
const groups = readSource('src/pages/account/GroupsPage.vue')
|
||||
assert.doesNotMatch(groups, /el-pagination/, '分组管理已像素复刻旧版(panel-group-manage 无分页)')
|
||||
assert.doesNotMatch(groups, /el-pagination/, '分组管理全量渲染无分页')
|
||||
assert.doesNotMatch(groups, /pagedRows/, '分组管理全量渲染无客户端切片')
|
||||
const invalid = readSource('src/pages/asin/AsinInvalidPage.vue')
|
||||
assert.match(invalid, /class="pagination"/, '品牌库已像素复刻,用旧式分页容器')
|
||||
assert.doesNotMatch(invalid, /el-pagination/, '品牌库不再用 EP 分页')
|
||||
const shops = readSource('src/pages/shop/ShopManagePage.vue')
|
||||
assert.match(shops, /class="pagination"/, '店铺管理已像素复刻,用旧式分页容器')
|
||||
assert.doesNotMatch(shops, /el-pagination/, '店铺管理不再用 EP 分页')
|
||||
const keys = readSource('src/pages/shop/ShopKeysPage.vue')
|
||||
assert.match(keys, /class="pagination"/, '店铺密钥已像素复刻,用旧式分页容器')
|
||||
assert.doesNotMatch(keys, /el-pagination/, '店铺密钥不再用 EP 分页')
|
||||
})
|
||||
|
||||
@@ -13,7 +13,7 @@ test('align_shop_data_grid_normal_primary_path', () => {
|
||||
|
||||
test('align_shop_data_grid_normal_variant_input', () => {
|
||||
const src = readSource(PAGE)
|
||||
assert.match(src, /cardPageSize\s*=\s*9|pageSize\s*=\s*9/, '卡片分页每页 9 张')
|
||||
assert.match(src, /cardPageSize = ref\(10\)|cardPageSize\.value/, '卡片分页默认 10 张且可调')
|
||||
assert.match(src, /cardPage\b/, '应有卡片页状态')
|
||||
assert.match(src, /pagedResultRows|cardPageRows/, '卡片应绑定按 9 张切片的数据')
|
||||
})
|
||||
|
||||
@@ -39,8 +39,10 @@ test('test_task_250_users_list_boundary_empty_input', () => {
|
||||
test('test_task_250_users_list_boundary_single_item', () => {
|
||||
// 边界:分页/合计形态为“共 N 条”,查询后回第一页。
|
||||
const page = readSource('src/pages/account/UsersPage.vue')
|
||||
assert.match(page, /共 .*total.*条/, '分页页脚应有“共 N 条”合计')
|
||||
assert.match(page, /page\s*=\s*1|filters\.page\s*=\s*USER_PAGE_MIN_PAGE/, '查询需重置回第一页')
|
||||
assert.match(page, /OldPagination/, '分页走共享组件')
|
||||
const comp = readSource('src/components/OldPagination.vue')
|
||||
assert.match(comp, /共 \{\{ total \}\} 条/, '共享分页含“共 N 条”合计')
|
||||
assert.match(page, /filters\.page = 1/, '查询需重置回第一页')
|
||||
})
|
||||
|
||||
test('test_task_250_users_list_boundary_limit_or_missing_field', () => {
|
||||
|
||||
Reference in New Issue
Block a user