自动化搭建博客工具
目录
软件使用
使用前请下载好git工具
项目介绍
温馨提示:本地搭建完网站框架后,每次新建文章的写作体验较差,可以看看我的另一个 hugo 博客自动化写作工具
src目录:存放图形化项目的源代码,使用 Qt6 可直接启动 QHugoInit 项目。
bin目录:存放项目的可执行二进制文件。
- exec_code.bat:用于写入代码执行脚本
- hugo.exe:构建博客的基石
- QHugoInit.exe:软件启动程序
- log.txt:整个程序执行的日志
项目关键源码
通过多线程防止下载步骤把画面给阻塞
//TODO 简单封装一个用于多线程通信的类
class run_thread:public QThread{
public:
run_thread() = delete;
run_thread(const std::function<void()>&Runnable,QObject* parent = nullptr):m_task(nullptr){
m_task = Runnable;
}
void run()override{
if(m_task!=nullptr);
m_task();
}
private:
std::function<void()>m_task;
};
通过文件io控制命令行的代码执行来执行对应的每一步
void MainWindow::on_right_Btn_clicked()
{
auto path = ui->input->text();
if(!QDir(path).exists()||path.isEmpty()){
QMessageBox::warning(nullptr,"提示","文件夹路径不存在");
return;
}
ui->w2->setVisible(false);
ui->w4->setVisible(false);
ui->w3->setVisible(true);
ui->l1->setText("一切即将准备就绪");
ui->l2->setText("正在初始化您的hugo网站");
ui->l3->setOpenExternalLinks(true);
ui->l3->setText(R"(<html> <style>
a {
color:#3281b8;
}
</style><head/><body><p>这可能会耗费几分钟,请不要强制关闭应用程序<br/><br/>闲得无聊?<a href="https://github.com/ACking-you/AutoHugoSetup">给个star</a></p></body></html>)");
QProcess qp;
std::ofstream writer;
m_Path = path;
auto std_str = m_Path.toStdString();
//first step
writer.open("./exec_code.bat");
if(!writer.is_open()){
QMessageBox::warning(nullptr,"提示","第一次写入文件打开失败");
writer.close();
QCoreApplication::exit(1);
}
ui->info_text->setText("正在初始化 hugo 博客");
std::replace(std_str.begin(),std_str.end(),'/','\\'); //这里注意:cmd32命令只支持反斜杠!
writer<<R"(chcp 65001)"<<'\n'; //设置编码为utf-8
writer<<R"(copy .\hugo.exe )"<<std_str<<'\n'; //copy一份hugo.exe到目标目录下
writer<<"cd /d"<<std_str<<'\n'; //切换到创建目录,这里/d代表直接一步到位的切换目录
writer<<R"(.\hugo new site myBlog)"<<'\n'; //初始化hugo命令
writer.close();
qp.startCommand(R"(.\exec_code.bat)");
if(qp.waitForFinished()){
QString str = qp.readAll();
m_logWriter<<"-----1st step-----\n\r"<<str.toStdString()<<'\n';
ui->info_text->setText(" hugo 博客初始化完成");
}
//second step:执行此步之前先判断git是否可用,此步执行时间最久,不要让它卡死主线程,故需要用到多线程技术
qp.startCommand("git");
if(!qp.waitForFinished()){
QMessageBox::warning(nullptr,"提示","未安装git工具或未设置到环境变量");
QCoreApplication::exit(1);
}
writer.open("./exec_code.bat");
if(!writer.is_open()){
QMessageBox::warning(nullptr,"提示","第二次写入文件打开失败");
writer.close();
QCoreApplication::exit(1);
}
ui->info_text->setText("正在下载 FeelIt 主题");
std::filesystem::path blog_path = std_str;
blog_path /= "myBlog";
m_Path = blog_path.string().c_str();
writer<<"cd /d"<<blog_path<<"\\themes"<<'\n'; //cd到themes文件夹目录下
writer<<"git clone https://gitee.com/acking-you/FeelIt.git"<<'\n';//开始通过git下载主题包
writer.close();
QThread* sub_thread = new run_thread([&]{ //最耗时间的工作别去干扰主线程的正常运行,否则主线程可能看起来会陷入瘫痪
QProcess tqp;
//信号槽机制,主线程等待子线程完成任务发送信号后再执行最后的步骤,因为这个过程肯定是要同步进行,故需要信号槽来等待
connect(&tqp,&QProcess::finished,[&](int exitCode, QProcess::ExitStatus exitStatus){
//step third
std::ofstream writer;
QProcess qp;
writer.open("./exec_code.bat");
if(!writer.is_open()){
QMessageBox::warning(nullptr,"提示","第三次写入文件打开失败");
writer.close();
QCoreApplication::exit(1);
}
ui->info_text->setText("配置本地主题中...");
writer<<"cd /d"<<m_Path.toStdString()<<'\n'; //cd到blog_path
writer<<R"(del .\config.toml)"<<'\n'; //删除原本的config文件
writer<<R"(move .\themes\FeelIt\config.toml .\)"<<'\n'; //将我的配置文件放到顶级目录去
writer<<R"(move .\themes\FeelIt\exampleSite\static\* .\static\)"<<'\n';//移动static图片资源
writer<<R"(move ..\hugo.exe .\)"<<'\n';//将之前的hugo.exe移动到真正的博客目录下
writer<<R"(mkdir .\content\posts)"<<'\n'; //创建用于写文章的目录
writer.close();
qp.startCommand(R"(.\exec_code.bat)");
if(qp.waitForFinished(120000)){
ui->info_text->setText("配置完成 ");
ending();
m_logWriter<<"-----3rd step-----\n\r"<<qp.readAll().toStdString();
}
});
tqp.startCommand(R"(.\exec_code.bat)");
if(!tqp.waitForFinished(120000)){
QMessageBox::warning(nullptr,"提示","下载主题响应超时");
QCoreApplication::exit(1);
}else{
m_logWriter<<"-----2nd step-----\n\r"<<tqp.readAll().toStdString();
}
});
sub_thread->start();
}