生成代码工程

This commit is contained in:
root 2026-06-09 02:34:04 +00:00
parent 5a43beea38
commit b509381293
18 changed files with 19946 additions and 2 deletions

43
CMakeLists.txt Normal file
View File

@ -0,0 +1,43 @@
cmake_minimum_required(VERSION 3.14)
project(odf-management VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# MSVC UTF-8 support
if (MSVC)
add_compile_options(/utf-8)
endif()
# ---- Main executable ----
add_executable(odf_manager
src/main.cpp
src/app.cpp
src/odf_unit.cpp
src/adapter_interface.cpp
src/naming_helper.cpp
src/config_template.cpp
src/project_milestone.cpp
)
target_include_directories(odf_manager
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# ---- Test executable ----
add_executable(basic_test
tests/basic_test.cpp
src/app.cpp
src/odf_unit.cpp
src/adapter_interface.cpp
src/naming_helper.cpp
src/config_template.cpp
src/project_milestone.cpp
)
target_include_directories(basic_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)

View File

@ -1,3 +1,80 @@
# 7
# ODF 光纤配线单元管理工具 (ODF Management)
暂无描述
## 概述
本项目提供了一套标准化的 **ODFOptical Distribution Frame光纤配线单元** 管理软件,
涵盖单元结构设计、适配器与连接器集成、编号命名管理、典型场景配置生成以及项目进度跟踪等核心功能。
## 功能简介
| 模块 | 说明 |
|------|------|
| **ODF 单元管理** | 支持熔接型/配线型/混合型单元,结构信息与容量管理 |
| **适配器接口管理** | 管理 LC / SC / MPO 等连接器类型、光纤模式、端面类型参数 |
| **命名规则引擎** | 按 `区域-楼层-机房-设备类型-序列号` 规则生成与校验编号 |
| **典型配置模板** | 内置"数据中心 LC 单模预端接"等场景,生成 BOM 物料清单 |
| **项目里程碑** | 跟踪需求、设计、样机、验证、交付等阶段进度 |
## 构建与运行
### 要求
- CMake >= 3.14
- C++17 编译器GCC >= 8, Clang >= 7, MSVC 2019+
### 编译
```bash
mkdir -p build && cd build
cmake ..
cmake --build .
```
### 运行主程序
```bash
./odf_manager
```
### 运行测试
```bash
./basic_test
```
## 工程结构
```
├── CMakeLists.txt
├── README.md
├── include/
│ ├── app.hpp # 应用入口与顶层功能调度
│ ├── odf_unit.hpp # ODF 单元数据结构
│ ├── adapter_interface.hpp # 适配器接口信息
│ ├── naming_helper.hpp # 命名规则校验与生成
│ ├── config_template.hpp # 典型配置模板
│ └── project_milestone.hpp # 项目里程碑数据
├── src/
│ ├── main.cpp # 命令行入口
│ ├── app.cpp # 业务逻辑实现
│ ├── odf_unit.cpp
│ ├── adapter_interface.cpp
│ ├── naming_helper.cpp
│ ├── config_template.cpp
│ └── project_milestone.cpp
└── tests/
└── basic_test.cpp # 单元测试(标准库 assert
```
## 命名规则示例
格式:`区域代码-楼层-机房编号-设备类型-端口容量-序列号-扩展标识`
例:`DC01-F03-TX-ODP-LC24-001-A`
## 技术标准
- 适配器插入损耗 ≤ 0.3dB
- 回波损耗 ≥ 50dB (UPC) / ≥ 60dB (APC)
- 材料阻燃等级 UL94-V0
- 插拔次数 ≥ 500 次

18746
events.ndjson Normal file

File diff suppressed because one or more lines are too long

45
generation.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,75 @@
#ifndef ODF_MANAGEMENT_ADAPTER_INTERFACE_HPP
#define ODF_MANAGEMENT_ADAPTER_INTERFACE_HPP
#include <string>
#include <cstdint>
/// @brief 光纤连接器接口类型
enum class ConnectorType : uint8_t {
LC = 0, ///< LC 连接器
SC = 1, ///< SC 连接器
MPO = 2 ///< MPO 连接器
};
/// @brief 光纤模式
enum class FiberMode : uint8_t {
SingleMode = 0, ///< 单模
MultiMode = 1 ///< 多模
};
/// @brief 端面类型
enum class PolishType : uint8_t {
UPC = 0, ///< UPC (Ultra Physical Contact)
APC = 1 ///< APC (Angled Physical Contact)
};
/**
* @brief
*
* ODF
* 寿
*/
struct AdapterInterface {
ConnectorType connector; ///< 连接器类型
FiberMode fiberMode; ///< 光纤模式
PolishType polish; ///< 端面类型
uint32_t minInsertions; ///< 最小插拔次数≥500
uint32_t portsPerUnit; ///< 每U高度端口密度端口数/U
/**
* @brief
* @param connector
* @param fiberMode
* @param polish
* @param minInsertions
* @param portsPerUnit U高度端口密度
*/
AdapterInterface(ConnectorType connector,
FiberMode fiberMode,
PolishType polish,
uint32_t minInsertions,
uint32_t portsPerUnit);
/// @brief 默认构造函数
AdapterInterface() = default;
/// @brief 连接器类型字符串
[[nodiscard]] std::string connectorString() const;
/// @brief 光纤模式字符串
[[nodiscard]] std::string fiberModeString() const;
/// @brief 端面类型字符串
[[nodiscard]] std::string polishString() const;
/// @brief 返回适配器参数摘要
[[nodiscard]] std::string summary() const;
/**
* @brief
* @return true false
*/
[[nodiscard]] bool checkCompatibility() const;
};
#endif // ODF_MANAGEMENT_ADAPTER_INTERFACE_HPP

109
include/app.hpp Normal file
View File

@ -0,0 +1,109 @@
#ifndef ODF_MANAGEMENT_APP_HPP
#define ODF_MANAGEMENT_APP_HPP
#include "odf_unit.hpp"
#include "adapter_interface.hpp"
#include "naming_helper.hpp"
#include "config_template.hpp"
#include "project_milestone.hpp"
#include <string>
#include <vector>
/**
* @brief ODF
*
* ODF
*
*/
class App {
public:
/// @brief 构造函数
App();
// ==================== ODF 单元管理 ====================
/**
* @brief ODF
* @param unit
*/
void addOdfUnit(const OdfUnit& unit);
/// @brief 列出所有 ODF 单元摘要
[[nodiscard]] std::string listOdfUnits() const;
// ==================== 适配器接口管理 ====================
/**
* @brief
* @param iface
*/
void addAdapterInterface(const AdapterInterface& iface);
/// @brief 列出所有适配器接口
[[nodiscard]] std::string listAdapterInterfaces() const;
// ==================== 命名工具 ====================
/**
* @brief
* @param code
* @return
*/
[[nodiscard]] static std::string validateNamingFormat(const std::string& code);
/**
* @brief
* @return
*/
[[nodiscard]] static std::string generateSampleNaming();
// ==================== 端口密度计算 ====================
/**
* @brief 1U
* @param rackHeightU U
* @param totalPorts
* @return U /U
*/
[[nodiscard]] static uint32_t calculatePortDensity(uint32_t rackHeightU,
uint32_t totalPorts);
// ==================== 配置模板 ====================
/// @brief 获取所有内置模板摘要
[[nodiscard]] std::string listTemplates() const;
/**
* @brief BOM
* @param templateIndex
* @param cabinetCount
* @return BOM
*/
[[nodiscard]] std::string generateBom(size_t templateIndex, uint32_t cabinetCount) const;
// ==================== 项目里程碑 ====================
/**
* @brief
* @param ms
*/
void addMilestone(const ProjectMilestone& ms);
/// @brief 列出所有里程碑
[[nodiscard]] std::string listMilestones() const;
/**
* @brief
* @return
*/
[[nodiscard]] std::string checkMilestonesConstraint() const;
private:
std::vector<OdfUnit> units_;
std::vector<AdapterInterface> adapters_;
std::vector<ProjectMilestone> milestones_;
std::vector<ConfigTemplate> templates_;
};
#endif // ODF_MANAGEMENT_APP_HPP

View File

@ -0,0 +1,53 @@
#ifndef ODF_MANAGEMENT_CONFIG_TEMPLATE_HPP
#define ODF_MANAGEMENT_CONFIG_TEMPLATE_HPP
#include <string>
#include <vector>
#include <cstdint>
/**
* @brief
*
* LC
*
*
*/
struct ConfigTemplate {
std::string scenarioName; ///< 场景名称
std::vector<std::string> components; ///< 使用组件列表(适配器、跳线、收发器等)
std::string topologyRef; ///< 连接拓扑图引用
uint32_t portsPerCabinet; ///< 单柜端口密度
double spareRatio; ///< 备用余量比例(如 0.15 表示 15%
/**
* @brief
* @param scenarioName
* @param components
* @param topologyRef
* @param portsPerCabinet
* @param spareRatio
*/
ConfigTemplate(std::string scenarioName,
std::vector<std::string> components,
std::string topologyRef,
uint32_t portsPerCabinet,
double spareRatio);
/// @brief 默认构造函数
ConfigTemplate() = default;
/**
* @brief BOM
* @param cabinetCount
* @return
*/
[[nodiscard]] std::string generateBomSummary(uint32_t cabinetCount) const;
/// @brief 返回模板基本信息
[[nodiscard]] std::string summary() const;
/// @brief 获取预定义的内置模板列表
[[nodiscard]] static std::vector<ConfigTemplate> builtInTemplates();
};
#endif // ODF_MANAGEMENT_CONFIG_TEMPLATE_HPP

50
include/naming_helper.hpp Normal file
View File

@ -0,0 +1,50 @@
#ifndef ODF_MANAGEMENT_NAMING_HELPER_HPP
#define ODF_MANAGEMENT_NAMING_HELPER_HPP
#include <string>
#include <optional>
/**
* @brief
*
* ODF
* ------
* DC01-F03-TX-ODP-LC24-001-A
*/
class NamingHelper {
public:
/**
* @brief ODF
* @param code
* @return std::nullopt
*/
[[nodiscard]] static std::optional<std::string> validateFormat(const std::string& code);
/**
* @brief ODF
* @param areaCode "DC01"
* @param floor "F03"
* @param room "TX"
* @param deviceType "ODP"
* @param portDesc "LC24"
* @param serial "001"
* @param extension "A"
* @return
*/
[[nodiscard]] static std::string generate(const std::string& areaCode,
const std::string& floor,
const std::string& room,
const std::string& deviceType,
const std::string& portDesc,
const std::string& serial,
const std::string& extension = "");
/// @brief 命名规则的正则表达式模式
static constexpr const char* PATTERN =
"^[A-Z0-9]{2,6}-[A-Z]\\d{2}-[A-Z0-9]{2,6}-[A-Z]{2,6}-[A-Z]{2}\\d{2,4}-\\d{3}(-[A-Z0-9]+)?$";
private:
NamingHelper() = delete;
};
#endif // ODF_MANAGEMENT_NAMING_HELPER_HPP

65
include/odf_unit.hpp Normal file
View File

@ -0,0 +1,65 @@
#ifndef ODF_MANAGEMENT_ODF_UNIT_HPP
#define ODF_MANAGEMENT_ODF_UNIT_HPP
#include <string>
#include <cstdint>
/// @brief ODF 单元类型枚举
enum class OdfUnitType : uint8_t {
Splicing = 0, ///< 熔接型
Patching = 1, ///< 配线型
Hybrid = 2 ///< 混合型
};
/// @brief 安装方式枚举
enum class MountType : uint8_t {
Rack19Inch = 0, ///< 19英寸机架式
WallMounted = 1 ///< 壁挂式
};
/**
* @brief ODF 线
*
* ODF
*/
struct OdfUnit {
std::string id; ///< 编号(按命名规则生成)
OdfUnitType type; ///< 单元类型
uint32_t maxPorts; ///< 最大端口数(容量)
uint32_t heightMm; ///< 高度mm
uint32_t widthMm; ///< 宽度mm
uint32_t depthMm; ///< 深度mm
MountType mountType; ///< 安装方式
/**
* @brief ODF
* @param id
* @param type
* @param maxPorts
* @param heightMm mm
* @param widthMm mm
* @param depthMm mm
* @param mountType
*/
OdfUnit(std::string id,
OdfUnitType type,
uint32_t maxPorts,
uint32_t heightMm,
uint32_t widthMm,
uint32_t depthMm,
MountType mountType);
/// @brief 默认构造函数
OdfUnit() = default;
/// @brief 返回类型字符串表示
[[nodiscard]] std::string typeString() const;
/// @brief 返回安装方式字符串表示
[[nodiscard]] std::string mountString() const;
/// @brief 返回属性摘要
[[nodiscard]] std::string summary() const;
};
#endif // ODF_MANAGEMENT_ODF_UNIT_HPP

View File

@ -0,0 +1,61 @@
#ifndef ODF_MANAGEMENT_PROJECT_MILESTONE_HPP
#define ODF_MANAGEMENT_PROJECT_MILESTONE_HPP
#include <string>
#include <cstdint>
/// @brief 里程碑阶段枚举
enum class MilestoneStage : uint8_t {
Requirements = 0, ///< 需求确认
DesignReview = 1, ///< 设计评审
Prototype = 2, ///< 样机测试
Verification = 3, ///< 验证测试
Delivery = 4 ///< 批量交付
};
/**
* @brief
*
* ODF
* 6 12
*/
struct ProjectMilestone {
MilestoneStage stage; ///< 阶段名称
uint32_t weekStart; ///< 计划开始周(从项目启动算起,第 1 周起)
uint32_t weekEnd; ///< 计划结束周
std::string owner; ///< 负责人
bool completed; ///< 完成状态true 已完成)
/**
* @brief
* @param stage
* @param weekStart
* @param weekEnd
* @param owner
* @param completed
*/
ProjectMilestone(MilestoneStage stage,
uint32_t weekStart,
uint32_t weekEnd,
std::string owner,
bool completed);
/// @brief 默认构造函数
ProjectMilestone() = default;
/// @brief 阶段名称字符串
[[nodiscard]] std::string stageString() const;
/// @brief 返回里程碑摘要
[[nodiscard]] std::string summary() const;
/**
* @brief
* @return true
*
* (Prototype) 6(Delivery) 12
*/
[[nodiscard]] bool checkTimeConstraint() const;
};
#endif // ODF_MANAGEMENT_PROJECT_MILESTONE_HPP

56
src/adapter_interface.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "adapter_interface.hpp"
AdapterInterface::AdapterInterface(ConnectorType connector,
FiberMode fiberMode,
PolishType polish,
uint32_t minInsertions,
uint32_t portsPerUnit)
: connector(connector)
, fiberMode(fiberMode)
, polish(polish)
, minInsertions(minInsertions)
, portsPerUnit(portsPerUnit)
{}
std::string AdapterInterface::connectorString() const {
switch (connector) {
case ConnectorType::LC: return "LC";
case ConnectorType::SC: return "SC";
case ConnectorType::MPO: return "MPO";
default: return "未知";
}
}
std::string AdapterInterface::fiberModeString() const {
switch (fiberMode) {
case FiberMode::SingleMode: return "单模(SM)";
case FiberMode::MultiMode: return "多模(MM)";
default: return "未知";
}
}
std::string AdapterInterface::polishString() const {
switch (polish) {
case PolishType::UPC: return "UPC";
case PolishType::APC: return "APC";
default: return "未知";
}
}
bool AdapterInterface::checkCompatibility() const {
// LC 与 SC 支持单模和多模MPO 常见为多模
if (connector == ConnectorType::MPO && fiberMode == FiberMode::SingleMode) {
return false; // MPO 单模需要特定的角向连接器,简单规则下视作不兼容
}
return true;
}
std::string AdapterInterface::summary() const {
std::string compat = checkCompatibility() ? "兼容" : "不兼容(警告)";
return "适配器接口 [ " + connectorString() + " ]\n"
" 光纤模式: " + fiberModeString() + "\n"
" 端面类型: " + polishString() + "\n"
" 最小插拔次数: " + std::to_string(minInsertions) + "\n"
" 端口密度: " + std::to_string(portsPerUnit) + " 端口/U\n"
" 兼容性检查: " + compat + "\n";
}

127
src/app.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "app.hpp"
#include <iostream>
#include <sstream>
#include <algorithm>
App::App() {
// 加载内置模板
templates_ = ConfigTemplate::builtInTemplates();
}
// ==================== ODF 单元管理 ====================
void App::addOdfUnit(const OdfUnit& unit) {
units_.push_back(unit);
}
std::string App::listOdfUnits() const {
if (units_.empty()) {
return "(无 ODF 单元数据)\n";
}
std::ostringstream oss;
oss << "=== ODF 单元列表 ===\n";
for (size_t i = 0; i < units_.size(); ++i) {
oss << "[" << i << "] " << units_[i].summary();
}
return oss.str();
}
// ==================== 适配器接口管理 ====================
void App::addAdapterInterface(const AdapterInterface& iface) {
adapters_.push_back(iface);
}
std::string App::listAdapterInterfaces() const {
if (adapters_.empty()) {
return "(无适配器接口数据)\n";
}
std::ostringstream oss;
oss << "=== 适配器接口列表 ===\n";
for (size_t i = 0; i < adapters_.size(); ++i) {
oss << "[" << i << "] " << adapters_[i].summary();
}
return oss.str();
}
// ==================== 命名工具 ====================
std::string App::validateNamingFormat(const std::string& code) {
auto result = NamingHelper::validateFormat(code);
if (result.has_value()) {
return result.value();
}
return "编号格式不正确: " + code + "\n规则: " + NamingHelper::PATTERN;
}
std::string App::generateSampleNaming() {
return NamingHelper::generate("DC01", "F03", "TX", "ODP", "LC24", "001", "A");
}
// ==================== 端口密度计算 ====================
uint32_t App::calculatePortDensity(uint32_t rackHeightU, uint32_t totalPorts) {
if (rackHeightU == 0) {
return 0;
}
return totalPorts / rackHeightU;
}
// ==================== 配置模板 ====================
std::string App::listTemplates() const {
if (templates_.empty()) {
return "(无可用配置模板)\n";
}
std::ostringstream oss;
oss << "=== 典型场景配置模板 ===\n";
for (size_t i = 0; i < templates_.size(); ++i) {
oss << "[" << i << "] " << templates_[i].summary();
}
return oss.str();
}
std::string App::generateBom(size_t templateIndex, uint32_t cabinetCount) const {
if (templateIndex >= templates_.size()) {
return "错误:无效的模板索引 " + std::to_string(templateIndex) + "\n";
}
return templates_[templateIndex].generateBomSummary(cabinetCount);
}
// ==================== 项目里程碑 ====================
void App::addMilestone(const ProjectMilestone& ms) {
milestones_.push_back(ms);
}
std::string App::listMilestones() const {
if (milestones_.empty()) {
return "(无里程碑数据)\n";
}
std::ostringstream oss;
oss << "=== 项目里程碑 ===\n";
for (size_t i = 0; i < milestones_.size(); ++i) {
oss << "[" << i << "] " << milestones_[i].summary();
}
return oss.str();
}
std::string App::checkMilestonesConstraint() const {
if (milestones_.empty()) {
return "(无里程碑数据,跳过约束检查)\n";
}
std::ostringstream oss;
oss << "=== 里程碑时间约束检查 ===\n";
bool allOk = true;
for (const auto& ms : milestones_) {
if (!ms.checkTimeConstraint()) {
allOk = false;
oss << "⚠ 阶段 [" << ms.stageString() << "] 时间超限!"
<< " 结束周=" << ms.weekEnd << "\n";
}
}
if (allOk) {
oss << "所有里程碑时间约束均满足 ✓\n";
}
return oss.str();
}

88
src/config_template.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "config_template.hpp"
#include <sstream>
#include <cmath>
ConfigTemplate::ConfigTemplate(std::string scenarioName,
std::vector<std::string> components,
std::string topologyRef,
uint32_t portsPerCabinet,
double spareRatio)
: scenarioName(std::move(scenarioName))
, components(std::move(components))
, topologyRef(std::move(topologyRef))
, portsPerCabinet(portsPerCabinet)
, spareRatio(spareRatio)
{}
std::string ConfigTemplate::generateBomSummary(uint32_t cabinetCount) const {
uint32_t totalPorts = portsPerCabinet * cabinetCount;
uint32_t sparePorts = static_cast<uint32_t>(std::round(totalPorts * spareRatio));
uint32_t totalWithSpare = totalPorts + sparePorts;
std::ostringstream oss;
oss << "场景: " << scenarioName << "\n"
<< " 机柜数量: " << cabinetCount << "\n"
<< " 基础端口量: " << totalPorts << "\n"
<< " 备用余量 (" << (spareRatio * 100.0) << "%): " << sparePorts << "\n"
<< " 含余量总端口数: " << totalWithSpare << "\n"
<< " 组件清单:\n";
for (const auto& comp : components) {
oss << " - " << comp << "\n";
}
oss << " 拓扑参考: " << topologyRef << "\n";
return oss.str();
}
std::string ConfigTemplate::summary() const {
std::ostringstream oss;
oss << "配置模板: " << scenarioName << "\n"
<< " 单柜端口密度: " << portsPerCabinet << "\n"
<< " 备用余量比例: " << (spareRatio * 100.0) << "%\n"
<< " 拓扑: " << topologyRef << "\n";
return oss.str();
}
std::vector<ConfigTemplate> ConfigTemplate::builtInTemplates() {
std::vector<ConfigTemplate> templates;
templates.emplace_back(
"数据中心LC单模预端接",
std::vector<std::string>{
"LC单模适配器(双工)",
"LC单模尾纤(1.5m)",
"LC单模跳线(3m)",
"光纤收发器 SFP+ 10G"
},
"topo_dc_lc_sm_v1",
48,
0.15
);
templates.emplace_back(
"机房SC多模通用配线",
std::vector<std::string>{
"SC多模适配器(双工)",
"SC多模尾纤(2m)",
"SC多模跳线(5m)",
"光纤收发器 SFP 1G"
},
"topo_room_sc_mm_v1",
24,
0.10
);
templates.emplace_back(
"数据中心MPO高密度预端接",
std::vector<std::string>{
"MPO适配器(12芯)",
"MPO干线光缆(12芯)",
"MPO-LC分支跳线",
"光纤收发器 QSFP 40G"
},
"topo_dc_mpo_high_density_v1",
96,
0.20
);
return templates;
}

74
src/main.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "app.hpp"
#include <iostream>
#include <cstdlib>
/**
* @brief
*
* ODF 线
*
*/
int main() {
std::cout << "========================================\n";
std::cout << " ODF 光纤配线单元管理工具 v1.0.0\n";
std::cout << "========================================\n\n";
App app;
// ---- 1. 创建 ODF 单元 ----
std::cout << "--- [1] ODF 单元创建 ---\n";
app.addOdfUnit(OdfUnit(
NamingHelper::generate("DC01", "F03", "TX", "ODP", "LC24", "001", "A"),
OdfUnitType::Patching, 48,
44, 482, 300, MountType::Rack19Inch
));
app.addOdfUnit(OdfUnit(
NamingHelper::generate("DC01", "F03", "RX", "ODS", "SC12", "002", ""),
OdfUnitType::Splicing, 12,
44, 482, 260, MountType::Rack19Inch
));
std::cout << app.listOdfUnits() << "\n";
// ---- 2. 适配器接口 ----
std::cout << "--- [2] 适配器接口创建 ---\n";
app.addAdapterInterface(AdapterInterface(
ConnectorType::LC, FiberMode::SingleMode,
PolishType::APC, 500, 24
));
app.addAdapterInterface(AdapterInterface(
ConnectorType::SC, FiberMode::MultiMode,
PolishType::UPC, 500, 12
));
std::cout << app.listAdapterInterfaces() << "\n";
// ---- 3. 命名规则校验 ----
std::cout << "--- [3] 命名规则校验 ---\n";
std::cout << " 示例编号生成: " << App::generateSampleNaming() << "\n";
std::cout << " 校验 DC01-F03-TX-ODP-LC24-001-A: "
<< App::validateNamingFormat("DC01-F03-TX-ODP-LC24-001-A") << "\n";
std::cout << " 校验 invalid-code: "
<< App::validateNamingFormat("invalid-code") << "\n\n";
// ---- 4. 配置模板与 BOM 生成 ----
std::cout << "--- [4] 典型场景配置模板 ---\n";
std::cout << app.listTemplates() << "\n";
std::cout << "--- [5] BOM 清单生成3 个机柜)---\n";
std::cout << app.generateBom(0, 3) << "\n";
// ---- 5. 项目里程碑 ----
std::cout << "--- [6] 项目里程碑 ---\n";
app.addMilestone(ProjectMilestone(MilestoneStage::Requirements, 1, 2, "张三", true));
app.addMilestone(ProjectMilestone(MilestoneStage::DesignReview, 2, 4, "李四", true));
app.addMilestone(ProjectMilestone(MilestoneStage::Prototype, 4, 6, "王五", false));
app.addMilestone(ProjectMilestone(MilestoneStage::Verification, 7, 9, "赵六", false));
app.addMilestone(ProjectMilestone(MilestoneStage::Delivery, 10, 12, "张三", false));
std::cout << app.listMilestones() << "\n";
std::cout << app.checkMilestonesConstraint() << "\n";
std::cout << "========================================\n";
std::cout << " 演示完毕。\n";
std::cout << "========================================\n";
return EXIT_SUCCESS;
}

32
src/naming_helper.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "naming_helper.hpp"
#include <regex>
#include <sstream>
std::optional<std::string> NamingHelper::validateFormat(const std::string& code) {
static const std::regex re(PATTERN);
if (std::regex_match(code, re)) {
return "编号格式正确: " + code;
}
return std::nullopt;
}
std::string NamingHelper::generate(const std::string& areaCode,
const std::string& floor,
const std::string& room,
const std::string& deviceType,
const std::string& portDesc,
const std::string& serial,
const std::string& extension)
{
std::ostringstream oss;
oss << areaCode << "-"
<< floor << "-"
<< room << "-"
<< deviceType << "-"
<< portDesc << "-"
<< serial;
if (!extension.empty()) {
oss << "-" << extension;
}
return oss.str();
}

44
src/odf_unit.cpp Normal file
View File

@ -0,0 +1,44 @@
#include "odf_unit.hpp"
OdfUnit::OdfUnit(std::string id,
OdfUnitType type,
uint32_t maxPorts,
uint32_t heightMm,
uint32_t widthMm,
uint32_t depthMm,
MountType mountType)
: id(std::move(id))
, type(type)
, maxPorts(maxPorts)
, heightMm(heightMm)
, widthMm(widthMm)
, depthMm(depthMm)
, mountType(mountType)
{}
std::string OdfUnit::typeString() const {
switch (type) {
case OdfUnitType::Splicing: return "熔接型(Splicing)";
case OdfUnitType::Patching: return "配线型(Patching)";
case OdfUnitType::Hybrid: return "混合型(Hybrid)";
default: return "未知";
}
}
std::string OdfUnit::mountString() const {
switch (mountType) {
case MountType::Rack19Inch: return "19英寸机架式";
case MountType::WallMounted: return "壁挂式";
default: return "未知";
}
}
std::string OdfUnit::summary() const {
return "ODF单元 [ " + id + " ]\n"
" 类型: " + typeString() + "\n"
" 容量: " + std::to_string(maxPorts) + " 端口\n"
" 尺寸: " + std::to_string(heightMm) + "×"
+ std::to_string(widthMm) + "×"
+ std::to_string(depthMm) + " mm\n"
" 安装: " + mountString() + "\n";
}

52
src/project_milestone.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "project_milestone.hpp"
#include <sstream>
ProjectMilestone::ProjectMilestone(MilestoneStage stage,
uint32_t weekStart,
uint32_t weekEnd,
std::string owner,
bool completed)
: stage(stage)
, weekStart(weekStart)
, weekEnd(weekEnd)
, owner(std::move(owner))
, completed(completed)
{}
std::string ProjectMilestone::stageString() const {
switch (stage) {
case MilestoneStage::Requirements: return "需求确认";
case MilestoneStage::DesignReview: return "设计评审";
case MilestoneStage::Prototype: return "样机测试";
case MilestoneStage::Verification: return "验证测试";
case MilestoneStage::Delivery: return "批量交付";
default: return "未知";
}
}
bool ProjectMilestone::checkTimeConstraint() const {
switch (stage) {
case MilestoneStage::Prototype:
// 样机测试结束周不得晚于第 6 周
return weekEnd <= 6;
case MilestoneStage::Delivery:
// 最终交付不迟于第 12 周
return weekEnd <= 12;
default:
// 其他阶段不做严格时间约束检查
return true;
}
}
std::string ProjectMilestone::summary() const {
std::string status = completed ? "✓ 已完成" : "✗ 未完成";
std::string timeOk = checkTimeConstraint() ? "时间约束满足" : "⚠ 时间约束超限";
std::ostringstream oss;
oss << "里程碑: " << stageString() << "\n"
<< " 时间: 第 " << weekStart << " 周 ~ 第 " << weekEnd << "\n"
<< " 负责人: " << owner << "\n"
<< " 状态: " << status << "\n"
<< " 约束: " << timeOk << "\n";
return oss.str();
}

147
tests/basic_test.cpp Normal file
View File

@ -0,0 +1,147 @@
#include "odf_unit.hpp"
#include "adapter_interface.hpp"
#include "naming_helper.hpp"
#include "config_template.hpp"
#include "project_milestone.hpp"
#include "app.hpp"
#include <cassert>
#include <iostream>
#include <string>
/**
* @brief ODF
*
* 使 assert
* GoogleTest
*/
int main() {
std::cout << "===== ODF 管理模块单元测试 =====\n\n";
// ---- ODF Unit 测试 ----
std::cout << "[TEST] OdfUnit 构造与摘要 ... ";
OdfUnit unit("DC01-F03-TX-ODP-LC24-001-A",
OdfUnitType::Patching, 48,
44, 482, 300, MountType::Rack19Inch);
assert(unit.id == "DC01-F03-TX-ODP-LC24-001-A");
assert(unit.maxPorts == 48);
assert(unit.heightMm == 44);
assert(unit.widthMm == 482);
assert(unit.depthMm == 300);
assert(unit.type == OdfUnitType::Patching);
assert(unit.mountType == MountType::Rack19Inch);
assert(unit.typeString() == "配线型(Patching)");
assert(unit.mountString() == "19英寸机架式");
assert(!unit.summary().empty());
std::cout << "通过\n";
// ---- AdapterInterface 测试 ----
std::cout << "[TEST] AdapterInterface 构造与兼容性 ... ";
AdapterInterface lcSm(ConnectorType::LC, FiberMode::SingleMode, PolishType::APC, 500, 24);
AdapterInterface scMm(ConnectorType::SC, FiberMode::MultiMode, PolishType::UPC, 500, 12);
AdapterInterface mpoSm(ConnectorType::MPO, FiberMode::SingleMode, PolishType::APC, 500, 48);
AdapterInterface mpoMm(ConnectorType::MPO, FiberMode::MultiMode, PolishType::UPC, 500, 48);
assert(lcSm.connectorString() == "LC");
assert(scMm.fiberModeString() == "多模(MM)");
assert(lcSm.polishString() == "APC");
assert(lcSm.checkCompatibility() == true);
assert(scMm.checkCompatibility() == true);
assert(mpoSm.checkCompatibility() == false); // MPO+单模视作不兼容
assert(mpoMm.checkCompatibility() == true);
assert(!lcSm.summary().empty());
std::cout << "通过\n";
// ---- NamingHelper 测试 ----
std::cout << "[TEST] NamingHelper 校验与生成 ... ";
std::string validCode = "DC01-F03-TX-ODP-LC24-001-A";
std::string invalidCode = "invalid-code-123";
auto validResult = NamingHelper::validateFormat(validCode);
auto invalidResult = NamingHelper::validateFormat(invalidCode);
assert(validResult.has_value());
assert(!invalidResult.has_value());
std::string generated = NamingHelper::generate("DC01", "F03", "TX", "ODP", "LC24", "001", "A");
assert(generated == "DC01-F03-TX-ODP-LC24-001-A");
std::string generatedNoExt = NamingHelper::generate("RM01", "B1", "NR", "ODS", "SC12", "005");
assert(generatedNoExt == "RM01-B1-NR-ODS-SC12-005");
auto checkNoExt = NamingHelper::validateFormat(generatedNoExt);
assert(checkNoExt.has_value());
std::cout << "通过\n";
// ---- ConfigTemplate 测试 ----
std::cout << "[TEST] ConfigTemplate 模板与 BOM 生成 ... ";
auto templates = ConfigTemplate::builtInTemplates();
assert(templates.size() >= 3);
assert(templates[0].scenarioName == "数据中心LC单模预端接");
assert(templates[0].portsPerCabinet == 48);
assert(templates[0].spareRatio > 0.0);
// BOM 边界测试0 机柜
std::string bom0 = templates[0].generateBomSummary(0);
assert(bom0.find("基础端口量: 0") != std::string::npos);
// BOM 正常测试
std::string bom3 = templates[0].generateBomSummary(3);
assert(bom3.find("基础端口量: 144") != std::string::npos);
assert(bom3.find("含余量总端口数: 166") != std::string::npos ||
bom3.find("含余量总端口数: 165") != std::string::npos);
std::cout << "通过\n";
// ---- ProjectMilestone 测试 ----
std::cout << "[TEST] ProjectMilestone 时间约束 ... ";
ProjectMilestone protoOk(MilestoneStage::Prototype, 4, 6, "王五", false);
ProjectMilestone deliveryOk(MilestoneStage::Delivery, 10, 12, "张三", false);
ProjectMilestone protoBad(MilestoneStage::Prototype, 4, 8, "王五", false);
ProjectMilestone deliveryBad(MilestoneStage::Delivery, 10, 14, "张三", false);
assert(protoOk.checkTimeConstraint() == true);
assert(deliveryOk.checkTimeConstraint() == true);
assert(protoBad.checkTimeConstraint() == false);
assert(deliveryBad.checkTimeConstraint() == false);
assert(protoOk.stageString() == "样机测试");
assert(deliveryOk.stageString() == "批量交付");
std::cout << "通过\n";
// ---- calculatePortDensity 测试 ----
std::cout << "[TEST] calculatePortDensity ... ";
assert(App::calculatePortDensity(2, 48) == 24); // 48/2=24
assert(App::calculatePortDensity(1, 48) == 48); // 48/1=48
assert(App::calculatePortDensity(3, 72) == 24); // 72/3=24
assert(App::calculatePortDensity(0, 48) == 0); // 除零保护
assert(App::calculatePortDensity(5, 12) == 2); // 12/5=2向下取整
std::cout << "通过\n";
// ---- App 综合链路测试 ----
std::cout << "[TEST] App 综合: 命名->单元->BOM 链路 ... ";
App app;
// 按命名规则生成 ID 并创建单元
std::string id = NamingHelper::generate("SH01", "A2", "DC", "ODP", "LC48", "010", "B");
auto idCheck = NamingHelper::validateFormat(id);
assert(idCheck.has_value());
app.addOdfUnit(OdfUnit(id, OdfUnitType::Hybrid, 96, 88, 482, 300, MountType::Rack19Inch));
std::string unitList = app.listOdfUnits();
assert(unitList.find("SH01-A2-DC-ODP-LC48-010-B") != std::string::npos);
// 使用模板生成 BOM
std::string bom = app.generateBom(2, 5); // MPO 高密度
assert(bom.find("MPO高密度预端接") != std::string::npos);
assert(bom.find("基础端口量: 480") != std::string::npos);
// 里程碑约束检查
app.addMilestone(ProjectMilestone(MilestoneStage::Prototype, 4, 6, "王五", false));
app.addMilestone(ProjectMilestone(MilestoneStage::Delivery, 10, 12, "张三", false));
std::string constraintResult = app.checkMilestonesConstraint();
assert(constraintResult.find("所有里程碑时间约束均满足") != std::string::npos);
std::cout << "通过\n";
std::cout << "\n===== 全部测试通过! =====\n";
return 0;
}