物联网实战--平台篇之(六)应用管理后台

news2024/11/23 17:01:01

目录

一、应用数据库

二、登录记忆

三、新建应用

四、获取应用列表

五、重命名应用


 本项目的交流QQ群:701889554

物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html

物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.html

本项目资源文件https://download.csdn.net/download/ypp240124016/89301894

sqlite数据库查看软件 https://download.csdn.net/download/ypp240124016/89302020

一、应用数据库

        在账户数据库中,除了账户表,还有个应用表,它的函数列表和示例内容如下两图所示,主要也是包含了建表、插入和更新等操作。

//建立应用表
bool AccountSqlite::createAppListTable(void)
{
    QString str_query = QString::asprintf("CREATE TABLE If Not Exists app_id_list ("
                                          "id INTEGER NOT NULL,"
                                          "app_id bigint NOT NULL UNIQUE,"
                                          "app_name char(30) DEFAULT NULL,"
                                          "creator char(30) DEFAULT NULL,"
                                          "create_time timestamp DEFAULT (datetime(\'now\',\'localtime\')),"
                                          "PRIMARY KEY (id)"
                                          ")"
                                         );


    if(runSqlQuery(str_query)==false)
    {
        qDebug("createAppLisTable error!");
        return false;
    }
    return true;
}

//添加应用ID
bool AccountSqlite::addAppIDToList(u32 app_id, QString creator)
{
    QString str_query = QString::asprintf("INSERT INTO app_id_list (app_id, app_name, creator) VALUES ( %u, \"%s\" , \"%s\" )", app_id, "新应用",creator.toUtf8().data());

    if( runSqlQuery(str_query))
    {
        qDebug("addAppIDToList ok!");

        AccountNodeStruct tag_account;
        tag_account.account.clear();
        selectAccountByName(creator, tag_account);
        if(tag_account.account.isEmpty()==false)
        {
            int nSize=tag_account.appList.size();
            for(int i=0; i<nSize; i++)
            {
                if(tag_account.appList.at(i)==app_id)
                {
                    return true;
                }
            }
            tag_account.appList.append(app_id);
            updateAccountAppList(creator, tag_account.appList);//更新应用列表
        }
        return true;
    }

    qDebug("addAppIDToList failed!");
    return false;
}

//更新应用名称
bool AccountSqlite::updateAppName(u32 app_id, QString app_name)
{
    QString str_query = QString::asprintf("UPDATE app_id_list SET app_name=\"%s\"   WHERE app_id=%u",
                                          app_name.toUtf8().data(), app_id);
//    qDebug()<<str_query;
    if( runSqlQuery(str_query))
    {
        qDebug("updateAppName ok!");
        return true;
    }
    return false;
}

//获取应用名称
QString AccountSqlite::selectAppName(u32 app_id)
{
    QString app_name="";
    QString str_query = QString::asprintf("select app_name from app_id_list where app_id=%u", app_id);
    if( runSqlQuery(str_query))
    {
        while(m_sqlQuery.next())
        {
            app_name=m_sqlQuery.value(0).toString();
            break;
        }
        m_sqlQuery.finish();
    }
    return app_name;
}

//查询应用节点信息
bool AccountSqlite::selectAppInfo(u32 app_id, AppNodeStruct &app_node)
{
    QString str_query = QString::asprintf("select app_id, app_name, creator, create_time from app_id_list where app_id=%u", app_id);
//    qDebug()<<str_query;
    if( runSqlQuery(str_query))
    {
        while(m_sqlQuery.next())
        {
            int ptr=0;
            app_node.appID=m_sqlQuery.value(ptr++).toUInt();
            app_node.appName=m_sqlQuery.value(ptr++).toString();
            app_node.creator=m_sqlQuery.value(ptr++).toString();
            app_node.createTime=m_sqlQuery.value(ptr++).toString();
            m_sqlQuery.finish();
            return true;
        }
        m_sqlQuery.finish();
    }
    return false;
}


//获取最大的应用ID
u32 AccountSqlite::selectMaxAppID(void)
{
    u32 max_app=0;
    QString str_query = QString::asprintf("SELECT app_id  FROM  app_id_list ORDER BY app_id DESC limit 10");
    if(runSqlQuery(str_query)==false)
    {
        qDebug("selectMaxAppID error_01!");
         return max_app;
    }
    while(m_sqlQuery.next())
    {
        max_app=m_sqlQuery.value(0).toUInt();
        break;
    }
    m_sqlQuery.finish();
//    qDebug()<<"selectAppList="<<app_list;
    return max_app;
}

//获取该账户下的应用数量
u32 AccountSqlite::getAppCountFromAccount(QString account)
{
    u32 app_cnts=0;
    QString str_query = QString::asprintf("select app_id from app_id_list where  creator=\"%s\"", account.toUtf8().data());
//    qDebug()<<str_query;
    if( runSqlQuery(str_query))
    {
        while(m_sqlQuery.next())
        {
          app_cnts++;
        }
    }
    return app_cnts;
}

        以上是应用相关的数据库函数,这里面比较特殊的是selectMaxAppID,用来查询最大的应用ID,这样用户在新建应用时候就知道该分配什么ID给他了,这里面用DESC依据app_id字段降序查询,这样第一个就是最大的应用ID了;还有一个getAppCountFromAccount用来获取某个账户下已经存在的应用数量,目的是为了判断改用户能否再新建应用,我这对这个有数量限制,目前是最多8个应用,这个可以自己更改,或者根据账户的权限等级自己去分配。

二、登录记忆

        在实际使用APP过程中,为了方便用户,一般在一定时间内(比如一星期)可以免登录,直接跳转到主界面进行使用了,那么,我们这边也使用这种模式。首次打开时,跳转到验证码登录页面,引导用户登录,正常操作登录后,用户端会保存当前账户和登录时间,密码不保存;在下次打开APP的时候,内部程序会先读取保存数据,如果有账户并且时间未过期,那么就以这个账户直接获取该账户下的应用列表,完成登录过程,这个过程用户无感,只需等待几秒即可,增强体验感。下面看下具体实现。

        首先需要一个密码保护配置文件,这个密码根据每个手机的MAC地址决定,这样配置文件就不会被复制利用了,具体的密码生成可以使用自己的方法,这里只是个参考。

        接下来就是读取和保存配置的内容了,writeConfig比较简单,就是保存当前登录账户和时间;读取readConfig后,需要检查账户是否符合要求,另外时间上我这里定的是3天以内,如果这两个条件满足要求,就直接免登录 ,同时再保存一次更新时间,如果这里不更新保存也行的,意味着3天后需要强制重新登录,相对安全些,就看自己要如何权衡便捷与安全了。

        另外,drv_com.readConfg和drv_com.writeConfg内部会根据密码自动加解密,如果不需要加密,那就密码传入NULL即可。


void AccountMan::readConfig(void)
{
    QString path=m_rootPath+"/account.txt";
    QJsonObject root_obj=drv_com.readConfg(path, m_keyBuff);
    
    if(root_obj.contains("account"))
    {
        QString account_str=root_obj.value("account").toString(); 
        qDebug()<<"account_str="<<account_str;
        m_accountWork.account=account_str;
    }
    if(root_obj.contains("login_time"))
    {
        qint64 login_time=root_obj.value("login_time").toDouble();
        qDebug()<<"login_time="<<login_time;
        m_accountWork.login_time=login_time;
    }
    qint64 det_time=QDateTime::currentDateTime().toTime_t()-m_accountWork.login_time;
    qDebug()<<"det_time="<<det_time;
    if(checkAccount(m_accountWork.account)==0 && det_time<86400*3)
    {
        emit siqSetLoginState(1);//免登录,发给前端
        writeConfig();//更新登录时间
        emit sigUpdateLoginAccount(m_accountWork.account, 1);//发给控制中心
    }
    else
    {
        emit siqSetLoginState(0);//引导登录
    }
}

void AccountMan::writeConfig(void)
{
    QString path=m_rootPath+"/account.txt";
    QJsonObject root_obj;
    QString account_str=m_accountWork.account;
    root_obj.insert("account", account_str);
    root_obj.insert("login_time", (qint64)QDateTime::currentDateTime().toTime_t());
    
    drv_com.writeConfig(path, root_obj, m_keyBuff);

}

三、新建应用

        账户注册的时候后台系统会自动创建一个应用,如果不够用,当前系统允许再新建7个应用,新建的过程也比较常规,就是请求——创建——回复。在这里,应用管理需要单独区分了,跟以后的分组管理和设备管理统一规划到中心管理去,就是下图新建的文件类;相应的,需要添加订阅的话题和组合新的发布话题。应用相关的订阅话题是yyy125/as/pub/center/AC:5A:FC:C7:15:3D/28454/app。

        在CenterMan类中,请求代码如下,核心参数是new_name,由前端输入,这样服务器后台会直接更新数据库内的应用名称。

void CenterMan::requestNewApp(QString new_name)
{
    QJsonObject root_obj;
    QJsonDocument json_doc;

    root_obj.insert("cmd_type", "new_app");
    root_obj.insert("account", m_loginAccount);
    root_obj.insert("new_name", new_name);
    root_obj.insert("rand_num", m_randNum);
    root_obj.insert("mac", m_macStr); 
    json_doc.setObject(root_obj);
    QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
    QString topic=makePubTopic("app");
    emit sigMqttPushMessage(topic, msg_ba);
}

        以下是后台服务器新建应用部分的代码,基本流程是检查账户合法性、检查应用数量、获取最大应用ID和添加应用。回复的时候同样会返回应用ID和名称。

  if(cmd_type=="new_app")//新建应用
    {
        qDebug()<<"account= "<<account<<" req new app!";
        AccountSqlite::AccountNodeStruct tag_account;
        AccountSqlite::AppNodeStruct tag_app;
        u32 new_app_id=0;
        tag_app.appID=0;
        tag_account.parentAccount="";
        m_accountSqlite->selectAccountByName(account, tag_account);
        qDebug("@@tag_account.auth=0x%08X", tag_account.auth);
        if(tag_account.account.isEmpty()==true)
        {
            qDebug()<<"account"<<account<<" is not found!";
            ackNewAppState(account, mac_str, rand_num, 0, "",1, account+" 未找到账号!");
            return;
        }
        if(tag_account.parentAccount.isEmpty()==false)//检测是否为根账号
        {
           qDebug()<<"account="<<account<<" is not a root count!";
           ackNewAppState(account, mac_str, rand_num, 0, "",1, account+" 该账号不是主账号!");
           return;
        }
        int app_cnts=m_accountSqlite->getAppCountFromAccount(account);//当前的应用数量
        if(app_cnts>=8)//限制每个账号创建应用的数量
        {
            ackNewAppState(account, mac_str, rand_num, 0, "",1, account+" 应用数量已达上限!");
            return;
        }
        u32 max_app=m_accountSqlite->selectMaxAppID();
        if(max_app>APP_ID_MIN)
            new_app_id=max_app+1;
        else  
            new_app_id=APP_ID_MIN+1;
        
        qDebug()<<"new_app_id="<<new_app_id;
       bool ok=m_accountSqlite->addAppIDToList(new_app_id, account);
       if(ok)
       {
           QString new_name="新应用";
           if(root_obj.contains("new_name"))//命令
           {
               QJsonValue value = root_obj.value("new_name");
                new_name=value.toString();
           }
           m_accountSqlite->updateAppName(new_app_id, new_name);   //更新数据库内应用名称
           ackNewAppState(account, mac_str, rand_num, new_app_id, new_name, 0, "创建成功!");
           qDebug()<<"111 addAppIDToList ok, new_app_id="<<new_app_id<<", account="<<account;
       }
       else
       {
           ackNewAppState(account, mac_str, rand_num, 0, "",1, "创建失败!");
       }
    }





void CenterThread::ackNewAppState(QString account, QString mac_str, int rand_num, u32 app_id, QString app_name, int result, QString ack_str)
{
    QJsonObject root_obj;
    QJsonDocument json_doc;
    root_obj.insert("cmd_type", "new_app");
    root_obj.insert("app_id", (qint64)app_id);
    root_obj.insert("app_name", app_name);
    root_obj.insert("create_time", QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    root_obj.insert("result", result);
    root_obj.insert("ack_str", ack_str);
    json_doc.setObject(root_obj);
    QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
    QString topic=makePubTopic(account, mac_str, rand_num, "app");
    emit sigMqttPushMessage(topic, msg_ba);
}

       以下是用户端对返回结果的解析和处理方式。

       if(cmd_type=="new_app")//返回新应用
         {
             u32 app_id=0;
             if(root_obj.contains("app_id"))
             {
                 QJsonValue value = root_obj.value("app_id");
                 if(value.isDouble())
                 {
                     app_id=value.toDouble();
                 }
             }
             if(app_id>0)
             {
                 QString app_name="新应用";
                 if(root_obj.contains("app_name"))
                 {
                     app_name=root_obj.value("app_name").toString();
                 }
                 AppWorkStruct tag_work_app;
                 tag_work_app.appID=app_id;
                 tag_work_app.appName=app_name;
                 m_appWorkList.append(tag_work_app);
             }
         }

四、获取应用列表

        登录成功后的第一件事就是获取当前账户下的应用列表,这样才能进行后续工作,请求代码如下:

void CenterMan::requestAppList(void)
{
    QJsonObject root_obj;
    QJsonDocument json_doc;

    root_obj.insert("account", m_loginAccount);
    root_obj.insert("rand_num", m_randNum);
    root_obj.insert("mac", m_macStr); 
    root_obj.insert("cmd_type", "app_list");
    json_doc.setObject(root_obj);
    QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
    QString topic=makePubTopic("app");
    emit sigMqttPushMessage(topic, msg_ba);
}

服务端代码如下,回复的内容相对繁琐,要一个个组成json数组发送回应。

    else if(cmd_type=="app_list")//获取应用列表
    {
        AccountSqlite::AccountNodeStruct tag_account;
        tag_account.account.clear();
        tag_account.appList.clear();
        m_accountSqlite->selectAccountByName(account, tag_account);
        if(tag_account.account.isEmpty()==false)
        {
            ackReqAppListState(account, mac_str, rand_num, tag_account.appList, 0, "应用获取成功!");
        }
    }



void CenterThread::ackReqAppListState(QString account, QString mac_str, int rand_num, QList<u32> app_list, int result, QString ack_str)
{
    QJsonArray app_array;
    QJsonObject root_obj;
    QJsonDocument json_doc;

    for(int i=0; i<app_list.size(); i++)
    {
        u32 app_id=app_list.at(i);
        if(app_id>0)
        {
            AccountSqlite::AppNodeStruct tag_app_node;
            m_accountSqlite->selectAppInfo(app_id, tag_app_node);
            QJsonObject app_obj;
            app_obj.insert("app_id", (qint64)app_id);
            app_obj.insert("app_name", tag_app_node.appName);
            app_obj.insert("create_time", tag_app_node.createTime);
            app_array.append(app_obj);
        }
    }
    root_obj.insert("cmd_type", "app_list");
    root_obj.insert("account", account);
    root_obj.insert("app_list", app_array);
    root_obj.insert("result", result);
    root_obj.insert("ack_str", ack_str);
    json_doc.setObject(root_obj);
    QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
    QString topic=makePubTopic(account, mac_str, rand_num, "app");
    emit sigMqttPushMessage(topic, msg_ba);
}

        用户端解析如下,有一个细节处理需要处理,就是上次操作的应用ID会保存在配置文件内,需要将此app_id跟当前应用列表逐一对比,如果有匹配则继续将当前app_id作为激活状态,如果没有,那就默认使用列表的第一个app_id,用户切换后会自动保存激活的app_id。

         else if(cmd_type=="app_list")//返回应用列表
         {
             if(root_obj.contains("app_list"))
             {
                 QJsonValue value=root_obj.value("app_list");
                 
                 if(value.isArray())
                 {
                     m_appWorkList.clear();//清除APP列表
                     bool curr_app_flag=false;
                     QJsonArray app_array=value.toArray();
                     qDebug()<<app_array;
                     int nSize=app_array.size();
                     for(int i=0; i<nSize; i++)
                     {
                         QJsonValue value=app_array.at(i);
                         if(value.isObject())
                         {
                             AppWorkStruct tag_app_work;
                             tag_app_work.appID=0;
                             QJsonObject app_obj=value.toObject();

                             if(app_obj.contains("app_name"))
                             {
                                 QJsonValue value=app_obj.value("app_name");
                                 tag_app_work.appName=value.toString();
                             }
                             if(app_obj.contains("app_id"))
                             {
                                 QJsonValue value=app_obj.value("app_id");
                                 if(value.isDouble())
                                 {
                                     u32 app_id=value.toDouble();
                                     if(app_id>0)
                                     {
                                         tag_app_work.appID=app_id;
                                         if(m_currAppWork.appID==app_id)
                                         {
                                             m_currAppWork.appName=tag_app_work.appName;
                                             curr_app_flag=true;
                                         }
                                     }
                                 }
                             }
                             if(app_obj.contains("create_time"))
                             {
                                 QJsonValue value=app_obj.value("create_time");
                                 tag_app_work.createTime=value.toString();
                             }
                             if(tag_app_work.appID>0)
                             {
                                 m_appWorkList.append(tag_app_work);   
                             }
                         }                    
                     }
                     if(curr_app_flag==false && m_appWorkList.size()>0)//没有默认应用
                     {
                         m_currAppWork=m_appWorkList.first();
                     }
                     
                     emit siqUpdateCurrAppName(m_currAppWork.appID, m_currAppWork.appName);
                     writeConfig();
                 }
             }     
         }

五、重命名应用

        用户有时候需要更改应用名称,具体代码如下,只需要传入应用ID和新名称即可。

void CenterMan::requestRenameApp(qint64 app_id, QString new_name)
{
    if(app_id==0)
        return;
    QJsonObject root_obj;
    QJsonDocument json_doc;
    root_obj.insert("account", m_loginAccount);
    root_obj.insert("cmd_type", "rename");
    root_obj.insert("rand_num", m_randNum);
    root_obj.insert("mac", m_macStr);
    root_obj.insert("app_id", (qint64)app_id);
    root_obj.insert("app_name", new_name);
    json_doc.setObject(root_obj);
    QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
    QString topic=makePubTopic("app");
    emit sigMqttPushMessage(topic, msg_ba);
}

        服务器端操作也相对简单,数据库进行更新操作即可。

    else if(cmd_type=="rename")//重命名应用
    {
        u32 app_id=0;
        if(root_obj.contains("app_id"))
        {
            QJsonValue value=root_obj.value("app_id");
            if(value.isDouble())
            {
                app_id=value.toDouble();
            }
        }
        QString app_name="新名称";
        if(root_obj.contains("app_name"))
        {
            QJsonValue value=root_obj.value("app_name");
            if(value.isString())
            {
                app_name=value.toString();
            }
        }
        if(app_id>0)
        {
            m_accountSqlite->updateAppName(app_id, app_name);   
            ackRenameAppState(account, mac_str, rand_num, app_id, app_name, 0, "更新成功!");
        }
        else
        {
            ackRenameAppState(account, mac_str, rand_num, app_id, app_name, 1, "更新失败!");
        }
       
    }





void CenterThread::ackRenameAppState(QString account, QString mac_str, int rand_num, u32 app_id, QString app_name, int result, QString ack_str)
{
    QJsonObject root_obj;
    QJsonDocument json_doc;
    root_obj.insert("cmd_type", "rename");
    root_obj.insert("app_id", (qint64)app_id);
    root_obj.insert("app_name", app_name);
    root_obj.insert("result", result);
    root_obj.insert("ack_str", ack_str);
    json_doc.setObject(root_obj);
    QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
    QString topic=makePubTopic(account, mac_str, rand_num, "app");
    emit sigMqttPushMessage(topic, msg_ba);
}

        用户端解析后将新名称更新到前端,完成闭环。

        else if(cmd_type=="rename")//返回重命名
         {
             u32 app_id=0;
             if(root_obj.contains("app_id"))
             {
                 QJsonValue value = root_obj.value("app_id");
                 if(value.isDouble())
                 {
                     app_id=value.toDouble();
                 }
             }
             QString app_name="";
             if(root_obj.contains("app_name"))
             {
                 QJsonValue value = root_obj.value("app_name");
                 if(value.isString())
                 {
                     app_name=value.toString();
                 }
             }
             if(app_id>0)
             {
                 int i=0;
                 for(auto iter : m_appWorkList)
                 {
                     if(iter.appID==app_id)
                     {
                         m_appWorkList[i].appName=app_name;
                     }
                     i++;
                 }
                 emit siqUpdateCurrAppName(app_id, app_name);
             }
         }

        目前账户和应用都没设计删除功能,主要是为了避免引起不必要的麻烦,比如我们的app_id是增长型的,每创建一个应用都会先查找最大的app_id,然后再+1,如果删除了,怕会出现混乱,所以就不提供此功能了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024统计建模成品论文39页(附带完整数据集和代码)

2024统计建模成品论文完整版一等奖论文【1.5w字全网最佳】2024统计建模大赛高质量成品论文39页配套完整代码运行全套数据集https://www.jdmm.cc/file/2710661/

华为配置带反射器的iNOF功能实验

配置带反射器的iNOF功能示例 适用产品和版本 安装了SAN系列单板的CE16800系列交换机V300R020C10或更高版本。 安装了P系列单板的CE16800系列交换机V300R021C00或更高版本。 CE6866、CE6866K、CE8851-32CQ8DQ-P、CE8851K系列交换机V300R020C00或更高版本。 CE6860-SAN、CE8850-S…

【全开源】商会招商项目系统基于FastAdmin+ThinkPHP+Uniapp(源码搭建/上线/运营/售后/维护更新)

一款基于FastAdminThinkPHPUniapp开发的商会招商项目系统&#xff0c;是一个集PC和移动端功能于一体的解决方案&#xff0c;线上线下进行服务&#xff0c;围绕 活动报名、在线课程、项目大厅、线下签到、会员系统等。为商会提供了更加便捷高效的管理方式&#xff0c;提升了商会…

python数据分析——seaborn绘图1

参考资料&#xff1a;活用pandas库 matplotlib库是python的和兴绘图工具&#xff0c;而seaborn基于matplotlib创建&#xff0c;它为绘制统计图提供了更高级的接口&#xff0c;使得只用少量代码就能生成更美观、更复杂的可视化效果。 seaborn库和pandas以及其他pydata库&#xf…

括号匹配(栈)

20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; c有栈 但是C语言没有 到那时我们可以自己造 这里的代码是直接调用栈&#xff0c;然后调用 等于三个左括号的任意一个 我们就入栈 左括号&#xff08;入栈&#xff09; 右括号 取出栈顶数据&#xff0c;出栈并且进行匹配…

用Transformers实现简单的大模型文本生成

根据输入的prompt&#xff0c;生成一段指定长度的文字。Llama跑起来太慢了&#xff0c;这里用GPT-2作为列子。 from transformers import GPT2LMHeadModel, GPT2Tokenizer import torchtokenizer GPT2Tokenizer.from_pretrained("gpt2") model GPT2LMHeadModel.fr…

Java 实现Mybatis plus 批量删除

数据库实体字段并不映射的情况&#xff0c;直接请求体集合接收。 PostMapping("/removeIdsInfo")public R<Void> removeIdsInfo(RequestBody List<Integer> ids) {return exStudentService.removeIdsInfo(ids);} /**** 学生模块根据集合id 批量删除数据*…

BGP基础配置实验

BGP基础配置实验 一、实验拓扑 初始拓扑&#xff1a; 最终拓扑&#xff1a; 二、实验要求及分析 实验要求&#xff1a; 1&#xff0c;R1为AS 100区域&#xff1b;R2、R3、R4为AS 200区域且属于OSPF协议&#xff1b;R5为AS 300区域&#xff1b; 2&#xff0c;每个设备上都有…

AIM可以像 LLM 一样进行扩展的自回归图像模型

0.引言 AIM&#xff08;Autoregressive Image Model&#xff09;是一种自回归学习图像模型&#xff0c;它是对语言模型的图像版本进行了推广。该模型的预训练图像特征质量会随着模型大小和数据质量的提高而提高&#xff0c;从而带来更好的性能。同时&#xff0c;下游任务的性能…

Linux 中 alarm 函数详解

目录 简介函数原型函数参数返回值使用示例设置 3 秒闹钟修改闹钟与取消闹钟设置 1 秒周期定时器 更多内容 简介 alarm 函数的功能是设置一个闹钟&#xff08;定时器&#xff09;&#xff0c;当闹钟时间到时&#xff0c;内核会向当前进程发送一个 SIGALRM 信号。 打开 Linux 终…

AI智能体|手把手教你申请一个Kimi(Moonshot)的API KEY

大家好&#xff0c;我是无界生长。 今天分享一下如何申请一个Kimi(Moonshot)的API KEY&#xff0c;为后面Kimi(Moonshot)接入微信机器人做铺垫。学会了的话&#xff0c;欢迎分享转发&#xff01; 前提 拥有一个Kimi(Moonshot)账号 使用手机号注册即可&#xff0c;新用户可免费…

五、Linux二进制安装MariaDB 六、MariaDB主从复制

目录 五、Linux二进制安装MariaDB1 卸载mariadb1.1 卸载相关的服务(mysql和mariadb都查询一下)1.2 查找MySQL和mariadb相关的文件目录 2 安装mariadb2.1 mariadb下载地址2.2 将安装包放入到服务器中并解压 (我放到opt下)2.3 将解压后的目录移动到安装目录下2.4 创建数据目录(根…

【iOS】架构模式

文章目录 前言一、MVC二、MVP三、MVVM 前言 之前写项目一直用的是MVC架构&#xff0c;现在来学一下MVP与MVVM两种架构&#xff0c;当然还有VIPER架构&#xff0c;如果有时间后面会单独学习 一、MVC MVC架构先前已经详细讲述&#xff0c;这里不再赘述&#xff0c;我们主要讲一…

YOLOv9改进策略目录 | 包含卷积、主干、检测头、注意力机制、Neck上百种创新机制

&#x1f451; YOLOv9有效涨点专栏目录 &#x1f451; 专栏视频介绍&#xff1a;包括专栏介绍、得到的项目文件、模型二次创新、权重文件的使用问题&#xff0c;点击即可跳转。 前言 Hello&#xff0c;各位读者们好 本专栏自开设两个月以来已经更新改进教程50余篇其中包含Re…

持续集成-Git

重要步骤命令 git init (初始化一个仓库) git add [文件名] (添加新的文件) git commit -m [关于本次提交的相关说明] (提交) git status (查看文件状态) git diff (如果文件改变&#xff0c;比较两个文件内容) git add[文件名] || git commit -a -m [关于本次提交的相关说…

Java入门1: 基础语法

Java入门1: 基础语法 MangoGO 芒狗狗 目录 1 基础语法1.1 Hello World1.2 常量1.3 数据类型1.4 String1.5 StringBuilder1.6 运算符1.7 位运算符1.8 逻辑运算符1.9 关系运算符1.10 练习&#xff1a;计算数字和1.11 关键字和语句1.12 流程控制1.13 数组1.14 用户输入操作参考代码…

WCF 双工 回调模式

wcfInterface 项目 》》》wcf服务端提供的服务协议 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; namespace wcfInterface {[ServiceContract(CallbackContract typeo…

【pouchdb-可视化工具 】

最近使用pouchdb&#xff0c;想找个其对应的可视化工具&#xff0c;可以对数据库进行操作。 找了好久才找到&#xff0c;网上有说先同步到couchdb&#xff0c;再用couchdb的可视化工具查看&#xff0c;其实没有那么麻烦&#xff0c;pouchdb的可视化工具其实藏在另外的pouchdb-…

自然语言转SQL(NL2SQL、Text2SQL)

使用 FastAPI 框架和 LangChain 库构建的简单 Web 服务&#xff0c;其目的是将自然语言处理&#xff08;NLP&#xff09;应用于 SQL 查询生成。以下是代码中使用的技术架构和业务流程的详细说明&#xff1a; 技术架构 FastAPI&#xff1a;一个现代、快速&#xff08;高性能&am…

Django开发实战之定制管理后台界面及知识梳理(下)

接上一篇&#xff1a;Django开发实战之定制管理后台界面及知识梳理&#xff08;中&#xff09; 1、前台设置 1、隐藏路由 当你输入一个错误地址时&#xff0c;可以看到这样的报错&#xff1a; 从这样的报错中&#xff0c;我们可以看到&#xff0c;这个报错页面暴漏了路由&a…