fix: 修复管理端前端 lint 与构建问题
- 收敛 easyflow-ui-admin 的 lint、格式和类型问题 - 修正 demo 页面与管理端前端构建失败点 - 验证 pnpm lint 与 pnpm build 均已通过
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": ["off"],
|
||||
}
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': ['off'],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div ref="divRef" :class="['tinyflow', className]" :style="style" />
|
||||
<div ref="divRef" :class="['tinyflow', className]" :style="style" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {Tinyflow as TinyflowNative, TinyflowOptions} from '@tinyflow-ai/ui';
|
||||
import { Tinyflow as TinyflowNative, TinyflowOptions } from '@tinyflow-ai/ui';
|
||||
import '@tinyflow-ai/ui/dist/index.css';
|
||||
import {onMounted, onUnmounted, ref, watch} from 'vue';
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
className?: string;
|
||||
style?: Record<string, string>;
|
||||
} & Omit<TinyflowOptions, 'element'>
|
||||
{
|
||||
className?: string;
|
||||
style?: Record<string, string>;
|
||||
} & Omit<TinyflowOptions, 'element'>
|
||||
>();
|
||||
|
||||
const divRef = ref<HTMLDivElement | null>(null);
|
||||
@@ -19,78 +19,84 @@ let tinyflow: TinyflowNative | null = null;
|
||||
|
||||
// 安全深拷贝工具函数
|
||||
function safeDeepClone<T>(obj: T): T {
|
||||
if (obj === null || typeof obj !== 'object') return obj;
|
||||
if (obj === null || typeof obj !== 'object') return obj;
|
||||
|
||||
try {
|
||||
return structuredClone(obj);
|
||||
} catch {
|
||||
try {
|
||||
return structuredClone(obj);
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
} catch {
|
||||
try {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
} catch {
|
||||
console.warn('Failed to clone object, returning original (may cause issues)', obj);
|
||||
return obj;
|
||||
}
|
||||
console.warn(
|
||||
'Failed to clone object, returning original (may cause issues)',
|
||||
obj,
|
||||
);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (divRef.value) {
|
||||
// 净化 props.data,避免响应式对象或函数污染
|
||||
const cleanedProps = { ...props } as any;
|
||||
if ('data' in cleanedProps && cleanedProps.data != null) {
|
||||
cleanedProps.data = safeDeepClone(cleanedProps.data);
|
||||
}
|
||||
|
||||
tinyflow = new TinyflowNative({
|
||||
...cleanedProps,
|
||||
element: divRef.value
|
||||
});
|
||||
if (divRef.value) {
|
||||
// 净化 props.data,避免响应式对象或函数污染
|
||||
const cleanedProps = { ...props } as any;
|
||||
if ('data' in cleanedProps && cleanedProps.data != null) {
|
||||
cleanedProps.data = safeDeepClone(cleanedProps.data);
|
||||
}
|
||||
|
||||
tinyflow = new TinyflowNative({
|
||||
...cleanedProps,
|
||||
element: divRef.value,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (tinyflow) {
|
||||
tinyflow.destroy();
|
||||
tinyflow = null;
|
||||
}
|
||||
if (tinyflow) {
|
||||
tinyflow.destroy();
|
||||
tinyflow = null;
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.theme,
|
||||
(theme) => {
|
||||
if (tinyflow) {
|
||||
tinyflow.setTheme(theme || 'light');
|
||||
}
|
||||
() => props.theme,
|
||||
(theme) => {
|
||||
if (tinyflow) {
|
||||
tinyflow.setTheme(theme || 'light');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const getData = () => {
|
||||
if (tinyflow) {
|
||||
return tinyflow.getData();
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return null;
|
||||
if (tinyflow) {
|
||||
return tinyflow.getData();
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return null;
|
||||
};
|
||||
|
||||
const getInstance = () => {
|
||||
if (tinyflow) {
|
||||
return tinyflow;
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return null;
|
||||
if (tinyflow) {
|
||||
return tinyflow;
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return null;
|
||||
};
|
||||
|
||||
const focusNode = async (nodeId: string, options?: { duration?: number; zoom?: number }) => {
|
||||
if (tinyflow) {
|
||||
return tinyflow.focusNode(nodeId, options);
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return false;
|
||||
const focusNode = async (
|
||||
nodeId: string,
|
||||
options?: { duration?: number; zoom?: number },
|
||||
) => {
|
||||
if (tinyflow) {
|
||||
return tinyflow.focusNode(nodeId, options);
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getData,
|
||||
getInstance,
|
||||
focusNode
|
||||
getData,
|
||||
getInstance,
|
||||
focusNode,
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {createApp} from 'vue'
|
||||
import App from './Tinyflow.vue'
|
||||
import { createApp } from 'vue';
|
||||
import App from './Tinyflow.vue';
|
||||
|
||||
createApp(App).mount('#app')
|
||||
createApp(App).mount('#app');
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "node",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "node",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
import {defineConfig} from 'vite';
|
||||
import {resolve} from 'path';
|
||||
import { defineConfig } from 'vite';
|
||||
import { resolve } from 'path';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import dts from 'vite-plugin-dts';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
emptyOutDir: true,
|
||||
minify: true,
|
||||
sourcemap: true,
|
||||
cssCodeSplit: true,
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'src/index.ts'),
|
||||
cssFileName: 'index',
|
||||
fileName: (format) => {
|
||||
return format === 'umd' ? 'index.umd.js' : 'index.js';
|
||||
},
|
||||
formats: ['es', 'umd'],
|
||||
name: 'Tinyflow'
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['vue'], // 排除 Vue 作为外部依赖
|
||||
output: {
|
||||
globals: {
|
||||
vue: 'Vue'
|
||||
}
|
||||
}
|
||||
}
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
emptyOutDir: true,
|
||||
minify: true,
|
||||
sourcemap: true,
|
||||
cssCodeSplit: true,
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'src/index.ts'),
|
||||
cssFileName: 'index',
|
||||
fileName: (format) => {
|
||||
return format === 'umd' ? 'index.umd.js' : 'index.js';
|
||||
},
|
||||
formats: ['es', 'umd'],
|
||||
name: 'Tinyflow',
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
dts({
|
||||
rollupTypes: true,
|
||||
tsconfigPath: './tsconfig.app.json'
|
||||
})
|
||||
]
|
||||
rollupOptions: {
|
||||
external: ['vue'], // 排除 Vue 作为外部依赖
|
||||
output: {
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
dts({
|
||||
rollupTypes: true,
|
||||
tsconfigPath: './tsconfig.app.json',
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user