feat: add python feature

This commit is contained in:
fly6516 2024-12-29 17:25:34 +08:00
parent 3093f7e624
commit 46493cf1b4
8 changed files with 3674 additions and 57 deletions

3503
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}

View File

@ -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,

View File

@ -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
View 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
View File

@ -0,0 +1,6 @@
body {
font-family: Arial, sans-serif;
background-color: lightblue;
text-align: center;
padding: 20px;
}

View File

@ -13,6 +13,7 @@
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"allowSyntheticDefaultImports": true, //
"plugins": [
{
"name": "next"

60
webpack.config.js Normal file
View 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', // 开启源码映射,方便调试
};