mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-01-11 17:04:13 +00:00
Fix playground bugs and remove TypeScript compiler
- Fix BUG1: JavaScript timeout with proper thread interruption using ScheduledExecutorService - Fix BUG2: Add URL regex validation before execution in playground test API - Fix BUG3: Register published parsers to CustomParserRegistry on save/update/delete - Remove TypeScript compiler functionality (tsCompiler.js, dependencies, UI) - Add password authentication for playground access - Add mobile responsive layout support - Load playground parsers on application startup
This commit is contained in:
174
web-front/MONACO_EDITOR_NPM.md
Normal file
174
web-front/MONACO_EDITOR_NPM.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Monaco Editor NPM包配置说明
|
||||
|
||||
## ✅ 已完成的配置
|
||||
|
||||
### 1. NPM包安装
|
||||
已在 `package.json` 中安装:
|
||||
- `monaco-editor`: ^0.45.0 - Monaco Editor核心包
|
||||
- `@monaco-editor/loader`: ^1.4.0 - Monaco Editor加载器
|
||||
- `monaco-editor-webpack-plugin`: ^7.1.1 - Webpack打包插件(devDependencies)
|
||||
|
||||
### 2. Webpack配置
|
||||
在 `vue.config.js` 中已配置:
|
||||
```javascript
|
||||
new MonacoEditorPlugin({
|
||||
languages: ['javascript', 'typescript', 'json'],
|
||||
features: ['coreCommands', 'find'],
|
||||
publicPath: process.env.NODE_ENV === 'production' ? './' : '/'
|
||||
})
|
||||
```
|
||||
|
||||
### 3. 组件配置
|
||||
在 `MonacoEditor.vue` 和 `Playground.vue` 中已配置:
|
||||
```javascript
|
||||
// 配置loader使用本地打包的文件,而不是CDN
|
||||
if (loader.config) {
|
||||
const vsPath = process.env.NODE_ENV === 'production'
|
||||
? './js/vs' // 生产环境使用相对路径
|
||||
: '/js/vs'; // 开发环境使用绝对路径
|
||||
|
||||
loader.config({
|
||||
paths: {
|
||||
vs: vsPath
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 工作原理
|
||||
|
||||
### 打包流程
|
||||
1. `monaco-editor-webpack-plugin` 在构建时将 Monaco Editor 文件打包到 `js/vs/` 目录
|
||||
2. `@monaco-editor/loader` 通过配置的路径加载本地文件
|
||||
3. 不再从 CDN(如 `https://cdn.jsdelivr.net`)加载
|
||||
|
||||
### 文件结构(构建后)
|
||||
```
|
||||
nfd-front/
|
||||
├── js/
|
||||
│ └── vs/
|
||||
│ ├── editor/
|
||||
│ ├── loader/
|
||||
│ ├── base/
|
||||
│ └── ...
|
||||
└── index.html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 验证方法
|
||||
|
||||
### 1. 检查网络请求
|
||||
打开浏览器开发者工具 → Network标签:
|
||||
- ✅ 应该看到请求 `/js/vs/...` 或 `./js/vs/...`
|
||||
- ❌ 不应该看到请求 `cdn.jsdelivr.net` 或其他CDN域名
|
||||
|
||||
### 2. 检查构建产物
|
||||
```bash
|
||||
cd web-front
|
||||
npm run build
|
||||
ls -la nfd-front/js/vs/
|
||||
```
|
||||
应该看到 Monaco Editor 的文件被打包到本地。
|
||||
|
||||
### 3. 离线测试
|
||||
1. 断开网络连接
|
||||
2. 访问 Playground 页面
|
||||
3. ✅ 编辑器应该正常加载(因为使用本地文件)
|
||||
4. ❌ 如果使用CDN,编辑器会加载失败
|
||||
|
||||
---
|
||||
|
||||
## 📝 修改的文件
|
||||
|
||||
1. ✅ `web-front/src/components/MonacoEditor.vue`
|
||||
- 添加了 `loader.config()` 配置,明确使用本地路径
|
||||
|
||||
2. ✅ `web-front/src/views/Playground.vue`
|
||||
- 在 `initMonacoTypes()` 中添加了相同的配置
|
||||
|
||||
3. ✅ `web-front/vue.config.js`
|
||||
- 添加了 `publicPath` 配置,确保路径正确
|
||||
|
||||
---
|
||||
|
||||
## 🚀 部署
|
||||
|
||||
### 开发环境
|
||||
```bash
|
||||
cd web-front
|
||||
npm install # 确保依赖已安装
|
||||
npm run serve
|
||||
```
|
||||
访问 `http://127.0.0.1:6444/playground`,编辑器应该从本地加载。
|
||||
|
||||
### 生产环境
|
||||
```bash
|
||||
cd web-front
|
||||
npm run build
|
||||
```
|
||||
构建后,Monaco Editor 文件会打包到 `nfd-front/js/vs/` 目录。
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 文件大小
|
||||
Monaco Editor 打包后会增加构建产物大小(约2-3MB),但这是正常的。
|
||||
|
||||
### 2. 首次加载
|
||||
- 开发环境:文件从 webpack dev server 加载
|
||||
- 生产环境:文件从本地 `js/vs/` 目录加载
|
||||
|
||||
### 3. 缓存
|
||||
浏览器会缓存 Monaco Editor 文件,更新后可能需要清除缓存。
|
||||
|
||||
---
|
||||
|
||||
## 🔧 故障排查
|
||||
|
||||
### 问题:编辑器无法加载
|
||||
**检查**:
|
||||
1. 确认 `npm install` 已执行
|
||||
2. 检查浏览器控制台是否有错误
|
||||
3. 检查 Network 标签,确认文件路径是否正确
|
||||
|
||||
### 问题:仍然从CDN加载
|
||||
**解决**:
|
||||
1. 清除浏览器缓存
|
||||
2. 确认 `loader.config()` 已正确配置
|
||||
3. 检查 `vue.config.js` 中的 `publicPath` 配置
|
||||
|
||||
### 问题:构建后路径错误
|
||||
**解决**:
|
||||
- 检查 `publicPath` 配置
|
||||
- 确认生产环境的相对路径 `./js/vs` 正确
|
||||
|
||||
---
|
||||
|
||||
## ✅ 优势
|
||||
|
||||
1. **离线可用** - 不依赖外部CDN
|
||||
2. **加载速度** - 本地文件通常比CDN更快
|
||||
3. **版本控制** - 使用固定版本的Monaco Editor
|
||||
4. **安全性** - 不依赖第三方CDN服务
|
||||
5. **稳定性** - CDN故障不影响使用
|
||||
|
||||
---
|
||||
|
||||
**配置状态**: ✅ 已完成
|
||||
**验证状态**: ⚠️ 待测试
|
||||
**建议**: 运行 `npm run build` 并检查构建产物
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"monaco-editor": "^0.45.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"splitpanes": "^4.0.4",
|
||||
"typescript": "^5.9.3",
|
||||
"vue": "^3.5.12",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-router": "^4.5.1",
|
||||
|
||||
@@ -170,54 +170,4 @@ export const playgroundApi = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存TypeScript代码及其编译结果
|
||||
*/
|
||||
async saveTypeScriptCode(parserId, tsCode, es5Code, compileErrors, compilerVersion, compileOptions, isValid) {
|
||||
try {
|
||||
const response = await axios.post('/v2/playground/typescript', {
|
||||
parserId,
|
||||
tsCode,
|
||||
es5Code,
|
||||
compileErrors,
|
||||
compilerVersion,
|
||||
compileOptions,
|
||||
isValid
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
throw new Error(error.response?.data?.error || error.response?.data?.msg || error.message || '保存TypeScript代码失败');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据parserId获取TypeScript代码
|
||||
*/
|
||||
async getTypeScriptCode(parserId) {
|
||||
try {
|
||||
const response = await axios.get(`/v2/playground/typescript/${parserId}`);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
throw new Error(error.response?.data?.error || error.response?.data?.msg || error.message || '获取TypeScript代码失败');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新TypeScript代码
|
||||
*/
|
||||
async updateTypeScriptCode(parserId, tsCode, es5Code, compileErrors, compilerVersion, compileOptions, isValid) {
|
||||
try {
|
||||
const response = await axios.put(`/v2/playground/typescript/${parserId}`, {
|
||||
tsCode,
|
||||
es5Code,
|
||||
compileErrors,
|
||||
compilerVersion,
|
||||
compileOptions,
|
||||
isValid
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
throw new Error(error.response?.data?.error || error.response?.data?.msg || error.message || '更新TypeScript代码失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
/**
|
||||
* TypeScript编译器工具类
|
||||
* 用于在浏览器中将TypeScript代码编译为ES5 JavaScript
|
||||
*/
|
||||
|
||||
/**
|
||||
* 编译TypeScript代码为ES5 JavaScript
|
||||
* @param {string} sourceCode - TypeScript源代码
|
||||
* @param {string} fileName - 文件名(默认为script.ts)
|
||||
* @returns {Object} 编译结果 { success: boolean, code: string, errors: Array }
|
||||
*/
|
||||
export function compileToES5(sourceCode, fileName = 'script.ts') {
|
||||
try {
|
||||
// 编译选项
|
||||
const compilerOptions = {
|
||||
target: ts.ScriptTarget.ES5, // 目标版本:ES5
|
||||
module: ts.ModuleKind.None, // 不使用模块系统
|
||||
lib: ['lib.es5.d.ts', 'lib.dom.d.ts'], // 包含ES5和DOM类型定义
|
||||
removeComments: false, // 保留注释
|
||||
noEmitOnError: true, // 有错误时不生成代码
|
||||
noImplicitAny: false, // 允许隐式any类型
|
||||
strictNullChecks: false, // 不进行严格的null检查
|
||||
suppressImplicitAnyIndexErrors: true, // 抑制隐式any索引错误
|
||||
downlevelIteration: true, // 支持ES5迭代器降级
|
||||
esModuleInterop: true, // 启用ES模块互操作性
|
||||
allowJs: true, // 允许编译JavaScript文件
|
||||
checkJs: false // 不检查JavaScript文件
|
||||
};
|
||||
|
||||
// 执行编译
|
||||
const result = ts.transpileModule(sourceCode, {
|
||||
compilerOptions,
|
||||
fileName,
|
||||
reportDiagnostics: true
|
||||
});
|
||||
|
||||
// 检查是否有诊断信息(错误/警告)
|
||||
const diagnostics = result.diagnostics || [];
|
||||
const errors = diagnostics.map(diagnostic => {
|
||||
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||
let location = '';
|
||||
if (diagnostic.file && diagnostic.start !== undefined) {
|
||||
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
location = `(${line + 1},${character + 1})`;
|
||||
}
|
||||
return {
|
||||
message,
|
||||
location,
|
||||
category: ts.DiagnosticCategory[diagnostic.category],
|
||||
code: diagnostic.code
|
||||
};
|
||||
});
|
||||
|
||||
// 过滤出真正的错误(不包括警告)
|
||||
const realErrors = errors.filter(e => e.category === 'Error');
|
||||
|
||||
return {
|
||||
success: realErrors.length === 0,
|
||||
code: result.outputText || '',
|
||||
errors: errors,
|
||||
hasWarnings: errors.some(e => e.category === 'Warning'),
|
||||
sourceMap: result.sourceMapText
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
code: '',
|
||||
errors: [{
|
||||
message: error.message || '编译失败',
|
||||
location: '',
|
||||
category: 'Error',
|
||||
code: 0
|
||||
}]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查代码是否为TypeScript代码
|
||||
* 简单的启发式检查,看是否包含TypeScript特有的语法
|
||||
* @param {string} code - 代码字符串
|
||||
* @returns {boolean} 是否为TypeScript代码
|
||||
*/
|
||||
export function isTypeScriptCode(code) {
|
||||
if (!code || typeof code !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TypeScript特有的语法模式
|
||||
const tsPatterns = [
|
||||
/:\s*(string|number|boolean|any|void|never|unknown|object)\b/, // 类型注解
|
||||
/interface\s+\w+/, // interface声明
|
||||
/type\s+\w+\s*=/, // type别名
|
||||
/enum\s+\w+/, // enum声明
|
||||
/<\w+>/, // 泛型
|
||||
/implements\s+\w+/, // implements关键字
|
||||
/as\s+(string|number|boolean|any|const)/, // as类型断言
|
||||
/public|private|protected|readonly/, // 访问修饰符
|
||||
/:\s*\w+\[\]/, // 数组类型注解
|
||||
/\?\s*:/ // 可选属性
|
||||
];
|
||||
|
||||
// 如果匹配任何TypeScript特有模式,则认为是TypeScript代码
|
||||
return tsPatterns.some(pattern => pattern.test(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化编译错误信息
|
||||
* @param {Array} errors - 错误数组
|
||||
* @returns {string} 格式化后的错误信息
|
||||
*/
|
||||
export function formatCompileErrors(errors) {
|
||||
if (!errors || errors.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return errors.map((error, index) => {
|
||||
const prefix = `[${error.category}]`;
|
||||
const location = error.location ? ` ${error.location}` : '';
|
||||
const code = error.code ? ` (TS${error.code})` : '';
|
||||
return `${index + 1}. ${prefix}${location}${code}: ${error.message}`;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证编译后的代码是否为有效的ES5
|
||||
* @param {string} code - 编译后的代码
|
||||
* @returns {Object} { valid: boolean, error: string }
|
||||
*/
|
||||
export function validateES5Code(code) {
|
||||
try {
|
||||
// 尝试使用Function构造函数验证语法
|
||||
// eslint-disable-next-line no-new-func
|
||||
new Function(code);
|
||||
return { valid: true, error: null };
|
||||
} catch (error) {
|
||||
return { valid: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取代码中的元数据注释
|
||||
* @param {string} code - 代码字符串
|
||||
* @returns {Object} 元数据对象
|
||||
*/
|
||||
export function extractMetadata(code) {
|
||||
const metadata = {};
|
||||
const metaRegex = /\/\/\s*@(\w+)\s+(.+)/g;
|
||||
let match;
|
||||
|
||||
while ((match = metaRegex.exec(code)) !== null) {
|
||||
const [, key, value] = match;
|
||||
metadata[key] = value.trim();
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
export default {
|
||||
compileToES5,
|
||||
isTypeScriptCode,
|
||||
formatCompileErrors,
|
||||
validateES5Code,
|
||||
extractMetadata
|
||||
};
|
||||
@@ -57,11 +57,10 @@
|
||||
<div class="card-header">
|
||||
<div class="header-left">
|
||||
<span class="title">JS解析器演练场</span>
|
||||
<!-- 语言选择器 -->
|
||||
<el-radio-group v-model="codeLanguage" size="small" style="margin-left: 15px;" @change="onLanguageChange">
|
||||
<el-radio-button :label="LANGUAGE.JAVASCRIPT">JavaScript</el-radio-button>
|
||||
<el-radio-button :label="LANGUAGE.TYPESCRIPT">TypeScript</el-radio-button>
|
||||
</el-radio-group>
|
||||
<!-- 语言显示(仅支持JavaScript) -->
|
||||
<span style="margin-left: 15px; color: var(--el-text-color-secondary); font-size: 12px;">
|
||||
JavaScript (ES5)
|
||||
</span>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<!-- 主要操作 -->
|
||||
@@ -536,7 +535,6 @@ import 'splitpanes/dist/splitpanes.css';
|
||||
import MonacoEditor from '@/components/MonacoEditor.vue';
|
||||
import { playgroundApi } from '@/utils/playgroundApi';
|
||||
import { configureMonacoTypes, loadTypesFromApi } from '@/utils/monacoTypes';
|
||||
import { compileToES5, isTypeScriptCode, formatCompileErrors } from '@/utils/tsCompiler';
|
||||
import JsonViewer from 'vue3-json-viewer';
|
||||
|
||||
export default {
|
||||
@@ -550,15 +548,11 @@ export default {
|
||||
setup() {
|
||||
// 语言常量
|
||||
const LANGUAGE = {
|
||||
JAVASCRIPT: 'JavaScript',
|
||||
TYPESCRIPT: 'TypeScript'
|
||||
JAVASCRIPT: 'JavaScript'
|
||||
};
|
||||
|
||||
const editorRef = ref(null);
|
||||
const jsCode = ref('');
|
||||
const codeLanguage = ref(LANGUAGE.JAVASCRIPT); // 新增:代码语言选择
|
||||
const compiledES5Code = ref(''); // 新增:编译后的ES5代码
|
||||
const compileStatus = ref({ success: true, errors: [] }); // 新增:编译状态
|
||||
|
||||
// ===== 加载和认证状态 =====
|
||||
const loading = ref(true);
|
||||
@@ -699,90 +693,6 @@ function parseById(shareLinkInfo, http, logger) {
|
||||
return "https://example.com/download?id=" + fileId;
|
||||
}`;
|
||||
|
||||
// TypeScript示例代码模板
|
||||
const exampleTypeScriptCode = `// ==UserScript==
|
||||
// @name TypeScript示例解析器
|
||||
// @type ts_example_parser
|
||||
// @displayName TypeScript示例网盘
|
||||
// @description 使用TypeScript实现的示例解析器
|
||||
// @match https?://example\.com/s/(?<KEY>\\w+)
|
||||
// @author yourname
|
||||
// @version 1.0.0
|
||||
// ==/UserScript==
|
||||
|
||||
/**
|
||||
* 解析单个文件下载链接
|
||||
* @param shareLinkInfo - 分享链接信息
|
||||
* @param http - HTTP客户端
|
||||
* @param logger - 日志对象
|
||||
* @returns 下载链接
|
||||
*/
|
||||
async function parse(
|
||||
shareLinkInfo: any,
|
||||
http: any,
|
||||
logger: any
|
||||
): Promise<string> {
|
||||
const url: string = shareLinkInfo.getShareUrl();
|
||||
logger.info(\`开始解析: \${url}\`);
|
||||
|
||||
// 使用fetch API (已在后端实现polyfill)
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(\`请求失败: \${response.status}\`);
|
||||
}
|
||||
|
||||
const html: string = await response.text();
|
||||
|
||||
// 这里添加你的解析逻辑
|
||||
// 例如:使用正则表达式提取下载链接
|
||||
const match = html.match(/download-url="([^"]+)"/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
return "https://example.com/download/file.zip";
|
||||
} catch (error: any) {
|
||||
logger.error(\`解析失败: \${error.message}\`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析文件列表(可选)
|
||||
*/
|
||||
async function parseFileList(
|
||||
shareLinkInfo: any,
|
||||
http: any,
|
||||
logger: any
|
||||
): Promise<any[]> {
|
||||
const dirId: string = shareLinkInfo.getOtherParam("dirId") || "0";
|
||||
logger.info(\`解析文件列表,目录ID: \${dirId}\`);
|
||||
|
||||
const fileList: any[] = [];
|
||||
|
||||
// 这里添加你的文件列表解析逻辑
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件ID获取下载链接(可选)
|
||||
*/
|
||||
async function parseById(
|
||||
shareLinkInfo: any,
|
||||
http: any,
|
||||
logger: any
|
||||
): Promise<string> {
|
||||
const paramJson = shareLinkInfo.getOtherParam("paramJson");
|
||||
const fileId: string = paramJson.fileId;
|
||||
logger.info(\`根据ID解析: \${fileId}\`);
|
||||
|
||||
// 这里添加你的按ID解析逻辑
|
||||
|
||||
return \`https://example.com/download?id=\${fileId}\`;
|
||||
}`;
|
||||
|
||||
// 编辑器主题
|
||||
const editorTheme = computed(() => {
|
||||
return isDarkMode.value ? 'vs-dark' : 'vs';
|
||||
@@ -880,15 +790,6 @@ async function parseById(
|
||||
jsCode.value = exampleCode;
|
||||
}
|
||||
|
||||
// 加载保存的语言选择
|
||||
const savedLanguage = localStorage.getItem('playground_language');
|
||||
if (savedLanguage) {
|
||||
codeLanguage.value = savedLanguage;
|
||||
}
|
||||
|
||||
setProgress(40, '准备加载TypeScript编译器...');
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
setProgress(50, '初始化Monaco Editor类型定义...');
|
||||
await initMonacoTypes();
|
||||
|
||||
@@ -965,8 +866,8 @@ async function parseById(
|
||||
|
||||
// 加载示例代码
|
||||
const loadTemplate = () => {
|
||||
jsCode.value = codeLanguage.value === LANGUAGE.TYPESCRIPT ? exampleTypeScriptCode : exampleCode;
|
||||
ElMessage.success(`已加载${codeLanguage.value}示例代码`);
|
||||
jsCode.value = exampleCode;
|
||||
ElMessage.success('已加载JavaScript示例代码');
|
||||
};
|
||||
|
||||
// 格式化代码
|
||||
@@ -1005,59 +906,6 @@ async function parseById(
|
||||
};
|
||||
|
||||
// 语言切换处理
|
||||
const onLanguageChange = (newLanguage) => {
|
||||
console.log('切换语言:', newLanguage);
|
||||
// 保存当前语言选择
|
||||
localStorage.setItem('playground_language', newLanguage);
|
||||
|
||||
// 如果切换到TypeScript,尝试编译当前代码
|
||||
if (newLanguage === 'TypeScript' && jsCode.value.trim()) {
|
||||
compileTypeScriptCode();
|
||||
}
|
||||
};
|
||||
|
||||
// 编译TypeScript代码
|
||||
const compileTypeScriptCode = () => {
|
||||
if (!jsCode.value.trim()) {
|
||||
compiledES5Code.value = '';
|
||||
compileStatus.value = { success: true, errors: [] };
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = compileToES5(jsCode.value);
|
||||
compiledES5Code.value = result.code;
|
||||
compileStatus.value = {
|
||||
success: result.success,
|
||||
errors: result.errors || [],
|
||||
hasWarnings: result.hasWarnings
|
||||
};
|
||||
|
||||
if (!result.success) {
|
||||
const errorMsg = formatCompileErrors(result.errors);
|
||||
ElMessage.error({
|
||||
message: '编译失败,请检查代码语法\n' + errorMsg,
|
||||
duration: 5000,
|
||||
showClose: true
|
||||
});
|
||||
} else if (result.hasWarnings) {
|
||||
ElMessage.warning({
|
||||
message: '编译成功,但存在警告',
|
||||
duration: 3000
|
||||
});
|
||||
} else {
|
||||
ElMessage.success('编译成功');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('编译错误:', error);
|
||||
compileStatus.value = {
|
||||
success: false,
|
||||
errors: [{ message: error.message || '编译失败' }]
|
||||
};
|
||||
ElMessage.error('编译失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// 执行测试
|
||||
const executeTest = async () => {
|
||||
if (!jsCode.value.trim()) {
|
||||
@@ -1101,67 +949,9 @@ async function parseById(
|
||||
testResult.value = null;
|
||||
consoleLogs.value = []; // 清空控制台
|
||||
|
||||
// 确定要执行的代码(TypeScript需要先编译)
|
||||
let codeToExecute = jsCode.value;
|
||||
|
||||
// 优先使用显式语言选择,如果是JavaScript模式但代码是TS,给出提示
|
||||
if (codeLanguage.value === LANGUAGE.TYPESCRIPT) {
|
||||
// TypeScript模式:始终编译
|
||||
try {
|
||||
const compileResult = compileToES5(jsCode.value);
|
||||
|
||||
if (!compileResult.success) {
|
||||
testing.value = false;
|
||||
const errorMsg = formatCompileErrors(compileResult.errors);
|
||||
ElMessage.error({
|
||||
message: 'TypeScript编译失败,请修复错误后再试\n' + errorMsg,
|
||||
duration: 5000,
|
||||
showClose: true
|
||||
});
|
||||
testResult.value = {
|
||||
success: false,
|
||||
error: 'TypeScript编译失败',
|
||||
stackTrace: errorMsg,
|
||||
logs: [],
|
||||
executionTime: 0
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用编译后的ES5代码
|
||||
codeToExecute = compileResult.code;
|
||||
compiledES5Code.value = compileResult.code;
|
||||
compileStatus.value = {
|
||||
success: true,
|
||||
errors: compileResult.errors || [],
|
||||
hasWarnings: compileResult.hasWarnings
|
||||
};
|
||||
|
||||
if (compileResult.hasWarnings) {
|
||||
ElMessage.warning('编译成功,但存在警告');
|
||||
}
|
||||
} catch (error) {
|
||||
testing.value = false;
|
||||
ElMessage.error('TypeScript编译失败: ' + error.message);
|
||||
testResult.value = {
|
||||
success: false,
|
||||
error: 'TypeScript编译失败: ' + error.message,
|
||||
logs: [],
|
||||
executionTime: 0
|
||||
};
|
||||
return;
|
||||
}
|
||||
} else if (isTypeScriptCode(jsCode.value)) {
|
||||
// JavaScript模式但检测到TypeScript语法:给出提示
|
||||
ElMessage.warning({
|
||||
message: '检测到TypeScript语法,建议切换到TypeScript模式',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await playgroundApi.testScript(
|
||||
codeToExecute, // 使用编译后的代码或原始JS代码
|
||||
jsCode.value, // 直接使用JavaScript代码
|
||||
testParams.value.shareUrl,
|
||||
testParams.value.pwd,
|
||||
testParams.value.method
|
||||
@@ -1610,9 +1400,6 @@ curl "${baseUrl}/json/parser?url=${encodeURIComponent(exampleUrl)}"</pre>
|
||||
LANGUAGE,
|
||||
editorRef,
|
||||
jsCode,
|
||||
codeLanguage,
|
||||
compiledES5Code,
|
||||
compileStatus,
|
||||
testParams,
|
||||
testResult,
|
||||
testing,
|
||||
@@ -1635,8 +1422,6 @@ curl "${baseUrl}/json/parser?url=${encodeURIComponent(exampleUrl)}"</pre>
|
||||
isMobile,
|
||||
updateIsMobile,
|
||||
onCodeChange,
|
||||
onLanguageChange,
|
||||
compileTypeScriptCode,
|
||||
loadTemplate,
|
||||
formatCode,
|
||||
saveCode,
|
||||
|
||||
Reference in New Issue
Block a user