用flutter 写一个专属于儿子的听书的app

背景:

儿子最近喜欢上了用儿童手表听故事,但是手表边里的应用免费内容很少,会员一年要300多,这么一笔巨款,怎能承担的起,所以打算自己开发一个专属于儿子的听书app。

最终效果:

架构:

后端由两个服务组成,一个文件服务用于预览图片和在线听故事。一个接口服务用于 获取故事列表和某个故事的详细内容。

前端app用flutter开发,一共三个页面。故事列表页,详细故事页,和播放页面。

服务端代码:

 

#include "crow.h"
#include <crow/json.h>
#include <iostream>
#include <dirent.h>
#include <string>
#include <vector>
#include <initializer_list>

using namespace std;

// 获取文件后缀名
std::string getFileExtension(const std::string& filename) {
    size_t lastDot = filename.find_last_of(".");
    if (lastDot != std::string::npos) {
        return filename.substr(lastDot + 1);
    }
    return ""; // 如果没有后缀,返回空字符串或其他你认为合适的默认值
}

//遍历文件夹
std::vector<string> scanDir(const char* dir, initializer_list<string> subStrinList){
    DIR* directory;
    struct dirent* entry;

    //获取所有后缀
    string suffixList("");
	for(auto beg=subStrinList.begin(); beg!=subStrinList.end(); ++beg)
		suffixList += *beg;

    std::cout<<"后缀 "<<suffixList<<std::endl;

    std::vector<std::string> allFile;
    directory = opendir(dir);
    if(directory!=nullptr){
        while((entry=readdir(directory))!=nullptr){
            std::string filename = entry->d_name;
            std::string fileSuffix = getFileExtension(filename);
            if(filename!="."&&filename!=".."&&fileSuffix.length()>0&&suffixList.find(fileSuffix)!=std::string::npos){
                allFile.push_back(filename);
            }
        }
        closedir(directory);
    }else{
         std::cerr << "Failed to open directory." << std::endl;
    }
    return allFile;
}

std::string url_decode(const std::string &str) {
    std::string result;
    std::istringstream iss(str);

    char ch;
    int i;
    while (iss >> std::noskipws >> ch) {
        if (ch == '%') {
            if (!(iss >> std::hex >> i)) {
                break;
            }
            result += static_cast<char>(i);
        } else if (ch == '+') {
            result += ' ';
        } else {
            result += ch;
        }
    }

    return result;
}

int main(int argc, char **argv)
{
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")
    ([]()
    {
        crow::response res;
        res.set_header("Content-Type", "text/plain; charset=utf-8");
        res.body = "你好啊,小朋友!";
        return res;
    });

    // 获取所有条目
    CROW_ROUTE(app, "/getAllEntry")
    ([]()
     {
        crow::response res;
        res.set_header("Content-Type", "text/plain; charset=utf-8");

        crow::json::wvalue j;
        std::vector<std::string> allEntry = scanDir("./data",{"jpg"});
        for(int i=0;i<allEntry.size();i++){
            j[i]=allEntry.at(i);
        }
        std::cout<<"allEntry "<<crow::json::dump(j)<<std::endl;
        res.body = crow::json::dump(j);
        return res; 
    });

    //获取某个条目的所有内容
    CROW_ROUTE(app, "/getDetailEntry/<string>")
    ([](string name)
     {
        std::string decodedQuery = url_decode(name);

        std::cout<<"getDetailEntry "<<decodedQuery<<std::endl;
        crow::response res;
        res.set_header("Content-Type", "text/plain; charset=utf-8");

        std::string dir=std::string("./data/")+decodedQuery;
        crow::json::wvalue j;
        std::vector<std::string> allFile = scanDir(dir.data(),{"mp3","m4a"});
        for(int i=0;i<allFile.size();i++){
            j[i]=allFile.at(i);
        }
        std::cout<<"allFile "<<crow::json::dump(j)<<std::endl;
        res.body = crow::json::dump(j);
        return res; 
    });

    app.port(18080).multithreaded().run();
}

内容:

当有了新的故事后,只需要准备一张故事的预览图,然后一起放到服务器上即可。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土拨鼠不是老鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值