fix: 修复管理端前端 lint 与构建问题

- 收敛 easyflow-ui-admin 的 lint、格式和类型问题

- 修正 demo 页面与管理端前端构建失败点

- 验证 pnpm lint 与 pnpm build 均已通过
This commit is contained in:
2026-04-05 21:39:13 +08:00
parent bb72e19c84
commit 7e7c236c2a
240 changed files with 5151 additions and 4701 deletions

View File

@@ -1,157 +1,163 @@
import type {useSvelteFlow} from '@xyflow/svelte';
import {componentName} from './consts';
import type {TinyflowData, TinyflowOptions, TinyflowTheme} from './types';
import type { useSvelteFlow } from '@xyflow/svelte';
import { componentName } from './consts';
import type { TinyflowData, TinyflowOptions, TinyflowTheme } from './types';
type FlowInstance = ReturnType<typeof useSvelteFlow>;
export class Tinyflow {
private options!: TinyflowOptions;
private rootEl!: Element;
private svelteFlowInstance!: FlowInstance;
private tinyflowEl!: HTMLElement & {
options: TinyflowOptions;
onInit: (svelteFlowInstance: FlowInstance) => void;
private options!: TinyflowOptions;
private rootEl!: Element;
private svelteFlowInstance!: FlowInstance;
private tinyflowEl!: HTMLElement & {
options: TinyflowOptions;
onInit: (svelteFlowInstance: FlowInstance) => void;
};
constructor(options: TinyflowOptions) {
if (
typeof options.element !== 'string' &&
!(options.element instanceof Element)
) {
throw new Error('element must be a string or Element');
}
this._setOptions(options);
this._init();
}
private _init() {
if (typeof this.options.element === 'string') {
this.rootEl = document.querySelector(this.options.element)!;
if (!this.rootEl) {
throw new Error(
`element not found by document.querySelector('${this.options.element}')`,
);
}
} else if (this.options.element instanceof Element) {
this.rootEl = this.options.element;
} else {
throw new Error('element must be a string or Element');
}
this.tinyflowEl = this._createTinyflowElement();
this.rootEl.appendChild(this.tinyflowEl);
}
private _setOptions(options: TinyflowOptions) {
this.options = {
theme: options.theme || 'light',
...options,
};
}
constructor(options: TinyflowOptions) {
if (typeof options.element !== 'string' && !(options.element instanceof Element)) {
throw new Error('element must be a string or Element');
}
this._setOptions(options);
this._init();
private _getFlowInstance() {
if (!this.svelteFlowInstance) {
console.warn('Tinyflow instance is not initialized');
return null;
}
return this.svelteFlowInstance;
}
private _applyThemeClass(targetEl: Element, theme?: TinyflowTheme) {
targetEl.classList.remove('tf-theme-light', 'tf-theme-dark');
targetEl.classList.add(
theme === 'dark' ? 'tf-theme-dark' : 'tf-theme-light',
);
}
private _createTinyflowElement() {
const tinyflowEl = document.createElement(componentName) as HTMLElement & {
options: TinyflowOptions;
onInit: (svelteFlowInstance: FlowInstance) => void;
};
tinyflowEl.style.display = 'block';
tinyflowEl.style.width = '100%';
tinyflowEl.style.height = '100%';
this._applyThemeClass(tinyflowEl, this.options.theme);
tinyflowEl.options = this.options;
tinyflowEl.onInit = (svelteFlowInstance: FlowInstance) => {
this.svelteFlowInstance = svelteFlowInstance;
};
return tinyflowEl;
}
getOptions() {
return this.options;
}
getData() {
const flow = this._getFlowInstance();
if (!flow) {
return null;
}
return flow.toObject();
}
async focusNode(
nodeId: string,
options?: { duration?: number; zoom?: number },
) {
const flow = this._getFlowInstance();
if (!flow) {
return false;
}
private _init() {
if (typeof this.options.element === 'string') {
this.rootEl = document.querySelector(this.options.element)!;
if (!this.rootEl) {
throw new Error(
`element not found by document.querySelector('${this.options.element}')`
);
}
} else if (this.options.element instanceof Element) {
this.rootEl = this.options.element;
} else {
throw new Error('element must be a string or Element');
}
this.tinyflowEl = this._createTinyflowElement();
this.rootEl.appendChild(this.tinyflowEl);
const targetNode = flow.getNode(nodeId);
if (!targetNode) {
return false;
}
private _setOptions(options: TinyflowOptions) {
this.options = {
theme: options.theme || 'light',
...options
};
// Keep only the target node selected so the canvas has a clear visual focus.
flow.getNodes().forEach((node) => {
flow.updateNode(node.id, { selected: node.id === nodeId });
});
const internalNode = flow.getInternalNode(nodeId) as any;
const absolutePosition = internalNode?.internals?.positionAbsolute ||
(targetNode as any)?.positionAbsolute ||
targetNode.position || { x: 0, y: 0 };
const width =
internalNode?.measured?.width ||
(targetNode as any)?.measured?.width ||
(targetNode as any)?.width ||
260;
const height =
internalNode?.measured?.height ||
(targetNode as any)?.measured?.height ||
(targetNode as any)?.height ||
120;
const centerX = absolutePosition.x + width / 2;
const centerY = absolutePosition.y + height / 2;
const nextZoom = options?.zoom ?? Math.max(flow.getZoom(), 1);
await flow.setCenter(centerX, centerY, {
zoom: nextZoom,
duration: options?.duration ?? 280,
});
return true;
}
setTheme(theme: TinyflowTheme) {
this.options.theme = theme;
if (this.tinyflowEl) {
this._applyThemeClass(this.tinyflowEl, theme);
}
}
private _getFlowInstance() {
if (!this.svelteFlowInstance) {
console.warn('Tinyflow instance is not initialized');
return null;
}
return this.svelteFlowInstance;
}
private _applyThemeClass(targetEl: Element, theme?: TinyflowTheme) {
targetEl.classList.remove('tf-theme-light', 'tf-theme-dark');
targetEl.classList.add(theme === 'dark' ? 'tf-theme-dark' : 'tf-theme-light');
}
private _createTinyflowElement() {
const tinyflowEl = document.createElement(componentName) as HTMLElement & {
options: TinyflowOptions;
onInit: (svelteFlowInstance: FlowInstance) => void;
};
tinyflowEl.style.display = 'block';
tinyflowEl.style.width = '100%';
tinyflowEl.style.height = '100%';
this._applyThemeClass(tinyflowEl, this.options.theme);
tinyflowEl.options = this.options;
tinyflowEl.onInit = (svelteFlowInstance: FlowInstance) => {
this.svelteFlowInstance = svelteFlowInstance;
};
return tinyflowEl;
}
getOptions() {
return this.options;
}
getData() {
const flow = this._getFlowInstance();
if (!flow) {
return null;
}
return flow.toObject();
}
async focusNode(nodeId: string, options?: { duration?: number; zoom?: number }) {
const flow = this._getFlowInstance();
if (!flow) {
return false;
}
const targetNode = flow.getNode(nodeId);
if (!targetNode) {
return false;
}
// Keep only the target node selected so the canvas has a clear visual focus.
flow.getNodes().forEach((node) => {
flow.updateNode(node.id, { selected: node.id === nodeId });
});
const internalNode = flow.getInternalNode(nodeId) as any;
const absolutePosition =
internalNode?.internals?.positionAbsolute ||
(targetNode as any)?.positionAbsolute ||
targetNode.position ||
{ x: 0, y: 0 };
const width =
internalNode?.measured?.width ||
(targetNode as any)?.measured?.width ||
(targetNode as any)?.width ||
260;
const height =
internalNode?.measured?.height ||
(targetNode as any)?.measured?.height ||
(targetNode as any)?.height ||
120;
const centerX = absolutePosition.x + width / 2;
const centerY = absolutePosition.y + height / 2;
const nextZoom = options?.zoom ?? Math.max(flow.getZoom(), 1);
await flow.setCenter(centerX, centerY, {
zoom: nextZoom,
duration: options?.duration ?? 280
});
return true;
}
setTheme(theme: TinyflowTheme) {
this.options.theme = theme;
if (this.tinyflowEl) {
this._applyThemeClass(this.tinyflowEl, theme);
}
}
setData(data: TinyflowData) {
this.options.data = data;
this.tinyflowEl = this._createTinyflowElement();
this.destroy();
this.rootEl.appendChild(this.tinyflowEl);
}
destroy() {
while (this.rootEl.firstChild) {
this.rootEl.removeChild(this.rootEl.firstChild);
}
setData(data: TinyflowData) {
this.options.data = data;
this.tinyflowEl = this._createTinyflowElement();
this.destroy();
this.rootEl.appendChild(this.tinyflowEl);
}
destroy() {
while (this.rootEl.firstChild) {
this.rootEl.removeChild(this.rootEl.firstChild);
}
}
}