diff --git a/electron/config/bin.js b/electron/config/bin.js index d3c0487..74b2d5e 100644 --- a/electron/config/bin.js +++ b/electron/config/bin.js @@ -49,7 +49,17 @@ module.exports = { directory: './go', cmd: 'go', args: ['build', '-o=../build/extraResources/goapp'], - } + }, + python_w: { + directory: './python', + cmd: 'pyinstaller', + args: ['-n=pyapp', '-F', './main.py'], + }, + python_m: { + directory: './python', + cmd: 'pyinstaller', + args: ['-n=pyapp', '-F', './main.py'], + }, }, /** @@ -77,6 +87,10 @@ module.exports = { dist: './public/images', target: './go/public/images' }, + python_dist: { + dist: './python/dist', + target: './build/extraResources/py' + }, }, /** @@ -124,6 +138,12 @@ module.exports = { directory: './', cmd: 'npm', args: ['-v'], - } + }, + python: { + directory: './python', + cmd: 'python', + args: ['./main.py', '--port=7074'], + stdio: "inherit", // ignore + }, }, }; \ No newline at end of file diff --git a/electron/config/config.default.js b/electron/config/config.default.js index 41aec1b..744a262 100644 --- a/electron/config/config.default.js +++ b/electron/config/config.default.js @@ -127,7 +127,15 @@ module.exports = (appInfo) => { name: 'goapp', args: ['--port=7073'], appExit: true, - } + }, + python: { + enable: false, + name: 'pyapp', + cmd: './py/pyapp', + directory: './py', + args: ['--port=7074'], + appExit: true, + }, }; /** diff --git a/electron/config/config.local.js b/electron/config/config.local.js index 49fe802..efe2b7c 100644 --- a/electron/config/config.local.js +++ b/electron/config/config.local.js @@ -41,7 +41,16 @@ module.exports = (appInfo) => { directory: './go', args: ['run', './main.go', '--env=dev','--basedir=../', '--port=7073'], appExit: true, - } + }, + python: { + enable: true, + name: 'pyapp', + cmd: 'python', + directory: './python', + args: ['./main.py', '--port=7074'], + stdio: "inherit", + appExit: true, + }, }; return { diff --git a/electron/controller/cross.js b/electron/controller/cross.js index 8b40b9e..b67f85a 100644 --- a/electron/controller/cross.js +++ b/electron/controller/cross.js @@ -67,6 +67,8 @@ class CrossController extends Controller { Services.get('cross').createGoServer(); } else if (program == 'java') { Services.get('cross').createJavaServer(); + } else if (program == 'python') { + Services.get('cross').createPythonServer(); } return; diff --git a/electron/service/cross.js b/electron/service/cross.js index 70ac15d..733fcb4 100644 --- a/electron/service/cross.js +++ b/electron/service/cross.js @@ -71,6 +71,33 @@ class CrossService extends Service { return; } + + /** + * create python service + * In the default configuration, services can be started with applications. + * Developers can turn off the configuration and create it manually. + */ + async createPythonServer() { + // method 1: Use the default Settings + //const entity = await Cross.run(serviceName); + + // method 2: Use custom configuration + const serviceName = "python"; + const opt = { + name: 'pyapp', + cmd: path.join(Ps.getExtraResourcesDir(), 'py', 'pyapp'), + directory: path.join(Ps.getExtraResourcesDir(), 'py'), + args: ['--port=7074'], + windowsExtname: true, + appExit: true, + } + const entity = await Cross.run(serviceName, opt); + Log.info('server name:', entity.name); + Log.info('server config:', entity.config); + Log.info('server url:', entity.getUrl()); + + return; + } } CrossService.toString = () => '[class CrossService]'; diff --git a/frontend/src/router/routerMap.js b/frontend/src/router/routerMap.js index 9506a92..2c4d39a 100644 --- a/frontend/src/router/routerMap.js +++ b/frontend/src/router/routerMap.js @@ -171,7 +171,12 @@ const constantRouterMap = [ path: '/cross/java/index', name: 'CrossJavaIndex', component: () => import('@/views/cross/java/Index.vue') - } + }, + { + path: '/cross/python/index', + name: 'CrossPythonIndex', + component: () => import('@/views/cross/python/Index.vue') + }, ] }, ] diff --git a/frontend/src/router/subMenu.js b/frontend/src/router/subMenu.js index 5646f9b..3201e7e 100644 --- a/frontend/src/router/subMenu.js +++ b/frontend/src/router/subMenu.js @@ -142,6 +142,12 @@ export default { title: 'java服务', pageName: 'CrossJavaIndex', params: {} - }, + }, + 'menu_120' : { + icon: 'profile', + title: 'python服务', + pageName: 'CrossPythonIndex', + params: {} + }, }, } diff --git a/frontend/src/views/cross/python/Index.vue b/frontend/src/views/cross/python/Index.vue new file mode 100644 index 0000000..cd56a23 --- /dev/null +++ b/frontend/src/views/cross/python/Index.vue @@ -0,0 +1,117 @@ + + + + \ No newline at end of file diff --git a/package.json b/package.json index 6b8aec6..4b091f7 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,13 @@ "dev-frontend": "ee-bin dev --serve=frontend", "dev-electron": "ee-bin dev --serve=electron", "dev-go": "ee-bin dev --serve=go", + "dev-python": "ee-bin exec --cmds=python", "build-frontend": "ee-bin build --cmds=frontend && ee-bin move --flag=frontend_dist", "build-go-w": "ee-bin build --cmds=go_w", "build-go-m": "ee-bin build --cmds=go_m", "build-go-l": "ee-bin build --cmds=go_l", + "build-python-w": "ee-bin build --cmds=python_w && ee-bin move --flag=python_dist", + "build-python-m": "ee-bin build --cmds=python_m && ee-bin move --flag=python_dist", "start": "ee-bin start", "move": "ee-bin move --flag=go_static,go_config,go_package,go_images", "rd": "ee-bin move --flag=frontend_dist", diff --git a/python/fastapi-demo.py b/python/fastapi-demo.py new file mode 100644 index 0000000..586df9e --- /dev/null +++ b/python/fastapi-demo.py @@ -0,0 +1,28 @@ +import argparse +import uvicorn +from fastapi import FastAPI + +app = FastAPI() + +# argparse +parser = argparse.ArgumentParser(description='Process some integers.') +parser.add_argument('--port', type=int, default=7074, help='The port number.') +args = parser.parse_args() + +@app.get("/") +async def index(): + return {"message": "Hello World"} + +@app.get("/api/hello") +async def hello(): + return { + "app_name": "FastAPI框架学习", + "app_version": "v0.0.1" + } + +if __name__ == "__main__": + # uvicorn会多创建一个进程,并且stdio独立于控制台,如果(开发时)出现进程没有关闭,可尝试关闭终端 + uvicorn.run(app, host="127.0.0.1", port=args.port) + +# 控制台默认关闭输出信息,如果想要查看控制台输出,请单独启动服务 npm run dev-python +print("python server is running at port:", args.port) \ No newline at end of file diff --git a/python/main.py b/python/main.py new file mode 100644 index 0000000..14e1e84 --- /dev/null +++ b/python/main.py @@ -0,0 +1,57 @@ +from flask import Flask, request, jsonify +from flask_cors import CORS +import argparse +import signal +import sys + +# flask-demo + +# argparse +parser = argparse.ArgumentParser(description='Process some integers.') +parser.add_argument('--port', type=int, default=7074, help='The port number.') +args = parser.parse_args() + +app = Flask(__name__) + +# 配置 CORS,允许所有来源 +CORS(app) + +# 定义路由和处理器 +@app.route('/', methods=['GET']) +def index(): + name = request.args.get('name', 'World') + return jsonify({'message': f'Hello, {name}!'}), 200 + + +@app.route('/api/hello', methods=['GET']) +def hello(): + name = request.args.get('name', 'World') + return jsonify({'message': f'Hello, {name}!'}), 200 + +# 通过信号来退出服务,否则会出现终端显示退出后,实际进程仍在运行 +# 定义信号处理函数 +def signal_handler(sig, frame): + print("[python] [flask] Received signal to terminate the server:", sig) + sys.exit(0) + + # 关闭 Flask 应用 + # func = request.environ.get('werkzeug.server.shutdown') + # if func is None: + # func = lambda: None + # func() + + # 退出主线程 + # threading.main_thread().exit() + +# 注册信号处理函数 +signal.signal(signal.SIGTERM, signal_handler) +signal.signal(signal.SIGINT, signal_handler) + +if __name__ == '__main__': + # 以api方式启动服务会出现警告,请忽略 + app.run(port=args.port) + +# 或许flask内置的stdio与node.js stdio有冲突,导致控制台无法显示信息。 +# 如果想要查看控制台输出,请单独启动服务 npm run dev-python +print("python server is running at port:", args.port) + diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 0000000..4c606c6 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,2 @@ +Flask==3.0.2 +Flask_Cors==4.0.0 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b5765c4 Binary files /dev/null and b/requirements.txt differ