remove deprecated api

This commit is contained in:
Timi
2026-08-07 10:46:14 +08:00
parent efea624376
commit f0ba55fe25
18 changed files with 194 additions and 306 deletions
+10 -10
View File
@@ -1,5 +1,5 @@
import {Attachment, BizUpdateReq, TempFileResp} from "../types";
import {axios} from "./BaseAPI";
import { Attachment, BizIdUpdate, TempFile } from "../types";
import { axios } from "./BaseAPI";
import CommonAPI from "./CommonAPI";
const BASE_URI = "/attach";
@@ -11,7 +11,7 @@ const BASE_URI = "/attach";
* @param ttl 有效期
* @returns 临时附件列表
*/
async function uploadTemp(file: File | File[], ttl?: string): Promise<TempFileResp[]> {
async function upload(file: File | File[], ttl?: string): Promise<TempFile[]> {
const formData = new FormData();
const fileList = Array.isArray(file) ? file : [file];
for (const item of fileList) {
@@ -28,8 +28,8 @@ async function uploadTemp(file: File | File[], ttl?: string): Promise<TempFileRe
*
* @param req 更新请求
*/
async function updateByBiz(req: BizUpdateReq): Promise<void> {
return await axios.post(`${BASE_URI}/update/biz`, req);
async function updateByBizId(req: BizIdUpdate): Promise<void> {
return await axios.post(`${BASE_URI}/update/biz/id`, req);
}
/**
@@ -39,8 +39,8 @@ async function updateByBiz(req: BizUpdateReq): Promise<void> {
* @param bizId 业务 ID
* @param attachTypeList 附件类型列表
*/
async function listByBiz(bizType: string, bizId: string, attachTypeList?: string[]): Promise<Attachment[]> {
return await axios.get(`${BASE_URI}/list/biz`, {
async function listByBizId(bizType: string, bizId: string, attachTypeList?: string[]): Promise<Attachment[]> {
return await axios.get(`${BASE_URI}/list/biz/id`, {
params: {
bizType,
bizId,
@@ -50,9 +50,9 @@ async function listByBiz(bizType: string, bizId: string, attachTypeList?: string
}
export default {
uploadTemp,
updateByBiz,
listByBiz,
upload,
updateByBizId,
listByBizId,
getReadURL: CommonAPI.getAttachmentReadAPI,
getTempReadURL: CommonAPI.getAttachmentTempReadAPI
};
+1 -11
View File
@@ -1,4 +1,4 @@
import { CaptchaData, Comment, CommentReply, Page, PageResult } from "../types";
import { CaptchaData, Comment, Page, PageResult } from "../types";
import { axios } from "./BaseAPI";
const BASE_URI = "/comment";
@@ -11,17 +11,7 @@ async function create(captchaData: CaptchaData<Comment>): Promise<void> {
return axios.post(`${BASE_URI}/create`, captchaData);
}
async function pageReply(page: Page<CommentReply>): Promise<PageResult<CommentReply>> {
return axios.post(`${BASE_URI}/reply/list`, page);
}
async function createReply(captchaData: CaptchaData<CommentReply>): Promise<void> {
return axios.post(`${BASE_URI}/reply/create`, captchaData);
}
export default {
page,
create,
createReply,
pageReply
};
+2 -7
View File
@@ -1,5 +1,5 @@
import {CaptchaResult, Setting, TemplateBizType} from "../types";
import {axios} from "./BaseAPI";
import { CaptchaResult, Setting } from "../types";
import { axios } from "./BaseAPI";
function getBaseURI(): string {
const baseURL = axios.defaults.baseURL;
@@ -19,10 +19,6 @@ const getAttachmentReadAPI = (id: string) => `${getBaseURI()}/attach/read/${id}`
const getAttachmentTempReadAPI = (id: string) => `${getBaseURI()}/attach/temp/read?id=${id}`;
async function getTemplate(bizType: TemplateBizType, code: string): Promise<string> {
return axios.get(`/template?bizType=${bizType}&bizCode=${code}`);
}
async function settingMap(map: Record<string, string[]>): Promise<Map<string, Map<string, Setting>>> {
const raw = await axios.post("/setting/map", map);
const moduleMap = new Map<string, Map<string, Setting>>();
@@ -47,6 +43,5 @@ export default {
captcha,
getAttachmentReadAPI,
getAttachmentTempReadAPI,
getTemplate,
settingMap
};
+4 -5
View File
@@ -1,5 +1,4 @@
import type {Attachment, CaptchaData, LoginRequest, LoginResponse, RegisterRequest, UpdatePasswordRequest, User} from "../types";
import {UserAttachType} from "../types";
import type {Attachment, CaptchaData, LoginRequest, LoginResponse, RegisterRequest, UpdatePasswordRequest, User, UserAttachType} from "../types";
import {axios} from "./BaseAPI";
import CommonAPI from "./CommonAPI";
@@ -55,17 +54,17 @@ async function view(id: string): Promise<User> {
function getAvatarURL(user?: UserAttachmentOwner) {
if (user?.attachmentList) {
return findAttachmentByType(user.attachmentList, [UserAttachType.AVATAR, UserAttachType.DEFAULT_AVATAR]);
return findAttachmentByType(user.attachmentList, "AVATAR");
}
}
function getWrapperURL(user?: UserAttachmentOwner) {
if (user?.attachmentList) {
return findAttachmentByType(user.attachmentList, [UserAttachType.WRAPPER, UserAttachType.DEFAULT_WRAPPER]);
return findAttachmentByType(user.attachmentList, "WRAPPER");
}
}
function findAttachmentByType(attachmentList: readonly 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;
+7 -7
View File
@@ -32,23 +32,23 @@ const isShortScreen = ref(false);
const isMobileLayout = ref(false);
/** 断点配置,单位:px */
enum Breakpoints {
const Breakpoints = {
/** 超小设备 */
XS = 480,
XS: 480,
/** 手机 */
SM = 650,
SM: 650,
/** 平板 */
MD = 768,
MD: 768,
/** 笔记本 */
LG = 1024,
LG: 1024,
/** 大屏幕 */
XL = 1440
}
XL: 1440
} as const;
Resizer.addListener("DEVICE_SIZE", (width, height) => {
screenWidth.value = width;
+7 -68
View File
@@ -2,12 +2,12 @@ import type { Attachment } from "./Attachment";
import type { Model } from "./Model";
// 文章
export type Article<E extends ArticleMusicExtendData | ArticleSoftwareExtendData> = {
export type Article<A> = {
title?: string;
type: ArticleType;
digest?: string;
data?: string;
extendData?: E;
args?: A;
reads: number;
likes: number;
showComment: boolean;
@@ -15,74 +15,13 @@ export type Article<E extends ArticleMusicExtendData | ArticleSoftwareExtendData
canRanking: boolean;
} & Model;
export type ArticleView<E extends ArticleMusicExtendData | ArticleSoftwareExtendData> = {
export type ArticleView<A> = {
comments?: number;
attachmentList: Attachment[];
} & Article<E>;
} & Article<A>;
export enum ArticleType {
export const ArticleType = "COMMON";
/** 公版 */
PUBLIC,
export type ArticleType = (typeof ArticleType)[keyof typeof ArticleType];
/** 音乐 */
MUSIC,
/** 软件 */
SOFTWARE
}
export enum ArticleAttachType {
COVER,
}
export type ArticleMusicExtendData = {
title: string;
list: ArticleMusicItem[];
info: {
key: string;
value: string;
}[];
}
export type ArticleSoftwareExtendData = {
url?: string;
downloads: ArticleSoftwareDownload[];
format: string;
runtime: ArticleSoftwareRuntime[];
size: number;
version: string;
password?: string;
}
export enum ArticleSoftwareDownloadType {
TIMI_MONGO,
TIMI_COS,
URL
}
export enum ArticleSoftwareRuntime {
JVM,
WINDOWS,
LINUX,
MAC_OS
}
export type ArticleSoftwareDownload = {
type: ArticleSoftwareDownloadType;
value: string;
}
export type ArticleMusicItem = {
title: string;
audio?: string;
video?: string;
}
export const ArticleAttachType = "COVER";
+6 -17
View File
@@ -1,10 +1,10 @@
import { Model } from "./Model";
export type Attachment = {
bizType: AttachmentBizType;
bizId: string;
bizType?: AttachmentBizType;
bizId?: string;
attachType?: string;
mongoId: string;
mongoId?: string;
title?: string;
name?: string;
mimeType?: string;
@@ -17,26 +17,15 @@ export type Attachment = {
tempFileId?: string;
} & Model;
export type TempFileResp = {
export type TempFile = {
id: string;
expireAt?: number;
};
export type BizUpdateReq = {
export type BizIdUpdate = {
bizType: AttachmentBizType;
bizId: string;
items: Partial<Attachment>[];
};
export enum AttachmentBizType {
USER = "USER",
GAO_CUSTOMER = "GAO_CUSTOMER",
GAO_REGISTER_RECORD = "GAO_REGISTER_RECORD",
TEMP_FILE = "TEMP_FILE",
MIRROR = "MIRROR"
}
export type AttachmentBizType = | "USER" | "GAO_CUSTOMER" | "GAO_REGISTER_RECORD" | "TEMP_FILE" | "MIRROR";
+3 -32
View File
@@ -13,10 +13,10 @@ export type Comment = {
user?: User;
/** 回复列表 */
replies?: CommentReply[];
replies?: Comment[];
/** 回复分页 */
repliesPage?: Page<CommentReply>;
repliesPage?: Page<Comment>;
/** 用于绑定组件当前页下标 */
repliesCurrent?: number;
@@ -31,33 +31,4 @@ export type Comment = {
repository?: object;
} & Model
export type CommentReply = {
replyId?: number;
commentId?: number;
senderId?: number;
senderNick?: string;
receiverId?: number;
receiverNick?: string;
content?: string;
comment?: Comment;
sender?: User;
receiver?: User;
} & Model;
export enum CommentReplyBizType {
COMMENT = "COMMENT",
SENDER = "SENDER",
RECEIVER = "RECEIVER"
}
export enum CommentBizType {
ARTICLE = "ARTICLE",
GIT_ISSUE = "GIT_ISSUE",
GIT_MERGE = "GIT_MERGE",
}
export type CommentBizType = "ARTICLE" | "GIT_ISSUE" | "GIT_MERGE";
+7 -17
View File
@@ -1,9 +1,3 @@
export enum RunEnv {
DEV = "DEV",
DEV_SSL = "DEV_SSL",
PROD = "PROD"
}
// 基本实体模型
export type Model = {
id?: string;
@@ -23,17 +17,17 @@ export type ApiResponse<T> = {
}
export type Page<T> = {
index: number;
size: number;
orderMap?: { [K in keyof T]?: OrderType };
equalsExample?: Partial<T>;
likesExample?: Partial<T>;
} & BasePage;
export type BasePage = {
index: number;
size: number;
}
export enum OrderType {
ASC = "ASC",
DESC = "DESC"
}
export type OrderType = "ASC" | "DESC";
export type PageResult<T> = {
total: number;
@@ -53,11 +47,7 @@ export type CaptchaResult = {
data: string;
}
export enum ImageType {
AUTO = "ir-auto",
SMOOTH = "ir-smooth",
PIXELATED = "ir-pixelated"
}
export type ImageType = "IR-AUTO" | "IR-SMOOTH" | "IR-PIXELATED";
export type KeyValue<V, K = string> = {
key: K;
-6
View File
@@ -1,6 +0,0 @@
export enum TemplateBizType {
GIT = "GIT",
FOREVER_MC = "FOREVER_MC"
}
+1 -18
View File
@@ -32,18 +32,7 @@ export type User = {
phoneNoVerified?: boolean;
} & Model;
export enum UserAttachType {
AVATAR = "AVATAR",
WRAPPER = "WRAPPER",
LICENSE = "LICENSE",
DEFAULT_AVATAR = "DEFAULT_AVATAR",
DEFAULT_WRAPPER = "DEFAULT_WRAPPER"
}
export type UserAttachType = "AVATAR" | "WRAPPER";
export type RegisterRequest = {
name: string;
@@ -76,12 +65,6 @@ export type LoginUser = {
user?: User;
};
export enum LoginType {
ALERT,
IFRAME,
REDIRECT
}
export type UserLevelType = {
exp: number; // 经验数值,和 UserData.exp 一样
value: number; // 经验对应等级,[0, 8]
-1
View File
@@ -8,7 +8,6 @@ export * from "./Model";
export * from "./Permission";
export * from "./Role";
export * from "./User";
export * from "./Template";
export * from "./Comment";
export * from "./Developer";
+12 -35
View File
@@ -1,28 +1,7 @@
import Text from "./Text";
export enum Unit {
/** B */
B = "B",
/** KB */
KB = "KB",
/** MB */
MB = "MB",
/** GB */
GB = "GB",
/** TB */
TB = "TB",
/** PB */
PB = "PB",
/** EB */
EB = "EB"
}
export const UNITS = ["B", "KB", "MB", "GB", "TB", "PB", "EB"] as const;
export type Unit = (typeof UNITS)[number];
/** 储存单位 */
export default class IOSize {
@@ -48,8 +27,6 @@ export default class IOSize {
/** 1 EB */
public static EB = IOSize.PB << 10;
public static Unit = Unit;
/**
* <p>格式化一个储存容量,保留两位小数
* <pre>
@@ -66,7 +43,7 @@ export default class IOSize {
if (size === undefined || size === null) {
return "0 B";
}
const units = Object.keys(Unit);
const units = Object.values(UNITS);
if (0 < size) {
for (let i = 0; i < units.length; i++, size /= 1024) {
const unit = units[i];
@@ -118,31 +95,31 @@ export default class IOSize {
let unit: Unit;
// 先尝试精确匹配枚举
if (Object.values(Unit).includes(unitStr as Unit)) {
if (Object.values(UNITS).includes(unitStr as Unit)) {
unit = unitStr as Unit;
} else {
// 处理单字母单位缩写(K/M/G/T/P/E
switch (unitStr.charAt(0)) {
case "K":
unit = Unit.KB;
unit = "KB";
break;
case "M":
unit = Unit.MB;
unit = "MB";
break;
case "G":
unit = Unit.GB;
unit = "GB";
break;
case "T":
unit = Unit.TB;
unit = "TB";
break;
case "P":
unit = Unit.PB;
unit = "PB";
break;
case "E":
unit = Unit.EB;
unit = "EB";
break;
case "B":
unit = Unit.B;
unit = "B";
break;
default:
throw new Error("Unknown unit: " + unitStr);
@@ -173,7 +150,7 @@ export default class IOSize {
if (val === undefined || val === null) {
return 0;
}
const units = Object.values(Unit);
const units = Object.values(UNITS);
const ordinal = units.indexOf(unit);
return Math.round(val * Math.pow(1024, ordinal));
}
+29 -25
View File
@@ -1,23 +1,25 @@
export enum PrismjsType {
PlainText = "PlainText",
Markdown = "Markdown",
JavaScript = "JavaScript",
TypeScript = "TypeScript",
Initialization = "Initialization",
PHP = "PHP",
SQL = "SQL",
XML = "XML",
CSS = "CSS",
VUE = "VUE",
LESS = "LESS",
Markup = "Markup",
YAML = "YAML",
Json = "Json",
Java = "Java",
Properties = "Properties",
NginxConf = "NginxConf",
ApacheConf = "ApacheConf"
}
export const PrismjsType = {
PlainText: "PlainText",
Markdown: "Markdown",
JavaScript: "JavaScript",
TypeScript: "TypeScript",
Initialization: "Initialization",
PHP: "PHP",
SQL: "SQL",
XML: "XML",
CSS: "CSS",
VUE: "VUE",
LESS: "LESS",
Markup: "Markup",
YAML: "YAML",
Json: "Json",
Java: "Java",
Properties: "Properties",
NginxConf: "NginxConf",
ApacheConf: "ApacheConf"
} as const;
export type PrismjsType = (typeof PrismjsType)[keyof typeof PrismjsType];
export type PrismjsProperties = {
@@ -26,14 +28,16 @@ export type PrismjsProperties = {
viewer: PrismjsViewer;
}
export enum PrismjsViewer {
export const PrismjsViewer = {
MARKDOWN = "MARKDOWN",
MARKDOWN: "MARKDOWN",
CODE = "CODE",
CODE: "CODE",
TEXT = "TEXT",
}
TEXT: "TEXT"
} as const;
export type PrismjsViewer = (typeof PrismjsViewer)[keyof typeof PrismjsViewer];
export default class Prismjs {
+15 -20
View File
@@ -1,7 +1,7 @@
export default class Storage {
/**
* 获取为布尔值
* 获取为布尔值,键不存在时返回 false
*
* @param key 键
* @returns 布尔值
@@ -11,7 +11,7 @@ export default class Storage {
}
/**
* 获取为布尔值并取反
* 获取为布尔值并取反,键不存在时返回 true
*
* @param key 键
* @returns 布尔值
@@ -25,13 +25,11 @@ export default class Storage {
*
* @template T 对象类型
* @param key 键
* @returns {T | undefined} 返回对象
* @returns 对象,键不存在时返回 null
*/
public static getObject<T>(key: string): T {
if (this.has(key)) {
return this.getJSON(key) as T;
}
throw Error(`not found ${key}`);
public static getObject<T>(key: string): T | null {
const value = this.getJSON(key);
return value === null ? null : value as T;
}
/**
@@ -54,24 +52,21 @@ export default class Storage {
* 获取为 JSON
*
* @param key 键
* @returns JSON 对象
* @returns JSON 对象,键不存在时返回 null;值无法解析时抛错
*/
public static getJSON(key: string) {
return JSON.parse(this.getString(key));
public static getJSON(key: string): unknown {
const value = this.getString(key);
return value === null ? null : JSON.parse(value);
}
/**
* 获取为字符串(其他获取方式一般经过这个方法,找不到配置或配置值无效时会抛错)
* 获取为字符串
*
* @param key 键
* @returns 字符串
* @returns 字符串,键不存在时返回 null
*/
public static getString(key: string): string {
const value = localStorage.getItem(key);
if (value) {
return value;
}
throw new Error(`not found: ${key}, ${value}`);
public static getString(key: string): string | null {
return localStorage.getItem(key);
}
/**
@@ -81,7 +76,7 @@ export default class Storage {
* @returns true 为存在
*/
public static has(key: string): boolean {
return localStorage.getItem(key) !== undefined && localStorage.getItem(key) !== null;
return localStorage.getItem(key) !== null;
}
/**
+46 -16
View File
@@ -232,43 +232,73 @@ export default class Toolkit {
return Object.keys(e)[Object.values(e).indexOf(value)];
}
// 防抖
// eslint-disable-next-line
public static debounce<T extends (...args: any[]) => any>(callback: T, defaultImmediate = true, delay = 600): T & {
cancel(): void
} {
let timerId: ReturnType<typeof setTimeout> | null = null; // 存储定时器
let immediate = defaultImmediate;
// 定义一个 cancel 办法,用于勾销防抖
/**
* 防抖函数
*
* 支持两种模式:
* - **立即模式**`immediate = true`,默认):首次调用立即执行,连续调用在延迟结束后再执行最后一次(leading + trailing
* - **延迟模式**`immediate = false`):所有调用在延迟结束后执行最后一次(trailing only
*
* @param callback 回调函数
* @param immediate 是否首次调用立即执行,默认 true
* @param delay 延迟毫秒数,默认 600
* @returns 防抖后的函数,附带 `cancel()` 方法用于取消 pending 执行并重置状态
*
* @example
* ```ts
* // 立即模式(默认):首次立即触发,连续调用后在延迟结束时再触发一次
* const fn = Toolkit.debounce((val: string) => {
* console.log(val);
* });
* fn("a"); // 立即输出 "a"
* fn("b"); // 600ms 后输出 "b"trailing
* fn.cancel(); // 取消 pending 的 trailing 调用,重置为初始状态
*
* // 延迟模式:连续调用只在停止后触发最后一次
* const fn2 = Toolkit.debounce((val: string) => {
* console.log(val);
* }, false);
* fn2("a"); // 不输出
* fn2("b"); // 600ms 后输出 "b"
* ```
*/
public static debounce<T extends (...args: any[]) => any>(
callback: T,
immediate = true,
delay = 300
): ((...args: Parameters<T>) => void) & { cancel(): void } {
let timerId: ReturnType<typeof setTimeout> | null = null;
let leading = immediate;
const cancel = (): void => {
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
leading = immediate;
};
const debounced = function (this: ThisParameterType<T>, ...args: Parameters<T>): void {
const context = this;
if (timerId) {
cancel();
clearTimeout(timerId);
timerId = null;
}
if (immediate) {
if (leading) {
callback.apply(context, args);
immediate = false;
leading = false;
timerId = setTimeout(() => {
immediate = defaultImmediate;
leading = immediate;
}, delay);
} else {
// 设置定时器,在延迟时间后执行指标函数
timerId = setTimeout(() => {
callback.apply(context, args);
immediate = defaultImmediate;
leading = immediate;
}, delay);
}
};
// 将 cancel 方法附加到 debounced 函数上
(debounced as any).cancel = cancel;
return debounced as T & { cancel(): void };
return debounced as ((...args: Parameters<T>) => void) & { cancel(): void };
}
public static toUserLevel(exp?: number): UserLevelType {
+6 -11
View File
@@ -1,12 +1,7 @@
import type { Directive, DirectiveBinding } from "vue";
import Toolkit from "../Toolkit";
export enum PopupType {
TEXT,
IMG,
HTML,
EL
}
export type PopupType = "TEXT" | "IMG" | "HTML" | "ELEMENT";
/** */
export type PopupConfig = {
@@ -30,7 +25,7 @@ const VPopup: Directive = {
config = binding.value as PopupConfig;
} else {
config = {
type: PopupType.TEXT,
type: "TEXT",
value: binding.value as any as string,
canShow: () => true
};
@@ -58,24 +53,24 @@ const VPopup: Directive = {
popup.appendChild(el);
}
switch (config.type) {
case PopupType.TEXT:
case "TEXT":
// 文本
el = document.createElement("div");
el.className = "text";
el.textContent = config.value as string;
popup.appendChild(el);
break;
case PopupType.IMG:
case "IMG":
// 图片
el = document.createElement("img");
(el as HTMLImageElement).src = config.value as string;
popup.appendChild(el);
break;
case PopupType.HTML:
case "HTML":
// HTML 字符串
popup.appendChild(Toolkit.toDOM(config.value as string));
break;
case PopupType.EL:
case "ELEMENT":
// DOM 节点
if (config.value instanceof HTMLElement) {
const valueEl = config.value as HTMLElement;