ywl
2025-07-03 e14d0fa48b271700281fc285c6549bb2490acecc
Merge branch 'master' of ssh://115.28.86.8:29418/~admin/智能网联_25-0305_617_v1
18个文件已添加
1个文件已删除
367 ■■■■■ 已修改文件
Client/Qt_ZNWL_0702_Client.7z 补丁 | 查看 | 原始文档 | blame | 历史
Client/寇百盛/document/5-项目总结2.docx 补丁 | 查看 | 原始文档 | blame | 历史
Client/徐蔓云/log/日志_徐蔓云_0701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/杨高权/document/日志_杨高权_250625 .doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/杨高权/document/项目总结_杨高权.doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/牛彦江/document/蚂蚁智能网联项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Client/王国壮/document/项目总结.md 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Client/王国壮/log/日志_王国壮_0701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/徐逸凡/document/项目总结.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/林余杰/document/项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Server/林余杰/log/日志_林余杰_20250701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/梁博/document/项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Server/段延冲/log/项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/code/logger.h 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/document/项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/log/日志_王鹏哲_20250629.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/log/日志_王鹏哲_20250630.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/log/日志_王鹏哲_20250701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/胡重阳/document/数据模型预处理--项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Client/Qt_ZNWL_0702_Client.7z
Binary files differ
Client/¿Ü°ÙÊ¢/document/5-ÏîÄ¿×ܽá2.docx
Binary files differ
Client/ÐìÂûÔÆ/log/ÈÕÖ¾_ÐìÂûÔÆ_0701.doc
Binary files differ
Client/Ñî¸ßȨ/document/ÈÕÖ¾_Ñî¸ßȨ_250625 .doc
Binary files differ
Client/Ñî¸ßȨ/document/ÏîÄ¿×ܽá_Ñî¸ßȨ.doc
Binary files differ
Client/Å£Ñå½­/document/ÂìÒÏÖÇÄÜÍøÁªÏîÄ¿×ܽá.docx
Binary files differ
Client/Íõ¹ú׳/document/ÏîÄ¿×ܽá.md
New file
@@ -0,0 +1,33 @@
### 1. **实时环境信息展示模块**
#### **实现方式:**
- **硬件与数据收集:** é€šè¿‡çŽ°åœºä¼ æ„Ÿå™¨ï¼ˆå¦‚æ¸©åº¦ã€æ¹¿åº¦ã€ç²‰å°˜æµ“åº¦ç­‰ï¼‰å®žæ—¶é‡‡é›†çŽ¯å¢ƒæ•°æ®ã€‚è¿™äº›æ•°æ®ä¼ è¾“åˆ°æœåŠ¡å™¨ç«¯ï¼Œé€šè¿‡æŽ¥å£è¿›è¡Œè½¬å‘ã€‚
- **大屏展示:** æ•°æ®é€šè¿‡å‰ç«¯ç•Œé¢å±•示在大屏上,区域划分显示不同信息,包括环境信息、施工进度、小地图、考勤情况和监控摄像头的动态轮播。
- **数据传输:** æ•°æ®ä¸Šä¼ åŽé€šè¿‡æœåŠ¡ç«¯è½¬å‘ç»™æ‰€æœ‰åœ¨çº¿å®¢æˆ·ç«¯ï¼Œå®žçŽ°å®žæ—¶åŒæ­¥ã€‚
#### **解决问题:**
- **数据准确性:** ç”±äºŽä¼ æ„Ÿå™¨æœ¬èº«çš„误差,实时数据可能会出现波动,导致展示不稳定。通过算法优化。
- **异步更新:** å°†æ•°æ®æ›´æ–°çš„æ“ä½œä¸Žç•Œé¢æ¸²æŸ“解耦,避免阻塞主线程,确保大屏展示流畅。
- **MSVC2015与Windows SDK版本兼容问题**:小地图需要使用webenginewidgets模块,所以切换到MSVC2015编译器,又产生兼容问题, é€šè¿‡**仅升级Qt Creator**解决,新版Qt Creator可指定SDK版本。
------
### 2. **警报管理模块**
#### **实现方式:**
- **警报判断:** é’ˆå¯¹çŽ¯å¢ƒæ•°æ®ä¸­çš„æ¸©åº¦ã€æ¹¿åº¦ã€ç²‰å°˜æµ“åº¦ç­‰è®¾ç½®é˜ˆå€¼ï¼Œè¶…å‡ºèŒƒå›´æ—¶è§¦å‘è­¦æŠ¥ã€‚
- **阈值管理:** ç³»ç»Ÿå…è®¸ç®¡ç†å‘˜åŠ¨æ€è°ƒæ•´é˜ˆå€¼ï¼Œç¡®ä¿ç³»ç»Ÿåœ¨ä¸åŒæƒ…å†µä¸‹ä»èƒ½æœ‰æ•ˆæŠ¥è­¦ã€‚
- **警报响应:** å½“警报触发时,硬件端会发出声光警报,软件端会通过服务端推送警报信息到所有在线客户端。若问题未解决,自动派单到值班室处理。
- **警报数据库:** è®¾ç½®â€œé˜ˆå€¼ä¿¡æ¯è¡¨â€å’Œâ€œè­¦æŠ¥ä¿¡æ¯è¡¨â€ï¼Œåˆ†åˆ«å­˜å‚¨æ¯ä¸ªè­¦æŠ¥é¡¹çš„阈值以及发生的具体警报记录。
#### **解决问题:**
- **实时性与稳定性:** è­¦æŠ¥éœ€è¦åœ¨å‘生异常的瞬间触发,如果系统响应延迟或发生错误,可能错过最佳处理时机。
- **界面设计:** ç¡®ä¿è­¦æŠ¥ä¿¡æ¯èƒ½å¤Ÿå®žæ—¶ã€æ¸…晰地展示给管理员,避免信息过载和显示不一致。
- **并发处理:** é€šè¿‡å¹¶å‘和异步技术,保证警报处理和数据更新能够同时进行,提高响应速度。
- **动态界面优化:** è­¦æŠ¥ä¿¡æ¯åº”在主界面突出显示,并确保界面能够快速更新,避免因信息过载导致管理人员遗漏重要信息。
Client/Íõ¹ú׳/log/ÈÕÖ¾_Íõ¹ú׳_0701.doc
Binary files differ
Server/ÐìÒÝ·²/document/ÏîÄ¿×ܽá.doc
Binary files differ
Server/ÁÖÓà½Ü/document/ÏîÄ¿×ܽá.docx
Binary files differ
Server/ÁÖÓà½Ü/log/ÈÕÖ¾_ÁÖÓà½Ü_20250701.doc
Binary files differ
Server/Áº²©/document/ÏîÄ¿×ܽá.docx
Binary files differ
Server/¶ÎÑÓ³å/log/ÏîÄ¿×ܽá.docx
Binary files differ
Server/ÍõÅôÕÜ/code/logger.h
New file
@@ -0,0 +1,334 @@
#pragma once
#include "common.h"
#include <cstring> // ç”¨äºŽstrerror
#include <cstdio>  // ç”¨äºŽstd::rename, std::remove
#include <utility> // ç”¨äºŽstd::forward
// æ—¥å¿—级别枚举
enum class LogLevel {
    TRACE,   // æœ€è¯¦ç»†çš„跟踪信息
    DEBUG,   // è°ƒè¯•信息
    INFO,    // å¸¸è§„信息
    WARNING, // è­¦å‘Šä¿¡æ¯
    ERRORL,  // é”™è¯¯ä¿¡æ¯
    FATAL    // ä¸¥é‡é”™è¯¯
};
// å°†æ—¥å¿—级别转换为字符串
inline const char* levelToString(LogLevel level) {
    switch (level) {
    case LogLevel::TRACE:   return "TRACE";
    case LogLevel::DEBUG:   return "DEBUG";
    case LogLevel::INFO:    return "INFO";
    case LogLevel::WARNING: return "WARNING";
    case LogLevel::ERRORL:  return "ERROR";
    case LogLevel::FATAL:   return "FATAL";
    default:                return "UNKNOWN";
    }
}
// æ—¥å¿—配置结构
struct LogConfig {
    LogLevel minLevel = LogLevel::INFO; // æœ€å°æ—¥å¿—级别
    bool consoleOutput = true;          // æ˜¯å¦è¾“出到控制台
    bool fileOutput = false;            // æ˜¯å¦è¾“出到文件
    std::string logFilePath = "temp.log";// æ—¥å¿—文件路径
    bool includeTimestamp = true;       // æ˜¯å¦åŒ…含时间戳
    bool includeThreadId = false;       // æ˜¯å¦åŒ…含线程ID
    size_t maxFileSize = 10 * 1024 * 1024; // æœ€å¤§æ–‡ä»¶å¤§å° (10MB)
    int maxBackupFiles = 5;             // æœ€å¤§å¤‡ä»½æ–‡ä»¶æ•°
};
class Logger {
public:
    // èŽ·å–æ—¥å¿—å®žä¾‹
    static Logger& instance() {
        static Logger instance;
        return instance;
    }
    // é…ç½®æ—¥å¿—系统
    void configure(const LogConfig& config) {
        std::lock_guard<std::mutex> lock(configMutex_);
        config_ = config;
        // å¦‚果启用文件输出,确保文件已打开
        if (config.fileOutput) {
            openLogFile();
        }
    }
    // è®°å½•日志 (模板方法,支持任何可流式输出的类型)
    template<typename... Args>
    void log(LogLevel level, Args&&... args) {
        if (shutdown_) return;
        // å¤åˆ¶é…ç½®ä»¥æœ€å°åŒ–锁范围
        LogConfig currentConfig;
        {
            std::lock_guard<std::mutex> lock(configMutex_);
            if (level < config_.minLevel) return;
            currentConfig = config_;
        }
        // æž„造日志消息
        std::ostringstream oss;
        formatLogPrefix(oss, level, currentConfig);
        using expander = int[];
        (void)expander {
            0, (void(oss << std::forward<Args>(args)), 0)...
        };
        // æ·»åŠ æ¢è¡Œç¬¦
        oss << '\n';
        std::string message = oss.str();
        // ç›´æŽ¥å†™å…¥æ—¥å¿—
        /*writeLog(message);*/
        // å°†æ—¥å¿—消息加入队列
        {
            std::lock_guard<std::mutex> lock(queueMutex_);
            logQueue_.push(std::move(message));
        }
        // é€šçŸ¥æ—¥å¿—线程有新消息
        queueCond_.notify_one();
    }
    // ä¾¿æ·æ—¥å¿—方法
    template<typename... Args> void trace(Args&&... args) {
        log(LogLevel::TRACE, std::forward<Args>(args)...);
    }
    template<typename... Args> void debug(Args&&... args) {
        log(LogLevel::DEBUG, std::forward<Args>(args)...);
    }
    template<typename... Args> void info(Args&&... args) {
        log(LogLevel::INFO, std::forward<Args>(args)...);
    }
    template<typename... Args> void warning(Args&&... args) {
        log(LogLevel::WARNING, std::forward<Args>(args)...);
    }
    template<typename... Args> void error(Args&&... args) {
        log(LogLevel::ERRORL, std::forward<Args>(args)...);
    }
    template<typename... Args> void fatal(Args&&... args) {
        log(LogLevel::FATAL, std::forward<Args>(args)...);
        flush();
        std::exit(EXIT_FAILURE);
    }
    // åˆ·æ–°æ—¥å¿—缓冲区
    void flush() {
        std::lock_guard<std::mutex> lock(fileMutex_);
        if (logFile_.is_open()) {
            logFile_.flush();
        }
    }
    // æžæž„函数
    ~Logger() {
        shutdown();
        flush();
    }
    // å®‰å…¨å…³é—­æ—¥å¿—系统
    void shutdown() {
        if (shutdown_) return;
        shutdown_ = true;
        queueCond_.notify_all();  // å”¤é†’线程以处理退出
        if (workerThread_.joinable()) {
            workerThread_.join(); // ç­‰å¾…线程结束
        }
        flush();  // æœ€ç»ˆåˆ·æ–°
    }
    // åˆ é™¤æ‹·è´æž„造函数和赋值运算符
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
private:
    LogConfig config_;                      // æ—¥å¿—配置
    std::ofstream logFile_;                 // æ—¥å¿—文件流
    std::mutex configMutex_;                // é…ç½®äº’斥锁
    std::mutex fileMutex_;                  // æ–‡ä»¶æ“ä½œäº’斥锁
    std::atomic<bool> shutdown_{ false };   // å…³é—­æ ‡å¿—
    // æ–°å¢žçº¿ç¨‹å®‰å…¨é˜Ÿåˆ—相关成员
    std::queue<std::string> logQueue_;      // æ—¥å¿—消息队列
    std::mutex queueMutex_;                 // é˜Ÿåˆ—互斥锁
    std::condition_variable queueCond_;     // é˜Ÿåˆ—条件变量
    std::thread workerThread_;              // æ—¥å¿—写入线程
    // ç§æœ‰æž„造函数
    Logger() {
        // å¯åŠ¨æ—¥å¿—å†™å…¥çº¿ç¨‹
        workerThread_ = std::thread(&Logger::processLogs, this);
    };
    // æ—¥å¿—处理线程函数
    void processLogs() {
        while (true) {
            std::unique_lock<std::mutex> lock(queueMutex_);
            // ç­‰å¾…新日志或关闭信号
            queueCond_.wait(lock, [this] {
                return !logQueue_.empty() || shutdown_;
                });
            // å¤„理关闭信号
            if (shutdown_ && logQueue_.empty()) {
                break;
            }
            // å–出所有待处理日志
            std::queue<std::string> tempQueue;
            std::swap(logQueue_, tempQueue);
            lock.unlock();
            // å¤„理所有取出的日志
            while (!tempQueue.empty()) {
                writeLog(tempQueue.front());
                tempQueue.pop();
            }
        }
    }
    // æ ¼å¼åŒ–日志前缀
    void formatLogPrefix(std::ostringstream& oss, LogLevel level, const LogConfig& config) {
        // æ—¥å¿—级别标签
        oss << "[" << levelToString(level) << "] ";
        // æ—¶é—´æˆ³
        if (config.includeTimestamp) {
            auto now = std::chrono::system_clock::now();
            auto in_time_t = std::chrono::system_clock::to_time_t(now);
            auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                now.time_since_epoch()) % 1000;
            std::tm tm;
#ifdef _WIN32
            localtime_s(&tm, &in_time_t);
#else
            localtime_r(&in_time_t, &tm);
#endif
            oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
            oss << '.' << std::setfill('0') << std::setw(3) << ms.count() << " ";
        }
        // çº¿ç¨‹ID
        if (config.includeThreadId) {
            oss << "[Thread:" << std::this_thread::get_id() << "] ";
        }
    }
    // æ‰“开日志文件
    void openLogFile() {
        // å…³é—­å½“前文件(如果已打开)
        if (logFile_.is_open()) {
            logFile_.close();
        }
        // æ£€æŸ¥æ–‡ä»¶å¤§å°ï¼Œå¿…要时轮转
        std::ifstream in(config_.logFilePath, std::ios::binary | std::ios::ate);
        if (in) {
            auto size = in.tellg();
            if (static_cast<size_t>(size) >= config_.maxFileSize) {
                rotateLogFiles();
            }
        }
        in.close();
        // æ‰“开新日志文件
        logFile_.open(config_.logFilePath, std::ios::out | std::ios::app);
        if (!logFile_.is_open()) {
            std::cerr << "Failed to open log file: "
                << config_.logFilePath << " - "
                << errno << std::endl;
        }
    }
    // è½®è½¬æ—¥å¿—文件
    void rotateLogFiles() {
        // åˆ é™¤æœ€æ—§çš„备份文件
        if (config_.maxBackupFiles > 0) {
            std::string oldestFile = config_.logFilePath + "." + std::to_string(config_.maxBackupFiles);
            std::remove(oldestFile.c_str());
            // é‡å‘½åçŽ°æœ‰å¤‡ä»½æ–‡ä»¶
            for (int i = config_.maxBackupFiles - 1; i >= 1; i--) {
                std::string oldName = config_.logFilePath + "." + std::to_string(i);
                std::string newName = config_.logFilePath + "." + std::to_string(i + 1);
                if (fileExists(oldName)) {
                    std::rename(oldName.c_str(), newName.c_str());
                }
            }
            // é‡å‘½åå½“前日志文件为备份1
            if (fileExists(config_.logFilePath)) {
                std::string newName = config_.logFilePath + ".1";
                std::rename(config_.logFilePath.c_str(), newName.c_str());
            }
        }
    }
    // æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å­˜åœ¨
    bool fileExists(const std::string& path) {
        std::ifstream f(path);
        return f.good();
    }
    // å®žé™…写入日志
    void writeLog(const std::string& message) {
        LogConfig currentConfig;
        {
            std::lock_guard<std::mutex> configLock(configMutex_);
            currentConfig = config_;
        }
        // è¾“出到控制台
        if (currentConfig.consoleOutput) {
            if (message.find("[ERROR]") != std::string::npos ||
                message.find("[FATAL]") != std::string::npos) {
                std::cerr << message;
            }
            else {
                std::cout << message;
            }
        }
        // è¾“出到文件
        if (currentConfig.fileOutput) {
            std::lock_guard<std::mutex> fileLock(fileMutex_);
            if (!logFile_.is_open() || !logFile_.good()) {
                openLogFile();
            }
            if (logFile_.good()) {
                logFile_ << message;
                logFile_.flush(); // å®žæ—¶åˆ·æ–°åˆ°ç£ç›˜
                // æ£€æŸ¥æ–‡ä»¶å¤§å°
                auto pos = logFile_.tellp();
                if (static_cast<size_t>(pos) >= currentConfig.maxFileSize) {
                    logFile_.close();
                    rotateLogFiles();
                    logFile_.open(currentConfig.logFilePath, std::ios::out | std::ios::app);
                }
            }
        }
    }
};
// æ—¥å¿—宏定义 - æä¾›æ–‡ä»¶åå’Œè¡Œå·ä¿¡æ¯
#define LOG_TRACE(...)   Logger::instance().trace("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_DEBUG(...)   Logger::instance().debug("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_INFO(...)    Logger::instance().info(__VA_ARGS__)
#define LOG_WARN(...)    Logger::instance().warning("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_ERROR(...)   Logger::instance().error("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_FATAL(...)   Logger::instance().fatal("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
Server/ÍõÅôÕÜ/document/ÏîÄ¿×ܽá.docx
Binary files differ
Server/ÍõÅôÕÜ/log/ÈÕÖ¾_ÍõÅôÕÜ_20250629.doc
Binary files differ
Server/ÍõÅôÕÜ/log/ÈÕÖ¾_ÍõÅôÕÜ_20250630.doc
Binary files differ
Server/ÍõÅôÕÜ/log/ÈÕÖ¾_ÍõÅôÕÜ_20250701.doc
Binary files differ
Server/ºúÖØÑô/document/Êý¾ÝÄ£ÐÍÔ¤´¦Àí--ÏîÄ¿×ܽá.docx
Binary files differ