重构用户权限
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2025-09-25 18:41:32 +08:00
parent 4429e2f018
commit efbca0e802
15 changed files with 619 additions and 187 deletions

View File

@@ -1,34 +1,30 @@
import { getTime, intervalToDuration, parseISO } from "date-fns"
import { getTime, intervalToDuration, parseISO, type Duration } from "date-fns"
import { User } from "./types"
import { USER_TYPE } from "./constants"
export function getACRate(acCount: number, totalCount: number) {
let rate = ""
if (totalCount === 0) rate = "0.00"
else {
if (acCount >= totalCount) rate = "100.00"
else rate = ((acCount / totalCount) * 100).toFixed(2)
}
return `${rate}%`
function calculateACRate(acCount: number, totalCount: number): string {
if (totalCount === 0) return "0.00"
if (acCount >= totalCount) return "100.00"
return ((acCount / totalCount) * 100).toFixed(2)
}
export function getACRateNumber(acCount: number, totalCount: number) {
let rate = ""
if (totalCount === 0) rate = "0.00"
else {
if (acCount >= totalCount) rate = "100.00"
else rate = ((acCount / totalCount) * 100).toFixed(2)
}
return parseFloat(rate)
export function getACRate(acCount: number, totalCount: number): string {
return `${calculateACRate(acCount, totalCount)}%`
}
export function filterEmptyValue(object: any) {
let query: any = {}
Object.keys(object).forEach((key) => {
if (object[key] || object[key] === 0 || object[key] === false) {
query[key] = object[key]
export function getACRateNumber(acCount: number, totalCount: number): number {
return parseFloat(calculateACRate(acCount, totalCount))
}
export function filterEmptyValue<T extends Record<string, any>>(
object: T,
): Partial<T> {
return Object.entries(object).reduce((query, [key, value]) => {
if (value != null && value !== "" && value !== undefined) {
query[key as keyof T] = value
}
})
return query
return query
}, {} as Partial<T>)
}
export function getTagColor(
@@ -50,56 +46,52 @@ export function parseTime(utc: Date | string, format = "YYYY年M月D日") {
return time.value
}
function getDurationObject(start: Date | string, end: Date | string) {
return intervalToDuration({
start: getTime(parseISO(start.toString())),
end: getTime(parseISO(end.toString())),
})
}
function formatDurationUnits(
duration: Duration,
units: Array<{ key: keyof Duration; suffix: string }>,
): string {
return units
.filter(({ key }) => duration[key])
.map(({ key, suffix }) => duration[key] + suffix)
.join("")
}
export function duration(
start: Date | string,
end: Date | string,
showSeconds = false,
): string {
const duration = intervalToDuration({
start: getTime(parseISO(start.toString())),
end: getTime(parseISO(end.toString())),
})
let result = ""
if (duration.years) {
result += duration.years + "年"
}
if (duration.months) {
result += duration.months + "月"
}
if (duration.days) {
result += duration.days + "天"
}
if (duration.hours) {
result += duration.hours + "小时"
}
if (duration.minutes) {
result += duration.minutes + "分钟"
}
if (showSeconds && duration.seconds) {
result += duration.seconds + "秒"
}
return result
const durationObj = getDurationObject(start, end)
const units = [
{ key: "years" as const, suffix: "年" },
{ key: "months" as const, suffix: "月" },
{ key: "days" as const, suffix: "天" },
{ key: "hours" as const, suffix: "小时" },
{ key: "minutes" as const, suffix: "分钟" },
...(showSeconds ? [{ key: "seconds" as const, suffix: "秒" }] : []),
]
return formatDurationUnits(durationObj, units)
}
export function durationToDays(
start: Date | string,
end: Date | string,
): string {
const duration = intervalToDuration({
start: getTime(parseISO(start.toString())),
end: getTime(parseISO(end.toString())),
})
let result = ""
if (duration.years) {
result += duration.years + "年"
}
if (duration.months) {
result += duration.months + "月"
}
if (duration.days) {
result += duration.days + "天"
}
return !!result ? result : "一天以内"
const durationObj = getDurationObject(start, end)
const units = [
{ key: "years" as const, suffix: "年" },
{ key: "months" as const, suffix: "月" },
{ key: "days" as const, suffix: "天" },
]
const result = formatDurationUnits(durationObj, units)
return result || "一天以内"
}
export function secondsToDuration(seconds: number): string {
@@ -126,13 +118,14 @@ export function submissionTimeFormat(time: number | string | undefined) {
return time + "ms"
}
export function debounce(fn: Function, n = 100) {
let handle: any
return (...args: any[]) => {
if (handle) clearTimeout(handle)
handle = setTimeout(() => {
fn(...args)
}, n)
export function debounce<T extends (...args: any[]) => any>(
fn: T,
delay = 100,
): (...args: Parameters<T>) => void {
let timeoutId: ReturnType<typeof setTimeout>
return (...args: Parameters<T>) => {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => fn(...args), delay)
}
}
@@ -140,50 +133,50 @@ export function getUserRole(role: User["admin_type"]): {
type: "default" | "info" | "error"
tagString: "普通" | "管理员" | "超管"
} {
const obj: {
type: "default" | "info" | "error"
tagString: "普通" | "管理员" | "超管"
} = { type: "default", tagString: "普通" }
switch (role) {
case "Regular User":
obj.type = "default"
obj.tagString = "普通"
break
case "Admin":
obj.type = "info"
obj.tagString = "管理员"
break
case "Super Admin":
obj.type = "error"
obj.tagString = "超管"
break
const roleMap = {
[USER_TYPE.REGULAR_USER]: {
type: "default" as const,
tagString: "普通" as const,
},
[USER_TYPE.ADMIN]: { type: "info" as const, tagString: "管理员" as const },
[USER_TYPE.SUPER_ADMIN]: {
type: "error" as const,
tagString: "超管" as const,
},
}
return obj
return roleMap[role] || roleMap[USER_TYPE.REGULAR_USER]
}
export function unique<T>(arr: T[]) {
return arr.reduce((prev: T[], curr: T) => {
if (!prev.includes(curr)) {
prev.push(curr)
}
return prev
}, [])
export function unique<T>(arr: T[]): T[] {
return [...new Set(arr)]
}
export function encode(string?: string) {
return btoa(String.fromCharCode(...new TextEncoder().encode(string ?? "")))
export function encode(string?: string): string {
try {
return btoa(String.fromCharCode(...new TextEncoder().encode(string ?? "")))
} catch (error) {
console.error("编码失败:", error)
return ""
}
}
export function decode(bytes?: string) {
const latin = atob(bytes ?? "")
return new TextDecoder("utf-8").decode(
Uint8Array.from({ length: latin.length }, (_, index) =>
latin.charCodeAt(index),
),
)
export function decode(bytes?: string): string {
try {
if (!bytes) return ""
const latin = atob(bytes)
return new TextDecoder("utf-8").decode(
Uint8Array.from({ length: latin.length }, (_, index) =>
latin.charCodeAt(index),
),
)
} catch (error) {
console.error("解码失败:", error)
return ""
}
}
export function getCSRFToken() {
export function getCSRFToken(): string {
if (typeof document === "undefined") {
return ""
}