v0.0.24
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
"module": "./dist/timi-web.mjs",
|
"module": "./dist/timi-web.mjs",
|
||||||
"style": "./dist/timi-web.css",
|
"style": "./dist/timi-web.css",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "0.0.23",
|
"version": "0.0.24",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
+6
-3
@@ -1,5 +1,5 @@
|
|||||||
import { axios } from "./BaseAPI";
|
import { axios } from "./BaseAPI";
|
||||||
import type { Page, PageResult, Permission, Role, RolePayload, UserRoleAuthorizeReq } from "../types";
|
import type { ModuleCode, Page, PageResult, Permission, Role, RolePayload, UserRoleAuthorizeReq } from "../types";
|
||||||
|
|
||||||
const BASE_URI = "/user/role";
|
const BASE_URI = "/user/role";
|
||||||
|
|
||||||
@@ -27,9 +27,12 @@ async function remove(id: string): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function authorizedList(userId: string): Promise<Role[]> {
|
async function authorizedList(userId: string, moduleCode?: ModuleCode): Promise<Role[]> {
|
||||||
return axios.post(`${BASE_URI}/authorized/list`, undefined, {
|
return axios.post(`${BASE_URI}/authorized/list`, undefined, {
|
||||||
params: { userId }
|
params: {
|
||||||
|
userId,
|
||||||
|
moduleCode
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,23 +103,23 @@ textarea {
|
|||||||
-webkit-filter: grayscale(1);
|
-webkit-filter: grayscale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bold {
|
.text-bold {
|
||||||
font-weight: bold !important;
|
font-weight: bold !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.italic {
|
.text-italic {
|
||||||
font-style: italic !important;
|
font-style: italic !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete {
|
.text-delete {
|
||||||
text-decoration: line-through !important;
|
text-decoration: line-through !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.underline {
|
.text-underline {
|
||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.not-underline {
|
.text-not-underline {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -15,7 +15,10 @@ export type Model = {
|
|||||||
|
|
||||||
export type ApiResponse<T> = {
|
export type ApiResponse<T> = {
|
||||||
code: number;
|
code: number;
|
||||||
msg?: string;
|
message: string;
|
||||||
|
messageCode: string;
|
||||||
|
success: boolean;
|
||||||
|
fail: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ const applyDefaultInterceptors = (instance: AxiosInstance) => {
|
|||||||
status: axiosResp?.status,
|
status: axiosResp?.status,
|
||||||
response: axiosResp,
|
response: axiosResp,
|
||||||
serverResponse: serverResp,
|
serverResponse: serverResp,
|
||||||
error: serverResp.msg
|
error: serverResp.message
|
||||||
});
|
});
|
||||||
if (globalErrorCallback) {
|
if (globalErrorCallback) {
|
||||||
globalErrorCallback(serverResp);
|
globalErrorCallback(serverResp);
|
||||||
}
|
}
|
||||||
// 由调用方处理
|
// 由调用方处理
|
||||||
return Promise.reject(serverResp.msg);
|
return Promise.reject(serverResp.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyResponseObserver({
|
notifyResponseObserver({
|
||||||
|
|||||||
+114
-27
@@ -3,6 +3,7 @@ export type ScrollListener = {
|
|||||||
source: Event;
|
source: Event;
|
||||||
viewWidth: number;
|
viewWidth: number;
|
||||||
viewHeight: number;
|
viewHeight: number;
|
||||||
|
scrollHeight: number;
|
||||||
top: number;
|
top: number;
|
||||||
bottom: number;
|
bottom: number;
|
||||||
}
|
}
|
||||||
@@ -14,35 +15,64 @@ export type ScrollBottomListenerOptions = {
|
|||||||
|
|
||||||
/** 返回 true 时才触发 */
|
/** 返回 true 时才触发 */
|
||||||
canLoad?: () => boolean;
|
canLoad?: () => boolean;
|
||||||
|
|
||||||
|
/** 自定义滚动容器,默认 window */
|
||||||
|
getElement?: () => HTMLElement | null | undefined;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Scroller {
|
export default class Scroller {
|
||||||
|
|
||||||
private static instance: Scroller;
|
private static instance: Scroller;
|
||||||
|
|
||||||
listeners = new Map<string, Function>();
|
listeners = new Map<string, {
|
||||||
|
target: HTMLElement | Window;
|
||||||
|
listener: EventListener;
|
||||||
|
}>();
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {}
|
||||||
|
|
||||||
window.addEventListener("scroll", source => {
|
private static waitForLayout(): Promise<void> {
|
||||||
// 滚动距离
|
return new Promise(resolve => {
|
||||||
const top = document.body.scrollTop || document.documentElement.scrollTop;
|
requestAnimationFrame(() => {
|
||||||
// 可视高度
|
requestAnimationFrame(() => resolve());
|
||||||
const viewWidth = document.documentElement.clientWidth || document.body.clientWidth;
|
});
|
||||||
// 可视高度
|
});
|
||||||
const viewHeight = document.documentElement.clientHeight || document.body.clientHeight;
|
}
|
||||||
// 滚动高度
|
|
||||||
const sH = document.documentElement.scrollHeight || document.body.scrollHeight;
|
private static getScrollState(element?: HTMLElement | null, source?: Event): ScrollListener {
|
||||||
// 触发事件
|
if (element) {
|
||||||
const bottom = sH - top - viewHeight;
|
return {
|
||||||
this.listeners.forEach(listener => listener({
|
source: source || new Event("scroll"),
|
||||||
source,
|
viewWidth: element.clientWidth,
|
||||||
viewWidth,
|
viewHeight: element.clientHeight,
|
||||||
viewHeight,
|
scrollHeight: element.scrollHeight,
|
||||||
top,
|
top: element.scrollTop,
|
||||||
bottom
|
bottom: element.scrollHeight - element.scrollTop - element.clientHeight
|
||||||
} as ScrollListener));
|
};
|
||||||
}, true);
|
}
|
||||||
|
const top = document.body.scrollTop || document.documentElement.scrollTop;
|
||||||
|
const viewWidth = document.documentElement.clientWidth || document.body.clientWidth;
|
||||||
|
const viewHeight = document.documentElement.clientHeight || document.body.clientHeight;
|
||||||
|
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
|
||||||
|
return {
|
||||||
|
source: source || new Event("scroll"),
|
||||||
|
viewWidth,
|
||||||
|
viewHeight,
|
||||||
|
scrollHeight,
|
||||||
|
top,
|
||||||
|
bottom: scrollHeight - top - viewHeight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bindTarget(name: string, target: HTMLElement | Window, listener: EventListener) {
|
||||||
|
target.addEventListener("scroll", listener, {
|
||||||
|
passive: true
|
||||||
|
});
|
||||||
|
Scroller.getInstance().listeners.set(name, {
|
||||||
|
target,
|
||||||
|
listener
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getInstance(): Scroller {
|
private static getInstance(): Scroller {
|
||||||
@@ -58,8 +88,24 @@ export default class Scroller {
|
|||||||
* @param name 事件名
|
* @param name 事件名
|
||||||
* @param listener 监听事件
|
* @param listener 监听事件
|
||||||
*/
|
*/
|
||||||
public static addListener(name: string, listener: (event: ScrollListener) => void) {
|
public static addListener(name: string, listener: (event: ScrollListener) => void, getElement?: () => HTMLElement | null | undefined) {
|
||||||
Scroller.getInstance().listeners.set(name, listener);
|
Scroller.removeListener(name);
|
||||||
|
const targetElement = getElement?.();
|
||||||
|
if (getElement && !targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = targetElement || window;
|
||||||
|
const eventListener: EventListener = source => {
|
||||||
|
if (!targetElement) {
|
||||||
|
const eventTarget = source.target;
|
||||||
|
const isWindowScrollTarget = eventTarget === document || eventTarget === document.documentElement || eventTarget === document.body;
|
||||||
|
if (!isWindowScrollTarget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listener(Scroller.getScrollState(targetElement, source));
|
||||||
|
};
|
||||||
|
Scroller.bindTarget(name, target, eventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,15 +117,51 @@ export default class Scroller {
|
|||||||
*/
|
*/
|
||||||
public static addBottomListener(name: string, listener: (event: ScrollListener) => void | Promise<void>, options: ScrollBottomListenerOptions = {}) {
|
public static addBottomListener(name: string, listener: (event: ScrollListener) => void | Promise<void>, options: ScrollBottomListenerOptions = {}) {
|
||||||
const distance = options.distance ?? 120;
|
const distance = options.distance ?? 120;
|
||||||
Scroller.addListener(name, event => {
|
let loading = false;
|
||||||
if (distance < event.bottom) {
|
let armed = true;
|
||||||
|
const triggerLoad = async (event: ScrollListener): Promise<void> => {
|
||||||
|
const inRange = event.bottom <= distance;
|
||||||
|
if (!inRange) {
|
||||||
|
armed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!armed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.canLoad && !options.canLoad()) {
|
if (options.canLoad && !options.canLoad()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void listener(event);
|
armed = false;
|
||||||
});
|
loading = true;
|
||||||
|
try {
|
||||||
|
let currentEvent = event;
|
||||||
|
while (true) {
|
||||||
|
const previousScrollHeight = currentEvent.scrollHeight;
|
||||||
|
await listener(currentEvent);
|
||||||
|
await Scroller.waitForLayout();
|
||||||
|
if (options.canLoad && !options.canLoad()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentEvent = Scroller.getScrollState(options.getElement?.());
|
||||||
|
if (distance < currentEvent.bottom) {
|
||||||
|
armed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (currentEvent.scrollHeight <= previousScrollHeight) {
|
||||||
|
armed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Scroller.addListener(name, event => {
|
||||||
|
void triggerLoad(event);
|
||||||
|
}, options.getElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,6 +170,11 @@ export default class Scroller {
|
|||||||
* @param name 事件名
|
* @param name 事件名
|
||||||
*/
|
*/
|
||||||
public static removeListener(name: string) {
|
public static removeListener(name: string) {
|
||||||
|
const entry = Scroller.getInstance().listeners.get(name);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry.target.removeEventListener("scroll", entry.listener);
|
||||||
Scroller.getInstance().listeners.delete(name);
|
Scroller.getInstance().listeners.delete(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user