add 项目运行截图
This commit is contained in:
463
.trae/documents/project-screenshot-automation-plan.md
Normal file
463
.trae/documents/project-screenshot-automation-plan.md
Normal file
@@ -0,0 +1,463 @@
|
|||||||
|
# 项目截图自动化功能实施计划
|
||||||
|
|
||||||
|
## 需求分析
|
||||||
|
|
||||||
|
根据用户提供的八爪鱼 RPA 流程图,需要实现以下功能:
|
||||||
|
|
||||||
|
### 项目结构
|
||||||
|
|
||||||
|
* **服务后端**: Java SpringBoot 项目
|
||||||
|
|
||||||
|
* **前台前端**: Vue3 前端项目(部分项目可能没有)
|
||||||
|
|
||||||
|
* **后台前端**: Vue3 管理后台项目
|
||||||
|
|
||||||
|
### 脚本文件
|
||||||
|
|
||||||
|
* `run_install_server.bat` - 后端 Maven 构建
|
||||||
|
|
||||||
|
* `run_install_front.bat` - 前台前端依赖安装
|
||||||
|
|
||||||
|
* `run_install_admin.bat` - 后台前端依赖安装
|
||||||
|
|
||||||
|
* `run_server.bat` - 启动服务后端
|
||||||
|
|
||||||
|
* `run_front.bat` - 启动前台前端
|
||||||
|
|
||||||
|
* `run_admin.bat` - 启动后台前端
|
||||||
|
|
||||||
|
* `run_sql.bat` - 导入 SQL 脚本(SQL 脚本在后端项目文件夹下的 db 文件夹中)
|
||||||
|
|
||||||
|
### 执行流程(根据八爪鱼流程图)
|
||||||
|
|
||||||
|
```
|
||||||
|
主流程
|
||||||
|
├── 初始化变量
|
||||||
|
├── 打开网页
|
||||||
|
├── 导入 SQL
|
||||||
|
├── 更换图片
|
||||||
|
├── 后台网页截图
|
||||||
|
├── 启动后端服务
|
||||||
|
├── 启动前端服务
|
||||||
|
├── 前端依赖 install
|
||||||
|
├── 前台网页截图
|
||||||
|
├── 收尾工作
|
||||||
|
└── 准备工作
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实施步骤
|
||||||
|
|
||||||
|
### 阶段 1: 创建核心模块
|
||||||
|
|
||||||
|
#### 1.1 创建 `project_screenshot.py` 模块
|
||||||
|
|
||||||
|
* 实现 `ProjectScreenshotAutomation` 类
|
||||||
|
|
||||||
|
* 功能包括:
|
||||||
|
|
||||||
|
* 项目路径配置管理
|
||||||
|
|
||||||
|
* 执行 bat 脚本(构建、安装依赖、启动服务)
|
||||||
|
|
||||||
|
* SQL 导入功能
|
||||||
|
|
||||||
|
* 使用 Playwright 进行浏览器控制和截图
|
||||||
|
|
||||||
|
* 菜单识别和遍历截图
|
||||||
|
|
||||||
|
#### 1.2 关键功能实现
|
||||||
|
|
||||||
|
**脚本执行功能:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def execute_bat(bat_path: str, cwd: str = None, timeout: int = 300) -> tuple[bool, str]:
|
||||||
|
"""执行 bat 脚本并返回结果"""
|
||||||
|
|
||||||
|
def wait_for_service(url: str, timeout: int = 120) -> bool:
|
||||||
|
"""等待服务启动完成"""
|
||||||
|
```
|
||||||
|
|
||||||
|
**SQL 导入功能:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def import_sql(sql_file: str, db_config: dict) -> bool:
|
||||||
|
"""导入 SQL 脚本到数据库"""
|
||||||
|
```
|
||||||
|
|
||||||
|
**更换前台轮播图片功能:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_random_images(bg_pic_folder: str, count: int = 3) -> list:
|
||||||
|
"""从指定文件夹随机获取指定数量的图片文件"""
|
||||||
|
|
||||||
|
def copy_images_to_target(source_images: list, target_folder: str) -> bool:
|
||||||
|
"""将源图片复制到目标文件夹并重命名为 swiperPicture1.jpg 等"""
|
||||||
|
|
||||||
|
def replace_swiper_images(project_path: str, desktop_path: str) -> str:
|
||||||
|
"""
|
||||||
|
更换前台轮播图片
|
||||||
|
1. 从桌面 bg_pic 文件夹随机选择 3 张图片
|
||||||
|
2. 复制到项目 server/src/main/resources/static/file 目录
|
||||||
|
3. 重命名为 swiperPicture1.jpg、swiperPicture2.jpg、swiperPicture3.jpg
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
**更换后台登录背景图功能:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def update_login_vue_background(project_path: str) -> bool:
|
||||||
|
"""
|
||||||
|
修改 login.vue 文件中的背景图片链接
|
||||||
|
1. 从预设图片列表中随机选择一张
|
||||||
|
2. 替换 front/manage_code/src/views/login.vue 中的 background: url()
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 预设后台登录背景图片列表
|
||||||
|
LOGIN_BACKGROUND_IMAGES = [
|
||||||
|
"http://img.yidaima.cn/7-dcd4fc1e8d0144aaa064bc282d1af289",
|
||||||
|
"http://img.yidaima.cn/6-3db67e2e6ff64e018d48282638900a67",
|
||||||
|
"http://img.yidaima.cn/5-74ee6fe2f0954a8db2574e8f7fbb8ef2",
|
||||||
|
"http://img.yidaima.cn/4-a926593ba8c444a3984100e99ae322bb",
|
||||||
|
"http://img.yidaima.cn/3-f91e9a0ed55d45c9aff80a08f554c625",
|
||||||
|
"http://img.yidaima.cn/2-2bd41cdd57b54b529dc3a139e66233e0",
|
||||||
|
"http://img.yidaima.cn/1-5a0b7ee2344a46bd987c1cafff19b3ba",
|
||||||
|
"http://img.yidaima.cn/8-495b9767a2f34197b963a13226d3e1d2",
|
||||||
|
"http://img.yidaima.cn/10-991483f941914f3d85bf87a4f8748fee",
|
||||||
|
"http://img.yidaima.cn/11-d274f1d695f7472a8fcd2c8c6238a79e",
|
||||||
|
"http://img.yidaima.cn/14-0e30653336d849379060ad8c436fe512",
|
||||||
|
"http://img.yidaima.cn/16-7a58235a2a4040f99e3431c3cac9ea7a",
|
||||||
|
"http://img.yidaima.cn/17-3406a546b81c412d9e3501cdb0f88b12",
|
||||||
|
"http://img.yidaima.cn/18-0a2fae1d6634480dabf5471fa86b3623",
|
||||||
|
"http://img.yidaima.cn/19-107196938e074c92a40b62c60aed18a4"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**截图功能:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def capture_screenshots(base_url: str, menu_selectors: list, output_dir: str) -> list:
|
||||||
|
"""根据菜单进行截图"""
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 2: 配置管理扩展
|
||||||
|
|
||||||
|
#### 2.1 更新 `config_loader.py`
|
||||||
|
|
||||||
|
添加项目截图自动化相关配置:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
project_screenshot:
|
||||||
|
# 项目路径配置
|
||||||
|
project_path: ""
|
||||||
|
has_front: true # 是否有前台前端
|
||||||
|
|
||||||
|
# 脚本路径配置(相对项目路径或绝对路径)
|
||||||
|
scripts:
|
||||||
|
install_server: "run_install_server.bat" # 后端 Maven 构建
|
||||||
|
install_front: "run_install_front.bat" # 前台前端依赖安装
|
||||||
|
install_admin: "run_install_admin.bat" # 后台前端依赖安装
|
||||||
|
run_server: "run_server.bat" # 启动服务后端
|
||||||
|
run_front: "run_front.bat" # 启动前台前端
|
||||||
|
run_admin: "run_admin.bat" # 启动后台前端
|
||||||
|
run_sql: "run_sql.bat" # 导入 SQL 脚本
|
||||||
|
|
||||||
|
# SQL 配置
|
||||||
|
sql:
|
||||||
|
script_path: "server/db/init.sql" # SQL 脚本路径(相对项目路径)
|
||||||
|
|
||||||
|
# 服务配置
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
url: "http://localhost:8080"
|
||||||
|
health_endpoint: "/actuator/health"
|
||||||
|
startup_timeout: 120
|
||||||
|
front:
|
||||||
|
url: "http://localhost:8082" # 前台前端地址
|
||||||
|
login_url: "http://localhost:8082/#/login" # 前台登录页面
|
||||||
|
startup_timeout: 60
|
||||||
|
admin:
|
||||||
|
url: "http://localhost:8081" # 后台前端地址
|
||||||
|
login_url: "http://localhost:8081/#/login" # 后台登录页面
|
||||||
|
startup_timeout: 60
|
||||||
|
|
||||||
|
# 登录配置
|
||||||
|
login:
|
||||||
|
admin: # 后台登录配置
|
||||||
|
username: "admin"
|
||||||
|
password: "admin"
|
||||||
|
username_selector: "input[placeholder='请输入用户名'], input[name='username'], #username"
|
||||||
|
password_selector: "input[placeholder='请输入密码'], input[name='password'], #password, input[type='password']"
|
||||||
|
submit_selector: "button[type='submit'], .login-btn, .el-button--primary"
|
||||||
|
front: # 前台登录配置
|
||||||
|
username: "2"
|
||||||
|
password: "123456"
|
||||||
|
username_selector: "input[placeholder='请输入用户名'], input[name='username'], #username"
|
||||||
|
password_selector: "input[placeholder='请输入密码'], input[name='password'], #password, input[type='password']"
|
||||||
|
submit_selector: "button[type='submit'], .login-btn, .el-button--primary"
|
||||||
|
|
||||||
|
# 截图配置
|
||||||
|
screenshot:
|
||||||
|
output_dir: "./screenshots"
|
||||||
|
full_page: true
|
||||||
|
menu_selectors: # 菜单识别选择器
|
||||||
|
admin: ".el-menu-item, .el-sub-menu__title"
|
||||||
|
front: ".nav-item, .menu-item"
|
||||||
|
delay: 2000 # 截图前等待时间(ms)
|
||||||
|
|
||||||
|
# 轮播图片配置
|
||||||
|
swiper_images:
|
||||||
|
source_folder: "{desktop_path}/bg_pic" # 图片来源文件夹(桌面 bg_pic)
|
||||||
|
target_subpath: "server/src/main/resources/static/file" # 目标路径(相对于项目路径)
|
||||||
|
target_names:
|
||||||
|
- "swiperPicture1.jpg"
|
||||||
|
- "swiperPicture2.jpg"
|
||||||
|
- "swiperPicture3.jpg"
|
||||||
|
count: 3 # 随机选择的图片数量
|
||||||
|
|
||||||
|
# 后台登录背景图配置
|
||||||
|
login_background:
|
||||||
|
vue_file_subpath: "front/manage_code/src/views/login.vue" # login.vue 相对项目路径
|
||||||
|
images: # 预设背景图片列表
|
||||||
|
- "http://img.yidaima.cn/7-dcd4fc1e8d0144aaa064bc282d1af289"
|
||||||
|
- "http://img.yidaima.cn/6-3db67e2e6ff64e018d48282638900a67"
|
||||||
|
- "http://img.yidaima.cn/5-74ee6fe2f0954a8db2574e8f7fbb8ef2"
|
||||||
|
- "http://img.yidaima.cn/4-a926593ba8c444a3984100e99ae322bb"
|
||||||
|
- "http://img.yidaima.cn/3-f91e9a0ed55d45c9aff80a08f554c625"
|
||||||
|
- "http://img.yidaima.cn/2-2bd41cdd57b54b529dc3a139e66233e0"
|
||||||
|
- "http://img.yidaima.cn/1-5a0b7ee2344a46bd987c1cafff19b3ba"
|
||||||
|
- "http://img.yidaima.cn/8-495b9767a2f34197b963a13226d3e1d2"
|
||||||
|
- "http://img.yidaima.cn/10-991483f941914f3d85bf87a4f8748fee"
|
||||||
|
- "http://img.yidaima.cn/11-d274f1d695f7472a8fcd2c8c6238a79e"
|
||||||
|
- "http://img.yidaima.cn/14-0e30653336d849379060ad8c436fe512"
|
||||||
|
- "http://img.yidaima.cn/16-7a58235a2a4040f99e3431c3cac9ea7a"
|
||||||
|
- "http://img.yidaima.cn/17-3406a546b81c412d9e3501cdb0f88b12"
|
||||||
|
- "http://img.yidaima.cn/18-0a2fae1d6634480dabf5471fa86b3623"
|
||||||
|
- "http://img.yidaima.cn/19-107196938e074c92a40b62c60aed18a4"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 3: GUI 界面开发
|
||||||
|
|
||||||
|
#### 3.1 在 `gui.py` 中添加新的 Tab
|
||||||
|
|
||||||
|
创建 "项目截图" Tab,包含以下区域:
|
||||||
|
|
||||||
|
**配置区域:**
|
||||||
|
|
||||||
|
* 项目路径选择(文件夹浏览器)
|
||||||
|
|
||||||
|
* 是否有前台前端复选框
|
||||||
|
|
||||||
|
* 各脚本路径配置(可编辑,有默认值)
|
||||||
|
|
||||||
|
* SQL 脚本路径配置
|
||||||
|
|
||||||
|
**服务配置区域:**
|
||||||
|
|
||||||
|
* 后端服务 URL 和端口
|
||||||
|
|
||||||
|
* 前台前端 URL 和端口
|
||||||
|
|
||||||
|
* 后台前端 URL 和端口
|
||||||
|
|
||||||
|
**操作按钮区域:**
|
||||||
|
|
||||||
|
1. **构建/安装按钮:**
|
||||||
|
|
||||||
|
* "Maven 构建后端" - 执行 run\_install\_server.bat
|
||||||
|
|
||||||
|
* "安装前台依赖" - 执行 run\_install\_front.bat
|
||||||
|
|
||||||
|
* "安装后台依赖" - 执行 run\_install\_admin.bat
|
||||||
|
|
||||||
|
* "导入 SQL" - 执行 run\_sql.bat
|
||||||
|
|
||||||
|
2. **启动按钮:**
|
||||||
|
|
||||||
|
* "启动后端服务" - 执行 run\_server.bat
|
||||||
|
|
||||||
|
* "启动前台前端" - 执行 run\_front.bat
|
||||||
|
|
||||||
|
* "启动后台前端" - 执行 run\_admin.bat
|
||||||
|
|
||||||
|
3. **截图按钮:**
|
||||||
|
|
||||||
|
* "后台截图" - 遍历后台菜单截图
|
||||||
|
|
||||||
|
* "前台截图" - 遍历前台菜单截图(如果有)
|
||||||
|
|
||||||
|
* "一键完整流程" - 按顺序执行所有步骤
|
||||||
|
|
||||||
|
**日志输出区域:**
|
||||||
|
|
||||||
|
* 显示执行日志
|
||||||
|
|
||||||
|
* 进度条显示当前步骤
|
||||||
|
|
||||||
|
### 阶段 4: 流程实现
|
||||||
|
|
||||||
|
#### 4.1 完整流程执行顺序
|
||||||
|
|
||||||
|
根据八爪鱼流程图,实现以下执行顺序:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 初始化变量
|
||||||
|
- 加载项目配置
|
||||||
|
- 检查必要文件是否存在
|
||||||
|
|
||||||
|
2. 准备工作
|
||||||
|
- 检查项目路径
|
||||||
|
- 验证脚本文件存在
|
||||||
|
- 创建截图输出目录
|
||||||
|
|
||||||
|
3. 导入 SQL
|
||||||
|
- 执行 run_sql.bat
|
||||||
|
- 或使用 Python 直接执行 SQL 文件
|
||||||
|
|
||||||
|
4. 更换图片
|
||||||
|
- **更换前台轮播图片**:
|
||||||
|
- 从桌面 bg_pic 文件夹随机选择 3 张图片
|
||||||
|
- 复制到项目 server/src/main/resources/static/file 目录
|
||||||
|
- 重命名为 swiperPicture1.jpg、swiperPicture2.jpg、swiperPicture3.jpg
|
||||||
|
- **更换后台登录背景图**:
|
||||||
|
- 修改 front/manage_code/src/views/login.vue 文件
|
||||||
|
- 从预设图片列表中随机选择一张背景图
|
||||||
|
- 替换 CSS 中的 background: url() 属性
|
||||||
|
|
||||||
|
5. 前端依赖 install
|
||||||
|
- 执行 run_install_front.bat(如果有前台)
|
||||||
|
- 执行 run_install_admin.bat
|
||||||
|
|
||||||
|
6. 启动后端服务
|
||||||
|
- 执行 run_server.bat
|
||||||
|
- 等待服务健康检查通过
|
||||||
|
|
||||||
|
7. 启动前端服务
|
||||||
|
- 执行 run_front.bat(如果有前台)
|
||||||
|
- 执行 run_admin.bat
|
||||||
|
- 等待服务启动
|
||||||
|
|
||||||
|
8. 打开后台网页并登录
|
||||||
|
- 使用 Playwright 打开后台登录页面 http://localhost:8081/#/login
|
||||||
|
- 输入用户名 admin,密码 admin
|
||||||
|
- 点击登录按钮
|
||||||
|
- 等待登录成功跳转
|
||||||
|
|
||||||
|
9. 后台网页截图
|
||||||
|
- 登录成功后访问 http://localhost:8081
|
||||||
|
- 识别菜单项
|
||||||
|
- 遍历每个菜单进行截图
|
||||||
|
|
||||||
|
10. 前台网页截图(如果有前台)
|
||||||
|
- 打开前台登录页面 http://localhost:8082/#/login
|
||||||
|
- 输入用户名 2,密码 123456
|
||||||
|
- 点击登录按钮
|
||||||
|
- 登录成功后访问 http://localhost:8082
|
||||||
|
- 识别菜单项
|
||||||
|
- 遍历每个菜单进行截图
|
||||||
|
|
||||||
|
11. 收尾工作
|
||||||
|
- 关闭浏览器
|
||||||
|
- 停止服务(可选)
|
||||||
|
- 生成截图报告
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 5: 截图功能实现
|
||||||
|
|
||||||
|
#### 5.1 菜单识别和截图
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ScreenshotCapture:
|
||||||
|
def __init__(self, browser, output_dir: str):
|
||||||
|
self.browser = browser
|
||||||
|
self.output_dir = output_dir
|
||||||
|
|
||||||
|
async def login(self, login_url: str, username: str, password: str,
|
||||||
|
username_selector: str, password_selector: str, submit_selector: str):
|
||||||
|
"""
|
||||||
|
执行登录操作
|
||||||
|
1. 打开登录页面
|
||||||
|
2. 输入用户名和密码
|
||||||
|
3. 点击登录按钮
|
||||||
|
4. 等待登录成功
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def capture_menu_screenshots(self, base_url: str, menu_selector: str):
|
||||||
|
"""
|
||||||
|
1. 访问基础页面(已登录状态)
|
||||||
|
2. 识别所有菜单项
|
||||||
|
3. 点击每个菜单并截图
|
||||||
|
4. 保存到输出目录
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def capture_full_page(self, url: str, filename: str):
|
||||||
|
"""截取整页截图"""
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 6: 测试和验证
|
||||||
|
|
||||||
|
#### 6.1 功能测试
|
||||||
|
|
||||||
|
* [ ] 单个 bat 脚本执行测试
|
||||||
|
|
||||||
|
* [ ] SQL 导入功能测试
|
||||||
|
|
||||||
|
* [ ] 服务启动和等待测试
|
||||||
|
|
||||||
|
* [ ] 菜单识别和截图测试
|
||||||
|
|
||||||
|
* [ ] 完整流程测试
|
||||||
|
|
||||||
|
#### 6.2 边界情况处理
|
||||||
|
|
||||||
|
* 项目没有前台前端的情况
|
||||||
|
|
||||||
|
* 服务启动超时处理
|
||||||
|
|
||||||
|
* 菜单识别失败处理
|
||||||
|
|
||||||
|
* 截图保存失败处理
|
||||||
|
|
||||||
|
## 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
yidaima/
|
||||||
|
├── gui.py # 主 GUI(添加项目截图 Tab)
|
||||||
|
├── config_loader.py # 配置加载器(扩展)
|
||||||
|
├── project_screenshot.py # 项目截图自动化核心模块(新增)
|
||||||
|
├── core/
|
||||||
|
│ └── browser.py # 浏览器控制(扩展 Playwright)
|
||||||
|
└── utils/
|
||||||
|
└── screenshot.py # 截图工具(扩展)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 依赖项
|
||||||
|
|
||||||
|
需要添加的依赖:
|
||||||
|
|
||||||
|
```
|
||||||
|
playwright>=1.40.0
|
||||||
|
```
|
||||||
|
|
||||||
|
安装命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install playwright
|
||||||
|
playwright install chromium
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实施顺序
|
||||||
|
|
||||||
|
1. **创建** **`project_screenshot.py`** - 核心自动化模块
|
||||||
|
2. **扩展** **`config_loader.py`** - 添加项目截图配置
|
||||||
|
3. **扩展** **`gui.py`** - 添加项目截图 Tab
|
||||||
|
4. **测试验证** - 完整流程测试
|
||||||
|
5. **打包发布** - PyInstaller 打包 exe
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **服务进程管理**: 启动的服务进程需要在适当的时候关闭
|
||||||
|
2. **端口占用检查**: 启动服务前检查端口是否被占用
|
||||||
|
3. **超时处理**: 每个步骤都需要有合理的超时时间
|
||||||
|
4. **错误恢复**: 某一步失败时能够优雅地停止并报告
|
||||||
|
5. **并发安全**: 避免同时执行多个自动化流程
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
BIN
__pycache__/project_screenshot.cpython-311.pyc
Normal file
BIN
__pycache__/project_screenshot.cpython-311.pyc
Normal file
Binary file not shown.
3
bat/close_cmd.bat
Normal file
3
bat/close_cmd.bat
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
taskkill /f /im cmd.exe /t
|
||||||
8
bat/run_admin.bat
Normal file
8
bat/run_admin.bat
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
cd /d D:\code\front\manage_code
|
||||||
|
|
||||||
|
npm run serve
|
||||||
|
|
||||||
|
pause
|
||||||
8
bat/run_front.bat
Normal file
8
bat/run_front.bat
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
cd /d D:\code\front\client_code
|
||||||
|
|
||||||
|
npm run serve
|
||||||
|
|
||||||
|
pause
|
||||||
25
bat/run_install_admin.bat
Normal file
25
bat/run_install_admin.bat
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
@echo off
|
||||||
|
:: 设置编码为 UTF-8
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
:: 1. 增加 /d 参数切换盘符,并检查路径是否存在
|
||||||
|
cd /d D:\code\front\manage_code
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [错误] 无法找到目录: D:\code\front\manage_code
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 当前目录: %cd%
|
||||||
|
|
||||||
|
:: 2. 判断 node_modules 是否存在
|
||||||
|
if not exist "node_modules\" (
|
||||||
|
echo 未检测到 node_modules 目录,开始安装依赖...
|
||||||
|
:: 使用 call 确保 npm 执行完后脚本继续运行
|
||||||
|
call npm install
|
||||||
|
) else (
|
||||||
|
echo 检测到 node_modules 目录,跳过依赖安装。
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 执行完毕!
|
||||||
25
bat/run_install_front.bat
Normal file
25
bat/run_install_front.bat
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
@echo off
|
||||||
|
:: 设置编码为 UTF-8
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
:: 1. 增加 /d 参数切换盘符,并检查路径是否存在
|
||||||
|
cd /d D:\code\front\client_code
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [错误] 无法找到目录: D:\code\front\client_code
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 当前目录: %cd%
|
||||||
|
|
||||||
|
:: 2. 判断 node_modules 是否存在
|
||||||
|
if not exist "node_modules\" (
|
||||||
|
echo 未检测到 node_modules 目录,开始安装依赖...
|
||||||
|
:: 使用 call 确保 npm 执行完后脚本继续运行
|
||||||
|
call npm install
|
||||||
|
) else (
|
||||||
|
echo 检测到 node_modules 目录,跳过依赖安装。
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 执行完毕!
|
||||||
47
bat/run_install_server.bat
Normal file
47
bat/run_install_server.bat
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
:: 强制切换到脚本所在目录(解决管理员模式启动默认在System32的问题)
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
echo 正确盘符: %~d0
|
||||||
|
echo 正确路径: %cd%
|
||||||
|
|
||||||
|
:: 使用/d参数强制切换驱动器+目录
|
||||||
|
cd /d "D:\code\server" 2>nul
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [ERROR] Can not enter D:\code\server
|
||||||
|
echo 请检查:
|
||||||
|
echo 1. D盘是否存在
|
||||||
|
echo 2. code目录是否存在
|
||||||
|
echo 3. 是否有权限访问
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 扫描子目录中...
|
||||||
|
dir /ad /b
|
||||||
|
|
||||||
|
set "first_dir="
|
||||||
|
for /f "delims=" %%d in ('dir /ad /b 2^>nul') do (
|
||||||
|
set "first_dir=%%d"
|
||||||
|
goto :dir_found
|
||||||
|
)
|
||||||
|
|
||||||
|
:dir_found
|
||||||
|
if not defined first_dir (
|
||||||
|
echo [ERROR] No subdirectory found
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 进入子目录: !first_dir!
|
||||||
|
cd /d "!first_dir!"
|
||||||
|
echo 当前路径: %cd%
|
||||||
|
|
||||||
|
if not exist "target\" (
|
||||||
|
echo 执行Maven构建...
|
||||||
|
call mvn clean package
|
||||||
|
) else (
|
||||||
|
pause
|
||||||
|
echo 检测到 target 目录,跳过Maven构建。
|
||||||
|
)
|
||||||
99
bat/run_server.bat
Normal file
99
bat/run_server.bat
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
:: 强制切换到脚本所在目录(解决管理员模式启动默认在System32的问题)
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
echo 正确盘符: %~d0
|
||||||
|
echo 正确路径: %cd%
|
||||||
|
|
||||||
|
:: 使用/d参数强制切换驱动器+目录
|
||||||
|
cd /d "D:\code\server" 2>nul
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [ERROR] Can not enter D:\code\server
|
||||||
|
echo 请检查:
|
||||||
|
echo 1. D盘是否存在
|
||||||
|
echo 2. code目录是否存在
|
||||||
|
echo 3. 是否有权限访问
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 扫描子目录中...
|
||||||
|
dir /ad /b
|
||||||
|
|
||||||
|
set "first_dir="
|
||||||
|
for /f "delims=" %%d in ('dir /ad /b 2^>nul') do (
|
||||||
|
set "first_dir=%%d"
|
||||||
|
goto :dir_found
|
||||||
|
)
|
||||||
|
|
||||||
|
:dir_found
|
||||||
|
if not defined first_dir (
|
||||||
|
echo [ERROR] No subdirectory found
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 进入子目录: !first_dir!
|
||||||
|
cd /d "!first_dir!"
|
||||||
|
echo 当前路径: %cd%
|
||||||
|
|
||||||
|
if not exist "target\" (
|
||||||
|
echo 执行Maven构建...
|
||||||
|
call mvn clean package
|
||||||
|
) else (
|
||||||
|
echo 检测到 target 目录,跳过Maven构建。
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 进入target目录...
|
||||||
|
cd target
|
||||||
|
echo 目录内容:
|
||||||
|
dir /b
|
||||||
|
|
||||||
|
:: ========== 新增端口检查功能 ==========
|
||||||
|
echo 正在检查8080端口占用...
|
||||||
|
set "port_pid="
|
||||||
|
for /f "tokens=5" %%p in ('netstat -ano -p tcp ^| findstr ":8080" ^| findstr "LISTENING"') do (
|
||||||
|
set "port_pid=%%p"
|
||||||
|
echo 检测到端口占用PID: !port_pid!
|
||||||
|
taskkill /F /PID !port_pid! >nul 2>&1 && (
|
||||||
|
echo 成功终止进程: !port_pid!
|
||||||
|
) || (
|
||||||
|
echo [警告] 无法终止进程: !port_pid!
|
||||||
|
echo 可能需要管理员权限,请右键用管理员身份运行
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not defined port_pid (
|
||||||
|
echo 8080端口未被占用
|
||||||
|
)
|
||||||
|
|
||||||
|
:: ========== 端口检查结束 ==========
|
||||||
|
|
||||||
|
set "jar_file="
|
||||||
|
for /f "delims=" %%j in ('dir /b /a-d *.jar ^| findstr /v "original.jar"') do (
|
||||||
|
set "jar_file=%%j"
|
||||||
|
goto :jar_found
|
||||||
|
)
|
||||||
|
|
||||||
|
:jar_found
|
||||||
|
if not defined jar_file (
|
||||||
|
echo [ERROR] No valid jar found
|
||||||
|
echo 建议检查:
|
||||||
|
echo 1. Maven构建是否成功
|
||||||
|
echo 2. target目录内容
|
||||||
|
dir /b *.jar
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 启动Jar包: !jar_file!
|
||||||
|
java -jar "!jar_file!"
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [ERROR] Java启动失败 (code: %errorlevel%)
|
||||||
|
echo 可能原因:
|
||||||
|
echo 1. 缺少依赖
|
||||||
|
echo 2. 端口占用
|
||||||
|
echo 3. 配置错误
|
||||||
|
pause
|
||||||
|
)
|
||||||
|
|
||||||
34
bat/run_sql.bat
Normal file
34
bat/run_sql.bat
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
cd /d D:\code\db
|
||||||
|
|
||||||
|
set "MYSQL_PATH=C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe"
|
||||||
|
|
||||||
|
for %%F in (*.sql) do (
|
||||||
|
echo 正在处理文件: %%F
|
||||||
|
"%MYSQL_PATH%" -u root -p123456 -e "CREATE DATABASE IF NOT EXISTS %%~nF;"
|
||||||
|
|
||||||
|
:: 第一次导入尝试
|
||||||
|
"%MYSQL_PATH%" -u root -p123456 %%~nF < %%F
|
||||||
|
|
||||||
|
:: 检查数据库是否存在
|
||||||
|
"%MYSQL_PATH%" -u root -p123456 -e "USE %%~nF;" 2>nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo 数据库 %%~nF 第一次导入失败,尝试重新导入...
|
||||||
|
|
||||||
|
:: 第二次导入尝试
|
||||||
|
"%MYSQL_PATH%" -u root -p123456 -e "DROP DATABASE IF EXISTS %%~nF; CREATE DATABASE %%~nF;"
|
||||||
|
"%MYSQL_PATH%" -u root -p123456 %%~nF < %%F
|
||||||
|
|
||||||
|
:: 再次检查
|
||||||
|
"%MYSQL_PATH%" -u root -p123456 -e "USE %%~nF;" 2>nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo 错误: 数据库 %%~nF 导入失败!
|
||||||
|
) else (
|
||||||
|
echo 数据库 %%~nF 重新导入成功
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo 数据库 %%~nF 导入完成
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -51,6 +51,89 @@ class Config:
|
|||||||
"database": "test",
|
"database": "test",
|
||||||
"user": "root",
|
"user": "root",
|
||||||
"password": "123456"
|
"password": "123456"
|
||||||
|
},
|
||||||
|
"project_screenshot": {
|
||||||
|
"project_path": "",
|
||||||
|
"desktop_path": "C:\\Users\\南音\\Desktop",
|
||||||
|
"has_front": True,
|
||||||
|
"bat_folder": "C:\\Users\\南音\\Desktop\\yidaima\\bat",
|
||||||
|
"show_cmd_window": True,
|
||||||
|
"code_source_folder": "code",
|
||||||
|
"code_target_path": "D:\\code",
|
||||||
|
"scripts": {
|
||||||
|
"install_server": "run_install_server.bat",
|
||||||
|
"install_front": "run_install_front.bat",
|
||||||
|
"install_admin": "run_install_admin.bat",
|
||||||
|
"run_server": "run_server.bat",
|
||||||
|
"run_front": "run_front.bat",
|
||||||
|
"run_admin": "run_admin.bat",
|
||||||
|
"run_sql": "run_sql.bat"
|
||||||
|
},
|
||||||
|
"sql": {
|
||||||
|
"script_path": "server/db/init.sql"
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"backend": {
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"health_endpoint": "/actuator/health",
|
||||||
|
"startup_timeout": 120
|
||||||
|
},
|
||||||
|
"front": {
|
||||||
|
"url": "http://localhost:8082",
|
||||||
|
"login_url": "http://localhost:8082/#/login",
|
||||||
|
"startup_timeout": 60
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"url": "http://localhost:8081",
|
||||||
|
"login_url": "http://localhost:8081/#/login",
|
||||||
|
"startup_timeout": 60
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"admin": {
|
||||||
|
"username": "admin",
|
||||||
|
"password": "admin"
|
||||||
|
},
|
||||||
|
"front": {
|
||||||
|
"username": "2",
|
||||||
|
"password": "123456"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"screenshot": {
|
||||||
|
"output_dir": "./screenshots",
|
||||||
|
"full_page": True,
|
||||||
|
"menu_selectors": {
|
||||||
|
"admin": ".el-menu-item, .el-sub-menu__title",
|
||||||
|
"front": ".nav-item, .menu-item"
|
||||||
|
},
|
||||||
|
"delay": 2000
|
||||||
|
},
|
||||||
|
"swiper_images": {
|
||||||
|
"source_folder": "bg_pic",
|
||||||
|
"target_subpath": "server/src/main/resources/static/file",
|
||||||
|
"target_names": ["swiperPicture1.jpg", "swiperPicture2.jpg", "swiperPicture3.jpg"],
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
"login_background": {
|
||||||
|
"vue_file_subpath": "front/manage_code/src/views/login.vue",
|
||||||
|
"images": [
|
||||||
|
"http://img.yidaima.cn/7-dcd4fc1e8d0144aaa064bc282d1af289",
|
||||||
|
"http://img.yidaima.cn/6-3db67e2e6ff64e018d48282638900a67",
|
||||||
|
"http://img.yidaima.cn/5-74ee6fe2f0954a8db2574e8f7fbb8ef2",
|
||||||
|
"http://img.yidaima.cn/4-a926593ba8c444a3984100e99ae322bb",
|
||||||
|
"http://img.yidaima.cn/3-f91e9a0ed55d45c9aff80a08f554c625",
|
||||||
|
"http://img.yidaima.cn/2-2bd41cdd57b54b529dc3a139e66233e0",
|
||||||
|
"http://img.yidaima.cn/1-5a0b7ee2344a46bd987c1cafff19b3ba",
|
||||||
|
"http://img.yidaima.cn/8-495b9767a2f34197b963a13226d3e1d2",
|
||||||
|
"http://img.yidaima.cn/10-991483f941914f3d85bf87a4f8748fee",
|
||||||
|
"http://img.yidaima.cn/11-d274f1d695f7472a8fcd2c8c6238a79e",
|
||||||
|
"http://img.yidaima.cn/14-0e30653336d849379060ad8c436fe512",
|
||||||
|
"http://img.yidaima.cn/16-7a58235a2a4040f99e3431c3cac9ea7a",
|
||||||
|
"http://img.yidaima.cn/17-3406a546b81c412d9e3501cdb0f88b12",
|
||||||
|
"http://img.yidaima.cn/18-0a2fae1d6634480dabf5471fa86b3623",
|
||||||
|
"http://img.yidaima.cn/19-107196938e074c92a40b62c60aed18a4"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +231,10 @@ class Config:
|
|||||||
def database_config(self) -> dict:
|
def database_config(self) -> dict:
|
||||||
return self.get("database", {})
|
return self.get("database", {})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def project_screenshot_config(self) -> dict:
|
||||||
|
return self.get("project_screenshot", {})
|
||||||
|
|
||||||
|
|
||||||
# 全局配置实例
|
# 全局配置实例
|
||||||
_config_instance = None
|
_config_instance = None
|
||||||
|
|||||||
532
gui.py
532
gui.py
@@ -15,6 +15,7 @@ from step2 import Step2Converter
|
|||||||
from editor_gui import open_editor
|
from editor_gui import open_editor
|
||||||
from markdown_editor import ThemeManager
|
from markdown_editor import ThemeManager
|
||||||
from db_manager import get_db_manager, reset_db_manager, ProjectOrder
|
from db_manager import get_db_manager, reset_db_manager, ProjectOrder
|
||||||
|
from project_screenshot import ProjectScreenshotAutomation, ProjectConfig
|
||||||
|
|
||||||
|
|
||||||
class YidaimaGUI:
|
class YidaimaGUI:
|
||||||
@@ -87,6 +88,11 @@ class YidaimaGUI:
|
|||||||
self.notebook.add(self.tab_manage, text="文章发布管理")
|
self.notebook.add(self.tab_manage, text="文章发布管理")
|
||||||
self._create_manage_tab()
|
self._create_manage_tab()
|
||||||
|
|
||||||
|
# === Tab 3: 项目运行截图 ===
|
||||||
|
self.tab_screenshot = ttk.Frame(self.notebook, padding="10")
|
||||||
|
self.notebook.add(self.tab_screenshot, text="项目运行截图")
|
||||||
|
self._create_screenshot_tab()
|
||||||
|
|
||||||
# === Tab 4: 参数设置 ===
|
# === Tab 4: 参数设置 ===
|
||||||
self.tab_settings = ttk.Frame(self.notebook, padding="10")
|
self.tab_settings = ttk.Frame(self.notebook, padding="10")
|
||||||
self.notebook.add(self.tab_settings, text="参数设置")
|
self.notebook.add(self.tab_settings, text="参数设置")
|
||||||
@@ -756,6 +762,532 @@ class YidaimaGUI:
|
|||||||
self.setting_db_user_var.set(self.config.get("database.user", "root"))
|
self.setting_db_user_var.set(self.config.get("database.user", "root"))
|
||||||
self.setting_db_pass_var.set(self.config.get("database.password", "123456"))
|
self.setting_db_pass_var.set(self.config.get("database.password", "123456"))
|
||||||
|
|
||||||
|
# ==================== 项目运行截图 Tab 方法 ====================
|
||||||
|
|
||||||
|
def _create_screenshot_tab(self):
|
||||||
|
"""创建项目运行截图 Tab"""
|
||||||
|
# 配置网格
|
||||||
|
self.tab_screenshot.columnconfigure(0, weight=1)
|
||||||
|
self.tab_screenshot.rowconfigure(3, weight=1)
|
||||||
|
|
||||||
|
# 获取项目截图配置
|
||||||
|
ps_config = self.config.get("project_screenshot", {})
|
||||||
|
|
||||||
|
# === 项目路径配置区域 ===
|
||||||
|
path_frame = ttk.LabelFrame(self.tab_screenshot, text="项目路径配置", padding="10")
|
||||||
|
path_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
|
||||||
|
path_frame.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
# 项目路径
|
||||||
|
ttk.Label(path_frame, text="项目路径:").grid(row=0, column=0, sticky=tk.W)
|
||||||
|
self.ps_project_path_var = tk.StringVar(value=ps_config.get("project_path", ""))
|
||||||
|
ps_project_path_entry = ttk.Entry(path_frame, textvariable=self.ps_project_path_var, width=60)
|
||||||
|
ps_project_path_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(10, 0))
|
||||||
|
ttk.Button(path_frame, text="浏览...", command=self._browse_project_path, width=10).grid(row=0, column=2, padx=(10, 0))
|
||||||
|
|
||||||
|
# 桌面路径
|
||||||
|
ttk.Label(path_frame, text="桌面路径:").grid(row=1, column=0, sticky=tk.W, pady=(10, 0))
|
||||||
|
self.ps_desktop_path_var = tk.StringVar(value=ps_config.get("desktop_path", r"C:\Users\南音\Desktop"))
|
||||||
|
ps_desktop_path_entry = ttk.Entry(path_frame, textvariable=self.ps_desktop_path_var, width=60)
|
||||||
|
ps_desktop_path_entry.grid(row=1, column=1, sticky=(tk.W, tk.E), padx=(10, 0), pady=(10, 0))
|
||||||
|
|
||||||
|
# bat 文件夹名称
|
||||||
|
ttk.Label(path_frame, text="bat文件夹:").grid(row=2, column=0, sticky=tk.W, pady=(10, 0))
|
||||||
|
self.ps_bat_folder_var = tk.StringVar(value=ps_config.get("bat_folder", r"C:\Users\南音\Desktop\yidaima\bat"))
|
||||||
|
ps_bat_folder_entry = ttk.Entry(path_frame, textvariable=self.ps_bat_folder_var, width=60)
|
||||||
|
ps_bat_folder_entry.grid(row=2, column=1, sticky=(tk.W, tk.E), padx=(10, 0), pady=(10, 0))
|
||||||
|
|
||||||
|
# 代码目标路径
|
||||||
|
ttk.Label(path_frame, text="代码目标路径:").grid(row=3, column=0, sticky=tk.W, pady=(10, 0))
|
||||||
|
self.ps_code_target_var = tk.StringVar(value=ps_config.get("code_target_path", r"D:\code"))
|
||||||
|
ps_code_target_entry = ttk.Entry(path_frame, textvariable=self.ps_code_target_var, width=60)
|
||||||
|
ps_code_target_entry.grid(row=3, column=1, sticky=(tk.W, tk.E), padx=(10, 0), pady=(10, 0))
|
||||||
|
|
||||||
|
# 是否有前台前端
|
||||||
|
self.ps_has_front_var = tk.BooleanVar(value=ps_config.get("has_front", True))
|
||||||
|
ttk.Checkbutton(path_frame, text="有前台前端", variable=self.ps_has_front_var).grid(row=4, column=1, sticky=tk.W, padx=(10, 0), pady=(10, 0))
|
||||||
|
|
||||||
|
# 是否显示 CMD 窗口
|
||||||
|
self.ps_show_cmd_var = tk.BooleanVar(value=ps_config.get("show_cmd_window", True))
|
||||||
|
ttk.Checkbutton(path_frame, text="显示CMD窗口", variable=self.ps_show_cmd_var).grid(row=5, column=1, sticky=tk.W, padx=(10, 0), pady=(10, 0))
|
||||||
|
|
||||||
|
# === 操作按钮区域 ===
|
||||||
|
button_frame = ttk.LabelFrame(self.tab_screenshot, text="操作按钮", padding="10")
|
||||||
|
button_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
|
||||||
|
|
||||||
|
# 构建/安装按钮
|
||||||
|
install_frame = ttk.Frame(button_frame)
|
||||||
|
install_frame.pack(fill=tk.X, pady=(0, 10))
|
||||||
|
|
||||||
|
ttk.Button(install_frame, text="整理代码", command=self._ps_organize_code, width=15).pack(side=tk.LEFT, padx=(0, 5))
|
||||||
|
ttk.Button(install_frame, text="Maven构建后端", command=self._ps_install_server, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(install_frame, text="安装前台依赖", command=self._ps_install_front, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(install_frame, text="安装后台依赖", command=self._ps_install_admin, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(install_frame, text="导入SQL", command=self._ps_run_sql, width=15).pack(side=tk.LEFT, padx=(5, 0))
|
||||||
|
|
||||||
|
# 启动按钮
|
||||||
|
start_frame = ttk.Frame(button_frame)
|
||||||
|
start_frame.pack(fill=tk.X, pady=(0, 10))
|
||||||
|
|
||||||
|
ttk.Button(start_frame, text="启动后端服务", command=self._ps_start_server, width=15).pack(side=tk.LEFT, padx=(0, 5))
|
||||||
|
ttk.Button(start_frame, text="启动前台前端", command=self._ps_start_front, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(start_frame, text="启动后台前端", command=self._ps_start_admin, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(start_frame, text="更换图片", command=self._ps_replace_images, width=15).pack(side=tk.LEFT, padx=(5, 0))
|
||||||
|
|
||||||
|
# 截图按钮
|
||||||
|
screenshot_frame = ttk.Frame(button_frame)
|
||||||
|
screenshot_frame.pack(fill=tk.X)
|
||||||
|
|
||||||
|
ttk.Button(screenshot_frame, text="后台截图", command=self._ps_capture_admin, width=15).pack(side=tk.LEFT, padx=(0, 5))
|
||||||
|
ttk.Button(screenshot_frame, text="前台截图", command=self._ps_capture_front, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(screenshot_frame, text="收尾工作", command=self._ps_finalize_screenshots, width=15).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(screenshot_frame, text="一键完整流程", command=self._ps_run_full_flow, width=20).pack(side=tk.LEFT, padx=(5, 5))
|
||||||
|
ttk.Button(screenshot_frame, text="关闭所有CMD", command=self._ps_close_all_cmd, width=15).pack(side=tk.LEFT, padx=(5, 0))
|
||||||
|
|
||||||
|
# === 日志输出区域 ===
|
||||||
|
log_frame = ttk.LabelFrame(self.tab_screenshot, text="运行日志", padding="10")
|
||||||
|
log_frame.grid(row=2, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(10, 0))
|
||||||
|
log_frame.columnconfigure(0, weight=1)
|
||||||
|
log_frame.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
|
self.ps_log_text = scrolledtext.ScrolledText(
|
||||||
|
log_frame,
|
||||||
|
wrap=tk.WORD,
|
||||||
|
width=80,
|
||||||
|
height=15,
|
||||||
|
font=("Consolas", 9)
|
||||||
|
)
|
||||||
|
self.ps_log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||||
|
|
||||||
|
# 进度条
|
||||||
|
self.ps_progress = ttk.Progressbar(
|
||||||
|
self.tab_screenshot,
|
||||||
|
mode='indeterminate',
|
||||||
|
length=400
|
||||||
|
)
|
||||||
|
self.ps_progress.grid(row=3, column=0, pady=(10, 0), sticky=(tk.W, tk.E))
|
||||||
|
|
||||||
|
# 状态标签
|
||||||
|
self.ps_status_var = tk.StringVar(value="就绪")
|
||||||
|
self.ps_status_label = ttk.Label(
|
||||||
|
self.tab_screenshot,
|
||||||
|
textvariable=self.ps_status_var,
|
||||||
|
foreground="#666"
|
||||||
|
)
|
||||||
|
self.ps_status_label.grid(row=4, column=0, pady=(10, 0))
|
||||||
|
|
||||||
|
def _browse_project_path(self):
|
||||||
|
"""浏览项目路径"""
|
||||||
|
from tkinter import filedialog
|
||||||
|
path = filedialog.askdirectory(title="选择项目文件夹")
|
||||||
|
if path:
|
||||||
|
self.ps_project_path_var.set(path)
|
||||||
|
|
||||||
|
def _ps_log(self, message: str):
|
||||||
|
"""添加项目截图日志"""
|
||||||
|
self.ps_log_text.insert(tk.END, f"{message}\n")
|
||||||
|
self.ps_log_text.see(tk.END)
|
||||||
|
self.root.update_idletasks()
|
||||||
|
|
||||||
|
def _get_ps_config(self) -> ProjectConfig:
|
||||||
|
"""获取项目截图配置"""
|
||||||
|
ps_config = self.config.get("project_screenshot", {})
|
||||||
|
return ProjectConfig(
|
||||||
|
project_path=self.ps_project_path_var.get(),
|
||||||
|
desktop_path=self.ps_desktop_path_var.get(),
|
||||||
|
has_front=self.ps_has_front_var.get(),
|
||||||
|
install_server=ps_config.get("scripts", {}).get("install_server", "run_install_server.bat"),
|
||||||
|
install_front=ps_config.get("scripts", {}).get("install_front", "run_install_front.bat"),
|
||||||
|
install_admin=ps_config.get("scripts", {}).get("install_admin", "run_install_admin.bat"),
|
||||||
|
run_server=ps_config.get("scripts", {}).get("run_server", "run_server.bat"),
|
||||||
|
run_front=ps_config.get("scripts", {}).get("run_front", "run_front.bat"),
|
||||||
|
run_admin=ps_config.get("scripts", {}).get("run_admin", "run_admin.bat"),
|
||||||
|
run_sql=ps_config.get("scripts", {}).get("run_sql", "run_sql.bat"),
|
||||||
|
bat_folder=self.ps_bat_folder_var.get(),
|
||||||
|
sql_script_path=ps_config.get("sql", {}).get("script_path", "server/db/init.sql"),
|
||||||
|
backend_url=ps_config.get("services", {}).get("backend", {}).get("url", "http://localhost:8080"),
|
||||||
|
backend_startup_timeout=ps_config.get("services", {}).get("backend", {}).get("startup_timeout", 120),
|
||||||
|
front_url=ps_config.get("services", {}).get("front", {}).get("url", "http://localhost:8082"),
|
||||||
|
front_login_url=ps_config.get("services", {}).get("front", {}).get("login_url", "http://localhost:8082/#/login"),
|
||||||
|
front_startup_timeout=ps_config.get("services", {}).get("front", {}).get("startup_timeout", 60),
|
||||||
|
admin_url=ps_config.get("services", {}).get("admin", {}).get("url", "http://localhost:8081"),
|
||||||
|
admin_login_url=ps_config.get("services", {}).get("admin", {}).get("login_url", "http://localhost:8081/#/login"),
|
||||||
|
admin_startup_timeout=ps_config.get("services", {}).get("admin", {}).get("startup_timeout", 60),
|
||||||
|
admin_username=ps_config.get("login", {}).get("admin", {}).get("username", "admin"),
|
||||||
|
admin_password=ps_config.get("login", {}).get("admin", {}).get("password", "admin"),
|
||||||
|
front_username=ps_config.get("login", {}).get("front", {}).get("username", "2"),
|
||||||
|
front_password=ps_config.get("login", {}).get("front", {}).get("password", "123456"),
|
||||||
|
screenshot_output_dir=ps_config.get("screenshot", {}).get("output_dir", "./screenshots"),
|
||||||
|
screenshot_delay=ps_config.get("screenshot", {}).get("delay", 2000),
|
||||||
|
admin_menu_selector=ps_config.get("screenshot", {}).get("menu_selectors", {}).get("admin", ".el-menu-item, .el-sub-menu__title"),
|
||||||
|
front_menu_selector=ps_config.get("screenshot", {}).get("menu_selectors", {}).get("front", ".nav-item, .menu-item"),
|
||||||
|
swiper_source_folder=ps_config.get("swiper_images", {}).get("source_folder", "bg_pic"),
|
||||||
|
swiper_target_subpath=ps_config.get("swiper_images", {}).get("target_subpath", "server/src/main/resources/static/file"),
|
||||||
|
swiper_target_names=ps_config.get("swiper_images", {}).get("target_names", ["swiperPicture1.jpg", "swiperPicture2.jpg", "swiperPicture3.jpg"]),
|
||||||
|
swiper_count=ps_config.get("swiper_images", {}).get("count", 3),
|
||||||
|
login_vue_subpath=ps_config.get("login_background", {}).get("vue_file_subpath", "front/manage_code/src/views/login.vue"),
|
||||||
|
login_background_images=ps_config.get("login_background", {}).get("images", []),
|
||||||
|
code_source_folder=ps_config.get("code_source_folder", "code"),
|
||||||
|
code_target_path=self.ps_code_target_var.get(),
|
||||||
|
show_cmd_window=self.ps_show_cmd_var.get()
|
||||||
|
)
|
||||||
|
|
||||||
|
def _ps_set_running(self, running: bool):
|
||||||
|
"""设置项目截图运行状态"""
|
||||||
|
if running:
|
||||||
|
self.ps_progress.start()
|
||||||
|
self.ps_status_var.set("运行中...")
|
||||||
|
else:
|
||||||
|
self.ps_progress.stop()
|
||||||
|
self.ps_status_var.set("就绪")
|
||||||
|
|
||||||
|
def _ps_install_server(self):
|
||||||
|
"""Maven 构建后端"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始 Maven 构建后端...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
success, msg = automation.install_server()
|
||||||
|
if success:
|
||||||
|
self._ps_log("Maven 构建完成!")
|
||||||
|
else:
|
||||||
|
self._ps_log(f"构建失败: {msg}")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_install_front(self):
|
||||||
|
"""安装前台前端依赖"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始安装前台前端依赖...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
success, msg = automation.install_front()
|
||||||
|
if success:
|
||||||
|
self._ps_log("前台依赖安装完成!")
|
||||||
|
else:
|
||||||
|
self._ps_log(f"安装失败: {msg}")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_install_admin(self):
|
||||||
|
"""安装后台前端依赖"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始安装后台前端依赖...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
success, msg = automation.install_admin()
|
||||||
|
if success:
|
||||||
|
self._ps_log("后台依赖安装完成!")
|
||||||
|
else:
|
||||||
|
self._ps_log(f"安装失败: {msg}")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_run_sql(self):
|
||||||
|
"""导入 SQL 脚本"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始导入 SQL...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
success, msg = automation.run_sql_script()
|
||||||
|
if success:
|
||||||
|
self._ps_log("SQL 导入完成!")
|
||||||
|
else:
|
||||||
|
self._ps_log(f"导入失败: {msg}")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_start_server(self):
|
||||||
|
"""启动后端服务"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("启动后端服务...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
automation.start_backend()
|
||||||
|
if automation.wait_for_service(config.backend_url, config.backend_startup_timeout):
|
||||||
|
self._ps_log("后端服务启动成功!")
|
||||||
|
else:
|
||||||
|
self._ps_log("后端服务启动超时,请手动检查")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_start_front(self):
|
||||||
|
"""启动前台前端"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("启动前台前端...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
automation.start_front()
|
||||||
|
if automation.wait_for_service(config.front_url, config.front_startup_timeout):
|
||||||
|
self._ps_log("前台前端启动成功!")
|
||||||
|
else:
|
||||||
|
self._ps_log("前台前端启动超时,请手动检查")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_organize_code(self):
|
||||||
|
"""整理项目代码"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始整理项目代码...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
sql_filename = automation.organize_project_code()
|
||||||
|
if sql_filename:
|
||||||
|
self._ps_log(f"代码整理完成!SQL文件名: {sql_filename}")
|
||||||
|
else:
|
||||||
|
self._ps_log("代码整理完成,但未获取到SQL文件名")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_start_admin(self):
|
||||||
|
"""启动后台前端"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("启动后台前端...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
automation.start_admin()
|
||||||
|
if automation.wait_for_service(config.admin_url, config.admin_startup_timeout):
|
||||||
|
self._ps_log("后台前端启动成功!")
|
||||||
|
else:
|
||||||
|
self._ps_log("后台前端启动超时,请手动检查")
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_replace_images(self):
|
||||||
|
"""更换图片"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("更换图片...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
|
||||||
|
# 更换前台轮播图片
|
||||||
|
self._ps_log("更换前台轮播图片...")
|
||||||
|
result = automation.replace_swiper_images()
|
||||||
|
self._ps_log(result)
|
||||||
|
|
||||||
|
# 更换后台登录背景图
|
||||||
|
self._ps_log("更换后台登录背景图...")
|
||||||
|
if automation.update_login_vue_background():
|
||||||
|
self._ps_log("后台登录背景图更换成功!")
|
||||||
|
else:
|
||||||
|
self._ps_log("后台登录背景图更换失败")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_capture_admin(self):
|
||||||
|
"""后台截图"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始后台截图...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
# 截图保存到桌面路径下的"截图"文件夹
|
||||||
|
output_dir = os.path.join(config.desktop_path, "截图")
|
||||||
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
|
||||||
|
screenshots = asyncio.run(automation.capture_admin_screenshots_only(output_dir))
|
||||||
|
self._ps_log(f"后台截图完成!共生成 {len(screenshots)} 张截图,保存到: {output_dir}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_capture_front(self):
|
||||||
|
"""前台截图"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始前台截图...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
# 截图保存到桌面路径下的"截图"文件夹
|
||||||
|
output_dir = os.path.join(config.desktop_path, "截图")
|
||||||
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
|
||||||
|
screenshots = asyncio.run(automation.capture_front_screenshots_only(output_dir))
|
||||||
|
self._ps_log(f"前台截图完成!共生成 {len(screenshots)} 张截图,保存到: {output_dir}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_finalize_screenshots(self):
|
||||||
|
"""截图收尾工作"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始执行截图收尾工作...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
|
||||||
|
# 截图保存到桌面路径下的"截图"文件夹
|
||||||
|
output_dir = os.path.join(config.desktop_path, "截图")
|
||||||
|
|
||||||
|
automation.finalize_screenshots(output_dir)
|
||||||
|
self._ps_log(f"截图收尾工作完成!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_run_full_flow(self):
|
||||||
|
"""一键完整流程"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
config = self._get_ps_config()
|
||||||
|
automation = ProjectScreenshotAutomation(config, log_callback=self._ps_log)
|
||||||
|
success = automation.run_full_flow()
|
||||||
|
if success:
|
||||||
|
self.root.after(0, lambda: messagebox.showinfo("成功", "完整流程执行成功!"))
|
||||||
|
else:
|
||||||
|
self.root.after(0, lambda: messagebox.showerror("错误", "流程执行失败,请查看日志"))
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
self.root.after(0, lambda: messagebox.showerror("错误", f"执行失败: {str(e)}"))
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
def _ps_close_all_cmd(self):
|
||||||
|
"""关闭所有CMD窗口"""
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
self._ps_set_running(True)
|
||||||
|
self._ps_log("=" * 50)
|
||||||
|
self._ps_log("开始关闭所有CMD窗口...")
|
||||||
|
config = self._get_ps_config()
|
||||||
|
|
||||||
|
# 构建 close_cmd.bat 路径
|
||||||
|
close_cmd_bat = os.path.join(config.desktop_path, config.bat_folder, "close_cmd.bat")
|
||||||
|
|
||||||
|
if not os.path.exists(close_cmd_bat):
|
||||||
|
self._ps_log(f"错误:close_cmd.bat 不存在: {close_cmd_bat}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self._ps_log(f"执行: {close_cmd_bat}")
|
||||||
|
|
||||||
|
# 执行 bat 文件(弹出CMD窗口)
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
if config.show_cmd_window:
|
||||||
|
# 显示CMD窗口
|
||||||
|
startupinfo = subprocess.STARTUPINFO()
|
||||||
|
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||||
|
startupinfo.wShowWindow = 1 # SW_SHOWNORMAL
|
||||||
|
|
||||||
|
subprocess.Popen(
|
||||||
|
['cmd', '/c', close_cmd_bat],
|
||||||
|
creationflags=subprocess.CREATE_NEW_CONSOLE,
|
||||||
|
startupinfo=startupinfo,
|
||||||
|
cwd=config.desktop_path
|
||||||
|
)
|
||||||
|
self._ps_log("CMD窗口已弹出执行关闭命令")
|
||||||
|
else:
|
||||||
|
# 不显示CMD窗口
|
||||||
|
result = subprocess.run(
|
||||||
|
['cmd', '/c', close_cmd_bat],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
encoding='utf-8',
|
||||||
|
errors='ignore'
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
self._ps_log("CMD窗口关闭成功!")
|
||||||
|
if result.stdout:
|
||||||
|
self._ps_log(result.stdout)
|
||||||
|
else:
|
||||||
|
self._ps_log(f"关闭失败: {result.stderr}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._ps_log(f"错误: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self._ps_set_running(False)
|
||||||
|
|
||||||
|
threading.Thread(target=run, daemon=True).start()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""启动 GUI"""
|
"""启动 GUI"""
|
||||||
|
|||||||
1611
project_screenshot.py
Normal file
1611
project_screenshot.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user