用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();
}

内容:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/201014.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读:Distributed Initialization for VVIRO with Position-Unknown UWB Network

前言 Distributed Initialization for Visual-Inertial-Ranging Odometry with Position-Unknown UWB Network这篇论文是发表在ICRA 2023上的一篇文章&#xff0c;本文提出了一种基于位置未知UWB网络的一致性视觉惯性紧耦合优化测距算法( DC-VIRO )的分布式初始化方法。 对于…

解决:ModuleNotFoundError: No module named ‘qt_material‘

解决&#xff1a;ModuleNotFoundError: No module named ‘qt_material’ 文章目录 解决&#xff1a;ModuleNotFoundError: No module named qt_material背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用之前的代码时&#xff0c;报错&…

Django快速搭建静态网页

Django的快速搭建 这个是例子 这个是一个目录 项目名称&#xff1a;项目似乎被命名为DJ0928&#xff0c;这是Django项目的根目录。 文件都是Django项目的核心配置文件。 settings.py 包含了项目的配置设置。urls.py 定义了项目的URL路由。wsgi.py 和 asgi.py 分别用于Web服务器…

力扣刷题篇之分治

系列文章目录 目录 系列文章目录 前言 一、分解问题 二、解决子问题 三、合并结果 总结 前言 刷题按照&#xff1a; [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 - 力扣&#xff08;LeetCode&#xff09; 参考&#xff1a; 「五大常用算法」一文搞懂分治算法…

爬虫学习 异步爬虫(五)

多线程 多进程 协程 进程 运行中的程序 线程 被CPU调度的执行过程,操作系统 运算调度的min单位 在进程之中,进程中实际运作单位 from threading import Thread#创建任务 def func(name):for i in range(100):print(name,i)if __name__ __main__:#创建线程t1 Thread(target …

异步操作的方法

在高级语言中已经有了异步的原语言&#xff0c;而在C 中的最好的方式就是 libevent 的方式,我这还是相当认同的&#xff0c;高级语言就不需要在苦哈哈的&#xff0c;事件转圈了&#xff0c;但是原理还是以事件为基础的 一句话就是在一个循环中等着他执行完,这个循环中有很多其他…

CodeMeter软件保护及授权管理解决方案(二)

客户端管理工具 CodeMeter Runtime是CodeMeter解决方案中的重要组成部分&#xff0c;其为独立软件包&#xff0c;开发者需要把CodeMeter Runtime和加密后的软件一起发布。CodeMeter Runtim包括以下组件用于实现授权的使用&#xff1a; CodeMeter License Server授权服务器 Co…

Leetcode(面试题 08.01.)三步问题

文章目录 前言一、题目分析二、算法原理1.状态表示2.状态转移方程3.初始化4.填表顺序5.返回值是什么 三、代码实现总结 前言 在本文章中&#xff0c;我们将要详细介绍一下Leetcode(面试题 08.01.)三步问题相关的内容 一、题目分析 1.小孩可以上一阶&#xff0c;两阶&#xff…

2948. 交换得到字典序最小的数组 (分组排序)

Problem: 2948. 交换得到字典序最小的数组 文章目录 题目思路Code 题目 给你一个下标从 0 开始的 正整数 数组 nums 和一个 正整数 limit 。 在一次操作中&#xff0c;你可以选择任意两个下标 i 和 j&#xff0c;如果 满足 |nums[i] - nums[j]| < limit &#xff0c;则交换…

Python之数据可视化

文章目录 一、1、matplotlib简单应用1.1、绘制带有中文标签和图例的图1.2、 绘制散点图1.3、绘制饼状图1.4、多个图形一起显示 一、 1、matplotlib简单应用 matplotlib模块依赖于numpy模块和tkinter模块&#xff0c;可以绘制多种形式的图形&#xff0c;包括线图、直方图、饼状…

05_MySQL主从复制架构

任务背景 ##一、真实案例 某同学刚入职公司&#xff0c;在熟悉公司业务环境的时候&#xff0c;发现他们的数据库架构是一主两从&#xff0c;但是两台从数据库和主库不同步。询问得知&#xff0c;已经好几个月不同步了&#xff0c;但是每天会全库备份主服务器上的数据到从服务…

一文详解Python中常用数据类型

文章目录 Python 中常用的数据类型包括&#xff1a;Python 中布尔类型(bool)Python 中的数字类型概述Pyhon中的字符串概述Python 中的List概述Python 中的元组类型(tuple)Python中的字典&#xff08;Dictionary&#xff09;Python中的集合&#xff08;Set&#xff09;Python中的…

Python---练习:求某同学成绩的总分及平均分

需求&#xff1a; 已知某同学的语文(70)、数学(90) 、英语(80)、历史(75)、地理(85)五门课的成绩,编程求该同学的总分以及平均分。 思考&#xff1a; 要求是算总分和平均分&#xff0c;先看总分&#xff0c;已经知道了各科成绩&#xff0c;那么可以用把成绩赋值给每个学科的…

使用Postman创建Mock Server

这篇文章将教会大家如何利用 Postman&#xff0c;通过 Mock 的方式测试我们的 API。 什么是 Mock Mock 是一项特殊的测试技巧&#xff0c;可以在没有依赖项的情况下进行单元测试。通常情况下&#xff0c;Mock 与其他方法的主要区别就是&#xff0c;用于取代代码依赖项的模拟对…

Linux下Docker 离线安装详细步骤,亲测成功

1.离线原因&#xff1a;公司新创不能使用开元linux&#xff0c;使用了一个变种centOS&#xff0c;致使yum被禁 2.步骤&#xff1a; 2.1 下载docker tar包&#xff0c;下载地址&#xff1a;Index of linux/https://download.docker.com/linux/ 2.2 新建自己的软件目录&am…

IELTS学习笔记_grammar_新东方

参考&#xff1a; 新东方 田静 语法 目录&#xff1a; 导学简单句… x.1 导学 学语法以应用为主。 基础为&#xff1a;单词&#xff0c;语法 进阶为&#xff1a;听说读写译&#xff0c;只考听说读写。 words -> chunks -> sentences, chunks&#xff08;语块的重要…

嵌入式设备与PC上位机通信协议设计的几点原则

嵌入式设备在运行中需要设置参数&#xff0c;这个工作经常由PC机来实现&#xff0c;需要为双方通信设计协议&#xff0c;有代表性协议是如下三种&#xff1a; 从上表可以看到&#xff0c;一般嵌入式设备内存和运算性能都有限&#xff0c;因此固定二进制是首选通信协议。 一&am…

使用 Docker 安装和配置 MySQL 数据库简介

目录 一、使用镜像安装 1、查询镜像 2、拉取镜像 3、查看本地镜像 4、启动docker镜像 二、使用Docker Compose安装 1、安装Docker和Docker Compose 2、创建Docker Compose文件&#xff1a; 3、启动MySQL容器 4、验证MySQL容器是否正常运行 5、连接到MySQL容器 6、停止…

智能优化算法应用:基于水循环算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于水循环算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于水循环算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.水循环算法4.实验参数设定5.算法结果6.参考文献7.…

Error running OrderServiceBoot. Command line is too long.

微服务启动不成功&#xff0c;报Error running OrderServiceBoot. Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun. 解决&#xff1a; 方法一&#xff1a; 右上角启动小三角 -->Edit configuration–>-右侧…