提交
This commit is contained in:
1 parent
246ad2228e
commit
8e2dd8b9f0
186 files changed
+38821
-2571
No files matched your search
@@ -2,11 +2,15 @@
|
||||
* 分页循环请求直至拿全数据(接口需返回 { list, total })。
|
||||
* 用于分类、单位、用户等列表接口,避免只取第一页导致下拉选项不全。
|
||||
*/
|
||||
/** 与后端 `/web/admin/*` 列表普遍 `Query(..., le=100)` 一致,超出会 422 */
|
||||
export const MAX_ADMIN_LIST_PAGE_SIZE = 100
|
||||
|
||||
export async function fetchAllPagedRecords<T>(
|
||||
fetchPage: (page: number, pageSize: number) => Promise<{ list?: T[]; total?: number }>,
|
||||
options?: { pageSize?: number; maxPages?: number }
|
||||
): Promise<T[]> {
|
||||
const pageSize = options?.pageSize ?? 100
|
||||
const requested = options?.pageSize ?? MAX_ADMIN_LIST_PAGE_SIZE
|
||||
const pageSize = Math.min(Math.max(1, requested), MAX_ADMIN_LIST_PAGE_SIZE)
|
||||
const maxPages = options?.maxPages ?? 50
|
||||
let page = 1
|
||||
const all: T[] = []
|
||||
|
||||
@@ -23,7 +23,7 @@ import { BaseResponse } from '@/types'
|
||||
import { decryptJson, deriveKey, encryptJson, randomNonce } from './crypto'
|
||||
|
||||
/** 请求配置常量 */
|
||||
const REQUEST_TIMEOUT = 15000
|
||||
const REQUEST_TIMEOUT = 60000
|
||||
const LOGOUT_DELAY = 500
|
||||
const RETRY_DELAY = 1000
|
||||
/** 幂等请求在网络抖动、唤醒后首包失败时自动重试次数 */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import { AppRouteRecord } from '@/types/router'
|
||||
import { router } from '@/router'
|
||||
import { isNavigableMenuItem } from './route'
|
||||
import { useSettingStore } from '@/store/modules/setting'
|
||||
|
||||
// 打开外部链接
|
||||
export const openExternalLink = (link: string) => {
|
||||
@@ -38,6 +39,10 @@ export const handleMenuJump = (item: AppRouteRecord, jumpToFirst: boolean = fals
|
||||
|
||||
// 如果不需要跳转到第一个子菜单,或者没有子菜单,直接跳转当前路径
|
||||
if (!jumpToFirst || !item.children?.length) {
|
||||
// 已经在当前页面时,刷新页面内容以重新加载列表数据
|
||||
if (router.currentRoute.value.path === item.path) {
|
||||
return useSettingStore().reload()
|
||||
}
|
||||
return router.push(item.path)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* 新增时默认排序号:当前列表中最大 sortOrder + 1;无任何数据时为 0。
|
||||
* 依赖列表接口按 sort_order 升序分页(最后一页含最大排序号)。
|
||||
*/
|
||||
import { MAX_ADMIN_LIST_PAGE_SIZE } from '@/utils/fetch-paged-list'
|
||||
|
||||
export async function fetchNextSortOrder(
|
||||
fetchList: (params: {
|
||||
page: number
|
||||
@@ -11,7 +13,8 @@ export async function fetchNextSortOrder(
|
||||
}) => Promise<{ list: { sortOrder?: number }[]; total: number }>,
|
||||
options?: { pageSize?: number }
|
||||
): Promise<number> {
|
||||
const pageSize = options?.pageSize ?? 100
|
||||
const requested = options?.pageSize ?? MAX_ADMIN_LIST_PAGE_SIZE
|
||||
const pageSize = Math.min(Math.max(1, requested), MAX_ADMIN_LIST_PAGE_SIZE)
|
||||
const first = await fetchList({ page: 1, pageSize })
|
||||
const total = first.total ?? 0
|
||||
if (total === 0) return 0
|
||||
|
||||
@@ -11,8 +11,16 @@ export type TreePathFlatNode = Record<string, unknown>
|
||||
export function buildTreePathLabelFromFlat(
|
||||
nodeId: string | null | undefined,
|
||||
flatList: TreePathFlatNode[] | null | undefined,
|
||||
separator: string = DEFAULT_TREE_PATH_SEPARATOR
|
||||
separatorOrOpts?: string | { separator?: string; nameKey?: string }
|
||||
): string {
|
||||
const separator =
|
||||
typeof separatorOrOpts === 'string'
|
||||
? separatorOrOpts
|
||||
: separatorOrOpts?.separator ?? DEFAULT_TREE_PATH_SEPARATOR
|
||||
const nameKey =
|
||||
typeof separatorOrOpts === 'string'
|
||||
? 'name'
|
||||
: separatorOrOpts?.nameKey ?? 'name'
|
||||
const cid = String(nodeId ?? '').trim()
|
||||
if (!cid) return ''
|
||||
const byId = new Map<string, TreePathFlatNode>()
|
||||
@@ -26,7 +34,7 @@ export function buildTreePathLabelFromFlat(
|
||||
while (cur && byId.has(cur) && !seen.has(cur)) {
|
||||
seen.add(cur)
|
||||
const cat: TreePathFlatNode = byId.get(cur)!
|
||||
const nm = String(cat?.name ?? '').trim()
|
||||
const nm = String(cat?.[nameKey] ?? '').trim()
|
||||
if (nm) names.unshift(nm)
|
||||
const pid: string = String(cat?.parentId ?? cat?.parent_id ?? '').trim()
|
||||
cur = pid || null
|
||||
@@ -70,12 +78,13 @@ export function resolveTreePathDisplay(
|
||||
flatList: TreePathFlatNode[] | null | undefined,
|
||||
fallbackName?: unknown,
|
||||
separator: string = DEFAULT_TREE_PATH_SEPARATOR,
|
||||
emptyPlaceholder = '—'
|
||||
emptyPlaceholder = '—',
|
||||
nameKey?: string
|
||||
): string {
|
||||
const path = buildTreePathLabelFromFlat(
|
||||
String(nodeId ?? '').trim() || undefined,
|
||||
flatList,
|
||||
separator
|
||||
{ separator, nameKey }
|
||||
)
|
||||
if (path) return path
|
||||
const fb = String(fallbackName ?? '').trim()
|
||||
|
||||
@@ -13,13 +13,16 @@ import {
|
||||
CircleClose,
|
||||
Close,
|
||||
CloseBold,
|
||||
CollectionTag,
|
||||
Connection,
|
||||
DArrowRight,
|
||||
DataAnalysis,
|
||||
DataBoard,
|
||||
Delete,
|
||||
Document,
|
||||
Edit,
|
||||
Expand,
|
||||
Fold,
|
||||
FolderOpened,
|
||||
FullScreen,
|
||||
Grid,
|
||||
HomeFilled,
|
||||
@@ -109,7 +112,12 @@ export const epIconMap: Record<string, Component> = {
|
||||
smile: ChatDotRound,
|
||||
brush: Brush,
|
||||
// Status
|
||||
warning: Warning
|
||||
warning: Warning,
|
||||
// Business
|
||||
'folder-opened': FolderOpened,
|
||||
'collection-tag': CollectionTag,
|
||||
workflow: Connection,
|
||||
'data-board': DataBoard
|
||||
}
|
||||
|
||||
export function resolveEpIcon(name: string | undefined): Component | undefined {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/** 未设置头像时统一使用中科兴皖 logo(与登录页、侧栏 ArtLogo 一致) */
|
||||
export const DEFAULT_USER_AVATAR_URL = '/logo.png'
|
||||
/** 未设置头像时使用 `public/avatart.jpg`(根路径 `/avatart.jpg`) */
|
||||
export const DEFAULT_USER_AVATAR_URL = '/avatart.jpg'
|
||||
|
||||
/** @deprecated 各角色默认已统一为 logo,保留参数仅为兼容旧调用 */
|
||||
/** @deprecated 各角色默认已统一为默认头像图,保留参数仅为兼容旧调用 */
|
||||
export function defaultAvatarPathByRole(_role: string | undefined): string {
|
||||
return DEFAULT_USER_AVATAR_URL
|
||||
}
|
||||
|
||||
/** 展示用头像:有自定义 URL 用自定义,否则用中科兴皖 logo */
|
||||
/** 展示用头像:`avatarUrl` 非空则用其值,否则用默认图 */
|
||||
export function resolveUserAvatarUrl(avatarUrl: string | null | undefined, role: string | undefined): string {
|
||||
const u = avatarUrl != null ? String(avatarUrl).trim() : ''
|
||||
if (u) return u
|
||||
|
||||
Reference in new issue
Block a user