添加一些数据

This commit is contained in:
yuding
2026-04-21 15:07:49 +08:00
parent d60cc4448d
commit aeb4c990ad
24 changed files with 39086 additions and 26411 deletions

9
demo-next/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
node_modules/
.next/
dist/
*.log
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

108
demo-next/README.md Normal file
View File

@@ -0,0 +1,108 @@
# iFlow Engine Next.js Demo
这是一个使用 Next.js 15 + React 19 + TypeScript 的演示项目,展示如何在现代 React 框架中集成 iFlow Engine BIM 引擎 SDK。
## 前置要求
1. 确保父项目已经构建完成:
```bash
cd ..
npm run build
```
2. 复制 SDK 文件到 public 目录:
```bash
npm run copy-sdk
```
3. 安装依赖:
```bash
npm install
```
## 运行
### 开发模式
```bash
npm run dev
```
服务器会在 `http://localhost:3000` 启动。
### 构建
```bash
npm run build
```
构建后的静态文件会在 `dist` 目录中。
### 预览构建结果
```bash
npm start
```
## 项目结构
```
demo-next/
├── app/ # Next.js App Router
│ ├── layout.tsx # 根布局
│ ├── page.tsx # 主页面
│ └── globals.css # 全局样式
├── components/ # React 组件
│ ├── BimViewer.tsx # BIM 引擎封装组件
│ └── ControlPanel.tsx # 控制面板组件
├── public/ # 静态资源
│ ├── lib/ # SDK 文件目录
│ │ ├── iflow-engine.umd.js
│ │ ├── iflow-engine.umd.js.map
│ │ └── iflow-engine.es.js
│ └── model/ # 3D 模型文件
├── package.json # 项目配置
├── tsconfig.json # TypeScript 配置
├── next.config.js # Next.js 配置
└── README.md # 说明文档
```
## 核心功能
- 🌍 **语言切换**: 支持中文/英文切换
- 🪟 **弹窗测试**: 测试对话框组件
- 🛠️ **工具栏控制**: 显示/隐藏工具栏和标签
- 🎨 **主题切换**: 深色/浅色/自定义主题
- 🎮 **3D 引擎**: 初始化引擎、加载模型、暂停/恢复渲染
## 使用说明
1. 点击 "初始化引擎" 按钮初始化 3D 引擎
2. 点击 "加载模型" 按钮加载默认 3D 模型(或输入自定义 URL
3. 其他功能按钮可以测试 SDK 的各种功能
## 技术栈
- Next.js 15.3
- React 19.1
- TypeScript 5.9
## 注意事项
- 确保父项目的 `dist` 目录中有构建好的 SDK 文件
- 使用 HTTP 服务器运行(不能直接打开 HTML 文件)以避免 CORS 问题
- 页面使用客户端组件('use client')因为 BIM 引擎需要浏览器环境
## 与 demo-vue 的区别
| 特性 | demo-vue | demo-next |
|------|----------|-----------|
| 框架 | Vue 3 | Next.js 15 + React 19 |
| 路由 | Vue Router | Next.js App Router |
| 样式 | Scoped CSS | CSS-in-JSX |
| 构建输出 | SPA | 静态导出 |
| TypeScript | 可选 | 默认 |
## 许可证
ISC

13
demo-next/app/globals.css Normal file
View File

@@ -0,0 +1,13 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

22
demo-next/app/layout.tsx Normal file
View File

@@ -0,0 +1,22 @@
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "iFlow Engine - Next.js Demo",
description: "iFlow Engine BIM Viewer Demo with Next.js + React",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="zh-CN">
<head>
<script src="/lib/iflow-engine.umd.js" defer></script>
</head>
<body>{children}</body>
</html>
);
}

9
demo-next/app/page.tsx Normal file
View File

@@ -0,0 +1,9 @@
import BimViewer from "@/components/BimViewer";
export default function Home() {
return (
<main style={{ width: "100vw", height: "100vh", overflow: "hidden" }}>
<BimViewer />
</main>
);
}

View File

@@ -0,0 +1,262 @@
'use client';
import { useEffect, useRef, useState, useCallback } from 'react';
import ControlPanel from './ControlPanel';
declare global {
interface Window {
IflowEngine: any;
}
}
const DEFAULT_MODEL_URL = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/';
export default function BimViewer() {
const containerRef = useRef<HTMLDivElement>(null);
const engineRef = useRef<any>(null);
const [engineStatus, setEngineStatus] = useState<string>('未初始化');
const [isLoading, setIsLoading] = useState(false);
const updateStatus = useCallback((status: string) => {
setEngineStatus(status);
}, []);
useEffect(() => {
if (!containerRef.current || typeof window === 'undefined') return;
if (!window.IflowEngine) {
console.error('SDK not found');
updateStatus('SDK 未加载');
return;
}
const Engine = window.IflowEngine.BimEngine;
const engine = new Engine(containerRef.current, { locale: 'zh-CN' });
engineRef.current = engine;
engine.rightKey.registerHandler((event: any) => {
const { x, y } = event;
return [
{
id: 'home',
label: 'toolbar.home',
icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>',
onClick: () => {
console.log('Go Home');
}
},
{
id: 'log-pos',
label: '打印坐标',
icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>',
onClick: () => {
console.log(`Clicked at: ${x}, ${y}`);
}
}
];
});
return () => {
if (engineRef.current) {
engineRef.current.destroy();
engineRef.current = null;
}
};
}, [updateStatus]);
const initEngine = useCallback(() => {
const engine = engineRef.current;
if (!engine || !engine.engine) {
alert('引擎未创建,请先等待页面加载完成');
return;
}
if (engine.engine.isInitialized()) {
alert('3D 引擎已经初始化过了');
updateStatus('已初始化');
return;
}
try {
const success = engine.engine.initialize({
backgroundColor: 0x333333,
version: 'v2',
showStats: false,
showViewCube: true
});
if (success) {
updateStatus('已初始化');
console.log('3D 引擎初始化成功');
} else {
updateStatus('初始化失败');
console.error('3D 引擎初始化失败');
}
} catch (error: any) {
updateStatus('初始化错误');
console.error('3D 引擎初始化错误:', error);
}
}, [updateStatus]);
const loadModel = useCallback((url?: string) => {
const engine = engineRef.current;
if (!engine || !engine.engine) {
alert('引擎未创建');
return;
}
if (!engine.engine.isInitialized()) {
alert('请先初始化 3D 引擎!');
return;
}
const modelUrl = url || DEFAULT_MODEL_URL;
if (!modelUrl.trim()) {
alert('请输入模型 URL');
return;
}
setIsLoading(true);
try {
engine.engine.loadModel([modelUrl], {
position: [0, 0, 0],
rotation: [0, 0, 0],
scale: [1, 1, 1]
});
console.log('模型加载请求已发送:', modelUrl);
} catch (error: any) {
console.error('模型加载错误:', error);
} finally {
setTimeout(() => setIsLoading(false), 2000);
}
}, []);
const setLang = useCallback((lang: 'zh-CN' | 'en-US') => {
if (engineRef.current) {
engineRef.current.setLocale(lang);
}
}, []);
const setTheme = useCallback((themeName: 'dark' | 'light') => {
if (engineRef.current) {
engineRef.current.setTheme(themeName);
}
}, []);
const setCustomTheme = useCallback(() => {
if (!engineRef.current) return;
engineRef.current.setCustomTheme({
name: 'red-alert',
primary: '#d32f2f',
primaryHover: '#b71c1c',
background: '#ffebee',
panelBackground: 'rgba(255, 255, 255, 0.9)',
textPrimary: '#b71c1c',
textSecondary: '#e57373',
border: '#ffcdd2',
icon: '#d32f2f',
iconActive: '#b71c1c',
componentBackground: 'rgba(255, 205, 210, 0.3)',
componentHover: 'rgba(255, 205, 210, 0.8)',
componentActive: '#e57373'
});
}, []);
const openTestDialog = useCallback(() => {
if (!engineRef.current || !engineRef.current.dialog) return;
engineRef.current.dialog.create({
title: 'dialog.testTitle',
width: 350,
height: 200,
position: 'center',
draggable: true,
resizable: true
});
}, []);
const openInfoDialog = useCallback(() => {
if (!engineRef.current || !engineRef.current.dialog) return;
engineRef.current.dialog.showInfoDialog();
}, []);
const openTreeDialog = useCallback(() => {
if (!engineRef.current || !engineRef.current.modelTree) return;
engineRef.current.modelTree.showStructTree();
}, []);
const toggleToolbar = useCallback((visible: boolean) => {
if (!engineRef.current || !engineRef.current.toolbar) return;
engineRef.current.toolbar.setVisible(visible);
}, []);
const toggleLabel = useCallback((visible: boolean) => {
if (!engineRef.current || !engineRef.current.toolbar) return;
engineRef.current.toolbar.setShowLabel(visible);
}, []);
const pauseRendering = useCallback(() => {
if (!engineRef.current?.engine?.isInitialized()) {
alert('请先初始化 3D 引擎!');
return;
}
engineRef.current.engine.pauseRendering();
console.log('渲染已暂停');
}, []);
const resumeRendering = useCallback(() => {
if (!engineRef.current?.engine?.isInitialized()) {
alert('请先初始化 3D 引擎!');
return;
}
engineRef.current.engine.resumeRendering();
console.log('渲染已恢复');
}, []);
return (
<div style={{ display: 'flex', width: '100%', height: '100%', overflow: 'hidden' }}>
<ControlPanel
engineStatus={engineStatus}
isLoading={isLoading}
onInitEngine={initEngine}
onLoadModel={loadModel}
onSetLang={setLang}
onSetTheme={setTheme}
onSetCustomTheme={setCustomTheme}
onOpenTestDialog={openTestDialog}
onOpenInfoDialog={openInfoDialog}
onOpenTreeDialog={openTreeDialog}
onToggleToolbar={toggleToolbar}
onToggleLabel={toggleLabel}
onPauseRendering={pauseRendering}
onResumeRendering={resumeRendering}
/>
<div
ref={containerRef}
style={{
flex: 1,
position: 'relative',
background: '#1a1a1a',
overflow: 'hidden'
}}
/>
{isLoading && (
<div
style={{
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
background: 'rgba(0, 0, 0, 0.8)',
color: '#fff',
padding: '20px 40px',
borderRadius: '8px',
zIndex: 9999,
fontSize: '16px'
}}
>
...
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,224 @@
'use client';
import { useState } from 'react';
interface ControlPanelProps {
engineStatus: string;
isLoading: boolean;
onInitEngine: () => void;
onLoadModel: (url?: string) => void;
onSetLang: (lang: 'zh-CN' | 'en-US') => void;
onSetTheme: (theme: 'dark' | 'light') => void;
onSetCustomTheme: () => void;
onOpenTestDialog: () => void;
onOpenInfoDialog: () => void;
onOpenTreeDialog: () => void;
onToggleToolbar: (visible: boolean) => void;
onToggleLabel: (visible: boolean) => void;
onPauseRendering: () => void;
onResumeRendering: () => void;
}
export default function ControlPanel({
engineStatus,
onInitEngine,
onLoadModel,
onSetLang,
onSetTheme,
onSetCustomTheme,
onOpenTestDialog,
onOpenInfoDialog,
onOpenTreeDialog,
onToggleToolbar,
onToggleLabel,
onPauseRendering,
onResumeRendering
}: ControlPanelProps) {
const [modelUrl, setModelUrl] = useState('');
const [isToolbarVisible, setIsToolbarVisible] = useState(true);
const [isLabelVisible, setIsLabelVisible] = useState(true);
const handleToggleToolbar = () => {
const newVisible = !isToolbarVisible;
setIsToolbarVisible(newVisible);
onToggleToolbar(newVisible);
};
const handleToggleLabel = () => {
const newVisible = !isLabelVisible;
setIsLabelVisible(newVisible);
onToggleLabel(newVisible);
};
const handleLoadModel = () => {
const url = modelUrl.trim();
onLoadModel(url || undefined);
};
const getStatusColor = () => {
switch (engineStatus) {
case '已初始化':
return '#28a745';
case '初始化失败':
case '初始化错误':
case 'SDK 未加载':
return '#dc3545';
default:
return '#666';
}
};
return (
<aside
style={{
width: '320px',
background: '#fff',
borderRight: '1px solid #e0e0e0',
padding: '20px',
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
gap: '20px',
boxShadow: '2px 0 5px rgba(0, 0, 0, 0.05)',
zIndex: 10
}}
>
<h1 style={{ fontSize: '1.4rem', color: '#333', marginBottom: '10px' }}>
iFlow Engine Demo
</h1>
<p style={{ fontSize: '0.85rem', color: '#666', marginBottom: '10px' }}>
Next.js + React
</p>
<ControlGroup title="🌍 语言 (Language)">
<ButtonGroup>
<button className="btn-primary" onClick={() => onSetLang('zh-CN')}></button>
<button className="btn-primary" onClick={() => onSetLang('en-US')}>English</button>
</ButtonGroup>
</ControlGroup>
<ControlGroup title="🪟 弹窗 (Dialog)">
<ButtonGroup>
<button onClick={onOpenTestDialog}></button>
<button onClick={onOpenInfoDialog}></button>
<button onClick={onOpenTreeDialog}></button>
</ButtonGroup>
</ControlGroup>
<ControlGroup title="🛠️ 工具栏 (Toolbar)">
<ButtonGroup>
<button onClick={handleToggleToolbar}>
{isToolbarVisible ? '隐藏工具栏' : '显示工具栏'}
</button>
<button onClick={handleToggleLabel}>
{isLabelVisible ? '隐藏标签' : '显示标签'}
</button>
</ButtonGroup>
</ControlGroup>
<ControlGroup title="🎨 样式 (Theme)">
<ButtonGroup>
<button onClick={() => onSetTheme('dark')}></button>
<button onClick={() => onSetTheme('light')}></button>
<button onClick={onSetCustomTheme}></button>
</ButtonGroup>
</ControlGroup>
<ControlGroup title="🎮 3D 引擎 (Engine)">
<ButtonGroup>
<button className="btn-primary" onClick={onInitEngine}></button>
<button className="btn-primary" onClick={handleLoadModel}></button>
</ButtonGroup>
<input
type="text"
value={modelUrl}
onChange={(e) => setModelUrl(e.target.value)}
placeholder="输入模型 URL可选"
style={{
width: '100%',
padding: '6px 8px',
fontSize: '0.85rem',
border: '1px solid #ddd',
borderRadius: '4px',
fontFamily: 'Consolas, Monaco, monospace',
outline: 'none',
marginTop: '8px'
}}
/>
<ButtonGroup style={{ marginTop: '8px' }}>
<button onClick={onPauseRendering}></button>
<button onClick={onResumeRendering}></button>
</ButtonGroup>
<div style={{ marginTop: '10px', fontSize: '0.85rem', color: '#666' }}>
: <span style={{ color: getStatusColor() }}>{engineStatus}</span>
</div>
</ControlGroup>
<style jsx>{`
button {
padding: 6px 12px;
font-size: 0.9rem;
border: 1px solid #ddd;
background: #fff;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
flex: 1 1 auto;
}
button:hover {
background: #f0f0f0;
border-color: #ccc;
}
.btn-primary {
background: #0078d4;
color: white;
border-color: #0063b1;
}
.btn-primary:hover {
background: #0063b1;
}
`}</style>
</aside>
);
}
function ControlGroup({ title, children }: { title: string; children: React.ReactNode }) {
return (
<div
style={{
background: '#f9f9f9',
padding: '15px',
borderRadius: '8px',
border: '1px solid #eee'
}}
>
<h2
style={{
fontSize: '1rem',
color: '#555',
marginBottom: '10px',
paddingBottom: '5px',
borderBottom: '2px solid #e0e0e0'
}}
>
{title}
</h2>
{children}
</div>
);
}
function ButtonGroup({ children, style }: { children: React.ReactNode; style?: React.CSSProperties }) {
return (
<div
style={{
display: 'flex',
flexWrap: 'wrap',
gap: '8px',
...style
}}
>
{children}
</div>
);
}

6
demo-next/next-env.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

9
demo-next/next.config.js Normal file
View File

@@ -0,0 +1,9 @@
const nextConfig = {
output: 'export',
distDir: 'dist',
images: {
unoptimized: true
}
};
module.exports = nextConfig;

2464
demo-next/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

25
demo-next/package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "iflow-engine-next-demo",
"version": "1.0.0",
"description": "iFlow Engine Next.js + React Demo",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"copy-sdk": "mkdir -p public/lib && cp ../dist/iflow-engine.umd.js public/lib/ && cp ../dist/iflow-engine.umd.js.map public/lib/ && cp ../dist/iflow-engine.es.js public/lib/"
},
"dependencies": {
"iflow-engine": "2.7.2",
"next": "^15.3.0",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@types/node": "^22.14.0",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"typescript": "^5.9.3"
}
}

40
demo-next/tsconfig.json Normal file
View File

@@ -0,0 +1,40 @@
{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": [
"./*"
]
},
"target": "ES2017"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
demo/texture/fill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

978
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1259,6 +1259,22 @@ export class Engine implements IBimComponent {
private static WALK_GRAVITY_KEY = 'bim-walk-gravity'; private static WALK_GRAVITY_KEY = 'bim-walk-gravity';
private static WALK_COLLISION_KEY = 'bim-walk-collision'; private static WALK_COLLISION_KEY = 'bim-walk-collision';
/**
* 获取漫游移动速度
* @returns 当前移动速度值
*/
public getWalkSpeed(): number {
if (!this._isInitialized || !this.engine?.controlModule) {
console.error('[Engine] Cannot get walk speed: engine not initialized.');
return 1;
}
if (typeof this.engine.controlModule.getMoveSpeed !== 'function') {
console.warn('[Engine] controlModule.getMoveSpeed not found, fallback to 1');
return 1;
}
return this.engine.controlModule.getMoveSpeed();
}
/** /**
* 设置漫游移动速度 * 设置漫游移动速度
* @param speed 移动速度值 * @param speed 移动速度值

View File

@@ -90,6 +90,11 @@ export class WalkControlPanel implements IBimComponent {
return { ...this.state }; return { ...this.state };
} }
public setSpeed(speed: number): void {
this.state.speed = Math.max(1, Math.min(10, speed));
this.updateSpeedDisplay();
}
// --- 私有方法 --- // --- 私有方法 ---
private createPanel(): HTMLElement { private createPanel(): HTMLElement {
@@ -145,8 +150,6 @@ export class WalkControlPanel implements IBimComponent {
// }); // });
container.appendChild(this.planViewBtn); container.appendChild(this.planViewBtn);
container.appendChild(this.pathModeBtn);
// container.appendChild(this.walkModeBtn);
return container; return container;
} }

View File

@@ -33,6 +33,10 @@ export class WalkDockPanel implements IBimComponent {
return this.panel.getState(); return this.panel.getState();
} }
public setSpeed(speed: number): void {
this.panel.setSpeed(speed);
}
public destroy(): void { public destroy(): void {
this.panel.destroy(); this.panel.destroy();
} }

File diff suppressed because one or more lines are too long

View File

@@ -35,7 +35,12 @@ export class WalkControlManager extends BaseManager {
console.log('[WalkControl] 打开漫游面板,激活第一人称模式'); console.log('[WalkControl] 打开漫游面板,激活第一人称模式');
this.engineComponent?.activateFirstPersonMode(); this.engineComponent?.activateFirstPersonMode();
const engineSpeed = this.engineComponent?.getWalkSpeed() ?? 1;
const panelSpeed = Math.round(engineSpeed / 0.1);
console.log('[WalkControl] 初始速度 - engineSpeed:', engineSpeed, 'panelSpeed:', panelSpeed);
this.panel = new WalkControlPanel({ this.panel = new WalkControlPanel({
defaultSpeed: panelSpeed,
onPlanViewToggle: (isActive) => { onPlanViewToggle: (isActive) => {
console.log('[WalkControl] 小地图:', isActive); console.log('[WalkControl] 小地图:', isActive);
this.engineComponent?.toggleMiniMap(); this.engineComponent?.toggleMiniMap();

View File

@@ -99,6 +99,11 @@ export class WalkDockManager extends BaseManager {
private onOpen(): void { private onOpen(): void {
this.engineComponent?.activateFirstPersonMode(); this.engineComponent?.activateFirstPersonMode();
this.syncMapState(); this.syncMapState();
const engineSpeed = this.engineComponent?.getWalkSpeed() ?? 1;
const panelSpeed = Math.round(engineSpeed / 0.1);
console.log('[WalkDock] 初始速度 - engineSpeed:', engineSpeed, 'panelSpeed:', panelSpeed);
this.panel?.setSpeed(panelSpeed);
} }
private onClose(): void { private onClose(): void {

View File

@@ -23,23 +23,23 @@ import type { Plugin } from 'rollup';
* *
* data URL 本身是绝对的,不需要 import.meta.url 作为 base因此这种替换是安全的。 * data URL 本身是绝对的,不需要 import.meta.url 作为 base因此这种替换是安全的。
*/ */
const fixWebpack5CompatPlugin = (): Plugin => ({ // const fixWebpack5CompatPlugin = (): Plugin => ({
name: 'fix-webpack5-compat', // name: 'fix-webpack5-compat',
renderChunk(code) { // renderChunk(code) {
// 匹配 new URL("data:...", import.meta.url).href 或 new URL('data:...', import.meta.url).href // // 匹配 new URL("data:...", import.meta.url).href 或 new URL('data:...', import.meta.url).href
const fixed = code.replace( // const fixed = code.replace(
/new URL\(["'](data:[^"']+)["'],\s*import\.meta\.url\)\.href/g, // /new URL\(["'](data:[^"']+)["'],\s*import\.meta\.url\)\.href/g,
'"$1"' // '"$1"'
); // );
if (fixed !== code) { // if (fixed !== code) {
console.log('[fix-webpack5-compat] Replaced new URL(data:..., import.meta.url) with direct data URL'); // console.log('[fix-webpack5-compat] Replaced new URL(data:..., import.meta.url) with direct data URL');
} // }
return { // return {
code: fixed, // code: fixed,
map: null, // map: null,
}; // };
}, // },
}); // });
export default defineConfig(() => { export default defineConfig(() => {
return { return {
@@ -81,9 +81,9 @@ export default defineConfig(() => {
// 禁用代码分割,将所有代码打包到一个文件 // 禁用代码分割,将所有代码打包到一个文件
inlineDynamicImports: true, inlineDynamicImports: true,
}, },
plugins: [ // plugins: [
fixWebpack5CompatPlugin(), // fixWebpack5CompatPlugin(),
], // ],
}, },
sourcemap: true, sourcemap: true,
emptyOutDir: true, emptyOutDir: true,