v0.0.23
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@
|
||||
"module": "./dist/timi-web.mjs",
|
||||
"style": "./dist/timi-web.css",
|
||||
"private": false,
|
||||
"version": "0.0.22",
|
||||
"version": "0.0.23",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
+9
-5
@@ -1,8 +1,12 @@
|
||||
import {Attachment, CaptchaData, LoginRequest, LoginResponse, RegisterRequest, UpdatePasswordRequest, User, UserAttachType} from "../types";
|
||||
import type {Attachment, CaptchaData, LoginRequest, LoginResponse, RegisterRequest, UpdatePasswordRequest, User} from "../types";
|
||||
import {UserAttachType} from "../types";
|
||||
import {axios} from "./BaseAPI";
|
||||
import CommonAPI from "./CommonAPI";
|
||||
|
||||
const BASE_URI = "/user";
|
||||
type UserAttachmentOwner = {
|
||||
attachmentList?: readonly Attachment[];
|
||||
};
|
||||
|
||||
async function register(req: CaptchaData<RegisterRequest>): Promise<LoginResponse> {
|
||||
return await axios.post(`${BASE_URI}/register`, req);
|
||||
@@ -31,7 +35,7 @@ async function logout(): Promise<void> {
|
||||
return await axios.post(`${BASE_URI}/logout`);
|
||||
}
|
||||
|
||||
async function updateCurrent(req: User): Promise<LoginResponse> {
|
||||
async function updateCurrent(req: Partial<User>): Promise<LoginResponse> {
|
||||
return await axios.post(`${BASE_URI}/current/update`, req);
|
||||
}
|
||||
|
||||
@@ -49,19 +53,19 @@ async function view(id: string): Promise<User> {
|
||||
return await axios.post(`${BASE_URI}/view/${id}`);
|
||||
}
|
||||
|
||||
function getAvatarURL(user?: User) {
|
||||
function getAvatarURL(user?: UserAttachmentOwner) {
|
||||
if (user?.attachmentList) {
|
||||
return findAttachmentByType(user.attachmentList, [UserAttachType.AVATAR, UserAttachType.DEFAULT_AVATAR]);
|
||||
}
|
||||
}
|
||||
|
||||
function getWrapperURL(user?: User) {
|
||||
function getWrapperURL(user?: UserAttachmentOwner) {
|
||||
if (user?.attachmentList) {
|
||||
return findAttachmentByType(user.attachmentList, [UserAttachType.WRAPPER, UserAttachType.DEFAULT_WRAPPER]);
|
||||
}
|
||||
}
|
||||
|
||||
function findAttachmentByType(attachmentList: Attachment[], types: UserAttachType[]) {
|
||||
function findAttachmentByType(attachmentList: readonly Attachment[], types: UserAttachType[]) {
|
||||
for (let i = 0; i < attachmentList.length; i++) {
|
||||
const attachType = attachmentList[i].attachType as UserAttachType | undefined;
|
||||
const id = attachmentList[i].id;
|
||||
|
||||
+25
-2
@@ -16,12 +16,35 @@ export type AccessMatchMode = "and" | "or";
|
||||
|
||||
let _storageKey = "loginUser";
|
||||
|
||||
function normalizeAccessList(list?: string[]): string[] {
|
||||
type AccessItem = string | {
|
||||
moduleCode?: string;
|
||||
code?: string;
|
||||
};
|
||||
|
||||
function normalizeAccessItem(item?: AccessItem): string {
|
||||
if (!item) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (typeof item === "string") {
|
||||
return item.trim();
|
||||
}
|
||||
|
||||
const code = item.code?.trim();
|
||||
if (!code) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const moduleCode = item.moduleCode?.trim();
|
||||
return moduleCode && !code.includes(":") ? `${moduleCode}:${code}` : code;
|
||||
}
|
||||
|
||||
function normalizeAccessList(list?: AccessItem[]): string[] {
|
||||
if (!list?.length) {
|
||||
return [];
|
||||
}
|
||||
return list
|
||||
.map(item => item?.trim())
|
||||
.map(normalizeAccessItem)
|
||||
.filter((item): item is string => !!item);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ export type Page<T> = {
|
||||
index: number;
|
||||
size: number;
|
||||
orderMap?: { [K in keyof T]?: OrderType };
|
||||
equalsExample?: T;
|
||||
likesExample?: T;
|
||||
equalsExample?: Partial<T>;
|
||||
likesExample?: Partial<T>;
|
||||
}
|
||||
|
||||
export enum OrderType {
|
||||
|
||||
@@ -7,6 +7,15 @@ export type ScrollListener = {
|
||||
bottom: number;
|
||||
}
|
||||
|
||||
export type ScrollBottomListenerOptions = {
|
||||
|
||||
/** 距离底部小于等于该值时触发 */
|
||||
distance?: number;
|
||||
|
||||
/** 返回 true 时才触发 */
|
||||
canLoad?: () => boolean;
|
||||
}
|
||||
|
||||
export default class Scroller {
|
||||
|
||||
private static instance: Scroller;
|
||||
@@ -53,6 +62,26 @@ export default class Scroller {
|
||||
Scroller.getInstance().listeners.set(name, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加触底监听
|
||||
*
|
||||
* @param name 事件名
|
||||
* @param listener 触底回调
|
||||
* @param options 触底配置
|
||||
*/
|
||||
public static addBottomListener(name: string, listener: (event: ScrollListener) => void | Promise<void>, options: ScrollBottomListenerOptions = {}) {
|
||||
const distance = options.distance ?? 120;
|
||||
Scroller.addListener(name, event => {
|
||||
if (distance < event.bottom) {
|
||||
return;
|
||||
}
|
||||
if (options.canLoad && !options.canLoad()) {
|
||||
return;
|
||||
}
|
||||
void listener(event);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除监听
|
||||
*
|
||||
|
||||
@@ -30,6 +30,10 @@ export default class Text {
|
||||
return template.replace(/\$\{(\w+)}/g, (_, key) => variables[key]);
|
||||
}
|
||||
|
||||
public static pad(value: number | string, length = 2, fill = "0"): string {
|
||||
return value.toString().padStart(length, fill);
|
||||
}
|
||||
|
||||
public static unitCompact(val: number | string | null | undefined, unit: string, fixed = 0): string {
|
||||
return this.unit(val, unit, fixed, true);
|
||||
};
|
||||
|
||||
+25
-6
@@ -1,4 +1,5 @@
|
||||
import Toolkit from "./Toolkit";
|
||||
import Text from "./Text";
|
||||
|
||||
export default class Time {
|
||||
|
||||
@@ -15,6 +16,25 @@ export default class Time {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
public static toTimestamp(date: Date): number {
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
public static toDateObject(unix?: number): Date | undefined {
|
||||
if (!unix) {
|
||||
return undefined;
|
||||
}
|
||||
return new Date(unix);
|
||||
}
|
||||
|
||||
public static formatDate(date: Date): string {
|
||||
return `${date.getFullYear()}-${Text.pad(date.getMonth() + 1)}-${Text.pad(date.getDate())}`;
|
||||
}
|
||||
|
||||
public static formatDateTime(date: Date): string {
|
||||
return `${this.formatDate(date)} ${Text.pad(date.getHours())}:${Text.pad(date.getMinutes())}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unix 时间戳转日期
|
||||
*
|
||||
@@ -22,8 +42,7 @@ export default class Time {
|
||||
*/
|
||||
public static toDate(unix?: number): string {
|
||||
if (!unix) return "";
|
||||
const d = new Date(unix);
|
||||
return `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, "0")}-${d.getDate().toString().padStart(2, "0")}`;
|
||||
return this.formatDate(new Date(unix));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,13 +53,13 @@ export default class Time {
|
||||
public static toTime(unix?: number): string {
|
||||
if (!unix) return "";
|
||||
const d = new Date(unix);
|
||||
return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}`;
|
||||
return `${Text.pad(d.getHours())}:${Text.pad(d.getMinutes())}`;
|
||||
}
|
||||
|
||||
public static toShortTime(unix?: number): string {
|
||||
if (!unix) return "";
|
||||
const d = new Date(unix);
|
||||
return `${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}`;
|
||||
return `${Text.pad(d.getMinutes())}:${Text.pad(d.getSeconds())}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,9 +150,9 @@ export default class Time {
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
const second = seconds % 60;
|
||||
if (0 < hours) {
|
||||
return `${hours}:${minutes.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}`;
|
||||
return `${hours}:${Text.pad(minutes)}:${Text.pad(second)}`;
|
||||
}
|
||||
return `${minutes.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}`;
|
||||
return `${Text.pad(minutes)}:${Text.pad(second)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -398,4 +398,15 @@ export default class Toolkit {
|
||||
}
|
||||
return JSON.stringify(JSON.parse(jsonStr), null, 4);
|
||||
}
|
||||
|
||||
public static downloadBlob(blob: Blob, fileName: string): void {
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = fileName;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
window.setTimeout(() => URL.revokeObjectURL(url), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user