feat: add python feature
This commit is contained in:
parent
3093f7e624
commit
46493cf1b4
3503
package-lock.json
generated
3503
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev-web": "webpack serve --open",
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
@ -20,10 +21,16 @@
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/webpack-env": "^1.18.5",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "15.1.3",
|
||||
"html-webpack-plugin": "^5.6.3",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5"
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.7.2",
|
||||
"webpack": "^5.97.1",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "^5.2.0"
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import Docker from 'dockerode';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
// 创建 Docker 客户端实例
|
||||
const docker = new Docker();
|
||||
|
||||
@ -15,14 +16,20 @@ export const runCode = async (params: { code: string; language: string }) => {
|
||||
throw new Error('Code and language are required.');
|
||||
}
|
||||
|
||||
const supportedLanguages = ['c', 'java'];
|
||||
const supportedLanguages = ['c', 'java', 'python'];
|
||||
if (!supportedLanguages.includes(language)) {
|
||||
throw new Error(`Language '${language}' is not supported. Only 'c' and 'java' are supported.`);
|
||||
throw new Error(`Language '${language}' is not supported. Only 'c', 'java', and 'python' are supported.`);
|
||||
}
|
||||
|
||||
// 根据语言选择文件名和编译命令
|
||||
const fileName = language === 'c' ? 'main.c' : 'Main.java';
|
||||
const compileCmd = language === 'c' ? 'gcc main.c -o main && ./main' : 'javac Main.java && java Main';
|
||||
// 根据语言选择文件名和编译/运行命令
|
||||
const fileName =
|
||||
language === 'c' ? 'main.c' :
|
||||
language === 'java' ? 'Main.java' :
|
||||
'script.py';
|
||||
const runCmd =
|
||||
language === 'c' ? 'gcc main.c -o main && ./main' :
|
||||
language === 'java' ? 'javac Main.java && java Main' :
|
||||
'python3 script.py';
|
||||
|
||||
// 创建临时目录用于存储代码文件
|
||||
const tempDir = path.join('/tmp', `${Date.now()}`);
|
||||
@ -35,7 +42,7 @@ export const runCode = async (params: { code: string; language: string }) => {
|
||||
// 创建并启动 Docker 容器
|
||||
const container = await docker.createContainer({
|
||||
Image: 'fly6516.synology.me:8080/multilang:latest',
|
||||
Cmd: ['sh', '-c', compileCmd],
|
||||
Cmd: ['sh', '-c', runCmd],
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Tty: false,
|
||||
|
122
src/app/page.tsx
122
src/app/page.tsx
@ -1,62 +1,86 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { runCode } from '@/actions'; // 导入 Server Action
|
||||
import { runCode } from '@/actions'; // 导入 Server Action
|
||||
|
||||
import './styles.css'; // 引入样式
|
||||
|
||||
const root = document.getElementById('root');
|
||||
if (root) {
|
||||
root.innerHTML = 'Hello, world!';
|
||||
}
|
||||
|
||||
/// <reference types="webpack-env" />
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept(() => {
|
||||
console.log('HMR is working!');
|
||||
});
|
||||
}
|
||||
|
||||
// 启用 HMR
|
||||
if (module.hot) {
|
||||
module.hot.accept('./styles.css', () => {
|
||||
console.log('CSS updated!');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const CodeRunner = () => {
|
||||
const [code, setCode] = useState('');
|
||||
const [language, setLanguage] = useState('c');
|
||||
const [output, setOutput] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [code, setCode] = useState('');
|
||||
const [language, setLanguage] = useState('c'); // 默认语言为 C
|
||||
const [output, setOutput] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const runCodeHandler = async () => {
|
||||
try {
|
||||
// 调用 Server Action 执行代码
|
||||
const result = await runCode({ code, language });
|
||||
const runCodeHandler = async () => {
|
||||
try {
|
||||
// 调用 Server Action 执行代码
|
||||
const result = await runCode({ code, language });
|
||||
|
||||
setOutput(result.output);
|
||||
setError('');
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
setOutput('');
|
||||
}
|
||||
};
|
||||
setOutput(result.output || ''); // 如果没有输出,设置为空字符串
|
||||
setError(result.error || ''); // 如果没有错误,设置为空字符串
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
setOutput('');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Code Runner</h1>
|
||||
<textarea
|
||||
value={code}
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
placeholder="Write your code here"
|
||||
rows={10}
|
||||
cols={50}
|
||||
/>
|
||||
return (
|
||||
<div>
|
||||
<label>
|
||||
Language:
|
||||
<select value={language} onChange={(e) => setLanguage(e.target.value)}>
|
||||
<option value="c">C</option>
|
||||
<option value="java">Java</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<button onClick={runCodeHandler}>Run Code</button>
|
||||
<h1>Code Runner</h1>
|
||||
<textarea
|
||||
value={code}
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
placeholder="Write your code here"
|
||||
rows={10}
|
||||
cols={50}
|
||||
/>
|
||||
<div>
|
||||
<label>
|
||||
Language:
|
||||
<select value={language} onChange={(e) => setLanguage(e.target.value)}>
|
||||
<option value="c">C</option>
|
||||
<option value="java">Java</option>
|
||||
<option value="python">Python</option> {/* 添加 Python */}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<button onClick={runCodeHandler}>Run Code</button>
|
||||
|
||||
{output && (
|
||||
<div>
|
||||
<h3>Output:</h3>
|
||||
<pre>{output}</pre>
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div>
|
||||
<h3>Error:</h3>
|
||||
<pre>{error}</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
{output && (
|
||||
<div>
|
||||
<h3>Output:</h3>
|
||||
<pre>{output}</pre>
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div>
|
||||
<h3>Error:</h3>
|
||||
<pre>{error}</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeRunner;
|
||||
|
11
src/index.html
Normal file
11
src/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Webpack HMR</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
6
src/style.css
Normal file
6
src/style.css
Normal file
@ -0,0 +1,6 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: lightblue;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"allowSyntheticDefaultImports": true, // 允许合成默认导入
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
|
60
webpack.config.js
Normal file
60
webpack.config.js
Normal file
@ -0,0 +1,60 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成 HTML 文件
|
||||
|
||||
module.exports = {
|
||||
// 入口文件
|
||||
entry: './src/app/page.tsx', // 将入口文件指定为 page.tsx
|
||||
|
||||
// 输出配置
|
||||
output: {
|
||||
filename: 'bundle.js', // 打包后的文件名
|
||||
path: path.resolve(__dirname, 'dist'), // 输出文件的目录
|
||||
},
|
||||
|
||||
// 模块解析
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.json'], // 支持 .ts, .tsx, .js, .json 文件
|
||||
},
|
||||
|
||||
// 模块加载规则
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/, // 匹配 TypeScript 和 JSX 文件
|
||||
use: 'ts-loader', // 使用 ts-loader 转换 TypeScript 为 JavaScript
|
||||
exclude: /node_modules/, // 排除 node_modules 目录
|
||||
},
|
||||
{
|
||||
test: /\.css$/, // 匹配 CSS 文件
|
||||
use: ['style-loader', 'css-loader'], // 使用 style-loader 和 css-loader 加载 CSS 文件
|
||||
},
|
||||
{
|
||||
test: /\.(jpg|jpeg|png|gif|svg)$/, // 匹配图片文件
|
||||
use: ['file-loader'], // 使用 file-loader 处理图片
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// 插件
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin(), // 启用热更新插件
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/index.html', // 自动生成 HTML 文件
|
||||
filename: 'index.html', // 生成的文件名
|
||||
}),
|
||||
],
|
||||
|
||||
// 开发服务器配置
|
||||
devServer: {
|
||||
static: path.join(__dirname, 'dist'), // 使用 static 配置替代 contentBase
|
||||
hot: true, // 启用热更新
|
||||
open: true, // 自动打开浏览器
|
||||
port: 8080, // 设置开发服务器端口
|
||||
historyApiFallback: true, // 支持单页应用(SPA)
|
||||
},
|
||||
|
||||
// 开发模式设置
|
||||
mode: 'development', // 开发模式
|
||||
devtool: 'source-map', // 开启源码映射,方便调试
|
||||
};
|
Loading…
Reference in New Issue
Block a user