diff --git a/Cigarette/alg_jd.cpp b/Cigarette/alg_jd.cpp index 0ca6301..0e5565b 100644 --- a/Cigarette/alg_jd.cpp +++ b/Cigarette/alg_jd.cpp @@ -1,8 +1,8 @@ #include "alg_jd.h" -#include "common.h" -// 主界面基本参数配置文件 -#define CONFIGURE_FILE "D:/conf/conf.txt" +#include //所需的库文件 + extern SysConf g_sys_conf; + // Remove the bounding boxes with low confidence using non-maxima suppression static void post_process(cv::Mat& frame, std::vector& outs, std::vector > &results); @@ -22,40 +22,8 @@ static int inpHeight = 416; // Height of network's input image static std::vector classes; -bool AlgJd::init() +bool AlgJd::init(QString model_path, QString jpg_path) { - QString model_path; - QString jpg_path; - std::fstream cfg_file; - cfg_file.open(CONFIGURE_FILE); - if (!cfg_file.is_open()) - { - std::cout << "Error: Open config file " << CONFIGURE_FILE << std::endl; - return false; - } - while (!cfg_file.eof()) - { - char tmp[256] = ""; - cfg_file.getline(tmp, 256); - std::string line(tmp); - if (line.length() > 0) - { - size_t pos = line.find('='); - std::string tmp_key = line.substr(0, pos); - if (tmp_key == "MODELPATH") - { - model_path = line.substr(pos + 1).c_str(); - } - if (tmp_key == "JPGPATH") - { - jpg_path = line.substr(pos + 1).c_str(); - } - } - } - cfg_file.close(); - - //std::cout << "MODEL PATH IS " << model_path.toStdString().c_str() << std::endl; - // Load names of classes std::string classesFile = "D:/model/jd.names"; diff --git a/Cigarette/alg_jd.h b/Cigarette/alg_jd.h index ac12df2..25263f2 100644 --- a/Cigarette/alg_jd.h +++ b/Cigarette/alg_jd.h @@ -8,11 +8,11 @@ #include #include #include - +#include "common.h" class AlgJd { public: - bool init(); + bool init(QString model_path, QString jpg_path); bool test_detect(); bool test_detect_batcht(int shoot); int detect(cv::Mat& in, cv::Mat &out, std::vector > &results); diff --git a/Cigarette/cigarette.cpp b/Cigarette/cigarette.cpp index a7042ce..dd1453e 100644 --- a/Cigarette/cigarette.cpp +++ b/Cigarette/cigarette.cpp @@ -8,23 +8,7 @@ #include #include "exportData.h" -// 主界面基本参数配置文件 -#define CONFIGURE_FILE "D:/conf/conf.txt" -// 相机旋转角度配置文件 -#define ROTATE_FILE "D:/conf/rotate.txt" -#define MODBUS_CONFIGURE_FILE "D:/conf/modbus.txt" -#define PLC_CONFIG_FILE "D:/conf/plc.txt" -#define SELECT_RECTS_FILE "D:/conf/SelectRects%d%d.txt" -#define STATISTIC_FILE "D:/conf/camera%d_statistic.txt" -#define ALARM_RECORD_FILE "alarm.txt" -#define OUTPUT_HIGH_WIDTH 20000 //输出信号的脉冲宽度,微秒 - -#define OP_TIME 300 //OP权限时长(默认300秒) - -#define ADMIN_TIME 600 //ADMIN权限时长(默认300秒) - -#define STOP_SECONDS 3 //检查多少次不变触发自动换班 int g_op_time; //OP权限时长(默认300秒) @@ -42,7 +26,9 @@ QDateTime g_ts_start; extern SingleCamInfoStruct SingleCamInfo[NumberOfSupportedCameras]; AlgJd alg_jd[NumberOfSupportedCameras]; //检测胶点的AI算法 - +#ifdef __DEBUG +AlgJd alg_test;//test AI算法 +#endif QThread* pThread[NumberOfSupportedCameras]; //巴鲁夫相机相关 @@ -303,7 +289,7 @@ Cigarette::Cigarette(QWidget *parent) { if(SingleCamInfo[i].Detect){ cam_status_mat[i]->setStyleSheet(tr("background-color: rgb(0, 170, 0);")); - if (!alg_jd[i].init()) + if (!alg_jd[i].init(g_sys_conf.model_path,g_sys_conf.jpg_path)) { QMessageBox::information(NULL, QStringLiteral("系统自检失败"), QStringLiteral("AI模型1初始化失败,请检查程序完整性"), QMessageBox::Ok); exit(-1); @@ -311,7 +297,9 @@ Cigarette::Cigarette(QWidget *parent) CreatWorkThread(SingleCamInfo[i].CamClass, i, this); } } - +#ifdef __DEBUG + alg_test.init(g_sys_conf.model_path,g_sys_conf.jpg_path); +#endif //自动打开所有相机 if (g_sys_conf.auto_open == 1) { @@ -668,6 +656,10 @@ void Cigarette::on_btn_setup_released() { dialog_setup = new DialogSetup(this); connect(dialog_setup, SIGNAL(system_exit()), this, SLOT(OnExit())); +#ifdef __DEBUG + connect(dialog_setup, SIGNAL(_testimg()), this, SLOT(TestImg())); + connect(dialog_setup, SIGNAL(_testimgs()), this, SLOT(TestImgs())); +#endif dialog_setup->setModal(true); dialog_setup->show(); dialog_setup->move((this->width() - dialog_setup->width()) / 2, (this->height() - dialog_setup->height()) / 2); @@ -676,7 +668,60 @@ void Cigarette::on_btn_setup_released() QMessageBox::information(NULL, QStringLiteral("权限检查"), QStringLiteral("请先点击解锁按钮,进入管理员模式"), QMessageBox::Ok); } } +#ifdef __DEBUG +void Cigarette::TestImg() +{ + QString srcDirPath = QString::fromStdString(SelectFileOFN()); + //输入图像 + std::cout << "open file------ " << srcDirPath.toStdString() << std::endl; + cv::Mat imagein = cv::imread(srcDirPath.toStdString(), cv::IMREAD_COLOR); + if (!imagein.data) + { + return; + } + std::vector > results; + cv::Mat output; + alg_test.detect(imagein, output,results); + cv::imshow("TestImg", output); + cv::waitKeyEx(1); +} + +void Cigarette::TestImgs() +{ + QString srcDirPath = QString::fromStdString(SelectDirIFD()); + + vector files; + std::cout << "srcDirPath=" << srcDirPath.toStdString() << std::endl; + srcDirPath += "/"; + //获取该路径下的所有文件 + getFiles(srcDirPath.toStdString() + "*.jpg", files); + if (files.size() == 0) + { + QMessageBox::StandardButton result = QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("没有找到图片")); + return; + } + + for (int index = 0; index < files.size(); index++) + { + //输入图像 + std::cout << "open file------ " << files[index] << std::endl; + cv::Mat imagein = cv::imread(srcDirPath.toStdString() + files[index], cv::IMREAD_COLOR); + if (!imagein.data) + { + break; + } + + cv::Mat output; + std::vector > results; + alg_test.detect(imagein, output,results); + cv::imshow("TestImg", output); + int k = cv::waitKeyEx(1); + if (k == 27)break;//ESC键 + QCoreApplication::processEvents(); + } +} +#endif //管理员登陆 void Cigarette::OnAdmin() { diff --git a/Cigarette/cigarette.h b/Cigarette/cigarette.h index 7a24f1d..a8a1e24 100644 --- a/Cigarette/cigarette.h +++ b/Cigarette/cigarette.h @@ -42,10 +42,9 @@ #include #include #include - - #include +#include class QTimer; #define OPEN true @@ -117,8 +116,11 @@ private slots : void OnOp(); void OnExit(); void OnRestart(); - void OnAdmin(); +#ifdef __DEBUG + void TestImg(); + void TestImgs(); +#endif private: Ui::CigaretteClass ui; DialogSetupPasswd *dialog_setup_passwd; diff --git a/Cigarette/common.cpp b/Cigarette/common.cpp index de4e86e..ab1697c 100644 --- a/Cigarette/common.cpp +++ b/Cigarette/common.cpp @@ -1,6 +1,12 @@ #include "common.h" #include #include "stdarg.h" +#include +#include +#include +#include +#include + int string_split(std::string str, std::string pattern,std::vector &out) { std::string::size_type pos; @@ -113,4 +119,247 @@ bool CheckSelectRects( } } return false; +} + +void getFiles(std::string path, std::vector& files) +{ + //鏂囦欢鍙ユ焺 + intptr_t hFile = 0; + //鏂囦欢淇℃伅 + struct _finddata_t fileinfo; + std::string p; + if ((hFile = _findfirst(p.assign(path).c_str(), &fileinfo)) != -1) + { + do + { + if (!(fileinfo.attrib & _A_SUBDIR)) + { + files.push_back(fileinfo.name); + } + } while (_findnext(hFile, &fileinfo) == 0); + _findclose(hFile); + } +} + +std::string WstringToString(std::wstring wstr) +{ + int nLen = wcslen(wstr.c_str()); + std::string str; + str.resize(nLen * 2, ' '); + int nResult = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wstr.c_str(), -1, (LPSTR)str.c_str(), nLen * 2, NULL, NULL); + return str; +} + +/* +TCHAR*杞琧har* +*/ +char* LPWSTR2LPSTR(LPWSTR lpwszStrIn) +{ + LPSTR pszOut = NULL; + if (lpwszStrIn != NULL) { + int nInputStrLen = wcslen(lpwszStrIn); + int nOutputStrLen = WideCharToMultiByte(CP_ACP, 0, lpwszStrIn, nInputStrLen, NULL, 0, 0, 0) + 2; + pszOut = new char[nOutputStrLen]; + if (pszOut != NULL) { + memset(pszOut, 0x00, nOutputStrLen); + WideCharToMultiByte(CP_ACP, 0, lpwszStrIn, nInputStrLen, pszOut, nOutputStrLen, 0, 0); + } + } + return pszOut; +} + +//浠巗tring s鐨勪綅缃畃os寮濮嬶紝鍚戝悗鎵撅紝鎵惧埌绗竴涓瓑浜巟鐨勪綅缃繑鍥炲叾浣嶇疆 +//鎵惧埌锛岃繑鍥炴壘鍒扮殑浣嶇疆锛屾壘涓嶅埌杩斿洖-1 +int __find(const std::string s, const int start, const char x) { + if (start >= s.length())return -1; + for (int i = start; i < s.length(); ++i) { + if (s[i] == x) return i; + } + return -1; +} +//鍙屾枩鏉犺浆鍗曟枩鏉 +void pathConvert_Double2Single(std::string& s) { + int start = 0; + while (start < s.length()) { + int pos = s.find('\\', start); + if (pos == -1)break; + s.replace(pos, 1,"/"); + start = pos + 1; + } +} + +int CALLBACK BrowseCallbackProc( + HWND hwnd, UINT uMsg, LPARAM /*lParam*/, LPARAM lpData) +{ + LPWSTR buf[1000]; + GetCurrentDirectory(1000, (LPWSTR)buf); + if (uMsg == BFFM_INITIALIZED) + { + SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM)TRUE, (LPARAM)buf); + } + + return 0; +} + +std::string SelectDirBRI() +{ + BROWSEINFO bi; + bi.hwndOwner = NULL; + bi.pidlRoot = CSIDL_DESKTOP; + bi.pszDisplayName = NULL; + bi.lpszTitle = NULL;//鏄?浣嶄簬瀵硅瘽妗嗗乏涓婇儴鐨勬彁?淇℃伅 + bi.ulFlags = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;//鏈夋柊寤?浠跺す鎸夐挳 + bi.lpfn = BrowseCallbackProc; + bi.iImage = 0; + LPITEMIDLIST pidl = SHBrowseForFolder(&bi);//璋?閫夋嫨瀵硅瘽妗 + if (pidl == NULL) + { + std::cout << "娌℃湁閫夋嫨鐩綍" << std::endl; + return ""; + } + TCHAR strFolder[MAX_PATH]; + SHGetPathFromIDList(pidl, strFolder); + std::string sFolder = ""; + sFolder = WstringToString(strFolder); + int pos = sFolder.find('\0'); + if (pos) + { + sFolder = sFolder.substr(0, pos); + } + return sFolder; +} + +std::string SelectFileOFN() +{ + OPENFILENAME ofn;//#include + TCHAR szOpenFileNames[80 * MAX_PATH] = { 0 }; + TCHAR szPath[MAX_PATH]; + TCHAR szFileName[80 * MAX_PATH]; + + int nLen = 0; + TCHAR* p = NULL; + ZeroMemory(&ofn, sizeof(ofn)); + + // 缁撴瀯浣撳ぇ灏 + ofn.lStructSize = sizeof(ofn); + // 鎷ユ湁鐫绐楀彛鍙ユ焺 + ofn.hwndOwner = NULL; + // 鎺ユ敹杩斿洖鐨勬枃浠跺悕锛屾敞鎰忕涓涓瓧绗﹂渶瑕佷负NULL + ofn.lpstrFile = szOpenFileNames; + // 缂撳啿鍖洪暱搴 + ofn.nMaxFile = sizeof(szOpenFileNames); + // _T鍙浛鎹负TEXT锛屼娇鐢╛T闇瑕佸紩tchar.h + ofn.lpstrFile[0] = _T('\0'); + // 璁剧疆杩囨护 + ofn.lpstrFilter = _T("All\0*.*\0.mp4\0*.mp4\0.avi\0*.avi\0.mkv\0*.mkv\0.rmvb\0*.rmvb\0.f4v\0*.f4v\0.flv\0*.flv\0.m4v\0*.m4v\0.mpg\0*.mpg\0\0"); + // 杩囨护鍣ㄧ储寮 + ofn.nFilterIndex = 1; + // 绐楀彛鏍囬 + ofn.lpstrTitle = _T("璇烽夋嫨鍥剧墖"); + + // 鏂囦欢蹇呴』瀛樺湪銆佸厑璁稿閫夈侀殣钘忓彧璇婚夐」銆佸璇濇浣跨敤璧勬簮绠$悊鍣ㄩ鏍肩殑鐢ㄦ埛鐣岄潰 + // 瀹樻柟鏂囨。锛歨ttps://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamea + ofn.Flags = OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_EXPLORER; + + // 濡傛灉鎵撳紑鏂囦欢澶辫触锛屽垯涓嶆搷浣 + if (!::GetOpenFileName(&ofn)) { + return ""; + } + + // 鎶婄涓涓枃浠跺悕鍓嶇殑澶嶅埗鍒皊zPath,鍗: + // 濡傛灉鍙変簡涓涓枃浠,灏卞鍒跺埌鏈鍚庝竴涓'/' + // 濡傛灉閫変簡澶氫釜鏂囦欢,灏卞鍒跺埌绗竴涓狽ULL瀛楃 + lstrcpyn(szPath, szOpenFileNames, ofn.nFileOffset); + + // 褰撳彧閫変簡涓涓枃浠舵椂,涓嬮潰杩欎釜NULL瀛楃鏄繀闇鐨. + // 杩欓噷涓嶅尯鍒寰呴変簡涓涓拰澶氫釜鏂囦欢鐨勬儏鍐 + szPath[ofn.nFileOffset] = '\0'; + nLen = lstrlen(szPath); + + // 濡傛灉閫変簡澶氫釜鏂囦欢,鍒欏繀椤诲姞涓'//' + if (szPath[nLen - 1] != '\\') { + lstrcat(szPath, _T("\\")); + } + + // 鎶婃寚閽堢Щ鍒扮涓涓枃浠 + p = szOpenFileNames + ofn.nFileOffset; + + // 瀵箂zFileName杩涜娓呴浂 + ZeroMemory(szFileName, sizeof(szFileName)); + + // 瀹氫箟瀛楃涓诧紝鐢ㄤ簬鎷兼帴鎵閫夌殑鎵鏈夋枃浠剁殑瀹屾暣璺緞 + std::string str = ""; + + while (*p) { + // 璇诲彇鏂囦欢鍚 + std::string fileName = LPWSTR2LPSTR(p); + // 璇诲彇鏂囦欢鎵鍦ㄦ枃浠跺す璺緞 + std::string filePath = LPWSTR2LPSTR(szPath); + // 鎷兼帴鏂囦欢瀹屾暣璺緞 + std::string completePath = filePath + fileName; + // 鎷兼帴瀛楃涓 + str += completePath; + //绉昏嚦涓嬩竴涓枃浠 + p += lstrlen(p) + 1; + } + + return str; + // 灏唖tring杞负char* + //char* strc = new char[strlen(str.c_str()) + 1]; + //const char* cc = str.c_str(); + //strcpy_s(strc, str.size() + 1, cc); +} + +//https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog?redirectedfrom=MSDN +std::string SelectDirIFD() +{ + std::string folderpath = ""; + // CoCreate the File Open Dialog object. + IFileDialog* pfd = NULL; + HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&pfd)); + if (SUCCEEDED(hr)) + { + // Set the options on the dialog. + DWORD dwFlags; + + // Before setting, always get the options first in order + // not to override existing options. + hr = pfd->GetOptions(&dwFlags); + if (SUCCEEDED(hr)) + { + // In this case, get shell items only for file system items. + hr = pfd->SetOptions(dwFlags | FOS_PICKFOLDERS); + if (SUCCEEDED(hr)) + { + // Show the dialog + hr = pfd->Show(NULL); + if (SUCCEEDED(hr)) + { + // Obtain the result once the user clicks + // the 'Open' button. + // The result is an IShellItem object. + IShellItem* psiResult; + hr = pfd->GetResult(&psiResult); + if (SUCCEEDED(hr)) + { + // We are just going to print out the + // name of the file for sample sake. + PWSTR pszFilePath = NULL; + hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH,&pszFilePath); + if (SUCCEEDED(hr)) + { + folderpath = LPWSTR2LPSTR(pszFilePath); + CoTaskMemFree(pszFilePath); + } + psiResult->Release(); + } + } + } + } + pfd->Release(); + } + return folderpath; } \ No newline at end of file diff --git a/Cigarette/common.h b/Cigarette/common.h index 83b7d20..c510d35 100644 --- a/Cigarette/common.h +++ b/Cigarette/common.h @@ -2,15 +2,15 @@ #include #include -#include "basecamera.h" #include +#include "basecamera.h" #include "QtCore\qdatetime.h" -//#define __DEBUG //debug信息输出功能 -#define __UDPSend //网络发送功能 +#define __DEBUG //debug信息输出功能 +//#define __UDPSend //网络发送功能 #define USB_BASLER_NEW_FW //使用basler定制固件 //#define IMM_PROCESS //拍照后立马处理,不等校验信号 -#define IMM_FEED_BACK //处理完后立马反馈,不等校验信号 +//#define IMM_FEED_BACK //处理完后立马反馈,不等校验信号 //#define ONE_TIME_SHIFT //错开一拍发送反馈(默认错开两次) #define AI_WARM_UP //AI识别开始前的热身动作 //#define LICENSE_VERIFY //开启license文件校验 @@ -32,8 +32,30 @@ #define DEBUG(format, ...) #endif +// 主界面基本参数配置文件 +#define CONFIGURE_FILE "../conf/conf.txt" +// 相机旋转角度配置文件 +#define ROTATE_FILE "../conf/rotate.txt" +#define MODBUS_CONFIGURE_FILE "../conf/modbus.txt" +#define PLC_CONFIG_FILE "../conf/plc.txt" +#define SELECT_RECTS_FILE "../conf/SelectRects%d%d.txt" +#define STATISTIC_FILE "../conf/camera%d_statistic.txt" +#define ALARM_RECORD_FILE "alarm.txt" + +#define OUTPUT_HIGH_WIDTH 20000 //输出信号的脉冲宽度,微秒 + +#define OP_TIME 300 //OP权限时长(默认300秒) + +#define ADMIN_TIME 600 //ADMIN权限时长(默认300秒) + +#define STOP_SECONDS 3 //检查多少次不变触发自动换班 + int string_split(std::string str, std::string pattern,std::vector &out); std::string format(const char *pszFmt, ...); +void getFiles(std::string path, std::vector& files); +std::string SelectDirBRI(); +std::string SelectFileOFN(); +std::string SelectDirIFD(); class SysConf { public: @@ -65,6 +87,8 @@ public: int MonitorPort; int FeedbackPort; int FilePort; + QString model_path; + QString jpg_path; //MonitorPort为数据端口 //MonitorPort+NumberOfSupportedCameras为图像端口 //MonitorPort+NumberOfSupportedCameras*2为发送命令端口,也就是FeedbackPort @@ -201,5 +225,5 @@ public: uint8_t Flag[2] = {0}; std::vector RectVet[2]; }; -void DrawSelectRects(cv::Mat input, DisplayLabelConf &t_DisplayLabelConf, int Cnt); -bool CheckSelectRects(cv::Mat input, std::vector > > &VecRects,int VecCnt, DisplayLabelConf &t_DisplayLabelConf, int LabelCnt); \ No newline at end of file +void DrawSelectRects(cv::Mat input, DisplayLabelConf& t_DisplayLabelConf, int Cnt); +bool CheckSelectRects(cv::Mat input, std::vector > >& VecRects, int VecCnt, DisplayLabelConf& t_DisplayLabelConf, int LabelCnt); diff --git a/Cigarette/dialogsetup.cpp b/Cigarette/dialogsetup.cpp index 3264be4..b710a04 100644 --- a/Cigarette/dialogsetup.cpp +++ b/Cigarette/dialogsetup.cpp @@ -70,6 +70,10 @@ DialogSetup::DialogSetup(QWidget * parent) : QDialog(parent) { break; } // +#ifndef __DEBUG + ui.pushButton_testimg->setVisible(false); + ui.pushButton_testimgs->setVisible(false); +#endif } DialogSetup::~DialogSetup() { @@ -623,3 +627,13 @@ void DialogSetup::recMsgFromChangeShift(QTime timeA, QTime timeB, QTime timeC) g_sys_conf.shiftB.setHMS(timeB.hour(), timeB.minute(), 0); g_sys_conf.shiftC.setHMS(timeC.hour(), timeC.minute(), 0); } +#ifdef __DEBUG +void DialogSetup::on_pushButton_testimg_released() +{ + emit _testimg(); +} +void DialogSetup::on_pushButton_testimgs_released() +{ + emit _testimgs(); +} +#endif \ No newline at end of file diff --git a/Cigarette/dialogsetup.hpp b/Cigarette/dialogsetup.hpp index 2095575..9e39c27 100644 --- a/Cigarette/dialogsetup.hpp +++ b/Cigarette/dialogsetup.hpp @@ -2,7 +2,7 @@ #include #include "ui_dialogsetup.h" #include "basecamera.h" - +#include #include #include #include @@ -14,7 +14,10 @@ signals : void sendMsgToShift(QTime timeA, QTime timeB, QTime timeC); void sendMsgToOutput(); void sendMsgToConfig(int ptr[][3]); - +#ifdef __DEBUG + void _testimg(); + void _testimgs(); +#endif private slots : void on_toolButton_keyboard_released(); void on_pushButton_exit_released(); @@ -39,6 +42,10 @@ private slots : void recMsgFromDialogConfig(int ptr[][3]); void recMsgFromChangeShift(QTime timeA, QTime timeB, QTime timeC); +#ifdef __DEBUG + void on_pushButton_testimg_released(); + void on_pushButton_testimgs_released(); +#endif public: DialogSetup(QWidget * parent = Q_NULLPTR); ~DialogSetup(); diff --git a/Cigarette/dialogsetup.ui b/Cigarette/dialogsetup.ui index a196ed4..b29c2d2 100644 --- a/Cigarette/dialogsetup.ui +++ b/Cigarette/dialogsetup.ui @@ -6,8 +6,8 @@ 0 0 - 679 - 800 + 690 + 830 @@ -28,11 +28,17 @@ 0 - -10 - 681 - 831 + 0 + 690 + 830 + + + 0 + 0 + + 0 @@ -46,15 +52,21 @@ 0 - 0 - 670 - 880 + -72 + 675 + 900 + + + 0 + 0 + + 670 - 880 + 900 @@ -1991,6 +2003,46 @@ 娓呯悊鍥剧墖 + + + + 530 + 820 + 131 + 21 + + + + + 寰蒋闆呴粦 + 75 + true + + + + 娴嬭瘯鍗曞紶鍥剧墖 + + + + + + 530 + 850 + 131 + 21 + + + + + 寰蒋闆呴粦 + 75 + true + + + + 娴嬭瘯澶氬紶鍥剧墖 + +