快速搜索神器

项目代码:github地址
先看看我们的项目成果吧

  • 汉字搜索
  • 汉字首字母搜索
  • 汉字全拼搜索

1.调研实现背景

在linux环境下有非常好用的find命令,查找文档非常的高效,但是在windows下文件夹框下是默认的暴力遍历查找,非常的慢。

此搜索神器就是为了解决这个问题,为了快速的查找到查找的文件或者目录。

2.项目实现目标以及框架

  1. 实现目标
    就是为了查找文件或者目录能够快速地查找到,另外它能够支持拼音搜索,拼音首字母搜索,拼音汉字混合搜索。

  2. 框架设计

3.文件监控系统

使用扫描+监控的方式,这里方式是谁也离不开谁,是互补的。

  1. 文件监控系统是利用windows上的接口函数监控某个目录下的文档的变化,是实时的。如果在监控程序没有启动的时候是没有办法检测到数据的变化。
  2. 文件系统扫描是通过系统接口,遍历获取目录下的所有文档和数据库中的符合条件的文档进行对比,获取文档的变化,有点是监控程序启动前,变化的文档也是可以对比的。添加到数据库中就是使用的此方法。

主要的获取目录文件使用的是_findfirst_findnext

static void DirectoryList(const std::string& path, std::vector<std::string>&subfiles, \std::vector<std::string>&subdirs){_finddata_t file;//定义一个文件结构体//此时的路径是需要改变的,需要遍历该目录下面的,传递进来的只是到底此目录文件std::string _path = path + "\\*.*";//intptr_t handle = _findfirst(_path.c_str(), &file);if (handle == -1){ERROE_LOG("_findfirst:%s", _path.c_str());}do {// _A_SUBDIR(文件夹)就是目录,否则就是文件,name就是file的名字属性,是一个数组,长度是256。if ((file.attrib & _A_SUBDIR)&&!(file.attrib&_A_HIDDEN)){//目录的时候需要判断是不是.或者..,如果包含了这两个文件在查询的时候就会递归死循环if ((strcmp(file.name, ".") != 0) && (strcmp(file.name, "..") != 0)){subdirs.push_back(file.name);}}else{//此时就是文件了subfiles.push_back(file.name);}} while (_findnext(handle, &file) == 0);_findclose(handle);
}

而监控使用的是windows上的接口ReadDirectoryChangesW来监控制定的文件夹

void fileWatcher()
{DWORD cbBytes;char file_name[MAX_PATH] = {'\0'}; //设置文件名;char file_rename[MAX_PATH] = {'\0'}; //设置文件重命名后的名字;char notify[1024] = { '\0' };int count = 0; //文件数量。可能同时拷贝、删除多个文件,可以进行更友好的提示;TCHAR *dir = _T("D:");std::string s = "D:";//HANDLE就是一个句柄HANDLE dirHandle = CreateFile(dir,GENERIC_READ | GENERIC_WRITE | FILE_LIST_DIRECTORY,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);if (dirHandle == INVALID_HANDLE_VALUE){ //若网络重定向或目标文件系统不支持该操作,函数失败,同时调用GetLastError()返回ERROR_INVALID_FUNCTIONcout << "error" + GetLastError() << endl;}//FILE_NOTIFY_INFORMATION是一个结构体,是柔型数组,将数组强转为结构体指针memset(notify, 0, strlen(notify));FILE_NOTIFY_INFORMATION *pnotify = (FILE_NOTIFY_INFORMATION*)notify;//   cout << "Start Monitor..." << endl;while (true){if (ReadDirectoryChangesW(dirHandle, &notify, 1024, true,FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,&cbBytes, NULL, NULL)){         pnotify = (FILE_NOTIFY_INFORMATION*)notify;//转换文件名为多字节字符串;if (pnotify->FileName){memset(file_name, 0, strlen(file_name));int ret = WideCharToMultiByte(CP_ACP, 0, pnotify->FileName, pnotify->FileNameLength / 2, file_name, 99, NULL, NULL);if (ret == 0){GetLastError();}//  cout <<"pmotify->FileName:"<< pnotify->FileName << endl;}if ((pnotify->Action == FILE_ACTION_ADDED) | (pnotify->Action == FILE_ACTION_REMOVED) | (pnotify->Action == FILE_ACTION_RENAMED_OLD_NAME)){// cout << "pnotify->FileName" << pnotify->FileName << endl;;//如果发生了这些事件的话需要重新扫描当前的目录文件//就需要获取当前的目录名称std::string dirpath = s + "\\" + file_name;get_dir_path(dirpath);//    cout << dirpath << endl;//返回上一层的目录ScanManager::CreateIntance()->ScanNotRecursion(dirpath);//cout << "扫描模块的地址monitor" << ScanManager::CreateIntance() << endl;//cout << "DirPath:" << dirpath << endl;}}}CloseHandle(dirHandle);
}

此外实现一个监控模块的类

class ScanManager{public:void Scan(const std::string& path);static ScanManager* CreateIntance(){static ScanManager s;return &s;}void startScan(const std::string& path){Scan(path);}void ScanNotRecursion(const std::string& path);
private://封装一个SqliteManager对象,用于我们数据的插入和删除ScanManager(){}//构造单例模式//需要的就是讲扫描出来的数据和数据库中的数据进行对别,新增的数据插入到数据库,删除的数据在数据库中删除。
};

这里实现了构造函数,为了在程序中永远只有一个类进行扫描,不会出现两个类同时扫描同一个文件夹。

4.数据持久化

数据持久化封装

这里采用sqlite进行数据持久化,为什么不选用mysql进行数据持久化了?因为本次文件搜索是使用在本地,而不是在网络中,不需要网络服务,mysql支持网络服务但是在累赘了,所以选用本地轻量级的sqlite即可。

sqlite官网下载
另外在菜鸟中也有sqlite的用法
sqlite菜鸟教程

我们直接操作数据库不符合习惯,所以对sqlite进行封装。
实现一个sqliteManager的类

class SqliteManager{public:SqliteManager():_db(nullptr){};~SqliteManager(){Close();}//打开一个数据库void Open(const std::string& path);//关闭数据库void Close();//对数据库执行插入删除等操作void ExecuteSql(const std::string sql);//对数据库进行查找操作,得到的是一个二维数组的指针,其实就是一个一个存放的,用二维数组表示,实际上是一维数组void GetTable(const std::string sql, int &row, int &col, char**&ppRet);//防止拷贝和赋值SqliteManager(const SqliteManager&) = delete;SqliteManager& operator=(const SqliteManager&) = delete;
private:sqlite3* _db;std::mutex _mutex;
};

其实就是在类中封装一个数据库的指针来指向这个数据库,并且使用的c++11中的mutex来保持线程安全,本质上sqlite是安全的,但是sqlite特会出现data_lock,虽然时间很短,但是仍然会导致线程不安全。

重点

因为在sqlite3_get_table(_db, sql.c_str(), &(ppRet), &row, &col, &errmsg);中会有一个布局变量二级指针,它的内存底层是malloc申请的,所以在使用的实收如果不进行free的话就会导致内存泄漏。所以实现RAII来管理这个指针。

class AutoGetTable{public:AutoGetTable(SqliteManager* dbMag, const std::string sql, int & row, int & col, char**& ppRet):_dbMag(dbMag), _ppVlaue(0){_dbMag->GetTable(sql, row, col, ppRet);_ppVlaue = ppRet;}virtual ~AutoGetTable(){if (_ppVlaue){sqlite3_free_table(_ppVlaue);}}private:SqliteManager* _dbMag;char ** _ppVlaue;
};
数据管理封装

在对数据库的接口进行封装之后实现一个对数据库的管理操作,这是和监控模块联系在一起的,因为文档中的内容和数据库中的内容比较的时候如果在数据库中存在文档中不存在就要删除,如果在数据库中不存在在文档中存在就要增加,都存在的时候就不变。

class DataManager{public:static DataManager* GetInstannce(){static DataManager m_db;return &m_db;}void Init();//得到数据库中的内容void GetDocs(std::string path, std::set<std::string>& dbset);//向数据库中插入数据void InsertDocs(const std::string path,const std::string doc);//在数据库中删除数据void DeleteDoc(const std::string& path,const std::string doc);//利用关键字进行查找void Search(const std::string& key, std::vector<std::pair<std::string, std::string>>&doc_paths);~DataManager(){}
private:DataManager(){Init();};//维护一个SqliteManager的对象SqliteManager _sqma;
};

中间逻辑层

中间逻辑主要是处理搜索和高亮模块,实现类似qq的搜索功能以及关键字出现高亮功能。例如下面关键字首字母搜索

关键字全拼搜索

关键字汉字搜索

  • 模糊匹配
    使用数据的like实现模糊匹配检索。
if (key.size() == 1){sprintf(ch, "select doc_name,doc_path from Doc_Tab where \doc_name_init like '%%%s%%';", InitPy.c_str());}else{sprintf(ch, "select doc_name,doc_path from Doc_Tab where doc_name_py  like '%%%s%%' or \doc_name_init like '%%%s%%';", pinyin.c_str(), InitPy.c_str());}
  • 拼音全拼搜索
    在数据库中存储文件名转换拼音全拼的内容,搜索的时候将关键字转换为全拼即可。[汉字转全拼],这里没有自己实现,参考别人的代码。(CSDN)csdn

  • 拼音首字母搜索
    存储时将文件名转换成一个拼音首字母存在数据库表的doc_nam_init字段中,搜索的时候也将关键字转换成拼音首字母,然后使用数据库模糊匹配

static std::string GetFirstLetter(const char* strChs)
{static int li_SecPosValue[] = {1601, 1637, 1833, 2078, 2274, 2302, 2433, 2594, 2787, 3106, 3212,3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249};static char* lc_FirstLetter[] = {"a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "l", "m", "n", "o","p", "q", "r", "s", "t", "w", "x", "y", "z"};static char* ls_SecondSecTable ="CJWGNSPGCGNE[Y[BTYYZDXYKYGT[JNNJQMBSGZSCYJSYY[PGKBZG\Y[YWJKGKLJYWKPJQHY[W[DZLSGMRYPYWWCCKZNKYYGTTNJJNYKKZYT\CJNMCYLQLYPYQFQRPZSLWBTGKJFYXJWZLTBNCXJJJJTXDTTSQZYCDXX\HGCK[PHFFSS[YBGXLPPBYLL[HLXS[ZM[JHSOJNGHDZQYKLGJHSGQZHXQ\GKEZZWYSCSCJXYEYXADZPMDSSMZJZQJYZC[J[WQJBYZPXGZNZCPWHKXH\QKMWFBPBYDTJZZKQHY""LYGXFPTYJYYZPSZLFCHMQSHGMXXSXJ[[DCSBBQBEFSJYHXWGZKPYLQBGLD\LCCTNMAYDDKSSNGYCSGXLYZAYBNPTSDKDYLHGYMYLCXPY[JNDQJWXQXFYYF\JLEJPZRXCCQWQQSBNKYMGPLBMJRQCFLNYMYQMSQYRBCJTHZTQFRXQHXMJJC\JLXQGJMSHZKBSWYEMYLTXFSYDSWLYCJQXSJNQBSCTYHBFTDCYZDJWYGHQFR\XWCKQKXEBPTLPXJZSRMEBWHJLBJSLYYSMDXLCLQKXLHXJRZJMFQHXHWY""WSBHTRXXGLHQHFNM[YKLDYXZPYLGG[MTCFPAJJZYLJTYANJGBJPLQGDZYQ\YAXBKYSECJSZNSLYZHSXLZCGHPXZHZNYTDSBCJKDLZAYFMYDLEBBGQYZKXG\LDNDNYSKJSHDLYXBCGHXYPKDJMMZNGMMCLGWZSZXZJFZNMLZZTHCSYDBDLL\SCDDNLKJYKJSYCJLKWHQASDKNHCSGANHDAASHTCPLCPQYBSDMPJLPZJOQLC\DHJJYSPRCHN[NNLHLYYQYHWZPTCZGWWMZFFJQQQQYXACLBHKDJXDGMMY""DJXZLLSYGXGKJRYWZWYCLZMSSJZLDBYD[FCXYHLXCHYZJQ[[QAGMNYXPFR\KSSBJLYXYSYGLNSCMHZWWMNZJJLXXHCHSY[[TTXRYCYXBYHCSMXJSZNPWGP\XXTAYBGAJCXLY[DCCWZOCWKCCSBNHCPDYZNFCYYTYCKXKYBSQKKYTQQXFCW\CHCYKELZQBSQYJQCCLMTHSYWHMKTLKJLYCXWHEQQHTQH[PQ[QSCFYMNDMGB\WHWLGSLLYSDLMLXPTHMJHWLJZYHZJXHTXJLHXRSWLWZJCBXMHZQXSDZP""MGFCSGLSXYMJSHXPJXWMYQKSMYPLRTHBXFTPMHYXLCHLHLZYLXGSSSSTCL\SLDCLRPBHZHXYYFHB[GDMYCNQQWLQHJJ[YWJZYEJJDHPBLQXTQKWHLCHQXA\GTLXLJXMSL[HTZKZJECXJCJNMFBY[SFYWYBJZGNYSDZSQYRSLJPCLPWXSDW\EJBJCBCNAYTWGMPAPCLYQPCLZXSBNMSGGFNZJJBZSFZYNDXHPLQKZCZWALS\BCCJX[YZGWKYPSGXFZFCDKHJGXDLQFSGDSLQWZKXTMHSBGZMJZRGLYJB""PMLMSXLZJQQHZYJCZYDJWBMYKLDDPMJEGXYHYLXHLQYQHKYCWCJMYYXNAT\JHYCCXZPCQLBZWWYTWBQCMLPMYRJCCCXFPZNZZLJPLXXYZTZLGDLDCKLYRZ\ZGQTGJHHGJLJAXFGFJZSLCFDQZLCLGJDJCSNZLLJPJQDCCLCJXMYZFTSXGC\GSBRZXJQQCTZHGYQTJQQLZXJYLYLBCYAMCSTYLPDJBYREGKLZYZHLYSZQLZ\NWCZCLLWJQJJJKDGJZOLBBZPPGLGHTGZXYGHZMYCNQSYCYHBHGXKAMTX""YXNBSKYZZGJZLQJDFCJXDYGJQJJPMGWGJJJPKQSBGBMMCJSSCLPQPDXCDY\YKY[CJDDYYGYWRHJRTGZNYQLDKLJSZZGZQZJGDYKSHPZMTLCPWNJAFYZDJC\NMWESCYGLBTZCGMSSLLYXQSXSBSJSBBSGGHFJLYPMZJNLYYWDQSHZXTYYWH\MZYHYWDBXBTLMSYYYFSXJC[DXXLHJHF[SXZQHFZMZCZTQCXZXRTTDJHNNYZ\QQMNQDMMG[YDXMJGDHCDYZBFFALLZTDLTFXMXQZDNGWQDBDCZJDXBZGS""QQDDJCMBKZFFXMKDMDSYYSZCMLJDSYNSBRSKMKMPCKLGDBQTFZSWTFGGLY\PLLJZHGJ[GYPZLTCSMCNBTJBQFKTHBYZGKPBBYMTDSSXTBNPDKLEYCJNYDD\YKZDDHQHSDZSCTARLLTKZLGECLLKJLQJAQNBDKKGHPJTZQKSECSHALQFMMG\JNLYJBBTMLYZXDCJPLDLPCQDHZYCBZSCZBZMSLJFLKRZJSNFRGJHXPDHYJY\BZGDLQCSEZGXLBLGYXTWMABCHECMWYJYZLLJJYHLG[DJLSLYGKDZPZXJ""YYZLWCXSZFGWYYDLYHCLJSCMBJHBLYZLYCBLYDPDQYSXQZBYTDKYXJY[CN\RJMPDJGKLCLJBCTBJDDBBLBLCZQRPPXJCJLZCSHLTOLJNMDDDLNGKAQHQHJGY\KHEZNMSHRP[QQJCHGMFPRXHJGDYCHGHLYRZQLCYQJNZSQTKQJYMSZSWLCFQQQ\XYFGGYPTQWLMCRNFKKFSYYLQBMQAMMMYXCTPSHCPTXXZZSMPHPSHMCLMLDQFY\QXSZYYDYJZZHQPDSZGLSTJBCKBXYQZJSGPSXQZQZRQTBDKYXZK""HHGFLBCSMDLDGDZDBLZYYCXNNCSYBZBFGLZZXSWMSCCMQNJQSBDQSJTXXMBL\TXZCLZSHZCXRQJGJYLXZFJPHYMZQQYDFQJJLZZNZJCDGZYGCTXMZYSCTLKPHT\XHTLBJXJLXSCDQXCBBTJFQZFSLTJBTKQBXXJJLJCHCZDBZJDCZJDCPRNPQCJP\FCZLCLZXZDMXMPHJSGZGSZZQLYLWTJPFSYASMCJBTZKYCWMYTCSJJLJCQLWZMA\LBXYFBPNLSFHTGJWEJJXXGLLJSTGSHJQLZFKCGNNNSZFDEQ""FHBSAQTGYLBXMMYGSZLDYDQMJJRGBJTKGDHGKBLQKBDMBYLXWCXYTTYBKMRT\JZXQJBHLMHMJJZMQASLDCYXYQDLQCAFYWYXQHZ";std::string result;int H = 0;int L = 0;int W = 0;size_t stringlen = strlen(strChs);for (int i = 0; i < stringlen; i++) {H = (unsigned char)(strChs[i + 0]);L = (unsigned char)(strChs[i + 1]);if (H < 0xA1 || L < 0xA1) {result += strChs[i];continue;}else {W = (H - 160) * 100 + L - 160;}if (W > 1600 && W < 5590) {for (int j = 22; j >= 0; j--) {if (W >= li_SecPosValue[j]) {result += lc_FirstLetter[j];i++;break;}}continue;}else {i++;W = (H - 160 - 56) * 94 + L - 161;if (W >= 0 && W <= 3007)result += ls_SecondSecTable[W];else {result += (char)H;result += (char)L;}}}return result;
}
  • 高亮模块
    高亮模块处理的时候需要注意处理的方法
static void ColourPrintf(const std::string str) {// 0-黑 1-蓝 2-绿 3-浅绿 4-红 5-紫 6-黄 7-白 8-灰 9-淡蓝 10-淡绿    // 11-淡浅绿  12-淡红 13-淡紫 14-淡黄 15-亮白     //颜色:前景色 + 背景色*0x10    //例如:字是红色,背景色是白色,即 红色 + 亮白 =  4 + 15*0x10 WORD color = 4 + 15 * 0x10;WORD colorOld;HANDLE handle = ::GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_SCREEN_BUFFER_INFO csbi;GetConsoleScreenBufferInfo(handle, &csbi);colorOld = csbi.wAttributes;SetConsoleTextAttribute(handle, color);cout << str;SetConsoleTextAttribute(handle, colorOld);
}
  1. 汉字搜索的时候处理直接进行匹配,进行find查找,直接分割成三个部分,使用高亮显示关键字的部分
  2. 拼音全拼搜索的时候将关键字转换成拼音全拼,然后将所查询到的字段转换成拼音全拼,进行截取,但是截取的不是转换成全拼之后的,而是原有的字段

算法:就是讲汉字一个一个转换成拼音全拼和查找的位置相比较,如果长度达到了查找的位置就开始截取关键字,知道截取到汉字转换为拼音的数量和关键字转换成全拼的数量相同的时候即可。

  1. 首字母查询
    同样使用like模糊查询,将查询到的字段和关键字都转换为汉字的首字母。

项目文件快速搜索神器相关推荐

  1. 【分享-windows文件快速搜索神器】Everything 免费、快速搜索文件/文件夹

    windows文件快速搜索神器 - Everything 下载:https://www.voidtools.com/ 先来体验一波 windows自带的搜索如下,等了一分钟还没搜索完: Everyth ...

  2. windows快速搜索神器everything,让你搜索文件提速百倍!

    我们在使用windows时经常需要查找电脑上的文件,有时候,电脑上的文件非常多,也很容易搞乱,一般情况下我们最对的还是windows自带的磁盘文件搜索功能,但是我们知道,这个搜索速度实在是太慢,有时候 ...

  3. WOX——Windows快速搜索神器

    WOX wox和mac上的Aflred类似,虽然在功能上稍有逊色,但是还是可以给我们使用windows电脑带来很多福利.首先你不需要在桌面放一堆应用软件的快捷方式,桌面可以非常干净整洁,想要打开某个应 ...

  4. linux删除文件夹下所有文件_本地文件快速搜索+批量删除空文件夹

    本号所有资源版权归原作者所有,如有侵权请加小编微信删除.本号免费分享,仅供学习交流,下载后24小时内请自觉删除,切勿用于商业用途,否则后果自负! 今天第一个分享是一个本地文件快速搜索神器Everyth ...

  5. 2019最新版本的PanDownload纯净版,网盘满速下载和搜索神器,追剧和动漫新番必不可少的下载工具【亲测有效】

    PanDownload是百度网盘的第三方下载神器,它支持快速搜索功能,快速找到你想要的东西,还支持满速下载,可谓是不可多得的下载神器. 下载地址:http://t.cn/EobUOTS 城通网盘下载地 ...

  6. mac搜索服务器文件,ProFind——文件搜索神器

    原标题:ProFind--文件搜索神器 ProFind for Mac版是一款实用的文件搜索软件,具有强大的功能和出色的性能,可为macOS提供高级文件搜索.并支持自然语言查询,应用程序启动,隐藏位置 ...

  7. Stark 组件:快速开发神器 —— 锦上添花

    Stark 组件:快速开发神器 -- 锦上添花 一.分页 二.排序 三.搜索 1.关键字搜索 2.组合搜索 四.批量操作 经过前面几个篇章,我们的 Stark 组件已经能够批量生成 URL,快速实现增 ...

  8. Stark 组件:快速开发神器 —— 页面显示

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

  9. Stark 组件:快速开发神器 —— 自动生成 URL

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

最新文章

  1. 揭开Annotation的面纱
  2. 用P3P header解决IE下iframe跨域访问时候session丢失的问题
  3. 从这个11.11开始,终结数据结构与算法的噩梦
  4. html的id不能有.吗,html – 哪些DOM元素不能接受id?
  5. Android隐式启动匹配:action,category,data
  6. 开源备份web_13个开源备份解决方案
  7. Django表单字段汇总
  8. 面试题_翻转句子中单词的顺序
  9. matlab四节点矩形单元的应变,四节点矩形单元有限元分析
  10. KeyStore(示例,出错代码)
  11. 通州区机器人比赛活动总结_机器人大赛总结报告
  12. linux怎么查看.pcd文件,PCD文件格式详解及在PCL下读取PCD文件
  13. sendcloud php 群发,laravel sendcloud发送邮件
  14. USB (十三)2022-04-02
  15. systemd wsl 测试笔记
  16. [机器学习与scikit-learn-15]:算法-决策树-分类问题代码详解
  17. 均值滤波与中值滤波(python实现)
  18. Office 365平台及其价值主张
  19. GO分析相关工具汇总
  20. MySQL酒店管理系统课程设计_酒店管理系统的设计与实现(PHP,MySQL)(含录像)

热门文章

  1. 行车记录仪com.android,如何在android系统行车记录仪安装新软件
  2. How to use segment advisor
  3. HSI、HSV、RGB、CMY、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV等颜色模型简介
  4. @Scheduled(cron = * * * * * *) cron表达式详解
  5. 【沃顿商学院学习笔记】商业基础——Operation Management:02运营管理活动中的详细流程分析
  6. 家乐福618保卫战二-零售O2O场景中的万级并发交易情况下的极限性能调优
  7. matlab atem(),ATEM-Ⅱ瞬变电磁仪数据处理软件的研制与应用
  8. windows系统搭建portal服务器,Windows下安装部署OpenPortal1.1
  9. 电路中滤波电容和退耦电容_电容的多种作用,定时,耦合,滤波,去耦,微分,分频...
  10. 第五天 黑马十次方 NUXT框架、前台的搭建、前台活动模块的功能、前台招聘模块的功能