当前位置: 首页 > news >正文

尝试使用tauri2+Django+React的项目

前言

使用Tauri2+前端,本质是进程间的通信。并非前后端。

而想使用nw,先后端打包exe,再和前端打包成exe,并没有完成成功。

而笔者从Tauri中看到这种可能性。很有可能成功基于SeaORM+MySQL+Tauri2+Vite+React等的CRUD交互项目-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146273043在github action工作流使用nw和nw-builder打包-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146126489?spm=1001.2014.3001.5502

关于前后端整合和打包成exe文件的个人的总结和思考_python pyproject.toml 打包exe-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146140425?spm=1001.2014.3001.5501 

正文

建立tq项目

 在前面的基础上。不必细说

直入主题

关键插件

@tauri-apps/plugin-shell | Tauri - Tauri 框架https://v2.tauri.org.cn/reference/javascript/shell/这个插件,可以在Rust运行cmd,也可以在JS中运行。

后端打包成exe,比如manage.exe,应该放到什么位置?这值得思考

一段代码的启示

笔者在下面这段代码发现,打印resolveResource

import {resolveResource} from '@tauri-apps/api/path'
console.log(await resolveResource())
// F:\Users\26644\webstormProject\tq\src-tauri\target\debug

结果是xxxx/xxx/target/debug

看到这里,笔者直觉感觉到放debug目录下。

进入debug目录,笔者发现了tq.exe

第二段代码的启示

在tauri2的官网关于shell的例子

Shell | Taurihttps://v2.tauri.app/zh-cn/plugin/shell/例子如下

JS代码

import { Command } from '@tauri-apps/plugin-shell';
// 当设置 `"withGlobalTauri": true`, 你可以使用
// const { Command } = window.__TAURI__.shell;

let result = await Command.create('exec-sh', [
  '-c',
  "echo 'Hello World!'",
]).execute();
console.log(result);

 Rust许可

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    {
      "identifier": "shell:allow-execute",
      "allow": [
        {
          "name": "exec-sh",
          "cmd": "sh",
          "args": [
            "-c",
            {
              "validator": "\\S+"
            }
          ],
          "sidecar": false
        }
      ]
    }
  ]
}

代码的目的就是在sh中打印hello world。

在许可中

name:exec-sh是名字,正是第一次参数

-c:对应-c

在许可中

validator是校验器,后面的正则表达式的意思是输入的字符串必须包含至少一个非空白字符

因此,笔者模仿了代码。

许多次尝试之后

1、将manage.exe放到debug目录下

2、前端的代码如下

import { Command } from '@tauri-apps/plugin-shell';
async function startDjangoServer() {
    try {
        console.log('Starting DjangoServer');
        // 关键代码
        let result = await Command.create("jango").execute();
        // 如果执行成功,直接阻塞,不会打印下面的语句
        console.log('Django server started successfully:', result);
    } catch (error) {
        console.log(error)
        console.error('Failed to start Django server:', error);
    }
}
export default startDjangoServer;

3、许可如下

"permissions": [
    "core:default",
    "opener:default",
    "core:window:allow-show",
    "core:window:allow-hide",
    "dialog:default",
    "shell:default",
    {
      "identifier": "shell:allow-execute",
      "allow": [
        {
          "name": "jango", 
          "cmd": "powershell",
          "args": [
            "manage.exe runserver --noreload"
          ],
          "sidecar": false
        }
      ]
    }
  ]

名字叫jango。

在powershell中。

运行参数 manage.exe runserver --noreload

运行

在没有运行项目前,端口号8000确实是关闭的

运行项目

刚开始

还没有完全启动,等了一会

完美,看8000端口号

不好的点

如果此时打开任务管理器,搜索manage.exe。

结果如下

可以发现,有多个exe, 

笔者猜测是在前端React的组件中运行的,React组件渲染过程中,多次调用了前面的js代码,而且每次刷新页面,都会增加几个exe。

既然如此,笔者把启动manage.exe的代码写在Tauri中,

其实笔者并不是很甘心,一直询问AI,看看官网,无论是单例模式,还是React-Redux或者其他东西,都尝试过,每次刷新页面,都会新增manage.exe。无可奈何,只能写在Tauri中。

在Tauri中的尝试

希望的逻辑如下。

1、开始的时候,连接exe。

2、关闭的时候,断开exe。

实际的代码

use tauri::Manager;
use tauri::WindowEvent;
use tauri_plugin_shell::ShellExt;
use std::sync::Mutex;
use std::process::Command;

struct DjangoState {
    pid: Option<u32>, // 存储 Django 服务的 PID
}

fn is_manage_exe_running() -> bool { // 判断manage.exe 是否在运行
    let output = Command::new("tasklist")
        .args(&["/FI", "IMAGENAME eq manage.exe"])
        .output();

    match output {
        Ok(output) => {
            let stdout = String::from_utf8_lossy(&output.stdout);
            stdout.contains("manage.exe")
        }
        Err(_) => false,
    }
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init()) // 初始化 shell 插件
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_opener::init())
        .manage(Mutex::new(DjangoState { pid: None })) // 初始化状态
        .setup(|app| {
            // 获取状态
            let state = app.state::<Mutex<DjangoState>>();

            // 检查是否已经启动
            let mut state = state.lock().unwrap();
            if state.pid.is_none() {
                // 检查 manage.exe 是否已经在运行
                if is_manage_exe_running() {
                    println!("manage.exe is already running.");
                } else {
                    // 启动 Django 服务
                    let shell = app.shell();
                    let result = shell
                        .command("powershell") // 或者 "manager.exe",确保路径正确
                        .args(["manage.exe", "runserver", "--noreload"])
                        .spawn();// 返回Result<(Receiver<CommandEvent>, CommandChild)>
                    match result {
                        Ok((_receiver, child)) => {
                            let pid = child.pid();
                            println!("Django server started with PID: {}", pid);

                            // 存储 PID
                            state.pid = Some(pid);
                        }
                        Err(err) => {
                            println!("Failed to start Django server: {:?}", err);
                        }
                    }
                }
            }

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

实际情况,笔者无法终结exe,首先,没有管理员权限。

其次,有bug

显示打开的是

PID是14588,然而,打开任务管理器

什么情况????????

为什么有两个,为什么PID不对?

笔者也找不到原因

运行没有bug,可以获得数据。

因此,实际的逻辑

1、查看是否有manage.exe在运行

2、有则跳过,没有则打开

很明显,不是很好,假如有其他的exe,也叫manage.exe,就G了。

但又不得不这样做,可以运行。

相关文章:

  • 如何获取与testFile同级目录下的所有文件?
  • 企业级AI架构探索:业务驱动,场景优先
  • 集成平台是选择专业iPaaS厂商还是大型软件企业?
  • 善用批处理的for命令倍增效率(附彩蛋:windows官方bug)
  • 【面试场景题-你知道readTimeOutException,会引发oom异常吗】
  • JavaScript 获取 URL 中参数值的详解
  • 【动态规划】详解混合背包问题
  • YOLO11改进-模块-引入空间带状注意力机制(Spatial Strip Attention,SSA)增强模型对空间信息处理能力的重要模块
  • Windows搭建免翻墙的BatteryHistorian
  • Animation - AI Controller控制SKM_Manny的一些问题
  • 笔记:代码随想录算法训练营day58:101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
  • 成都文创浪潮中,国际数字影像产业园的标杆塑造之路
  • Netlify 的深度解析及使用指南
  • 深入探讨 `ip2region` 中三种初始化方法:newWithBuffer、newWithVectorIndex 和 newWithFileOnly
  • 针对耳鸣患者推荐的一些菜谱和食材
  • 产品更新 | 数字助决胜:华望M-Arch平台实现从体系模型到仿真推演
  • ManiWAV:通过野外的音频-视频数据学习机器人操作
  • C#自定义曲线便器功能实现(简化版)
  • PTA团体程序设计天梯赛-练习集46-50题
  • qt程序打包成一个文件
  • 奥园集团将召开债券持有人会议,拟调整“H20奥园2”本息兑付方案
  • 扶桑谈|素称清廉的石破茂被曝受贿,日本政坛或掀起倒阁浪潮
  • 酒店取消订单加价卖何以屡禁不绝?专家建议建立黑名单并在商家页面醒目标注
  • 外交部:印巴都表示不希望局势升级,望双方都能保持冷静克制
  • 央行、证监会:科技创新债券含公司债券、企业债券、非金融企业债务融资工具等
  • 吴清:加强监管的同时传递监管温度,尽力帮助受影响企业应对美加征关税的冲击