unknown
2025-07-03 285129506509321686aeea3e34ad255d0db7a22b
Merge branch 'master' of ssh://115.28.86.8:29418/~admin/智能网联_25-0305_617_v1
1 文件已重命名
21个文件已添加
412 ■■■■■ 已修改文件
Client/Qt_ZNWL_0702_Client.7z 补丁 | 查看 | 原始文档 | blame | 历史
Client/于文龙/code/project_client_permission_management.rar 补丁 | 查看 | 原始文档 | blame | 历史
Client/于文龙/document/项目总结.txt 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Client/于文龙/log/日志-于文龙-250702.doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/寇百盛/document/5-项目总结2.docx 补丁 | 查看 | 原始文档 | blame | 历史
Client/徐蔓云/log/日志_徐蔓云_0701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/杨高权/document/项目总结_杨高权.doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/牛彦江/document/蚂蚁智能网联项目总结.docx 补丁 | 查看 | 原始文档 | blame | 历史
Client/王国壮/document/项目总结.md 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Client/王国壮/log/日志_王国壮_0701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Client/陈豪/document/项目总结.txt 24 ●●●●● 补丁 | 查看 | 原始文档 | 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/ÓÚÎÄÁú/code/project_client_permission_management.rar
Binary files differ
Client/ÓÚÎÄÁú/document/ÏîÄ¿×ܽá.txt
New file
@@ -0,0 +1,21 @@
1.负责的模块及实现
    æˆ‘所完成的项目模块为权限管理模块和客户端更新模块;
    æƒé™ç®¡ç†æ¨¡å—:是对整个智能工地所有用户的管理员、报表导出、日志查询等9大权限的管理;需要用到两个数据库表(角色权限表、用户注册表),
    åœ¨Ui界面上,分为3部分,第一部分为查询,用户名、工号、注册时间段、部门等相关信息在对应lineEdit上输入完成后,点击查询按钮,将输入的文本信息通过socket网
    ç»œé€šä¿¡å‘送给服务端,服务端通过与用户注册表中的相关数据进行比较,完成后将相关数据(包含角色权限表中的角色对应权限)打包发送回客户端,客户端完成解包操作,
    å°†ä¿¡æ¯åœ¨Ui界面的tableView上展示;ui界面的第三个部分就是是具体的权限管理部分,使用checkBox选择对应的权限,同时角色拥有的权限在查询成功后也会对应的展
    ç¤ºå‡ºæ¥ï¼›å½“修改权限后,点击保存按钮,会将checkBox对应的每一个权限的状态发送回服务端,将用户权限表进行更新,以保证下次重新进入权限管理模块,用户的权限是
    æœ€æ–°çš„æƒé™çŠ¶æ€ã€‚
    å®¢æˆ·ç«¯æ›´æ–°æ¨¡å—:是打开更新界面,点击ui界面设置的检查更新会连接到服务端将当前版本的版本号发送给服务端;服务端响应,对版本号进行比较,判断是否更新,如果需
    è¦æ›´æ–°ï¼Œå®¢æˆ·ç«¯å¼¹å‡ºå¯¹åº”çš„Box对话框让用户选择对应的更新方式(全量更新、增量更新),使用processBar进度条和标签(xx%)来查看更新进度,下方的TextEdit用来
    æŸ¥çœ‹è¯¦ç»†çš„æ—¥å¿—信息(更新过程中的操作和状态变化等);同样有数据库表(版本信息表),用来存储相关信息;其中的断点重传是在每次更新前都要先进行的一个检查,根据
    èµ·å§‹ä½ç½®æ¥åˆ¤æ–­è¦è¿›è¡Œæ–­ç‚¹é‡ä¼ è¿˜æ˜¯ä¸‹è½½ï¼Œåœ¨å®Œæˆæ–­ç”µé‡ä¼ åŽï¼Œè¦å°†ä¹‹å‰çš„æ–­ç‚¹è®°å½•清楚以保证不影响后续的更新下载
    åœ¨è¿‡ç¨‹é‡åˆ°çš„问题:
    æƒé™ç®¡ç†æ¨¡å—与与客户端更新模块都有怎么去和服务端建立网络通信以完成数据的收发相关操作,将数据或者相关的配置文件完成到客户端下
    åŠŸèƒ½çš„ç›¸å…³å®žçŽ°ç”±ç›¸å…³å¤§æ¨¡åž‹çš„å¸®åŠ©ï¼Œèƒ½æž„å®žçŽ°ç†è§£ï¼Œä½†è¿˜éœ€ä¼˜åŒ–ï¼Œä¸Žå¸‚é¢ä¸Šçš„ç›¸å…³åº”ç”¨çš„åŠŸèƒ½ç»†èŠ‚ä¸Šå·®è·å¾ˆå¤§
Client/ÓÚÎÄÁú/log/ÈÕÖ¾-ÓÚÎÄÁú-250702.doc
Binary files differ
Client/¿Ü°ÙÊ¢/document/5-ÏîÄ¿×ܽá2.docx
Binary files differ
Client/ÐìÂûÔÆ/log/ÈÕÖ¾_ÐìÂûÔÆ_0701.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
Client/³ÂºÀ/document/ÏîÄ¿×ܽá.txt
New file
@@ -0,0 +1,24 @@
一、模块实现说明
1、地图显示模块
基于 QWebEngineView å®žçŽ°åœ°å›¾æ˜¾ç¤ºï¼Œé€šè¿‡æœ¬åœ° HTML æ–‡ä»¶åŠ è½½ç™¾åº¦åœ°å›¾ JavaScript API,
使用 WebChannel å®žçް Qt ä¸Ž JavaScript é€šä¿¡ï¼Œå®žçŽ°åœ°å›¾åˆå§‹åŒ–å’Œé…ç½®ç®¡ç†ã€‚
2、设备管理模块
定义 DeviceInfo ç»“构体来存储设备的基本信息,包括设备 ID、名称、经纬度和状态等。
使用 QMap æ•°æ®ç»“构存储设备数据,方便进行设备的增删改查操作。
通过状态枚举对设备的不同状态(如在线、离线、故障)进行管理。
3、 æ•°æ®åŒæ­¥æ¨¡å—
提供设备信息的本地保存功能,确保数据在本地的持久化存储。
设计数据导入导出接口,方便数据的迁移和备份。
支持设备信息的实时更新,当数据发生变更时,系统自动同步数据。
二、遇到的问题及解决方案
1、地图无法加载:增加页面加载超时时间的设置,同时实现自动重试机制。优化 WebEngine çš„全局配置,
添加加载状态提示,让用户了解加载进度。
2、设备状态更新不及时,显示不准确:实现状态更新队列,确保状态按顺序更新。
添加状态变更验证机制,保证状态的准确性。使用状态缓存机制,减少频繁的数据交互。
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