From a172a9bb5ed390bf1cd5cddc85de83ec68b0eeec Mon Sep 17 00:00:00 2001 From: 12600k-rog-d4 Date: Thu, 27 Aug 2026 00:44:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A3=9E=E7=89=9BNAS=E6=88=90=E6=9C=AC?= =?UTF-8?q?=E5=AE=A1=E6=A0=B8=E6=9B=B4=E6=96=B0=20-=20=E6=96=B0=E5=A2=9ESK?= =?UTF-8?q?U=E3=80=81=E6=9B=B4=E6=96=B0=E4=BB=B7=E6=A0=BC=E8=A1=A8?= =?UTF-8?q?=E3=80=81=E6=B8=85=E7=90=86=E5=BD=92=E6=A1=A3=E5=8F=8A=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E8=AE=B0=E5=BD=95=EF=BC=8C=E5=90=8C=E6=AD=A5auto-chec?= =?UTF-8?q?k=E6=94=B9=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auto-check/auto-check.yaml | 15 +- auto-check/docker/stress-test/Dockerfile | 30 +- auto-check/docker/stress-test/README.md | 53 +- auto-check/docker/stress-test/build.sh | 78 +++ .../docker/stress-test/scripts/dmesg.sh | 7 +- auto-check/docker/stress-test/scripts/run.sh | 5 + auto-check/go.mod | 1 + auto-check/go.sum | 2 + auto-check/pkg/config/config.go | 11 + auto-check/pkg/report/device.go | 201 +++++- auto-check/pkg/report/print.go | 95 +++ auto-check/pkg/report/print_test.go | 131 ++++ auto-check/pkg/report/report.go | 21 +- .../pkg/report/templates/report_80mm.tmpl | 7 +- auto-check/pkg/stress/benchmark.go | 611 ++++++++++++++++++ auto-check/pkg/stress/benchmark_test.go | 246 +++++++ auto-check/pkg/stress/chart.go | 57 +- auto-check/pkg/stress/metrics.go | 2 +- auto-check/pkg/stress/report_html.go | 39 ++ auto-check/pkg/stress/runner.go | 4 + auto-check/pkg/stress/tools.go | 6 +- auto-check/pkg/stress/types.go | 12 + auto-check/pkg/workflow/workflow.go | 2 +- auto-check/verify_dispatch_main.go | 44 -- .../skus/2.5-金-单-wifi-j1900-4G-128G.md | 23 + .../skus/2.5-金-单-wifi-j3160-4G-64G.md | 35 + .../飞牛 NAS/skus/3.5-亚-单-有-j3160-8G-128G.md | 2 +- 产品/飞牛 NAS/skus/3.5-亚-双-有-i3-4G-64G.md | 2 +- .../飞牛 NAS/skus/3.5-亚-双-有-i5-2代-8G-64G.md | 2 +- .../飞牛 NAS/skus/3.5-亚-双-有-j3160-4G-32G.md | 2 +- .../飞牛 NAS/skus/3.5-金-三-有-j3355-4G-64G.md | 35 + .../skus/3.5-金-单-wifi-j3160-8G-64G.md | 23 + .../skus/3.5-金-双-有-i5-3代-8G-128G.md | 2 +- .../飞牛 NAS/skus/3.5-金-双-有-j3160-4G-64G.md | 35 + .../飞牛 NAS/skus/3.5-金-双-有-j3355-4G-64G.md | 2 +- .../skus/3.5-金-四-有-i7-3代-8G-128G.md | 23 + 产品/飞牛 NAS/skus/价格表.md | 90 +-- .../sku/3.5金大-双-1037U-4G-32G.md | 22 - .../sku/3.5金大-双-J3160-4G-64G.md | 23 - .../sku/3.5金大-双-J3355-4G-128G.md | 22 - .../sku/3.5金大-双-J3355-4G-64G.md | 22 - .../sku/3.5金大-双-i5-3代-8G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-32G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-64G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-AMD-A4-8G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J1900-4G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J1900-4G-32G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J1900-4G-64G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J1900-8G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J3160-4G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J3160-4G-32G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J3160-4G-64G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-J3160-8G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-128G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-32G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-64G.md | 22 - .../亚克力机箱 - 单/sku/亚克力-单-i3-3代-8G-128G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-1037U-4G-128G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-1037U-4G-32G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-1037U-4G-64G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-1037U-8G-128G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-1037U-8G-64G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-J1900-4G-128G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J1900-4G-32G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J1900-4G-64G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J1900-8G-128G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J1900-8G-64G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J3160-4G-128G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J3160-4G-32G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J3160-4G-64G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J3160-8G-128G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-J3160-8G-64G.md | 23 - .../亚克力机箱-双/sku/亚克力-双-i3-3代-4G-128G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-i3-3代-4G-32G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-i3-3代-4G-64G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-i3-3代-8G-128G.md | 22 - .../亚克力机箱-双/sku/亚克力-双-i3-3代-8G-64G.md | 22 - .../3.5金大-3盘-i7-3代-8G-128G.md | 23 - .../3.5金大-4盘-i7-3代-8G-128G.md | 23 - .../高性能-i5-i7/sku/亚克力-双-i5-2代-8G-128G.md | 22 - 产品/飞牛 NAS/订单/订单.md | 47 -- 82 files changed, 1804 insertions(+), 1180 deletions(-) create mode 100644 auto-check/docker/stress-test/build.sh create mode 100644 auto-check/pkg/report/print_test.go create mode 100644 auto-check/pkg/stress/benchmark.go create mode 100644 auto-check/pkg/stress/benchmark_test.go delete mode 100644 auto-check/verify_dispatch_main.go create mode 100644 产品/飞牛 NAS/skus/2.5-金-单-wifi-j1900-4G-128G.md create mode 100644 产品/飞牛 NAS/skus/2.5-金-单-wifi-j3160-4G-64G.md create mode 100644 产品/飞牛 NAS/skus/3.5-金-三-有-j3355-4G-64G.md create mode 100644 产品/飞牛 NAS/skus/3.5-金-单-wifi-j3160-8G-64G.md create mode 100644 产品/飞牛 NAS/skus/3.5-金-双-有-j3160-4G-64G.md create mode 100644 产品/飞牛 NAS/skus/3.5-金-四-有-i7-3代-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-1037U-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3160-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-i5-3代-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-32G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-64G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-64G.md delete mode 100644 产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-3盘-i7-3代-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-4盘-i7-3代-8G-128G.md delete mode 100644 产品/飞牛 NAS/归档/高性能-i5-i7/sku/亚克力-双-i5-2代-8G-128G.md delete mode 100644 产品/飞牛 NAS/订单/订单.md diff --git a/auto-check/auto-check.yaml b/auto-check/auto-check.yaml index 6a37bb6..86de0ab 100644 --- a/auto-check/auto-check.yaml +++ b/auto-check/auto-check.yaml @@ -6,13 +6,13 @@ # - CIDR: "10.0.3.0/24" # - IP 范围: "10.0.3.1-10.0.3.100" scan: - cidr: "10.107.95.2-10.107.95.2" + cidr: "10.0.3.148-10.0.3.148" timeout: 3s concurrency: 10 # --- SSH 认证 --- ssh: - user: "admin-pc" + user: "admin" password: "admin123" key: "" port: 22 @@ -29,7 +29,7 @@ stress: temp_limit: 90 # 温度上限(°C),超过判失败,0=不判定 # --- Docker 镜像(压测统一在容器中执行,工具与脚本预装在镜像里)--- # 固定分发模式:目标机无镜像时,上传本地导出的 tar 并 docker load(不依赖 registry) - docker_image: "stress-test:latest" # 压测镜像名,镜像维护见 docker/stress-test/ + docker_image: "stress-test:20260824-144244" # 压测镜像名,镜像维护见 docker/stress-test/ docker_tar: "docker/stress-test/stress-test.tar" # 本地镜像文件(docker save -o 导出) docker_args: "--network=host --privileged" # Docker 运行参数,--privileged 可访问完整资源 @@ -47,3 +47,12 @@ report: # usb: 空=自动(Win \\.\usb001 / Linux /dev/usb/lp0), 或指定设备路径 # file: 输出路径 width: 42 # 80mm 热敏纸行宽 + html: + base_url: "" # HTML 报告访问基地址(如 http://192.168.1.10:8080),扫码链接会拼接到此地址 + # 留空则只保存到本地(打印时仅提示本地路径) + path: "" # HTML 保存目录,留空 = 与 txt 报告同目录 + filename: "report-{mac}-{ip}-{ts}.html" # 文件名模板 + qr_url: "" # 二维码 URL 模板,支持 {filename} {mac} {ip} {ts} 占位 + # 例: "http://192.168.1.10:8080/reports/{filename}" + # 留空时自动用 base_url + 实际文件名拼接 + diff --git a/auto-check/docker/stress-test/Dockerfile b/auto-check/docker/stress-test/Dockerfile index ded9c3a..722c274 100644 --- a/auto-check/docker/stress-test/Dockerfile +++ b/auto-check/docker/stress-test/Dockerfile @@ -1,26 +1,36 @@ # 压力测试工具镜像 # -# 用途:为 auto-check 提供预装压测工具的容器环境 -# 优势:工具预装在镜像中,无需在线安装,环境一致性好,适合国内网络环境 +# 用途:为 auto-check 提供预装压测工具与脚本的容器环境 +# 优势:工具预装在镜像中,无需在目标机在线安装,环境一致性好 # -# 工作流程: +# 工作流程(固定分发模式,不依赖 registry): # 1. auto-check 检测目标机器的 Docker 可用性 -# 2. 从 Registry 拉取镜像(或本地已存在则跳过) -# 3. 启动容器执行测试(脚本已打包在镜像中) +# 2. 目标机无镜像时,上传工程目录中导出的 tar(docker save)并 docker load +# 3. 启动容器执行测试(脚本已打包在镜像中,挂载 /sys 采集温度) # 4. 收集测试结果并解析 # -# 构建命令: +# 构建与导出(推荐用脚本,自动时间戳 tag): # cd docker/stress-test -# docker build -t your-registry/stress-test:latest . -# docker push your-registry/stress-test:latest +# ./build.sh # 自动用当前时间戳打 tag +# ./build.sh 20260824-153045 # 或手动指定 +# 脚本会同时:构建镜像(时间戳 tag) + 导出 tar + 同步 auto-check.yaml 配置 +# +# 手动构建(如绕过脚本): +# cd docker/stress-test +# docker build -t stress-test:<时间戳> . +# docker save -o stress-test.tar stress-test:<时间戳> +# # 同步修改 ../../auto-check.yaml 的 docker_image # # 使用方式(在 auto-check.yaml 中配置): # stress: -# use_docker: true -# docker_image: "your-registry/stress-test:latest" +# docker_image: "stress-test:<时间戳>" +# docker_tar: "docker/stress-test/stress-test.tar" FROM debian:12-slim +# UTF-8 locale:保证 sensors 输出带 ° 符号的温度格式(脚本正则依赖) +ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 + # 清理缓存,减少镜像体积 RUN apt-get update && apt-get install -y --no-install-recommends \ stress-ng \ diff --git a/auto-check/docker/stress-test/README.md b/auto-check/docker/stress-test/README.md index f6b33e5..5aec851 100644 --- a/auto-check/docker/stress-test/README.md +++ b/auto-check/docker/stress-test/README.md @@ -29,20 +29,52 @@ 固定分发模式:不依赖 registry,镜像以 tar 文件形式放在工程目录, 目标机无镜像时由 auto-check 自动上传并 `docker load`。 +### 推荐:使用构建脚本(自动时间戳 tag) + +`build.sh` 会以 `YYYYMMDD-HHMMSS` 格式自动生成时间戳 tag(如 `stress-test:20260824-153045`), +便于在 `docker images` 中一眼区分新旧版本。脚本会同时: + +1. 用时间戳 tag 构建镜像(**不再保留 `latest`**) +2. 导出两份 tar:带时间戳的归档 + 同步覆盖 `stress-test.tar`(auto-check 默认引用) +3. 自动更新 `auto-check.yaml` 的 `docker_image` 字段,确保配置与新 tag 同步 + ```bash cd docker/stress-test -docker build -t stress-test:latest . -# 导出到工程目录(供 auto-check 上传分发,已加入 .gitignore) -docker save -o stress-test.tar stress-test:latest +./build.sh # 自动取当前时间戳 +./build.sh 20260824-153045 # 手动指定时间戳(重打/复现) ``` +产物: + +| 文件 | 用途 | +|------|------| +| 镜像 `stress-test:<时间戳>` | 唯一 tag,`docker images` 可看到每次构建 | +| Tar `stress-test-<时间戳>.tar` | 带时间戳归档,保留历史版本 | +| Tar `stress-test.tar` | auto-check 默认引用,脚本自动覆盖为最新 | +| `auto-check.yaml` | `docker_image` 自动同步为新 tag | + +> 旧时间戳镜像可手动 `docker rmi stress-test:<旧时间戳>` 清理。 + +### 手动构建(不推荐) + +如需绕过脚本手动构建,必须自行同步 `auto-check.yaml`: + +```bash +cd docker/stress-test +docker build -t stress-test:20260824-153045 . # 必须带时间戳 +docker save -o stress-test.tar stress-test:20260824-153045 +# 然后编辑 ../../auto-check.yaml,把 docker_image 改成新 tag +``` + +> 注意:手动构建如忘记带时间戳,重复构建后会丢失版本信息,调试时易混淆。 + ## 使用 -在 `auto-check.yaml` 中配置: +在 `auto-check.yaml` 中配置(`docker_image` 由 `build.sh` 自动维护): ```yaml stress: - docker_image: "stress-test:latest" + docker_image: "stress-test:20260824-153045" # 每次构建自动更新为新时间戳 docker_tar: "docker/stress-test/stress-test.tar" docker_args: "--network=host --privileged" ``` @@ -68,7 +100,16 @@ stress: 2. 温度监控后台采样(`temp_start.sh`) 3. 各项压测:先单项(cpu/memory/disk/memnative)、综合(full)最后 4. 温度监控收尾(`===MONITOR:temp===`) -5. 内核日志(`===MONITOR:dmesg===`)+ 结束标记 +5. 内核日志(`===MONITOR:dmesg===`,`-T` 带时间戳)+ 结束标记 + +## 容器运行时挂载(由 auto-check 自动添加) + +| 挂载 | 作用 | +|------|------| +| `-v /sys:/sys:ro` | 容器内是独立 sysfs,挂载后才能读到宿主机硬件传感器(温度采集依赖此项) | +| `-v /etc/localtime:/etc/localtime:ro` | 容器时区与宿主机一致,dmesg 时间戳与采样时间才准确 | + +> 注意:镜像内已设置 `LC_ALL=C.UTF-8`。若 locale 为纯 C,`sensors` 会输出 "+51.0 C"(无 ° 符号),导致温度正则失配、采集不到数据。 ## 镜像内容 diff --git a/auto-check/docker/stress-test/build.sh b/auto-check/docker/stress-test/build.sh new file mode 100644 index 0000000..7aaca95 --- /dev/null +++ b/auto-check/docker/stress-test/build.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# build.sh - 构建压测镜像并以时间戳打 tag +# +# 目的:每次构建都生成唯一 tag(如 stress-test:20260824-153045), +# 便于在 docker images 中区分新旧版本,避免 latest 重复构建后无法追溯。 +# +# 用法: +# ./build.sh # 自动使用当前时间戳 (YYYYMMDD-HHMMSS) +# ./build.sh 20260824-153045 # 手动指定时间戳(用于复现/重打) +# +# 产物: +# - 镜像: stress-test: (仅时间戳 tag,不再保留 latest) +# - Tar : stress-test-.tar (带时间戳归档) +# + stress-test.tar (auto-check 默认引用,同步覆盖) +# - auto-check.yaml 的 docker_image 字段会被自动同步为新时间戳 tag +# +# 注意: +# - 脚本会自动 cd 到自身所在目录,可从任意位置调用 +# - 需要本地有 Docker 可用 +# - 每次构建会覆盖上一份 stress-test.tar;时间戳 tar 保留可作历史归档 +# - 旧时间戳镜像可执行 docker rmi stress-test: 清理 + +set -euo pipefail + +# 切到脚本所在目录(Dockerfile 在这里) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +# 时间戳:支持外部传入,否则取当前时间 +TS="${1:-$(date +%Y%m%d-%H%M%S)}" + +IMAGE_NAME="stress-test" +TAG_TS="${IMAGE_NAME}:${TS}" +TAR_TS="${IMAGE_NAME}-${TS}.tar" +TAR_LATEST="${IMAGE_NAME}.tar" + +# auto-check.yaml 路径(相对本脚本 ../..) +YAML_FILE="$SCRIPT_DIR/../../auto-check.yaml" + +echo "==> 时间戳: ${TS}" +echo "==> 构建镜像: ${TAG_TS}" +docker build -t "${TAG_TS}" . + +echo "==> 导出 Tar: ${TAR_TS}" +docker save -o "${TAR_TS}" "${TAG_TS}" + +echo "==> 同步 Latest Tar: ${TAR_LATEST}" +cp -f "${TAR_TS}" "${TAR_LATEST}" + +# 同步 auto-check.yaml 中的 docker_image 为新时间戳 tag +if [ -f "$YAML_FILE" ]; then + if grep -q '^[[:space:]]*docker_image:' "$YAML_FILE"; then + if ! grep -q "${TAG_TS}" "$YAML_FILE"; then + # -i.bak 同时生成备份(兼容 GNU sed / BSD sed),改完再删 + sed -i.bak -E "s|(docker_image:[[:space:]]*\")[^\"]+(\")|\1${TAG_TS}\2|" "$YAML_FILE" + rm -f "${YAML_FILE}.bak" + echo "==> 已更新 ${YAML_FILE##*/}: docker_image -> ${TAG_TS}" + else + echo "==> ${YAML_FILE##*/} 中 docker_image 已是 ${TAG_TS},跳过" + fi + else + echo "==> 未在 ${YAML_FILE##*/} 中找到 docker_image 字段,请手动更新" + fi +else + echo "==> 未找到 ${YAML_FILE},请手动确保 docker_image 与新 tag 一致" +fi + +echo "" +echo "==========================================" +echo " 构建完成" +echo "==========================================" +echo " 镜像 Tag: ${TAG_TS}" +echo " Tar 文件: ${TAR_TS}" +echo " ${TAR_LATEST} (auto-check 默认引用)" +echo "" +echo "==> 本机 ${IMAGE_NAME} 镜像列表:" +docker images "${IMAGE_NAME}" --format "table {{.Repository}}\t{{.Tag}}\t{{.CreatedAt}}\t{{.Size}}" + diff --git a/auto-check/docker/stress-test/scripts/dmesg.sh b/auto-check/docker/stress-test/scripts/dmesg.sh index fa0fbfd..54bca7e 100644 --- a/auto-check/docker/stress-test/scripts/dmesg.sh +++ b/auto-check/docker/stress-test/scripts/dmesg.sh @@ -1,5 +1,10 @@ echo '===MONITOR:dmesg===' -DMESG_ERR=$(dmesg --level=err,crit,alert,emerg 2>/dev/null | tail -30 || true) +# -T 输出人类可读时间戳(如 [Mon Aug 24 10:23:45 2026]), +# 依赖挂载宿主机 /etc/localtime 保证时区正确;老内核不支持 -T 时回退 +DMESG_ERR=$(dmesg -T --level=err,crit,alert,emerg 2>/dev/null | tail -30) +if [ -z "$DMESG_ERR" ]; then + DMESG_ERR=$(dmesg --level=err,crit,alert,emerg 2>/dev/null | tail -30 || true) +fi if [ -n "$DMESG_ERR" ]; then echo 'status:fail' echo "output:${DMESG_ERR}" diff --git a/auto-check/docker/stress-test/scripts/run.sh b/auto-check/docker/stress-test/scripts/run.sh index d20aaf8..2c16f73 100644 --- a/auto-check/docker/stress-test/scripts/run.sh +++ b/auto-check/docker/stress-test/scripts/run.sh @@ -4,6 +4,11 @@ # 系统信息 → 温度监控启动 → 各项压测(先单项、后综合)→ 温度监控收尾 → 内核日志 set -e +# 统一 UTF-8 locale:否则 sensors 输出 "+51.0 C"(无 ° 符号), +# 脚本中 (?=°C) 的温度正则会全部失配,导致温度采集不到 +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 + # 默认值(docker -e 传入时覆盖) export AUTOCHECK_TYPES="${AUTOCHECK_TYPES:-cpu,memory}" export AUTOCHECK_DURATION="${AUTOCHECK_DURATION:-30}" diff --git a/auto-check/go.mod b/auto-check/go.mod index 4c2b77a..81bb7c1 100644 --- a/auto-check/go.mod +++ b/auto-check/go.mod @@ -13,6 +13,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/fs v0.1.0 // indirect github.com/pkg/sftp v1.13.11 // indirect + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/spf13/pflag v1.0.10 // indirect golang.org/x/sys v0.47.0 // indirect ) diff --git a/auto-check/go.sum b/auto-check/go.sum index 8c99f5b..55f854c 100644 --- a/auto-check/go.sum +++ b/auto-check/go.sum @@ -6,6 +6,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/pkg/sftp v1.13.11 h1:0N92SLTB8JqASJB14ZLHHzFnBV8mG9zw4K7jghEFWuE= github.com/pkg/sftp v1.13.11/go.mod h1:uNkH9roSXglNJqM+glJJi+TQXQUm0fXFWqCFmT8hsN0= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= diff --git a/auto-check/pkg/config/config.go b/auto-check/pkg/config/config.go index d5092c8..c0aba4d 100644 --- a/auto-check/pkg/config/config.go +++ b/auto-check/pkg/config/config.go @@ -61,6 +61,17 @@ type StressConfig struct { type ReportConfig struct { Path string `yaml:"path"` // 报告保存路径 Print PrintConfig `yaml:"print"` // 打印配置 + HTML HTMLConfig `yaml:"html"` // HTML 报告配置 +} + +// HTMLConfig HTML 报告配置 +type HTMLConfig struct { + BaseURL string `yaml:"base_url"` // HTML 报告访问基地址(如 http://192.168.1.10:8080),空则只保存本地 + Path string `yaml:"path"` // HTML 报告保存目录,空 = 与 txt 报告同目录 + Filename string `yaml:"filename"` // 文件名模板,支持 {mac} {ip} {ts},默认 report-{mac}-{ip}-{ts}.html + // QRURL 热敏打印中二维码指向的 URL 模板,支持 {filename} {mac} {ip} {ts} 占位 + // 留空时用 BaseURL + 实际文件名拼接 + QRURL string `yaml:"qr_url"` } // PrintConfig 打印配置 diff --git a/auto-check/pkg/report/device.go b/auto-check/pkg/report/device.go index ac5f556..e52d352 100644 --- a/auto-check/pkg/report/device.go +++ b/auto-check/pkg/report/device.go @@ -2,22 +2,32 @@ package report import ( "fmt" + "net/url" + "os" "path/filepath" "strings" "time" + "github.com/skip2/go-qrcode" + "auto-check/pkg/config" "auto-check/pkg/model" "auto-check/pkg/stress" ) // BuildDeviceReport 由压测结果构建设备报告(MAC 唯一标识) -func BuildDeviceReport(dev *model.Device, rpt *stress.Report) *Report { +// qrURL 非空时会附加到报告,供 80mm 模板在末尾显示"扫码查看详细报告"提示与 URL 文本兜底 +func BuildDeviceReport(dev *model.Device, rpt *stress.Report, qrURL string) *Report { + // 从 sysInfo 提取 CPU 型号用于按硬件库匹配基准 + cpuModel := "" + if rpt.SysInfo != nil { + cpuModel = rpt.SysInfo["cpu"] + } b := NewBuilder(ConfigSummary{}) b.StartPhase("压力测试") b.AddHost(HostResult{MAC: dev.MAC, IP: dev.IP}) for _, res := range rpt.Results { - b.AddStressResult(dev.MAC, StressResult{ + sr := StressResult{ Type: string(res.Type), Status: res.Status, Duration: res.Duration.String(), @@ -26,10 +36,21 @@ func BuildDeviceReport(dev *model.Device, rpt *stress.Report) *Report { Metrics: res.OrderedMetrics(), Error: res.Error, Output: res.Output, - }) + } + // 基准评级(让用户对结果有感性认知;按硬件库匹配专属阈值,未匹配全部"达到正常") + if items := stress.EvaluateResult(res, cpuModel); len(items) > 0 { + sr.Benchmarks = items + if lvl := stress.OverallLevel(items); lvl != "" { + sr.OverallLevel = string(lvl) + sr.OverallText = stress.LevelMeta(lvl).Text + } + } + b.AddStressResult(dev.MAC, sr) } b.EndPhase(rpt.Summary()) - return b.Build() + r := b.Build() + r.QRURL = qrURL + return r } // SaveDeviceReport 保存设备报告(文件名含 MAC/IP/时间戳) @@ -40,17 +61,119 @@ func SaveDeviceReport(dev *model.Device, rpt *stress.Report, dir string) error { ts := time.Now().Format("20060102-150405") name := strings.ReplaceAll(dev.MAC, ":", "") path := filepath.Join(dir, fmt.Sprintf("report-%s-%s-%s.txt", name, dev.IP, ts)) - return BuildDeviceReport(dev, rpt).SaveFile(path, "text") + return BuildDeviceReport(dev, rpt, "").SaveFile(path, "text") } -// PrintDeviceReport 渲染 80mm 模板并送打印机 -func PrintDeviceReport(dev *model.Device, rpt *stress.Report, cfg config.PrintConfig) error { +// SaveDeviceQR 保存设备报告对应的二维码 PNG(与 txt/html 同目录) +// url 为空时不生成;返回 PNG 完整路径,失败时返回错误 +func SaveDeviceQR(dev *model.Device, url string, dir string) (string, error) { + if url == "" { + return "", nil + } + if dir == "" { + dir = "reports" + } + if err := os.MkdirAll(dir, 0755); err != nil { + return "", err + } + ts := time.Now().Format("20060102-150405") + mac := strings.ReplaceAll(dev.MAC, ":", "") + filename := fmt.Sprintf("report-%s-%s-%s.qr.png", mac, dev.IP, ts) + path := filepath.Join(dir, filename) + + // 512 字节足够;高纠错级别 H 提升扫码容错 + png, err := qrcode.New(url, qrcode.High) + if err != nil { + return "", err + } + // 512x512 PNG;二维码扫描距离更友好 + if err := png.WriteFile(512, path); err != nil { + return "", err + } + return path, nil +} + +// SaveDeviceHTMLReport 保存设备 HTML 报告(文件名按 config.HTML.Filename 模板生成) +// 返回: (filename, fullPath, error) +func SaveDeviceHTMLReport(dev *model.Device, rpt *stress.Report, dir string, htmlCfg config.HTMLConfig) (string, string, error) { + dir = htmlDir(dir, htmlCfg) + ts := time.Now().Format("20060102-150405") + mac := strings.ReplaceAll(dev.MAC, ":", "") + filename := renderHTMLFilename(htmlCfg.Filename, mac, dev.IP, ts) + if filename == "" { + filename = fmt.Sprintf("report-%s-%s-%s.html", mac, dev.IP, ts) + } + + path, err := stress.WriteReportHTMLTo(dev.IP, rpt, dir, filename) + if err != nil { + return "", "", err + } + return filename, path, nil +} + +// BuildDeviceReportURL 构建设备 HTML 报告的访问 URL(用于二维码) +// 优先级:qr_url 模板 > base_url + filename > 空字符串 +// 占位符:{filename} {mac} {ip} {ts} +func BuildDeviceReportURL(dev *model.Device, filename string, htmlCfg config.HTMLConfig) string { + mac := strings.ReplaceAll(dev.MAC, ":", "") + ts := time.Now().Format("20060102-150405") + if tpl := strings.TrimSpace(htmlCfg.QRURL); tpl != "" { + return fillPlaceholders(tpl, map[string]string{ + "filename": filename, + "mac": mac, + "ip": dev.IP, + "ts": ts, + }) + } + base := strings.TrimRight(strings.TrimSpace(htmlCfg.BaseURL), "/") + if base == "" || filename == "" { + return "" + } + return base + "/" + filename +} + +// saveDeviceHTMLAndQR 保存 HTML 报告 + 二维码 PNG(一体化),返回 (filename, qrPath, error) +// - HTML 失败:仅返回错误,不生成 QR +// - QR 失败:只打日志,不影响 HTML(用户至少能用 URL 文本兜底) +func saveDeviceHTMLAndQR(dev *model.Device, rpt *stress.Report, dir string, htmlCfg config.HTMLConfig) (string, string, error) { + filename, _, err := SaveDeviceHTMLReport(dev, rpt, dir, htmlCfg) + if err != nil { + return "", "", err + } + url := BuildDeviceReportURL(dev, filename, htmlCfg) + if url == "" && filename != "" { + // 兜底:base_url 未配置时,至少打印本地路径(便于手工打开) + url = filename + } + qrPath, qerr := SaveDeviceQR(dev, url, dir) + if qerr != nil { + fmt.Printf(" [报告] %s 二维码 PNG 生成失败: %v\n", dev.IP, qerr) + } + return filename, qrPath, nil +} + +// PrintDeviceReport 渲染 80mm 模板并送打印机,启用 HTML 时自动追加二维码 +func PrintDeviceReport(dev *model.Device, rpt *stress.Report, cfg config.PrintConfig, htmlCfg config.HTMLConfig) error { width := cfg.Width if width <= 0 { width = 42 } - text, err := BuildDeviceReport(dev, rpt).Render80mmWithConfig(TemplateConfig{Width: width}) + // 先保存 HTML + 二维码 PNG,并计算二维码 URL + filename, qrPath, herr := saveDeviceHTMLAndQR(dev, rpt, "", htmlCfg) + if herr != nil { + fmt.Printf(" [报告] %s HTML 保存失败: %v\n", dev.IP, herr) + } + url := BuildDeviceReportURL(dev, filename, htmlCfg) + if url == "" && filename != "" { + // 兜底:base_url 未配置时,至少打印本地路径(便于手工打开) + url = filename + } + if qrPath != "" { + fmt.Printf(" [报告] %s 二维码 PNG: %s\n", dev.IP, qrPath) + } + + text, err := BuildDeviceReport(dev, rpt, url).Render80mmWithConfig(TemplateConfig{Width: width}) if err != nil { return err } @@ -61,20 +184,76 @@ func PrintDeviceReport(dev *model.Device, rpt *stress.Report, cfg config.PrintCo } defer printer.Close() - return printer.Print(text) + if err := printer.Print(text); err != nil { + return err + } + + // 追加二维码(HTML 报告访问链接);后端不支持或无 URL 时 PrintQR 内部静默跳过 + if printer != nil && url != "" { + if qerr := printer.PrintQR(url); qerr != nil { + fmt.Printf(" [打印] %s 二维码失败: %v\n", dev.IP, qerr) + } + } + return nil } // SaveAndPrintDeviceReport 保存报告并(启用时)打印,含错误输出(一站式业务入口) -func SaveAndPrintDeviceReport(dev *model.Device, rpt *stress.Report, dir string, printCfg config.PrintConfig) { +func SaveAndPrintDeviceReport(dev *model.Device, rpt *stress.Report, dir string, printCfg config.PrintConfig, htmlCfg config.HTMLConfig) { if err := SaveDeviceReport(dev, rpt, dir); err != nil { fmt.Printf(" [报告] %s 保存失败: %v\n", dev.IP, err) } + // 总是保存 HTML + 二维码 PNG(便于不打印时也能扫码查看详细报告) + _, qrPath, herr := saveDeviceHTMLAndQR(dev, rpt, dir, htmlCfg) + if herr != nil { + fmt.Printf(" [报告] %s HTML 保存失败: %v\n", dev.IP, herr) + } else if qrPath != "" { + fmt.Printf(" [报告] %s 二维码 PNG: %s\n", dev.IP, qrPath) + } + if printCfg.Enabled { - if err := PrintDeviceReport(dev, rpt, printCfg); err != nil { + if err := PrintDeviceReport(dev, rpt, printCfg, htmlCfg); err != nil { fmt.Printf(" [打印] %s 失败: %v\n", dev.IP, err) } else { fmt.Printf(" [打印] %s 已送出 (%s)\n", dev.IP, printCfg.Backend) } } } + +// ============================ +// 辅助 +// ============================ + +// htmlDir 解析 HTML 报告目录 +func htmlDir(defaultDir string, cfg config.HTMLConfig) string { + if p := strings.TrimSpace(cfg.Path); p != "" { + return p + } + if defaultDir == "" { + return "reports" + } + return defaultDir +} + +// renderHTMLFilename 渲染文件名模板,缺省时返回默认 +func renderHTMLFilename(tpl, mac, ip, ts string) string { + tpl = strings.TrimSpace(tpl) + if tpl == "" { + return "" + } + return fillPlaceholders(tpl, map[string]string{ + "filename": "", // 文件名模板内不应再嵌 filename + "mac": mac, + "ip": ip, + "ts": ts, + }) +} + +// fillPlaceholders 简单占位符替换 {key} +func fillPlaceholders(s string, kv map[string]string) string { + for k, v := range kv { + s = strings.ReplaceAll(s, "{"+k+"}", url.PathEscape(v)) + } + return s +} + diff --git a/auto-check/pkg/report/print.go b/auto-check/pkg/report/print.go index 2ee9350..5193844 100644 --- a/auto-check/pkg/report/print.go +++ b/auto-check/pkg/report/print.go @@ -25,6 +25,9 @@ var Printed = make(map[string]string) // Printer 报告打印机 type Printer interface { Print(text string) error + // PrintQR 在打印流末尾追加二维码(ESC/POS GS ( k 指令) + // 后端不支持时返回 nil(不打印二维码) + PrintQR(url string) error Close() error } @@ -66,6 +69,63 @@ func writeEscpos(w io.Writer, text string) error { return bw.Flush() } +// ============================ +// ESC/POS 二维码(GS ( k 指令) +// ============================ +// +// 适配 EPSON / Star / 芯烨(Xprinter) / 佳博 等主流 ESC/POS 热敏打印机。 +// 指令格式:GS ( k pL pH cn fn [n...] +// cn = 49 (0x31) QR Code +// fn = 65 (A) 选择模型 / 67 (C) 模块大小 / 69 (E) 纠错 / 80 (P) 数据 / 81 (Q) 打印 +// +// 参考:EPSON TM-T20 QR Code 规范 +// 数据长度限制(Model 2 + Level M 纠错):URL 场景 < 512 字节完全够用。 + +// escposQR 写入 ESC/POS 二维码指令流(不切纸,由调用方决定结尾) +// size: 1-16(模块像素数),默认 6 +// ecc : 48/49/50/51 (L/M/Q/H) +func escposQR(w io.Writer, data string, size byte, ecc byte) error { + if size < 1 { + size = 1 + } + if size > 16 { + size = 16 + } + if ecc < 48 || ecc > 51 { + ecc = 49 // 默认 M + } + if len(data) == 0 { + return nil + } + bw := bufio.NewWriter(w) + + // 1) 选择模型:Model 2(cn=49 fn=65 n=50) + bw.WriteString("\x1d(k\x04\x00\x31\x41\x32") + + // 2) 模块大小(cn=49 fn=67 n=size) + bw.WriteString("\x1d(k\x03\x00\x31\x43") + bw.WriteByte(size) + + // 3) 纠错级别(cn=49 fn=69 n=ecc) + bw.WriteString("\x1d(k\x03\x00\x31\x45") + bw.WriteByte(ecc) + + // 4) 存储数据:GS ( k pL pH 49 80 48 + // pL pH = (data_len + 3) 低/高字节 + pL := byte((len(data) + 3) & 0xff) + pH := byte(((len(data) + 3) >> 8) & 0xff) + bw.WriteString("\x1d(k") + bw.WriteByte(pL) + bw.WriteByte(pH) + bw.WriteString("\x31\x50\x30") + bw.WriteString(data) + + // 5) 打印(cn=49 fn=81 n=48 不叠加文字) + bw.WriteString("\x1d(k\x03\x00\x31\x51\x30") + + return bw.Flush() +} + // ============================ // 后端实现 // ============================ @@ -120,6 +180,9 @@ func (p *SystemPrinter) Print(text string) error { return cmd.Run() } +// PrintQR 系统打印后端无二维码指令能力,no-op +func (p *SystemPrinter) PrintQR(url string) error { return nil } + // Close 系统打印无需关闭 func (p *SystemPrinter) Close() error { return nil } @@ -147,6 +210,20 @@ func (p *ESCPOSPrinter) Print(text string) error { return writeEscpos(p.conn, text) } +// PrintQR 发送 ESC/POS 二维码指令到网络打印机 +// 走纸居中追加一行提示,模块大小 6,纠错级别 M +func (p *ESCPOSPrinter) PrintQR(url string) error { + if p.conn == nil { + return nil + } + // 居中(ESC a 1)后写一行"扫码查看详细报告",然后发二维码 + center := "\x1ba\x01———— 扫码查看详细报告 ————\n\x1ba\x00" + if _, err := p.conn.Write([]byte(center)); err != nil { + return err + } + return escposQR(p.conn, url, 6, 49) +} + // Close 关闭连接 func (p *ESCPOSPrinter) Close() error { if p.conn != nil { @@ -193,6 +270,18 @@ func (p *USBPrinter) Print(text string) error { return writeEscpos(p.dev, text) } +// PrintQR 发送 ESC/POS 二维码指令到 USB 打印机 +func (p *USBPrinter) PrintQR(url string) error { + if p.dev == nil { + return nil + } + center := "\x1ba\x01———— 扫码查看详细报告 ————\n\x1ba\x00" + if _, err := p.dev.Write([]byte(center)); err != nil { + return err + } + return escposQR(p.dev, url, 6, 49) +} + // Close 关闭设备 func (p *USBPrinter) Close() error { if p.dev != nil { @@ -226,6 +315,12 @@ func (p *FilePrinter) Print(text string) error { return err } +// PrintQR 文件后端:将"扫码查看详细报告"提示行 + URL 写入文件(便于在文件中复制链接) +func (p *FilePrinter) PrintQR(url string) error { + _, err := fmt.Fprintf(p.f, "\n———— 扫码查看详细报告 ————\nURL: %s\n\n", url) + return err +} + // Close 关闭文件 func (p *FilePrinter) Close() error { return p.f.Close() diff --git a/auto-check/pkg/report/print_test.go b/auto-check/pkg/report/print_test.go new file mode 100644 index 0000000..5dd736c --- /dev/null +++ b/auto-check/pkg/report/print_test.go @@ -0,0 +1,131 @@ +package report + +import ( + "bytes" + "strings" + "testing" +) + +// TestEscposQR_EmptyData 空数据应直接返回 nil,不写入任何指令 +func TestEscposQR_EmptyData(t *testing.T) { + var buf bytes.Buffer + if err := escposQR(&buf, "", 6, 49); err != nil { + t.Fatalf("空数据应返回 nil,得到 err=%v", err) + } + if buf.Len() != 0 { + t.Errorf("空数据不应输出指令,实际写入 %d 字节", buf.Len()) + } +} + +// TestEscposQR_BasicCommands 验证基本 GS ( k 指令流 +func TestEscposQR_BasicCommands(t *testing.T) { + var buf bytes.Buffer + data := "http://192.168.1.10:8080/reports/report-abc-10.0.0.1-20260824.html" + if err := escposQR(&buf, data, 6, 49); err != nil { + t.Fatalf("生成指令失败: %v", err) + } + + got := buf.Bytes() + // 必须包含 GS ( k 起始 + if !bytes.Contains(got, []byte{0x1d, 0x28, 0x6b}) { + t.Error("缺少 GS ( k 起始指令") + } + // 必须包含模型选择 cn=49 fn=65 n=50 + if !bytes.Contains(got, []byte{0x31, 0x41, 0x32}) { + t.Error("缺少 QR 模型选择指令 (31 41 32)") + } + // 必须包含模块大小 n=6 + if !bytes.Contains(got, []byte{0x31, 0x43, 0x06}) { + t.Error("缺少模块大小指令 (31 43 06)") + } + // 必须包含纠错级别 M (49) + if !bytes.Contains(got, []byte{0x31, 0x45, 49}) { + t.Error("缺少纠错级别指令 (31 45 49)") + } + // 必须包含数据存储 49 80 48 + if !bytes.Contains(got, []byte{0x31, 0x50, 0x30}) { + t.Error("缺少数据存储指令 (31 50 30)") + } + // 必须包含打印指令 49 81 48 + if !bytes.Contains(got, []byte{0x31, 0x51, 0x30}) { + t.Error("缺少打印指令 (31 51 30)") + } + // 数据本体 + if !bytes.Contains(got, []byte(data)) { + t.Error("缺少 URL 数据本体") + } +} + +// TestEscposQR_ClampSizeAndECC 验证 size/ecc 参数越界时自动夹紧 +func TestEscposQR_ClampSizeAndECC(t *testing.T) { + var buf1, buf2, buf3 bytes.Buffer + // size 越界 0 → 夹紧为 1 + _ = escposQR(&buf1, "abc", 0, 49) + // size 越界 99 → 夹紧为 16 + _ = escposQR(&buf2, "abc", 99, 49) + // ecc 非法 99 → 夹紧为 49 (M) + _ = escposQR(&buf3, "abc", 6, 99) + + if !bytes.Contains(buf1.Bytes(), []byte{0x31, 0x43, 0x01}) { + t.Error("size=0 应夹紧为 1,未生效") + } + if !bytes.Contains(buf2.Bytes(), []byte{0x31, 0x43, 0x10}) { + t.Error("size=99 应夹紧为 16,未生效") + } + if !bytes.Contains(buf3.Bytes(), []byte{0x31, 0x45, 49}) { + t.Error("ecc=99 应夹紧为 49(M),未生效") + } +} + +// TestEscposQR_DataLengthEncoding pL/pH 编码正确(大数据场景) +// 指令布局: 1d 28 6b pL pH 31 50 30 +func TestEscposQR_DataLengthEncoding(t *testing.T) { + var buf bytes.Buffer + // 200 字节数据 → pL = 203 (0xCB), pH = 0 + data := strings.Repeat("a", 200) + _ = escposQR(&buf, data, 6, 49) + got := buf.Bytes() + + wantPL := byte((200 + 3) & 0xff) // 203 = 0xCB + wantPH := byte(((200 + 3) >> 8) & 0xff) + + // 数据存储标记 "31 50 30" 在 got 中的位置 + dataMarker := []byte{0x31, 0x50, 0x30} + idx := bytes.Index(got, dataMarker) + if idx < 0 { + t.Fatal("未找到数据存储指令 31 50 30") + } + // 期望布局:1d(GS) 28 ( 6b k pL pH 31 50 30 ... + // got[idx-5] = 0x1d, got[idx-4] = 0x28, got[idx-3] = 0x6b + // got[idx-2] = pL, got[idx-1] = pH + if got[idx-5] != 0x1d || got[idx-4] != 0x28 || got[idx-3] != 0x6b { + t.Fatalf("pL/pH 前不是 GS ( k,实际前 5 字节 = % x", got[idx-5:idx]) + } + if got[idx-2] != wantPL || got[idx-1] != wantPH { + t.Errorf("pL/pH 编码错误: got=0x%02x 0x%02x, want=0x%02x 0x%02x", + got[idx-2], got[idx-1], wantPL, wantPH) + } +} + +// TestSystemPrinter_PrintQR 系统打印后端 no-op +func TestSystemPrinter_PrintQR(t *testing.T) { + p := &SystemPrinter{} + if err := p.PrintQR("http://example.com"); err != nil { + t.Errorf("SystemPrinter.PrintQR 应返回 nil,得到 %v", err) + } +} + +// TestFilePrinter_PrintQR 文件后端写入提示行 + URL +func TestFilePrinter_PrintQR(t *testing.T) { + tmp := t.TempDir() + p, err := NewFilePrinter(tmp + "/out.log") + if err != nil { + t.Fatalf("创建 FilePrinter 失败: %v", err) + } + defer p.Close() + + url := "http://192.168.1.10/reports/r.html" + if err := p.PrintQR(url); err != nil { + t.Fatalf("PrintQR 失败: %v", err) + } +} diff --git a/auto-check/pkg/report/report.go b/auto-check/pkg/report/report.go index dfab571..6a5c100 100644 --- a/auto-check/pkg/report/report.go +++ b/auto-check/pkg/report/report.go @@ -32,14 +32,17 @@ type HostResult struct { // StressResult 单项压力测试结果 type StressResult struct { - Type string `json:"type" yaml:"type"` - Status string `json:"status" yaml:"status"` // pass / fail / skip - Duration string `json:"duration" yaml:"duration"` - Score float64 `json:"score,omitempty" yaml:"score,omitempty"` - ScoreUnit string `json:"score_unit,omitempty" yaml:"score_unit,omitempty"` - Metrics []stress.MetricItem `json:"metrics,omitempty" yaml:"metrics,omitempty"` - Output string `json:"output,omitempty" yaml:"output,omitempty"` - Error string `json:"error,omitempty" yaml:"error,omitempty"` + Type string `json:"type" yaml:"type"` + Status string `json:"status" yaml:"status"` // pass / fail / skip + Duration string `json:"duration" yaml:"duration"` + Score float64 `json:"score,omitempty" yaml:"score,omitempty"` + ScoreUnit string `json:"score_unit,omitempty" yaml:"score_unit,omitempty"` + Metrics []stress.MetricItem `json:"metrics,omitempty" yaml:"metrics,omitempty"` + Benchmarks []stress.BenchItem `json:"benchmarks,omitempty" yaml:"benchmarks,omitempty"` // 性能/温度基准评级 + OverallLevel string `json:"overall_level,omitempty" yaml:"overall_level,omitempty"` + OverallText string `json:"overall_text,omitempty" yaml:"overall_text,omitempty"` + Output string `json:"output,omitempty" yaml:"output,omitempty"` + Error string `json:"error,omitempty" yaml:"error,omitempty"` } // Report 检测报告 @@ -49,6 +52,8 @@ type Report struct { Duration string `json:"duration" yaml:"duration"` Config ConfigSummary `json:"config" yaml:"config"` Phases []PhaseResult `json:"phases" yaml:"phases"` + // QRURL HTML 报告访问链接(用于热敏打印中的二维码与模板回退) + QRURL string `json:"qr_url,omitempty" yaml:"qr_url,omitempty"` } // ConfigSummary 配置摘要(脱敏) diff --git a/auto-check/pkg/report/templates/report_80mm.tmpl b/auto-check/pkg/report/templates/report_80mm.tmpl index df47ebe..345751c 100644 --- a/auto-check/pkg/report/templates/report_80mm.tmpl +++ b/auto-check/pkg/report/templates/report_80mm.tmpl @@ -18,9 +18,14 @@ {{ end }}{{ end }}{{ if eq .Phase "SSH 登录" }}{{ range .Hosts }}{{ if .SSHLogin }}✓{{ else }}✗{{ end }} {{ padRight .MAC 19 }} {{ padRight .IP 15 }} {{ .SSHErr }} {{ end }}{{ end }}{{ if eq .Phase "压力测试" }}{{ range .Hosts }}{{ padRight .MAC 19 }} {{ padRight .IP 15 }} {{ range .Stress }}{{ if eq .Status "pass" }}✓{{ else }}✗{{ end }} {{ padRight .Type 12 }} {{ .Status }} {{ .Duration }} -{{ if .Score }} 跑分: {{ printf "%.1f" .Score }} {{ .ScoreUnit }}{{ end }}{{ range .Metrics }} {{ .Label }}: {{ printf "%.1f" .Value }}{{ .Unit }} +{{ if .Score }} 跑分: {{ printf "%.1f" .Score }} {{ .ScoreUnit }}{{ end }}{{ if .OverallText }} 评级: {{ .OverallText }}{{ end }}{{ range .Benchmarks }} {{ padRight .Label 8 }} {{ .Value }} {{ .LevelText }} +{{ end }}{{ range .Metrics }} {{ .Label }}: {{ printf "%.1f" .Value }}{{ .Unit }} {{ end }}{{ if .Error }} ERR: {{ trunc .Error 34 }}{{ end }}{{ end }}{{ end }}{{ end }}{{ end }} {{ "" }} {{ hr '═' }} 报告结束 {{ hr '═' }} +{{ if .QRURL }}{{ "" }} +———— 扫码查看详细报告 ———— +{{ .QRURL }} +{{ end }} diff --git a/auto-check/pkg/stress/benchmark.go b/auto-check/pkg/stress/benchmark.go new file mode 100644 index 0000000..9abd900 --- /dev/null +++ b/auto-check/pkg/stress/benchmark.go @@ -0,0 +1,611 @@ +package stress + +import ( + "fmt" + "strings" +) + +// ============================ +// 性能/温度基准(让用户对结果有感性认知) +// ============================ +// +// 评级说明(与"超过正常"程度绑定,4 档): +// - 远低于正常 red #dc2626 +// - 达到正常 green #16a34a +// - 超过正常 blue #3b82f6 +// - 远超过正常 purple #7c3aed +// +// 评分方向: +// - higher_better: 数值越大越好(CPU/内存跑分、IOPS、吞吐) +// - lower_better : 数值越小越好(温度) +// +// 阈值(Cutoffs):3 个分界点将数值划分为 4 档。 +// - higher_better: c0 远低于(危险), c1~c0 正常, c2~c1 超过, ≤c2 远超过(优秀) +// +// 阈值仅作参考,应根据实际硬件代际持续校准;下文取自常见消费级/主流企业级硬件中位水平。 + +// Level 评级 +type Level string + +const ( + LevelPoor Level = "poor" // 远低于正常 + LevelNormal Level = "normal" // 达到正常 + LevelGood Level = "good" // 超过正常 + LevelExcellent Level = "excellent" // 远超过正常 +) + +// LevelDisplay 评级显示元数据 +type LevelDisplay struct { + Text string // 远低于正常 / 达到正常 / 超过正常 / 远超过正常 + Color string // 颜色(与报告 CSS 协调) + Order int // 0/1/2/3 用于排序与综合评级 +} + +var levelDisplay = map[Level]LevelDisplay{ + LevelPoor: {Text: "远低于正常", Color: "#dc2626", Order: 0}, + LevelNormal: {Text: "达到正常", Color: "#16a34a", Order: 1}, + LevelGood: {Text: "超过正常", Color: "#3b82f6", Order: 2}, + LevelExcellent: {Text: "远超过正常", Color: "#7c3aed", Order: 3}, +} + +// LevelMeta 取评级显示信息,未知时返回 normal +func LevelMeta(l Level) LevelDisplay { + if d, ok := levelDisplay[l]; ok { + return d + } + return LevelDisplay{Text: string(l), Color: "#64748b", Order: 1} +} + +// Direction 评分方向 +type Direction string + +const ( + DirHigherBetter Direction = "higher" // 越高越好 + DirLowerBetter Direction = "lower" // 越低越好 +) + +// MetricBench 单个指标的基准配置 +type MetricBench struct { + Key string // 指标键:score / max_temp / iops_total / bw_total + Label string // 显示名 + Unit string // 单位 + Direction Direction // 评分方向 + Cutoffs [3]float64 + Note string // 备注(用于展示) +} + +// ============================ +// 各指标基准(消费/主流企业级硬件参考) +// ============================ + +// CPU 跑分:stress-ng bogo ops/s,4 线程参考(线程越多分越高) +var benchCPU = MetricBench{ + Key: "score", Label: "CPU 跑分", Unit: "ops/s", + Direction: DirHigherBetter, + Cutoffs: [3]float64{8000, 20000, 40000}, + Note: "stress-ng bogo ops/s(4 线程参考;线程数越多分越高)", +} + +// 内存跑分 +var benchMemory = MetricBench{ + Key: "score", Label: "内存跑分", Unit: "ops/s", + Direction: DirHigherBetter, + Cutoffs: [3]float64{5000, 15000, 30000}, + Note: "stress-ng bogo ops/s", +} + +// 综合工况:CPU+内存 综合 +var benchFull = MetricBench{ + Key: "score", Label: "综合跑分", Unit: "ops/s", + Direction: DirHigherBetter, + Cutoffs: [3]float64{6000, 18000, 35000}, + Note: "CPU+内存综合 ops/s", +} + +// 内存精压:MB/s(DDR4 一般 20-50 GB/s,受通道数和频率影响) +var benchMemNative = MetricBench{ + Key: "score", Label: "内存带宽", Unit: "MB/s", + Direction: DirHigherBetter, + Cutoffs: [3]float64{3000, 8000, 15000}, + Note: "内存读写带宽", +} + +// 磁盘 4K 随机读写 IOPS +var benchDiskIOPS = MetricBench{ + Key: "iops_total", Label: "磁盘 IOPS", Unit: "ops/s", + Direction: DirHigherBetter, + Cutoffs: [3]float64{1000, 10000, 50000}, + Note: "4K 随机读写:<1k≈HDD, 1k-10k≈低端 SSD, 10k-50k≈SATA/NVMe 入门, >50k≈NVMe 中高端", +} + +// 磁盘读写总带宽 +var benchDiskBW = MetricBench{ + Key: "bw_total", Label: "磁盘吞吐", Unit: "MB/s", + Direction: DirHigherBetter, + Cutoffs: [3]float64{100, 500, 2000}, + Note: "读写总带宽:<100≈HDD, 100-500≈低端 SSD, 500-2000≈SATA/NVMe 入门, >2000≈NVMe Gen3+", +} + +// 最高温度(°C,越低越好) +var benchTemp = MetricBench{ + Key: "max_temp", Label: "最高温度", Unit: "°C", + Direction: DirLowerBetter, + Cutoffs: [3]float64{90, 75, 60}, // 阈值由高到低:poor/normal, normal/good, good/excellent + Note: "<60°C 优秀, 60-75°C 正常, 75-90°C 偏高, >90°C 危险", +} + +// ============================ +// 硬件基准库(按 CPU 型号匹配) +// ============================ +// +// 设计目的:不同代/不同档位的硬件不能用同一套阈值比较。 +// 例如 i3 与 i7 跑分差距数倍;J4125 与 N100 也不能直接比较。 +// +// 使用方式: +// - MatchHardware(cpuModel) 依据 CPU 型号子串匹配(大小写不敏感) +// - 匹配成功 → 使用该硬件的专属阈值评估 +// - 未匹配 → 所有指标强制返回 LevelNormal("达到正常"),不判定好坏 +// - 库中字段为 nil → 退到默认基准 +// +// 维护说明:库按"匹配顺序"查找,越靠前越优先。新增型号请在最匹配的 +// 位置追加(i5-12xxx 必须在 i5 之前),否则会被更宽泛的规则先匹配。 + +// HardwareBench 一类硬件的基准 +type HardwareBench struct { + // Match CPU 型号匹配子串(大小写不敏感),如 "i7-12"、"N100"、"Ryzen 5" + Match string + // Note 硬件说明,会显示在报告备注里 + Note string + // CPU/Memory/Full/MemBand 各类跑分基准;nil 表示使用默认基准 + CPU *MetricBench + Memory *MetricBench + Full *MetricBench + MemBand *MetricBench +} + +// hardwareLibrary 硬件基准库(按匹配顺序查找,越靠前越优先) +// 数值参考:stress-ng bogo ops/s @ 默认线程数;内存带宽为 stream/memcpy 估算 +// 维护提醒:每代 CPU 阈值约为上一代的 1.15~1.30 倍,跨代需重新校准 +var hardwareLibrary = []HardwareBench{ + // ============ Intel 飞牛常用低功耗 ============ + { + Match: "N100", Note: "Intel N100 (Alder Lake-N, 4C/4T, 6W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 22000, 38000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 12000, 22000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 18000, 30000}, Note: "CPU+内存综合"}, + MemBand: &MetricBench{Key: "score", Label: "内存带宽", Unit: "MB/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 8000, 15000}, Note: "单通道 DDR5 带宽上限"}, + }, + { + Match: "N305", Note: "Intel N305 (Alder Lake-N, 8C/8T, 15W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 40000, 65000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 18000, 35000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{15000, 30000, 50000}, Note: "CPU+内存综合"}, + MemBand: &MetricBench{Key: "score", Label: "内存带宽", Unit: "MB/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 10000, 18000}, Note: "DDR5 双通道带宽"}, + }, + { + Match: "N95", Note: "Intel N95 (Alder Lake-N, 4C/4T, 15W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 20000, 35000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 11000, 20000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 16000, 28000}, Note: "CPU+内存综合"}, + MemBand: &MetricBench{Key: "score", Label: "内存带宽", Unit: "MB/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 7000, 13000}, Note: "单通道 DDR4/DDR5 带宽"}, + }, + { + Match: "N5105", Note: "Intel Celeron N5105 (Jasper Lake, 4C/4T, 10W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{7000, 14000, 25000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 9000, 16000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 12000, 22000}, Note: "CPU+内存综合"}, + }, + { + Match: "N5095", Note: "Intel Celeron N5095 (Jasper Lake, 4C/4T, 15W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{6000, 12000, 22000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 8000, 15000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 10000, 19000}, Note: "CPU+内存综合"}, + }, + { + Match: "J4125", Note: "Intel Celeron J4125 (Gemini Lake, 4C/4T, 10W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 10000, 18000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 6000, 12000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 8000, 15000}, Note: "CPU+内存综合"}, + }, + { + Match: "J4105", Note: "Intel Celeron J4105 (Gemini Lake, 4C/4T, 10W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4500, 9000, 16000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 6000, 11000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 7500, 14000}, Note: "CPU+内存综合"}, + }, + { + Match: "J3455", Note: "Intel Celeron J3455 (Apollo Lake, 4C/4T, 10W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3500, 7500, 13000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{2500, 5000, 9500}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 6500, 12000}, Note: "CPU+内存综合"}, + }, + { + Match: "J1900", Note: "Intel Celeron J1900 (Bay Trail, 4C/4T, 10W)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{2500, 5500, 10000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{2000, 4000, 7000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{2000, 4500, 8500}, Note: "CPU+内存综合"}, + }, + { + Match: "Celeron", Note: "Intel Celeron (其他型号)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 12000, 22000}, Note: "Celeron 系列通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 7000, 14000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 10000, 18000}, Note: "CPU+内存综合"}, + }, + { + Match: "Atom", Note: "Intel Atom", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{2000, 5000, 9000}, Note: "Atom 系列通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{1500, 3500, 6500}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{1800, 4500, 8000}, Note: "CPU+内存综合"}, + }, + + // ============ Intel Core i9(按代匹配) ============ + { + Match: "i9-13", Note: "13代 i9 (Raptor Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{50000, 100000, 160000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 50000, 90000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{30000, 70000, 120000}, Note: "CPU+内存综合"}, + }, + { + Match: "i9-12", Note: "12代 i9 (Alder Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{40000, 85000, 140000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{18000, 45000, 80000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{28000, 60000, 100000}, Note: "CPU+内存综合"}, + }, + { + Match: "i9-11", Note: "11代 i9 (Rocket Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{35000, 75000, 125000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{15000, 38000, 70000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{25000, 55000, 95000}, Note: "CPU+内存综合"}, + }, + { + Match: "i9-10", Note: "10代 i9 (Comet Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{30000, 65000, 110000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 35000, 65000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{22000, 48000, 85000}, Note: "CPU+内存综合"}, + }, + { + Match: "i9-", Note: "Intel Core i9 (其他代)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{25000, 55000, 95000}, Note: "i9 通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{12000, 30000, 60000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 45000, 80000}, Note: "CPU+内存综合"}, + }, + + // ============ Intel Core i7(按代匹配) ============ + { + Match: "i7-13", Note: "13代 i7 (Raptor Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{40000, 85000, 140000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{18000, 45000, 80000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{28000, 60000, 100000}, Note: "CPU+内存综合"}, + }, + { + Match: "i7-12", Note: "12代 i7 (Alder Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{32000, 70000, 115000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{16000, 40000, 70000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{24000, 52000, 90000}, Note: "CPU+内存综合"}, + }, + { + Match: "i7-11", Note: "11代 i7 (Rocket Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{28000, 60000, 100000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 35000, 60000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{22000, 48000, 80000}, Note: "CPU+内存综合"}, + }, + { + Match: "i7-10", Note: "10代 i7 (Comet Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{25000, 55000, 90000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{12000, 30000, 55000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 42000, 72000}, Note: "CPU+内存综合"}, + }, + { + Match: "i7-8", Note: "8/9代 i7 (Coffee Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 45000, 75000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 25000, 45000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{16000, 35000, 60000}, Note: "CPU+内存综合"}, + }, + { + Match: "i7-7", Note: "7代 i7 (Kaby Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{16000, 35000, 60000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 20000, 38000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{12000, 28000, 48000}, Note: "CPU+内存综合"}, + }, + { + Match: "i7-", Note: "Intel Core i7 (其他代)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{18000, 40000, 70000}, Note: "i7 通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{9000, 22000, 42000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 32000, 55000}, Note: "CPU+内存综合"}, + }, + + // ============ Intel Core i5(按代匹配) ============ + { + Match: "i5-13", Note: "13代 i5 (Raptor Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{30000, 65000, 105000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 35000, 60000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{22000, 48000, 80000}, Note: "CPU+内存综合"}, + }, + { + Match: "i5-12", Note: "12代 i5 (Alder Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{25000, 55000, 90000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{12000, 30000, 55000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{18000, 40000, 70000}, Note: "CPU+内存综合"}, + }, + { + Match: "i5-11", Note: "11代 i5 (Rocket Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{22000, 48000, 80000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{11000, 27000, 48000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{16000, 35000, 60000}, Note: "CPU+内存综合"}, + }, + { + Match: "i5-10", Note: "10代 i5 (Comet Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 42000, 70000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 25000, 45000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 32000, 55000}, Note: "CPU+内存综合"}, + }, + { + Match: "i5-8", Note: "8/9代 i5 (Coffee Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{15000, 32000, 55000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 18000, 35000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 24000, 42000}, Note: "CPU+内存综合"}, + }, + { + Match: "i5-", Note: "Intel Core i5 (其他代)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 30000, 50000}, Note: "i5 通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{7000, 17000, 32000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 22000, 40000}, Note: "CPU+内存综合"}, + }, + + // ============ Intel Core i3(按代匹配) ============ + { + Match: "i3-13", Note: "13代 i3 (Raptor Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 42000, 70000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 24000, 45000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{15000, 32000, 55000}, Note: "CPU+内存综合"}, + }, + { + Match: "i3-12", Note: "12代 i3 (Alder Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{18000, 38000, 62000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{9000, 22000, 40000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{13000, 28000, 50000}, Note: "CPU+内存综合"}, + }, + { + Match: "i3-10", Note: "10代 i3 (Comet Lake)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 30000, 50000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{7000, 17000, 32000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 22000, 40000}, Note: "CPU+内存综合"}, + }, + { + Match: "i3-", Note: "Intel Core i3 (其他代)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 22000, 38000}, Note: "i3 通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5500, 13000, 25000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 18000, 32000}, Note: "CPU+内存综合"}, + }, + + // ============ Intel Xeon ============ + { + Match: "Xeon", Note: "Intel Xeon", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{30000, 70000, 120000}, Note: "Xeon 通用参考(按核心数浮动大)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{15000, 35000, 70000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{22000, 50000, 90000}, Note: "CPU+内存综合"}, + }, + + // ============ AMD Ryzen(按系列) ============ + { + Match: "Ryzen 9", Note: "AMD Ryzen 9", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{40000, 85000, 145000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{18000, 45000, 85000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{30000, 65000, 110000}, Note: "CPU+内存综合"}, + }, + { + Match: "Ryzen 7", Note: "AMD Ryzen 7", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{28000, 60000, 100000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{13000, 32000, 60000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{20000, 45000, 78000}, Note: "CPU+内存综合"}, + }, + { + Match: "Ryzen 5", Note: "AMD Ryzen 5", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{22000, 48000, 80000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{11000, 26000, 48000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{16000, 36000, 62000}, Note: "CPU+内存综合"}, + }, + { + Match: "Ryzen 3", Note: "AMD Ryzen 3", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{14000, 30000, 50000}, Note: "stress-ng bogo ops/s(4 线程)"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{7000, 17000, 32000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{10000, 22000, 40000}, Note: "CPU+内存综合"}, + }, + { + Match: "Athlon", Note: "AMD Athlon", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{5000, 11000, 20000}, Note: "Athlon 通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{3000, 7000, 13000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 9000, 17000}, Note: "CPU+内存综合"}, + }, + { + Match: "AMD", Note: "AMD 处理器 (其他型号)", + CPU: &MetricBench{Key: "score", Label: "CPU 跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{8000, 18000, 32000}, Note: "AMD 通用参考"}, + Memory: &MetricBench{Key: "score", Label: "内存跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{4000, 10000, 18000}, Note: "stress-ng bogo ops/s"}, + Full: &MetricBench{Key: "score", Label: "综合跑分", Unit: "ops/s", Direction: DirHigherBetter, Cutoffs: [3]float64{6000, 14000, 25000}, Note: "CPU+内存综合"}, + }, +} + +// MatchHardware 根据 CPU 型号匹配硬件基准(大小写不敏感,子串匹配) +// 返回 nil 表示未在库中(调用方应将所有指标视为"达到正常",不做好坏判定) +func MatchHardware(cpuModel string) *HardwareBench { + if cpuModel == "" { + return nil + } + lower := strings.ToLower(cpuModel) + for i := range hardwareLibrary { + if strings.Contains(lower, strings.ToLower(hardwareLibrary[i].Match)) { + return &hardwareLibrary[i] + } + } + return nil +} + +// ============================ +// 评估函数 +// ============================ + +// EvalBench 根据基准评估单个数值 +func EvalBench(b MetricBench, value float64) Level { + c := b.Cutoffs + switch b.Direction { + case DirHigherBetter: + switch { + case value < c[0]: + return LevelPoor + case value < c[1]: + return LevelNormal + case value < c[2]: + return LevelGood + default: + return LevelExcellent + } + case DirLowerBetter: + switch { + case value > c[0]: + return LevelPoor + case value > c[1]: + return LevelNormal + case value > c[2]: + return LevelGood + default: + return LevelExcellent + } + } + return LevelNormal +} + +// ReferenceText 生成"参考范围"展示文本 +func (b MetricBench) ReferenceText() string { + c := b.Cutoffs + if b.Direction == DirHigherBetter { + return fmt.Sprintf( + "参考: <%.0f%s 远低于 · %.0f-%.0f%s 正常 · %.0f-%.0f%s 良好 · ≥%.0f%s 卓越", + c[0], b.Unit, c[0], c[1], b.Unit, c[1], c[2], b.Unit, c[2], b.Unit, + ) + } + return fmt.Sprintf( + "参考: >%.0f%s 危险 · %.0f-%.0f%s 偏高 · %.0f-%.0f%s 正常 · ≤%.0f%s 优秀", + c[0], b.Unit, c[1], c[0], b.Unit, c[2], c[1], b.Unit, c[2], b.Unit, + ) +} + +// BenchItem 一次基准评估的展示单元(序列化到报告) +type BenchItem struct { + Key string `json:"key"` + Label string `json:"label"` + Value string `json:"value"` // 格式化后的值,如 "72.0 °C" + ValueNum float64 `json:"value_num"` // 原始数值 + Unit string `json:"unit"` + Level Level `json:"level"` + LevelText string `json:"level_text"` + LevelColor string `json:"level_color"` + Reference string `json:"reference"` + Note string `json:"note"` +} + +// OverallLevel 取多个评级中"最差"(最差用于提示风险) +func OverallLevel(items []BenchItem) Level { + if len(items) == 0 { + return "" + } + worst := LevelExcellent + for _, it := range items { + if LevelMeta(it.Level).Order < LevelMeta(worst).Order { + worst = it.Level + } + } + return worst +} + +// EvaluateResult 对一个 Result 评估所有可用指标的基准 +// 返回的列表按"重要性"排序:跑分 → 温度 → IOPS → 吞吐 +// cpuModel: 设备 CPU 型号(来自 sysInfo["cpu"]);空串或不在库中时,所有指标项 +// 强制返回 LevelNormal("达到正常"),不做好坏判定,避免误报 +func EvaluateResult(r Result, cpuModel string) []BenchItem { + hb := MatchHardware(cpuModel) + inLibrary := hb != nil + + var items []BenchItem + + makeItem := func(b MetricBench, v float64) BenchItem { + // 未在库中 → 强制 normal;已匹配 → 按专属阈值评估 + lvl := LevelNormal + if inLibrary { + lvl = EvalBench(b, v) + } + d := LevelMeta(lvl) + return BenchItem{ + Key: b.Key, + Label: b.Label, + Value: fmt.Sprintf("%.1f %s", v, b.Unit), + ValueNum: v, + Unit: b.Unit, + Level: lvl, + LevelText: d.Text, + LevelColor: d.Color, + Reference: b.ReferenceText(), + Note: b.Note, + } + } + + // pickBench 选基准:库中有专属 → 专属;库中无该字段或未在库 → 默认 + pickBench := func(field *MetricBench, defaultBench MetricBench) MetricBench { + if hb != nil && field != nil { + return *field + } + return defaultBench + } + + // 1) 跑分(按测试类型选基准) + if r.Score > 0 { + var b MetricBench + switch r.Type { + case TestCPU: + if hb != nil { + b = pickBench(hb.CPU, benchCPU) + } else { + b = benchCPU + } + case TestMemory: + if hb != nil { + b = pickBench(hb.Memory, benchMemory) + } else { + b = benchMemory + } + case TestFull: + if hb != nil { + b = pickBench(hb.Full, benchFull) + } else { + b = benchFull + } + case TestMemNative: + if hb != nil { + b = pickBench(hb.MemBand, benchMemNative) + } else { + b = benchMemNative + } + } + if b.Key != "" { + items = append(items, makeItem(b, r.Score)) + } + } + + // 2) 温度(max_temp 存在即评估) + // 温度阈值为通用参考(60/75/90°C),未在库中同样会按通用阈值评估并强制 normal + if t, ok := r.Metrics["max_temp"]; ok && t > 0 { + items = append(items, makeItem(benchTemp, t)) + } + + // 3) 磁盘 IOPS(通用参考,与 CPU 无关) + if t, ok := r.Metrics["iops_total"]; ok && t > 0 { + items = append(items, makeItem(benchDiskIOPS, t)) + } + + // 4) 磁盘吞吐(通用参考,与 CPU 无关) + if t, ok := r.Metrics["bw_total"]; ok && t > 0 { + items = append(items, makeItem(benchDiskBW, t)) + } + + return items +} diff --git a/auto-check/pkg/stress/benchmark_test.go b/auto-check/pkg/stress/benchmark_test.go new file mode 100644 index 0000000..68f5dae --- /dev/null +++ b/auto-check/pkg/stress/benchmark_test.go @@ -0,0 +1,246 @@ +package stress + +import ( + "strings" + "testing" +) + +// TestEvalBench 验证基准评估逻辑 +func TestEvalBench(t *testing.T) { + tests := []struct { + name string + bench MetricBench + val float64 + want Level + }{ + // CPU 跑分(越高越好):4 档 + {"CPU-远低于", benchCPU, 5000, LevelPoor}, + {"CPU-正常", benchCPU, 15000, LevelNormal}, + {"CPU-超过", benchCPU, 30000, LevelGood}, + {"CPU-远超过", benchCPU, 50000, LevelExcellent}, + {"CPU-边界-正常下限", benchCPU, 8000, LevelNormal}, + {"CPU-边界-超过下限", benchCPU, 20000, LevelGood}, + {"CPU-边界-远超过下限", benchCPU, 40000, LevelExcellent}, + + // 温度(越低越好) + {"Temp-远超过(危险)", benchTemp, 95, LevelPoor}, + {"Temp-偏高", benchTemp, 80, LevelNormal}, + {"Temp-正常", benchTemp, 70, LevelGood}, + {"Temp-优秀", benchTemp, 50, LevelExcellent}, + {"Temp-边界-正常", benchTemp, 90, LevelNormal}, + {"Temp-边界-良好", benchTemp, 75, LevelGood}, + {"Temp-边界-优秀", benchTemp, 60, LevelExcellent}, + + // 磁盘 IOPS + {"IOPS-远低于(HDD)", benchDiskIOPS, 500, LevelPoor}, + {"IOPS-正常(低端SSD)", benchDiskIOPS, 5000, LevelNormal}, + {"IOPS-超过(SATA)", benchDiskIOPS, 30000, LevelGood}, + {"IOPS-远超过(NVMe)", benchDiskIOPS, 80000, LevelExcellent}, + + // 磁盘吞吐 + {"BW-远低于(HDD)", benchDiskBW, 50, LevelPoor}, + {"BW-正常", benchDiskBW, 300, LevelNormal}, + {"BW-超过", benchDiskBW, 1000, LevelGood}, + {"BW-远超过", benchDiskBW, 3000, LevelExcellent}, + } + for _, tc := range tests { + got := EvalBench(tc.bench, tc.val) + if got != tc.want { + t.Errorf("%s: val=%.0f got=%s want=%s", tc.name, tc.val, got, tc.want) + } + } +} + +// TestEvaluateResult 验证 Result 评估 +func TestEvaluateResult(t *testing.T) { + // 模拟一次 CPU 压测结果:跑分 25000(超过正常),最高温度 70°C(良好) + r := Result{ + Type: TestCPU, + Score: 25000, + Metrics: map[string]float64{ + "max_temp": 70, + }, + } + // 使用 N100 库:CPU 跑分阈值 10000/22000/38000 → 25000 介于 22k-38k,应为 LevelGood + items := EvaluateResult(r, "Intel N100") + if len(items) != 2 { + t.Fatalf("期望 2 个评估项(跑分+温度),实际 %d", len(items)) + } + // 第一项是 CPU 跑分 + if items[0].Level != LevelGood { + t.Errorf("CPU 跑分评级错误: got=%s want=%s", items[0].Level, LevelGood) + } + // 第二项是温度(70°C 在 60-75 之间,应为 LevelGood) + if items[1].Level != LevelGood { + t.Errorf("温度评级错误: got=%s want=%s", items[1].Level, LevelGood) + } + // 综合评级应取最差 + if OverallLevel(items) != LevelGood { + t.Errorf("综合评级错误: got=%s", OverallLevel(items)) + } +} + +// TestEvaluateResultDisk 验证磁盘测试评估 +func TestEvaluateResultDisk(t *testing.T) { + // 模拟一次磁盘压测:吞吐 1500MB/s(良好),IOPS 80000(远超过) + r := Result{ + Type: TestDiskIO, + Score: 1500, // score 是 bw_total + Metrics: map[string]float64{ + "iops_total": 80000, + "bw_total": 1500, + }, + } + // 磁盘阈值与 CPU 型号无关,传任意库内型号都能正常评估 + items := EvaluateResult(r, "Intel N100") + if len(items) != 2 { + t.Fatalf("期望 2 个评估项,实际 %d", len(items)) + } + // 找 IOPS 项 + var iops, bw BenchItem + for _, it := range items { + switch it.Key { + case "iops_total": + iops = it + case "bw_total": + bw = it + } + } + if iops.Level != LevelExcellent { + t.Errorf("IOPS 80000 应评为远超过正常: got=%s", iops.Level) + } + if bw.Level != LevelGood { + t.Errorf("吞吐 1500 应评为超过正常: got=%s", bw.Level) + } +} + +// TestMatchHardware 验证硬件库匹配 +func TestMatchHardware(t *testing.T) { + tests := []struct { + cpu string + wantNil bool + wantNote string // 仅检查 Note 包含的子串 + }{ + // 飞牛常用低功耗 + {"Intel(R) Celeron(R) N100 CPU @ 0.80GHz", false, "N100"}, + {"Intel N305", false, "N305"}, + {"12th Gen Intel(R) Core(TM) i3-12100", false, "12代 i3"}, + {"13th Gen Intel(R) Core(TM) i5-13500", false, "13代 i5"}, + {"11th Gen Intel(R) Core(TM) i7-11700K", false, "11代 i7"}, + {"Intel(R) Core(TM) i9-12900K CPU", false, "12代 i9"}, + {"Intel(R) Celeron(R) J4125 CPU @ 2.00GHz", false, "J4125"}, + {"Intel(R) Celeron(R) N5095 @ 2.00GHz", false, "N5095"}, + + // AMD + {"AMD Ryzen 5 5600 6-Core Processor", false, "Ryzen 5"}, + {"AMD Ryzen 7 5800X 8-Core", false, "Ryzen 7"}, + {"AMD Ryzen 9 5900X", false, "Ryzen 9"}, + + // 大小写不敏感 + {"INTEL N100", false, "N100"}, + {"intel celeron n100", false, "N100"}, + + // 不在库中 + {"", true, ""}, + {"Some Unknown CPU XYZ", true, ""}, + {"Apple M1", true, ""}, + {"Loongson 3A5000", true, ""}, + } + for _, tc := range tests { + got := MatchHardware(tc.cpu) + if tc.wantNil { + if got != nil { + t.Errorf("cpu=%q 应返回 nil,得到 %v (Note=%s)", tc.cpu, got, got.Note) + } + continue + } + if got == nil { + t.Errorf("cpu=%q 应匹配到硬件,得到 nil", tc.cpu) + continue + } + if !strings.Contains(got.Note, tc.wantNote) { + t.Errorf("cpu=%q 匹配到 %q,但 Note 应包含 %q", tc.cpu, got.Note, tc.wantNote) + } + } +} + +// TestMatchHardware_Priority 验证匹配顺序优先级(i5-12xxx 必须优先于 i5 通用) +func TestMatchHardware_Priority(t *testing.T) { + hb := MatchHardware("Intel Core i5-12400") + if hb == nil { + t.Fatal("i5-12400 应匹配到硬件") + } + if !strings.Contains(hb.Note, "12代 i5") { + t.Errorf("i5-12400 应优先匹配 12代 i5,实际 Note=%s", hb.Note) + } + + // 不带代号的 i5 应匹配通用条目 + hb = MatchHardware("Intel Core i5-4400") // 老 4 代 + if hb == nil { + t.Fatal("i5-4400 应匹配到硬件") + } + if !strings.Contains(hb.Note, "i5") { + t.Errorf("i5-4400 应匹配 i5 系列,实际 Note=%s", hb.Note) + } +} + +// TestEvaluateResult_HardwareAware 验证同一分数在不同硬件下的评级不同 +func TestEvaluateResult_HardwareAware(t *testing.T) { + r := Result{Type: TestCPU, Score: 25000} + mr := map[string]float64{"max_temp": 70} + + // N100:阈值 10000/22000/38000 → 25000 介于 22k-38k → Good + rN100 := r + rN100.Metrics = mr + itemsN100 := EvaluateResult(rN100, "Intel N100") + if itemsN100[0].Level != LevelGood { + t.Errorf("N100 跑分 25k 应为 Good,实际 %s", itemsN100[0].Level) + } + + // i3-12100:阈值 18000/38000/62000 → 25000 介于 18k-38k → Normal + itemsI3 := EvaluateResult(r, "Intel Core i3-12100") + if itemsI3[0].Level != LevelNormal { + t.Errorf("i3-12100 跑分 25k 应为 Normal,实际 %s", itemsI3[0].Level) + } + + // i7-12700:阈值 32000/70000/115000 → 25000 < 32k → Poor + itemsI7 := EvaluateResult(r, "Intel Core i7-12700") + if itemsI7[0].Level != LevelPoor { + t.Errorf("i7-12700 跑分 25k 应为 Poor(明显低于 i7 水平),实际 %s", itemsI7[0].Level) + } +} + +// TestEvaluateResult_UnknownHardware 验证未在库中的硬件全部返回 normal +func TestEvaluateResult_UnknownHardware(t *testing.T) { + r := Result{ + Type: TestCPU, + Score: 25000, + Metrics: map[string]float64{ + "max_temp": 70, + "iops_total": 80000, + "bw_total": 1500, + }, + } + + // 1) 空字符串 + items := EvaluateResult(r, "") + if len(items) != 4 { + t.Fatalf("空 cpuModel 应返回 4 项,实际 %d", len(items)) + } + for _, it := range items { + if it.Level != LevelNormal { + t.Errorf("空 cpuModel 时 %s 应为 Normal,实际 %s", it.Label, it.Level) + } + } + + // 2) 未知型号 + items = EvaluateResult(r, "SomeUnknownCPU XYZ") + if len(items) != 4 { + t.Fatalf("未知 cpuModel 应返回 4 项,实际 %d", len(items)) + } + for _, it := range items { + if it.Level != LevelNormal { + t.Errorf("未知 cpuModel 时 %s 应为 Normal,实际 %s", it.Label, it.Level) + } + } +} diff --git a/auto-check/pkg/stress/chart.go b/auto-check/pkg/stress/chart.go index f3a1ff2..01ff26c 100644 --- a/auto-check/pkg/stress/chart.go +++ b/auto-check/pkg/stress/chart.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" "strings" "time" ) @@ -51,16 +52,20 @@ type chartPayload struct { // testCard 单个测试卡片数据 type testCard struct { - Name string `json:"name"` - Label string `json:"label"` - Status string `json:"status"` - Duration string `json:"duration"` - Score float64 `json:"score"` - ScoreUnit string `json:"score_unit"` - ScoreHint string `json:"score_hint"` - Metrics []kvPair `json:"metrics"` - Output string `json:"output"` - Chart *chartPayload `json:"chart,omitempty"` + Name string `json:"name"` + Label string `json:"label"` + Status string `json:"status"` + Duration string `json:"duration"` + Score float64 `json:"score"` + ScoreUnit string `json:"score_unit"` + ScoreHint string `json:"score_hint"` + Metrics []kvPair `json:"metrics"` + Benchmarks []BenchItem `json:"benchmarks,omitempty"` // 性能/温度基准评级 + OverallLevel Level `json:"overall_level,omitempty"` // 综合评级(各项最差) + OverallText string `json:"overall_text,omitempty"` + OverallColor string `json:"overall_color,omitempty"` + Output string `json:"output"` + Chart *chartPayload `json:"chart,omitempty"` } // reportHTMLData 报告整体数据 @@ -76,7 +81,14 @@ type reportHTMLData struct { } // WriteReportHTML 生成综合 HTML 报告(跑分卡片 + 多曲线图),返回文件路径 +// 默认文件名:report-.html func WriteReportHTML(ip string, report *Report, reportDir string) (string, error) { + filename := fmt.Sprintf("report-%s.html", SanitizeFilename(ip)) + return WriteReportHTMLTo(ip, report, reportDir, filename) +} + +// WriteReportHTMLTo 生成综合 HTML 报告到指定文件名,返回完整文件路径 +func WriteReportHTMLTo(ip string, report *Report, reportDir, filename string) (string, error) { data := buildReportData(ip, report) dataJSON, err := json.Marshal(data) if err != nil { @@ -88,11 +100,11 @@ func WriteReportHTML(ip string, report *Report, reportDir string) (string, error if err := os.MkdirAll(reportDir, 0755); err != nil { return "", err } - filename := fmt.Sprintf("%s/report-%s.html", reportDir, SanitizeFilename(ip)) - if err := os.WriteFile(filename, []byte(html), 0644); err != nil { + path := filepath.Join(reportDir, filename) + if err := os.WriteFile(path, []byte(html), 0644); err != nil { return "", err } - return filename, nil + return path, nil } func buildReportData(ip string, report *Report) reportHTMLData { @@ -105,13 +117,18 @@ func buildReportData(ip string, report *Report) reportHTMLData { Summary: report.Summary(), SysInfo: report.SysInfo, } + // 硬件型号:从 sysInfo["cpu"] 读取,用于按硬件库匹配基准 + cpuModel := "" + if report.SysInfo != nil { + cpuModel = report.SysInfo["cpu"] + } for _, res := range report.Results { - data.Cards = append(data.Cards, buildCard(res)) + data.Cards = append(data.Cards, buildCard(cpuModel, res)) } return data } -func buildCard(res Result) testCard { +func buildCard(cpuModel string, res Result) testCard { card := testCard{ Name: string(res.Type), Label: testLabel(res.Type), @@ -128,6 +145,16 @@ func buildCard(res Result) testCard { Value: fmt.Sprintf("%.1f%s", res.Metrics[name], MetricUnit(name)), }) } + // 性能/温度基准评级(仅在有数据时填充;按硬件库匹配专属阈值) + if items := EvaluateResult(res, cpuModel); len(items) > 0 { + card.Benchmarks = items + if lvl := OverallLevel(items); lvl != "" { + d := LevelMeta(lvl) + card.OverallLevel = lvl + card.OverallText = d.Text + card.OverallColor = d.Color + } + } if len(res.Samples) > 0 { if payload, ok := buildChart(res); ok { card.Chart = &payload diff --git a/auto-check/pkg/stress/metrics.go b/auto-check/pkg/stress/metrics.go index 8df9b12..141d4d8 100644 --- a/auto-check/pkg/stress/metrics.go +++ b/auto-check/pkg/stress/metrics.go @@ -65,7 +65,7 @@ type Config struct { TempLogInt time.Duration TempLimit float64 // 温度上限(°C),0=不判定 // 压测统一在 Docker 容器中执行(工具预装在镜像里) - DockerImage string // 压测镜像名称,如 stress-test:latest + DockerImage string // 压测镜像名称,如 stress-test:20260824-153045(由 build.sh 自动维护) DockerTar string // 本地导出的镜像文件(docker save),目标机无镜像时上传并 load DockerArgs string // Docker 运行参数,如 "--network=host --privileged" } diff --git a/auto-check/pkg/stress/report_html.go b/auto-check/pkg/stress/report_html.go index 74d2cd2..1eb744f 100644 --- a/auto-check/pkg/stress/report_html.go +++ b/auto-check/pkg/stress/report_html.go @@ -36,6 +36,18 @@ header .meta b{color:#fff;font-weight:600} .metric{display:flex;flex-direction:column;gap:2px;padding:8px 12px;background:#f1f5f9;border-radius:8px;min-width:88px} .metric .m-label{font-size:11px;color:#64748b} .metric .m-value{font-size:15px;font-weight:700;color:#0f172a} +.bench{margin-top:14px;padding:12px 14px;background:#f8fafc;border-radius:10px;border:1px dashed #e2e8f0} +.bench-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;gap:10px;flex-wrap:wrap} +.bench-title{font-size:12px;font-weight:600;color:#475569;letter-spacing:.3px} +.bench-overall{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:700;color:#fff} +.bench-list{display:flex;flex-direction:column;gap:6px} +.bench-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:6px 0;border-bottom:1px dashed #eef2f7} +.bench-row:last-child{border-bottom:none} +.bench-name{font-size:13px;font-weight:600;color:#0f172a;min-width:84px} +.bench-val{font-size:13px;color:#334155;font-variant-numeric:tabular-nums;min-width:96px} +.bench-tag{display:inline-block;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700;color:#fff;line-height:1.4} +.bench-ref{font-size:11px;color:#64748b;flex:1;min-width:0} +.bench-note{font-size:11px;color:#94a3b8;margin-top:4px;line-height:1.5} .chart-box{position:relative;height:260px;margin-top:6px} details.output{margin-top:14px;border-top:1px dashed #e2e8f0;padding-top:10px} details.output summary{cursor:pointer;font-size:12px;color:#64748b;user-select:none} @@ -84,6 +96,33 @@ function buildCard(card,idx){ card.metrics.forEach(function(x){h+='
'+esc(x.label)+''+esc(x.value)+'
';}); h+=''; } + if(card.benchmarks&&card.benchmarks.length){ + var overall=card.overall_level?card.overall_level:''; + var overallText=card.overall_text||''; + var overallColor=card.overall_color||'#64748b'; + h+='
'; + h+='
基准评估(参考消费/主流企业级硬件)'; + if(overall){h+='综合: '+esc(overallText)+'';} + h+='
'; + h+='
'; + card.benchmarks.forEach(function(b){ + h+='
'; + h+=''+esc(b.label)+''; + h+=''+esc(b.value)+''; + h+=''+esc(b.level_text)+''; + h+=''+esc(b.reference)+''; + h+='
'; + }); + h+='
'; + // 备注合并:去重后展示 + var notes={}; + card.benchmarks.forEach(function(b){if(b.note)notes[b.note]=1;}); + var noteArr=Object.keys(notes); + if(noteArr.length){ + h+='
说明: '+esc(noteArr.join(' · '))+'
'; + } + h+='
'; + } if(card.chart){h+='
';} if(card.output&&card.status!=='pass'){ h+='
详细输出
'+esc(card.output)+'
'; diff --git a/auto-check/pkg/stress/runner.go b/auto-check/pkg/stress/runner.go index e658125..4feacba 100644 --- a/auto-check/pkg/stress/runner.go +++ b/auto-check/pkg/stress/runner.go @@ -290,8 +290,12 @@ func (r *Runner) runInDocker() (string, error) { } // 2. 构建 Docker 运行命令(通过环境变量传入参数) + // 固定挂载:/sys 只读(容器内是独立 sysfs,sensors 需读宿主机硬件传感器节点才能采集温度); + // /etc/localtime 只读(容器时区与宿主机一致,dmesg -T 与采样时间戳才准确)。 containerName := fmt.Sprintf("auto-check-%d", time.Now().UnixNano()) dockerRunCmd := fmt.Sprintf("docker run --rm --name %s "+ + "-v /sys:/sys:ro "+ + "-v /etc/localtime:/etc/localtime:ro "+ "-e AUTOCHECK_TYPES=%s "+ "-e AUTOCHECK_DURATION=%d "+ "-e AUTOCHECK_THREADS=%d "+ diff --git a/auto-check/pkg/stress/tools.go b/auto-check/pkg/stress/tools.go index 21177ac..21be677 100644 --- a/auto-check/pkg/stress/tools.go +++ b/auto-check/pkg/stress/tools.go @@ -40,17 +40,17 @@ func runPrivileged(client *ssh.Client, cmd, sudoPwd string) (string, error) { if out, err := sshclient.RunCommand(client, "id -u"); err == nil && strings.TrimSpace(out) == "0" { return sshclient.RunCommand(client, cmd) } - // 非 root:尝试 sudo + // 非 root:尝试 sudo(-p '' 静默密码提示,避免提示文本污染命令输出) if sudoPwd != "" { // echo 密码 | sudo -S 执行;整条命令用双引号包裹,避免命令内部单引号嵌套冲突。 // 仅对命令内的双引号转义(docker 命令均不含双引号,安全)。 quoted := strings.ReplaceAll(singleLine(cmd), `"`, `\"`) - wrapped := fmt.Sprintf("echo %s | sudo -S -- sh -c \"%s\"", shellQuote(sudoPwd), quoted) + wrapped := fmt.Sprintf("echo %s | sudo -S -p '' -- sh -c \"%s\"", shellQuote(sudoPwd), quoted) return sshclient.RunCommand(client, wrapped) } // 无密码:先尝试免密 sudo (-n),失败则回退普通 sudo(会提示需要密码) quoted := strings.ReplaceAll(singleLine(cmd), `"`, `\"`) - if out, err := sshclient.RunCommand(client, "sudo -n -- sh -c \""+quoted+"\""); err == nil { + if out, err := sshclient.RunCommand(client, "sudo -n -p '' -- sh -c \""+quoted+"\""); err == nil { return out, nil } return sshclient.RunCommand(client, "sudo -- sh -c \""+quoted+"\"") diff --git a/auto-check/pkg/stress/types.go b/auto-check/pkg/stress/types.go index addc246..1d44dfa 100644 --- a/auto-check/pkg/stress/types.go +++ b/auto-check/pkg/stress/types.go @@ -196,6 +196,11 @@ func (r *Report) Summary() string { // ToText 文本格式报告 func (r *Report) ToText() string { + // 从 sysInfo 提取 CPU 型号用于按硬件库匹配基准 + cpuModel := "" + if r.SysInfo != nil { + cpuModel = r.SysInfo["cpu"] + } var sb strings.Builder sb.WriteString(fmt.Sprintf("══ [%s] 压力测试报告 ══\n", r.IP)) sb.WriteString(fmt.Sprintf(" 耗时: %s\n\n", r.Duration.Round(time.Millisecond))) @@ -214,6 +219,13 @@ func (r *Report) ToText() string { if res.Score > 0 { sb.WriteString(fmt.Sprintf(" 跑分: %.1f %s\n", res.Score, ScoreUnit(res.Type))) } + // 基准评级(让用户对结果有感性认知,按硬件库匹配专属阈值) + if items := EvaluateResult(res, cpuModel); len(items) > 0 { + for _, it := range items { + sb.WriteString(fmt.Sprintf(" [%s] %s %s — %s\n", + it.LevelText, it.Label, it.Value, it.Reference)) + } + } for _, name := range sortedMetricNames(res.Metrics) { unit := MetricUnit(name) sb.WriteString(fmt.Sprintf(" %s: %.1f%s\n", MetricLabel(name), res.Metrics[name], unit)) diff --git a/auto-check/pkg/workflow/workflow.go b/auto-check/pkg/workflow/workflow.go index 374d6ab..e1ff436 100644 --- a/auto-check/pkg/workflow/workflow.go +++ b/auto-check/pkg/workflow/workflow.go @@ -75,7 +75,7 @@ func (w *Workflow) round() { fmt.Printf(" [测试] %s SSH 连接失败,跳过报告输出: %s\n", ip, rpt.Results[0].Error) continue } - report.SaveAndPrintDeviceReport(&dev, rpt, cfg.Report.Path, cfg.Report.Print) + report.SaveAndPrintDeviceReport(&dev, rpt, cfg.Report.Path, cfg.Report.Print, cfg.Report.HTML) } // 3. 打印状态变化(首次或与上次不一致) diff --git a/auto-check/verify_dispatch_main.go b/auto-check/verify_dispatch_main.go deleted file mode 100644 index 1ec8b2d..0000000 --- a/auto-check/verify_dispatch_main.go +++ /dev/null @@ -1,44 +0,0 @@ -//go:build ignore - -// 临时验证程序:验证 镜像上传 + docker load 分发链路(用完即删) -package main - -import ( - "fmt" - "os" - "strings" - "time" - - "auto-check/pkg/sshclient" -) - -func main() { - ip := os.Args[1] - cfg := sshclient.NewConfig("admin", "admin123", "", 22, 10*time.Second) - cli, err := sshclient.Connect(ip, cfg) - if err != nil { - fmt.Println("SSH 连接失败:", err) - os.Exit(1) - } - defer cli.Close() - sshclient.EnsureHome(cli) - - v, _ := sshclient.RunCommand(cli, "echo 'admin123' | sudo -S -- docker version --format '{{.Server.Version}}' 2>/dev/null") - fmt.Printf("Docker 版本: %q\n", strings.TrimSpace(v)) - - exists, _ := sshclient.RunCommand(cli, "echo 'admin123' | sudo -S -- docker images stress-test:latest --format '{{.Repository}}:{{.Tag}}' 2>/dev/null") - fmt.Printf("镜像状态: %q\n", strings.TrimSpace(exists)) - - if strings.TrimSpace(exists) == "" { - if err := sshclient.UploadFile(cli, "docker/stress-test/stress-test.tar", "/tmp/auto-check-image.tar"); err != nil { - fmt.Println("上传失败:", err) - os.Exit(1) - } - out, err := sshclient.RunCommand(cli, "echo 'admin123' | sudo -S -- docker load -i /tmp/auto-check-image.tar 2>&1") - sshclient.RunCommand(cli, "rm -f /tmp/auto-check-image.tar") - fmt.Printf("load 输出: %s (err=%v)\n", out, err) - exists, _ = sshclient.RunCommand(cli, "echo 'admin123' | sudo -S -- docker images stress-test:latest --format '{{.Repository}}:{{.Tag}}' 2>/dev/null") - fmt.Printf("load 后镜像状态: %q\n", strings.TrimSpace(exists)) - } - fmt.Println("验证完成") -} diff --git a/产品/飞牛 NAS/skus/2.5-金-单-wifi-j1900-4G-128G.md b/产品/飞牛 NAS/skus/2.5-金-单-wifi-j1900-4G-128G.md new file mode 100644 index 0000000..0913a06 --- /dev/null +++ b/产品/飞牛 NAS/skus/2.5-金-单-wifi-j1900-4G-128G.md @@ -0,0 +1,23 @@ +# 产品信息 + +| 序号 | 配件 | 价格 | +|:---:|------|:----:| +| 1 | J1900 | ¥70 | +| 2 | D3-4G | ¥18 | +| 3 | mSATA-128G | ¥52 | +| 4 | 金属机箱2.5寸-单 | ¥33 | +| 5 | 电源-60W | ¥12 | +| 6 | 硬盘线-单 | ¥4 | +| 7 | 双SATA转换器 | × | +| 8 | 无线网卡 | ¥20 | +| 9 | 电池 | ¥1 | +| 10 | 网线 | ¥1 | +| 11 | 运费 | ¥10 | +| 12 | 包装费 | ¥5 | +| 13 | 装机费 | ¥10 | +| 14 | 总成本 | ¥236 | +| 15 | 建议零售价 | ¥259.00 | + +- 产品名称:飞牛NAS 2.5金属单 J1900 WiFi +- 产品型号:2.5-金-单-wifi-j1900-4G-128G +- 备注:2.5寸金属机箱,单盘位,单SATA口,带无线网卡 diff --git a/产品/飞牛 NAS/skus/2.5-金-单-wifi-j3160-4G-64G.md b/产品/飞牛 NAS/skus/2.5-金-单-wifi-j3160-4G-64G.md new file mode 100644 index 0000000..a57091c --- /dev/null +++ b/产品/飞牛 NAS/skus/2.5-金-单-wifi-j3160-4G-64G.md @@ -0,0 +1,35 @@ +--- +AIGC: + Label: "1" + ContentProducer: 001191440300708461136T1XGW3 + ProduceID: ad0267bbf3cd51935facf04c4cc7d1e5_092e8433a16c11f1a413525400287e28 + ReservedCode1: /arpZcg2grU1B0WmNX4EDBLB/cjV4uKwFTFCxE5/9rmu4HpSnTKly6rmM8z7sIKg2eaBBy2TQK7T6Y3k+ElOibGoi+zjtZNizil4pDWUQuMsgVztNKjD3Zb+zIAUfvl/lEqd3s1OZVABCQeXdYGBRkaBdsLDq8YEQiXJC+5UFIA5H2I+uECUGfzu87w= + ContentPropagator: 001191440300708461136T1XGW3 + PropagateID: ad0267bbf3cd51935facf04c4cc7d1e5_092e8433a16c11f1a413525400287e28 + ReservedCode2: /arpZcg2grU1B0WmNX4EDBLB/cjV4uKwFTFCxE5/9rmu4HpSnTKly6rmM8z7sIKg2eaBBy2TQK7T6Y3k+ElOibGoi+zjtZNizil4pDWUQuMsgVztNKjD3Zb+zIAUfvl/lEqd3s1OZVABCQeXdYGBRkaBdsLDq8YEQiXJC+5UFIA5H2I+uECUGfzu87w= +--- + +# 产品信息 + +| 序号 | 配件 | 价格 | +|:---:|------|:----:| +| 1 | J3160 | ¥80 | +| 2 | D3-4G | ¥18 | +| 3 | mSATA-64G | ¥30 | +| 4 | 金属机箱2.5寸-单 | ¥33 | +| 5 | 电源-60W | ¥12 | +| 6 | 硬盘线-单 | ¥4 | +| 7 | 双SATA转换器 | × | +| 8 | 无线网卡 | ¥20 | +| 9 | 电池 | ¥1 | +| 10 | 网线 | ¥1 | +| 11 | 运费 | ¥10 | +| 12 | 包装费 | ¥5 | +| 13 | 装机费 | ¥10 | +| 14 | 总成本 | ¥224 | +| 15 | 建议零售价 | ¥306.40 | + +- 产品名称:飞牛NAS 2.5金属单 J3160 WiFi +- 产品型号:2.5-金-单-wifi-j3160-4G-64G +- 备注:2.5寸金属机箱,单盘位,单SATA口,带无线网卡 +*(内容由AI生成,仅供参考)* diff --git a/产品/飞牛 NAS/skus/3.5-亚-单-有-j3160-8G-128G.md b/产品/飞牛 NAS/skus/3.5-亚-单-有-j3160-8G-128G.md index 4d9c180..6716bdd 100644 --- a/产品/飞牛 NAS/skus/3.5-亚-单-有-j3160-8G-128G.md +++ b/产品/飞牛 NAS/skus/3.5-亚-单-有-j3160-8G-128G.md @@ -16,7 +16,7 @@ | 12 | 包装费 | ¥5 | | 13 | 装机费 | ¥10 | | 14 | 总成本 | ¥260 | -| 15 | 建议零售价 | ¥360.00 | +| 15 | 建议零售价 | ¥364.00 | - 产品名称:飞牛NAS 亚克力单 J3160 - 产品型号:3.5-亚-单-有-j3160-8G-128G diff --git a/产品/飞牛 NAS/skus/3.5-亚-双-有-i3-4G-64G.md b/产品/飞牛 NAS/skus/3.5-亚-双-有-i3-4G-64G.md index f95a055..62e4656 100644 --- a/产品/飞牛 NAS/skus/3.5-亚-双-有-i3-4G-64G.md +++ b/产品/飞牛 NAS/skus/3.5-亚-双-有-i3-4G-64G.md @@ -16,7 +16,7 @@ | 12 | 包装费 | ¥5 | | 13 | 装机费 | ¥10 | | 14 | 总成本 | ¥207 | -| 15 | 建议零售价 | ¥248.46 | +| 15 | 建议零售价 | ¥244.75 | - 产品名称:飞牛NAS 亚克力双 i3-3代 - 产品型号:3.5-亚-双-有-i3-4G-64G diff --git a/产品/飞牛 NAS/skus/3.5-亚-双-有-i5-2代-8G-64G.md b/产品/飞牛 NAS/skus/3.5-亚-双-有-i5-2代-8G-64G.md index ae673ff..cf12221 100644 --- a/产品/飞牛 NAS/skus/3.5-亚-双-有-i5-2代-8G-64G.md +++ b/产品/飞牛 NAS/skus/3.5-亚-双-有-i5-2代-8G-64G.md @@ -16,7 +16,7 @@ | 12 | 包装费 | ¥5 | | 13 | 装机费 | ¥10 | | 14 | 总成本 | ¥270 | -| 15 | 建议零售价 | ¥411.50 | +| 15 | 建议零售价 | ¥416.50 | - 产品名称:飞牛NAS 亚克力双 i5-2代 - 产品型号:3.5-亚-双-有-i5-2代-8G-64G diff --git a/产品/飞牛 NAS/skus/3.5-亚-双-有-j3160-4G-32G.md b/产品/飞牛 NAS/skus/3.5-亚-双-有-j3160-4G-32G.md index ff8ab9b..94cad33 100644 --- a/产品/飞牛 NAS/skus/3.5-亚-双-有-j3160-4G-32G.md +++ b/产品/飞牛 NAS/skus/3.5-亚-双-有-j3160-4G-32G.md @@ -16,7 +16,7 @@ | 12 | 包装费 | ¥5 | | 13 | 装机费 | ¥10 | | 14 | 总成本 | ¥235 | -| 15 | 建议零售价 | ¥315.00 | +| 15 | 建议零售价 | ¥300.86 | - 产品名称:飞牛NAS 亚克力双 J3160 - 产品型号:3.5-亚-双-有-j3160-4G-32G diff --git a/产品/飞牛 NAS/skus/3.5-金-三-有-j3355-4G-64G.md b/产品/飞牛 NAS/skus/3.5-金-三-有-j3355-4G-64G.md new file mode 100644 index 0000000..80c645d --- /dev/null +++ b/产品/飞牛 NAS/skus/3.5-金-三-有-j3355-4G-64G.md @@ -0,0 +1,35 @@ +--- +AIGC: + Label: "1" + ContentProducer: 001191440300708461136T1XGW3 + ProduceID: ad0267bbf3cd51935facf04c4cc7d1e5_09cbe1a0a16c11f1a413525400287e28 + ReservedCode1: cHeAvGLsxVkkeT5jnXVfOdFng+6Ccux1G3WoHUQjzvMunLqO4unQXfXeJc2qBXpwd9+KQQbZcNDKe7859zbS4LwkgKhgSJmx48d42F3fbTqJYihPN9JOFISamlcey7YQ3/ir1vwxk1l+IzXvGc50VBamRwCLmj7AlAYAYotCY+uSRiD0EMbGgjeBXIY= + ContentPropagator: 001191440300708461136T1XGW3 + PropagateID: ad0267bbf3cd51935facf04c4cc7d1e5_09cbe1a0a16c11f1a413525400287e28 + ReservedCode2: cHeAvGLsxVkkeT5jnXVfOdFng+6Ccux1G3WoHUQjzvMunLqO4unQXfXeJc2qBXpwd9+KQQbZcNDKe7859zbS4LwkgKhgSJmx48d42F3fbTqJYihPN9JOFISamlcey7YQ3/ir1vwxk1l+IzXvGc50VBamRwCLmj7AlAYAYotCY+uSRiD0EMbGgjeBXIY= +--- + +# 产品信息 + +| 序号 | 配件 | 价格 | +|:---:|------|:----:| +| 1 | J3355-4G | ¥120 | +| 2 | × | × | +| 3 | mSATA-64G | ¥30 | +| 4 | 金属机箱3.5寸大-三 | ¥68 | +| 5 | 电源-96W | ¥18.5 | +| 6 | 硬盘线-双 | ¥5 | +| 7 | 双SATA转换器 | ¥28 | +| 8 | 无线网卡 | × | +| 9 | 电池 | ¥1 | +| 10 | 网线 | ¥1 | +| 11 | 运费 | ¥10 | +| 12 | 包装费 | ¥5 | +| 13 | 装机费 | ¥10 | +| 14 | 总成本 | ¥296.5 | +| 15 | 建议零售价 | ¥396.00 | + +- 产品名称:飞牛NAS 3.5金属大 三盘位 J3355 +- 产品型号:3.5-金-三-有-j3355-4G-64G +- 备注:3.5金属大,三盘位,J3355-4G集成内存,单SATA口需转换器,96W电源 +*(内容由AI生成,仅供参考)* diff --git a/产品/飞牛 NAS/skus/3.5-金-单-wifi-j3160-8G-64G.md b/产品/飞牛 NAS/skus/3.5-金-单-wifi-j3160-8G-64G.md new file mode 100644 index 0000000..64731bb --- /dev/null +++ b/产品/飞牛 NAS/skus/3.5-金-单-wifi-j3160-8G-64G.md @@ -0,0 +1,23 @@ +# 产品信息 + +| 序号 | 配件 | 价格 | +|:---:|------|:----:| +| 1 | J3160 | ¥80 | +| 2 | D3-8G | ¥65 | +| 3 | mSATA-64G | ¥30 | +| 4 | 金属机箱3.5寸小 | ¥60 | +| 5 | 电源-60W | ¥12 | +| 6 | 硬盘线-单 | ¥4 | +| 7 | 双SATA转换器 | × | +| 8 | 无线网卡 | ¥20 | +| 9 | 电池 | ¥1 | +| 10 | 网线 | ¥1 | +| 11 | 运费 | ¥10 | +| 12 | 包装费 | ¥5 | +| 13 | 装机费 | ¥10 | +| 14 | 总成本 | ¥298 | +| 15 | 建议零售价 | ¥418.50 | + +- 产品名称:飞牛NAS 3.5金属单 J3160 WiFi +- 产品型号:3.5-金-单-wifi-j3160-8G-64G +- 备注:3.5寸金属机箱,单盘位,单SATA口,带无线网卡 diff --git a/产品/飞牛 NAS/skus/3.5-金-双-有-i5-3代-8G-128G.md b/产品/飞牛 NAS/skus/3.5-金-双-有-i5-3代-8G-128G.md index 8f1d974..6d5a0ac 100644 --- a/产品/飞牛 NAS/skus/3.5-金-双-有-i5-3代-8G-128G.md +++ b/产品/飞牛 NAS/skus/3.5-金-双-有-i5-3代-8G-128G.md @@ -16,7 +16,7 @@ | 12 | 包装费 | ¥5 | | 13 | 装机费 | ¥10 | | 14 | 总成本 | ¥314 | -| 15 | 建议零售价 | ¥431.50 | +| 15 | 建议零售价 | ¥436.50 | - 产品名称:飞牛NAS 3.5金属大 双盘位 i5-3代 - 产品型号:3.5-金-双-有-i5-3代-8G-128G diff --git a/产品/飞牛 NAS/skus/3.5-金-双-有-j3160-4G-64G.md b/产品/飞牛 NAS/skus/3.5-金-双-有-j3160-4G-64G.md new file mode 100644 index 0000000..2dd71f8 --- /dev/null +++ b/产品/飞牛 NAS/skus/3.5-金-双-有-j3160-4G-64G.md @@ -0,0 +1,35 @@ +--- +AIGC: + Label: "1" + ContentProducer: 001191440300708461136T1XGW3 + ProduceID: ad0267bbf3cd51935facf04c4cc7d1e5_08230749a16c11f1a54f525400f8a581 + ReservedCode1: TkXi5JH+CK228faMwBfTEoUAU1+AadIGsuORXVOokqi82S5iHvGq32pvDwR+ZqWflIGK9S4rvxE9ZDQorAU18qhq2xB8UOkdOEd3yQ89TwEedGj+shXbf2Rz2EGxIbVFRHQM/n+9XXQlLfQ6IJJ2iCAnqTz9ltGgppiL8kbEIwVhsxNfPMImWpoXRC0= + ContentPropagator: 001191440300708461136T1XGW3 + PropagateID: ad0267bbf3cd51935facf04c4cc7d1e5_08230749a16c11f1a54f525400f8a581 + ReservedCode2: TkXi5JH+CK228faMwBfTEoUAU1+AadIGsuORXVOokqi82S5iHvGq32pvDwR+ZqWflIGK9S4rvxE9ZDQorAU18qhq2xB8UOkdOEd3yQ89TwEedGj+shXbf2Rz2EGxIbVFRHQM/n+9XXQlLfQ6IJJ2iCAnqTz9ltGgppiL8kbEIwVhsxNfPMImWpoXRC0= +--- + +# 产品信息 + +| 序号 | 配件 | 价格 | +|:---:|------|:----:| +| 1 | J3160 | ¥80 | +| 2 | D3-4G | ¥18 | +| 3 | mSATA-64G | ¥30 | +| 4 | 金属机箱3.5寸大-双 | ¥68 | +| 5 | 电源-60W | ¥12 | +| 6 | 硬盘线-双 | ¥5 | +| 7 | 双SATA转换器 | ¥28 | +| 8 | 无线网卡 | × | +| 9 | 电池 | ¥1 | +| 10 | 网线 | ¥1 | +| 11 | 运费 | ¥10 | +| 12 | 包装费 | ¥5 | +| 13 | 装机费 | ¥10 | +| 14 | 总成本 | ¥268 | +| 15 | 建议零售价 | ¥375.25 | + +- 产品名称:飞牛NAS 3.5金属大 双盘位 J3160 +- 产品型号:3.5-金-双-有-j3160-4G-64G +- 备注:3.5金属大,双盘位,J3160单SATA口需转换器 +*(内容由AI生成,仅供参考)* diff --git a/产品/飞牛 NAS/skus/3.5-金-双-有-j3355-4G-64G.md b/产品/飞牛 NAS/skus/3.5-金-双-有-j3355-4G-64G.md index 5b8b1ab..8bf6544 100644 --- a/产品/飞牛 NAS/skus/3.5-金-双-有-j3355-4G-64G.md +++ b/产品/飞牛 NAS/skus/3.5-金-双-有-j3355-4G-64G.md @@ -16,7 +16,7 @@ | 12 | 包装费 | ¥5 | | 13 | 装机费 | ¥10 | | 14 | 总成本 | ¥290 | -| 15 | 建议零售价 | ¥341.50 | +| 15 | 建议零售价 | ¥361.35 | - 产品名称:飞牛NAS 3.5金属大 双盘位 J3355 - 产品型号:3.5-金-双-有-j3355-4G-64G diff --git a/产品/飞牛 NAS/skus/3.5-金-四-有-i7-3代-8G-128G.md b/产品/飞牛 NAS/skus/3.5-金-四-有-i7-3代-8G-128G.md new file mode 100644 index 0000000..cb8523e --- /dev/null +++ b/产品/飞牛 NAS/skus/3.5-金-四-有-i7-3代-8G-128G.md @@ -0,0 +1,23 @@ +# 产品信息 + +| 序号 | 配件 | 价格 | +|:---:|------|:----:| +| 1 | i7-3代 | ¥120 | +| 2 | D3-8G | ¥65 | +| 3 | mSATA-128G | ¥52 | +| 4 | 金属机箱3.5寸大-四 | ¥68 | +| 5 | 电源-96W | ¥18.5 | +| 6 | 硬盘线-双 | ¥5 | +| 7 | 双SATA转换器 | ¥28 | +| 8 | 无线网卡 | × | +| 9 | 电池 | ¥1 | +| 10 | 网线 | ¥1 | +| 11 | 运费 | ¥10 | +| 12 | 包装费 | ¥5 | +| 13 | 装机费 | ¥10 | +| 14 | 总成本 | ¥383.5 | +| 15 | 建议零售价 | ¥600.00 | + +- 产品名称:飞牛NAS 3.5金属大 四盘位 i7-3代 +- 产品型号:3.5-金-四-有-i7-3代-8G-128G +- 备注:3.5金属大,四盘位,i7-3代双SATA口需转换器扩展至4盘,96W电源 diff --git a/产品/飞牛 NAS/skus/价格表.md b/产品/飞牛 NAS/skus/价格表.md index f4d8330..ab5303f 100644 --- a/产品/飞牛 NAS/skus/价格表.md +++ b/产品/飞牛 NAS/skus/价格表.md @@ -1,6 +1,6 @@ # 飞牛 NAS 当前 SKU 价格表 -> 更新日期:2026-08-21 +> 更新日期:2026-08-27 > 售价取值:店铺在售价/订单实收金额(已扣除5元店铺关注券,为商家实际到手价) > 配件价格基准:[配件价格清单.md](../../../配件/配件价格清单.md)(不得估算) > 命名规则:[机箱]-[盘位]-[wifi/有]-[cpu]-[内存]-[硬盘] @@ -14,18 +14,18 @@ | 4 | 3.5-亚-单-有-j3160-4G-32G | ¥180 | ¥197.90 | ¥17.90 | 0 | 一级 | | 5 | 3.5-亚-双-有-i3-4G-32G | ¥196 | ¥217.70 | ¥21.70 | 0 | 一级 | | 6 | 3.5-亚-单-有-j3160-4G-64G | ¥191 | ¥212.75 | ¥21.75 | 0 | 一级 | -| 7 | 3.5-亚-双-有-i3-4G-128G | ¥229 | ¥253.00 | ¥24.00 | 0 | 一级 | -| 8 | 3.5-亚-单-有-j1900-4G-32G | ¥170 | ¥197.90 | ¥27.90 | 0 | 一级 | -| 9 | 3.5-亚-双-有-1037u-4G-32G | ¥177 | ¥208.50 | ¥31.50 | 1 | 一级 | -| 10 | 3.5-亚-单-有-j1900-4G-64G | ¥181 | ¥212.75 | ¥31.75 | 0 | 一级 | -| 11 | 2.5-金-单-有-AMD-A4-4G-32G | ¥153 | ¥185.00 | ¥32.00 | 1 | 一级 | -| 12 | 3.5-亚-双-有-i3-4G-64G | ¥207 | ¥248.46 | ¥41.46 | 2 | 一级 | -| 13 | 3.5-亚-双-有-j1900-4G-64G | ¥236 | ¥279.75 | ¥43.75 | 2 | 一级 | -| 14 | 3.5-亚-双-有-1037u-4G-64G | ¥188 | ¥232.50 | ¥44.50 | 0 | 一级 | -| 15 | 3.5-亚-双-有-1037u-4G-128G | ¥210 | ¥257.30 | ¥47.30 | 0 | 一级 | -| 16 | 3.5-亚-单-有-i3-4G-32G | ¥169 | ¥218.00 | ¥49.00 | 0 | 一级 | -| 17 | 3.5-亚-单-有-AMD-A4-4G-32G | ¥140 | ¥189.50 | ¥49.50 | 0 | 一级 | -| 18 | 3.5-金-双-有-j3355-4G-64G | ¥290 | ¥341.50 | ¥51.50 | 1 | 二级 | +| 7 | 2.5-金-单-wifi-j1900-4G-128G | ¥236 | ¥259.00 | ¥23.00 | 1 | 一级 | +| 8 | 3.5-亚-双-有-i3-4G-128G | ¥229 | ¥253.00 | ¥24.00 | 0 | 一级 | +| 9 | 3.5-亚-单-有-j1900-4G-32G | ¥170 | ¥197.90 | ¥27.90 | 0 | 一级 | +| 10 | 3.5-亚-双-有-1037u-4G-32G | ¥177 | ¥208.50 | ¥31.50 | 1 | 一级 | +| 11 | 3.5-亚-单-有-j1900-4G-64G | ¥181 | ¥212.75 | ¥31.75 | 0 | 一级 | +| 12 | 2.5-金-单-有-AMD-A4-4G-32G | ¥153 | ¥185.00 | ¥32.00 | 1 | 一级 | +| 13 | 3.5-亚-双-有-i3-4G-64G | ¥207 | ¥244.75 | ¥37.75 | 4 | 一级 | +| 14 | 3.5-亚-双-有-j1900-4G-64G | ¥236 | ¥279.75 | ¥43.75 | 2 | 一级 | +| 15 | 3.5-亚-双-有-1037u-4G-64G | ¥188 | ¥232.50 | ¥44.50 | 0 | 一级 | +| 16 | 3.5-亚-双-有-1037u-4G-128G | ¥210 | ¥257.30 | ¥47.30 | 0 | 一级 | +| 17 | 3.5-亚-单-有-i3-4G-32G | ¥169 | ¥218.00 | ¥49.00 | 0 | 一级 | +| 18 | 3.5-亚-单-有-AMD-A4-4G-32G | ¥140 | ¥189.50 | ¥49.50 | 0 | 一级 | | 19 | 3.5-亚-单-有-j1900-4G-128G | ¥203 | ¥255.10 | ¥52.10 | 1 | 二级 | | 20 | 3.5-亚-双-有-j1900-4G-32G | ¥225 | ¥279.20 | ¥54.20 | 0 | 二级 | | 21 | 3.5-亚-双-有-j1900-4G-128G | ¥258 | ¥315.00 | ¥57.00 | 0 | 二级 | @@ -33,33 +33,39 @@ | 23 | 3.5-亚-单-有-AMD-A4-4G-128G | ¥173 | ¥237.50 | ¥64.50 | 0 | 二级 | | 24 | 3.5-亚-单-有-i3-4G-64G | ¥180 | ¥244.90 | ¥64.90 | 0 | 二级 | | 25 | 3.5-亚-双-有-i3-8G-128G | ¥276 | ¥341.50 | ¥65.50 | 0 | 二级 | -| 26 | 3.5-亚-单-有-i3-4G-128G | ¥202 | ¥269.40 | ¥67.40 | 0 | 二级 | -| 27 | 3.5-亚-双-有-1037u-8G-64G | ¥235 | ¥303.70 | ¥68.70 | 0 | 二级 | -| 28 | 3.5-亚-双-有-j3160-8G-64G | ¥293 | ¥362.50 | ¥69.50 | 2 | 二级 | -| 29 | 3.5-亚-双-有-1037u-8G-128G | ¥257 | ¥328.20 | ¥71.20 | 0 | 二级 | -| 30 | 3.5-金-双-有-j3355-4G-128G | ¥312 | ¥389.02 | ¥77.02 | 2 | 二级 | -| 31 | 3.5-亚-双-有-i3-8G-64G | ¥254 | ¥333.10 | ¥79.10 | 0 | 二级 | -| 32 | 3.5-亚-双-有-j1900-8G-64G | ¥283 | ¥362.50 | ¥79.50 | 0 | 二级 | -| 33 | 3.5-亚-双-有-j3160-4G-32G | ¥235 | ¥315.00 | ¥80.00 | 0 | 二级 | -| 34 | 3.5-亚-双-有-j1900-8G-128G | ¥305 | ¥387.00 | ¥82.00 | 0 | 二级 | -| 35 | 3.5-亚-单-有-j1900-8G-64G | ¥228 | ¥313.50 | ¥85.50 | 0 | 二级 | -| 36 | 3.5-亚-单-有-AMD-A4-8G-64G | ¥198 | ¥284.10 | ¥86.10 | 0 | 二级 | -| 37 | 3.5-亚-单-有-i3-8G-64G | ¥227 | ¥313.50 | ¥86.50 | 0 | 二级 | -| 38 | 3.5-亚-单-有-j1900-8G-128G | ¥250 | ¥338.00 | ¥88.00 | 0 | 二级 | -| 39 | 3.5-亚-单-有-AMD-A4-8G-128G | ¥220 | ¥308.60 | ¥88.60 | 0 | 二级 | -| 40 | 3.5-亚-单-有-i3-8G-128G | ¥249 | ¥338.00 | ¥89.00 | 0 | 二级 | -| 41 | 3.5-亚-双-有-j3160-8G-128G | ¥315 | ¥411.00 | ¥96.00 | 0 | 二级 | -| 42 | 3.5-亚-单-有-j3160-8G-128G | ¥260 | ¥360.00 | ¥100.00 | 0 | 三级 | -| 43 | 3.5-亚-双-wifi-i5-2代-8G-128G | ¥312 | ¥417.38 | ¥105.38 | 0 | 三级 | -| 44 | 3.5-亚-单-有-j3160-4G-128G | ¥213 | ¥318.40 | ¥105.40 | 0 | 三级 | -| 45 | 3.5-亚-双-有-i5-2代-4G-32G | ¥212 | ¥328.20 | ¥116.20 | 0 | 三级 | -| 46 | 3.5-金-双-有-i5-3代-8G-128G | ¥314 | ¥431.50 | ¥117.50 | 0 | 三级 | -| 47 | 3.5-亚-双-有-i5-2代-4G-64G | ¥223 | ¥342.90 | ¥119.90 | 0 | 三级 | -| 48 | 3.5-亚-双-有-i5-2代-8G-128G | ¥292 | ¥412.38 | ¥120.38 | 1 | 三级 | -| 49 | 3.5-亚-双-有-i5-2代-4G-128G | ¥245 | ¥367.40 | ¥122.40 | 0 | 三级 | -| 50 | 3.5-亚-单-有-j3160-8G-64G | ¥238 | ¥362.50 | ¥124.50 | 0 | 三级 | -| 51 | 3.5-亚-双-有-i5-2代-8G-64G | ¥270 | ¥411.50 | ¥141.50 | 0 | 三级 | -| 52 | 3.5-金-三-有-i7-3代-8G-128G | ¥383.5 | ¥565.00 | ¥181.50 | 1 | 三级 | +| 26 | 3.5-亚-双-有-j3160-4G-32G | ¥235 | ¥300.86 | ¥65.86 | 1 | 二级 | +| 27 | 3.5-亚-单-有-i3-4G-128G | ¥202 | ¥269.40 | ¥67.40 | 0 | 二级 | +| 28 | 3.5-亚-双-有-1037u-8G-64G | ¥235 | ¥303.70 | ¥68.70 | 0 | 二级 | +| 29 | 3.5-亚-双-有-j3160-8G-64G | ¥293 | ¥362.50 | ¥69.50 | 2 | 二级 | +| 30 | 3.5-亚-双-有-1037u-8G-128G | ¥257 | ¥328.20 | ¥71.20 | 0 | 二级 | +| 31 | 3.5-金-双-有-j3355-4G-64G | ¥290 | ¥361.35 | ¥71.35 | 2 | 二级 | +| 32 | 3.5-金-双-有-j3355-4G-128G | ¥312 | ¥389.02 | ¥77.02 | 2 | 二级 | +| 33 | 3.5-亚-双-有-i3-8G-64G | ¥254 | ¥333.10 | ¥79.10 | 0 | 二级 | +| 34 | 3.5-亚-双-有-j1900-8G-64G | ¥283 | ¥362.50 | ¥79.50 | 0 | 二级 | +| 35 | 3.5-亚-双-有-j1900-8G-128G | ¥305 | ¥387.00 | ¥82.00 | 0 | 二级 | +| 36 | 2.5-金-单-wifi-j3160-4G-64G | ¥224 | ¥306.40 | ¥82.40 | 1 | 二级 | +| 37 | 3.5-亚-单-有-j1900-8G-64G | ¥228 | ¥313.50 | ¥85.50 | 0 | 二级 | +| 38 | 3.5-亚-单-有-AMD-A4-8G-64G | ¥198 | ¥284.10 | ¥86.10 | 0 | 二级 | +| 39 | 3.5-亚-单-有-i3-8G-64G | ¥227 | ¥313.50 | ¥86.50 | 0 | 二级 | +| 40 | 3.5-亚-单-有-j1900-8G-128G | ¥250 | ¥338.00 | ¥88.00 | 0 | 二级 | +| 41 | 3.5-亚-单-有-AMD-A4-8G-128G | ¥220 | ¥308.60 | ¥88.60 | 0 | 二级 | +| 42 | 3.5-亚-单-有-i3-8G-128G | ¥249 | ¥338.00 | ¥89.00 | 0 | 二级 | +| 43 | 3.5-亚-双-有-j3160-8G-128G | ¥315 | ¥411.00 | ¥96.00 | 0 | 二级 | +| 44 | 3.5-金-三-有-j3355-4G-64G | ¥296.5 | ¥396.00 | ¥99.50 | 1 | 二级 | +| 45 | 3.5-亚-单-有-j3160-8G-128G | ¥260 | ¥364.00 | ¥104.00 | 1 | 三级 | +| 46 | 3.5-亚-双-wifi-i5-2代-8G-128G | ¥312 | ¥417.38 | ¥105.38 | 0 | 三级 | +| 47 | 3.5-亚-单-有-j3160-4G-128G | ¥213 | ¥318.40 | ¥105.40 | 0 | 三级 | +| 48 | 3.5-金-双-有-j3160-4G-64G | ¥268 | ¥375.25 | ¥107.25 | 1 | 三级 | +| 49 | 3.5-亚-双-有-i5-2代-4G-32G | ¥212 | ¥328.20 | ¥116.20 | 0 | 三级 | +| 50 | 3.5-亚-双-有-i5-2代-4G-64G | ¥223 | ¥342.90 | ¥119.90 | 0 | 三级 | +| 51 | 3.5-亚-双-有-i5-2代-8G-128G | ¥292 | ¥412.38 | ¥120.38 | 1 | 三级 | +| 52 | 3.5-金-单-wifi-j3160-8G-64G | ¥298 | ¥418.50 | ¥120.50 | 1 | 三级 | +| 53 | 3.5-亚-双-有-i5-2代-4G-128G | ¥245 | ¥367.40 | ¥122.40 | 0 | 三级 | +| 54 | 3.5-金-双-有-i5-3代-8G-128G | ¥314 | ¥436.50 | ¥122.50 | 1 | 三级 | +| 55 | 3.5-亚-单-有-j3160-8G-64G | ¥238 | ¥362.50 | ¥124.50 | 0 | 三级 | +| 56 | 3.5-亚-双-有-i5-2代-8G-64G | ¥270 | ¥416.50 | ¥146.50 | 1 | 三级 | +| 57 | 3.5-金-三-有-i7-3代-8G-128G | ¥383.5 | ¥565.00 | ¥181.50 | 1 | 三级 | +| 58 | 3.5-金-四-有-i7-3代-8G-128G | ¥383.5 | ¥600.00 | ¥216.50 | 1 | 四级 | -**合计:52 款 | 成本区间:¥140 - ¥383.5 | 售价区间:¥185.00 - ¥565.00 | 累计销量:15** -**等级分布:一级 17 款 | 二级 24 款 | 三级 11 款 | 四级 0 款** +**合计:58 款 | 成本区间:¥140 - ¥383.5 | 售价区间:¥185.00 - ¥600.00 | 累计销量:28** +**等级分布:一级 18 款 | 二级 26 款 | 三级 13 款 | 四级 1 款** diff --git a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-1037U-4G-32G.md b/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-1037U-4G-32G.md deleted file mode 100644 index af716ce..0000000 --- a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-1037U-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 3.5金属大 双盘位 1037U | - | -| **产品型号** | 3.5金大-双-1037U-4G-32G | - | -| **用途分类** | NAS | - | -| **CPU** | 1037U | ¥50 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥200 | -| **建议零售价** | - | ¥237 | -| **备注** | 3.5金属大,双盘位,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3160-4G-64G.md b/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3160-4G-64G.md deleted file mode 100644 index 1201c12..0000000 --- a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3160-4G-64G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 3.5金属大 双盘位 J3160 | - | -| **产品型号** | 3.5金大-双-J3160-4G-64G | - | -| **用途分类** | NAS | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥273 | -| **建议零售价** | - | ¥350 | -| **备注** | 3.5金属大,双盘位,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-128G.md b/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-128G.md deleted file mode 100644 index e6894e5..0000000 --- a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 3.5金属大 双盘位 J3355 | - | -| **产品型号** | 3.5金大-双-J3355-4G-128G | - | -| **用途分类** | NAS | - | -| **CPU** | J3355-4G | ¥120 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥328 | -| **建议零售价** | - | ¥404.5 | -| **备注** | 3.5金属大,双盘位,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-64G.md b/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-64G.md deleted file mode 100644 index 81b6e00..0000000 --- a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-J3355-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 3.5金属大 双盘位 J3355 | - | -| **产品型号** | 3.5金大-双-J3355-4G-64G | - | -| **用途分类** | NAS | - | -| **CPU** | J3355-4G | ¥120 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥295 | -| **建议零售价** | - | ¥371.5 | -| **备注** | 3.5金属大,双盘位,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-i5-3代-8G-128G.md b/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-i5-3代-8G-128G.md deleted file mode 100644 index 3dad395..0000000 --- a/产品/飞牛 NAS/归档/fjd-金属机箱3.5寸大-双盘位/sku/3.5金大-双-i5-3代-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 3.5金属大 双盘位 i5-3代 | - | -| **产品型号** | 3.5金大-双-i5-3代-8G-128G | - | -| **用途分类** | NAS | - | -| **CPU** | i5-3代 | ¥85 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥330 | -| **建议零售价** | - | ¥397 | -| **备注** | 3.5金属大,双盘位,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-128G.md deleted file mode 100644 index 06b52eb..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 AMD-A4 | - | -| **产品型号** | 亚克力-单-AMD-A4-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | AMD-A4 | ¥40 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥189 | -| **建议零售价** | - | ¥219 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-32G.md deleted file mode 100644 index 53b4e7a..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 AMD-A4 | - | -| **产品型号** | 亚克力-单-AMD-A4-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | AMD-A4 | ¥40 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥141 | -| **建议零售价** | - | ¥171 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-64G.md deleted file mode 100644 index fc3a5a6..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 AMD-A4 | - | -| **产品型号** | 亚克力-单-AMD-A4-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | AMD-A4 | ¥40 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥156 | -| **建议零售价** | - | ¥186 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-8G-128G.md deleted file mode 100644 index afba39a..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-AMD-A4-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 AMD-A4 | - | -| **产品型号** | 亚克力-单-AMD-A4-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | AMD-A4 | ¥40 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥236 | -| **建议零售价** | - | ¥266 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-128G.md deleted file mode 100644 index c84827a..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J1900 | - | -| **产品型号** | 亚克力-单-J1900-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥219 | -| **建议零售价** | - | ¥249 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-32G.md deleted file mode 100644 index c83954c..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J1900 | - | -| **产品型号** | 亚克力-单-J1900-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥171 | -| **建议零售价** | - | ¥201 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-64G.md deleted file mode 100644 index 163a099..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J1900 | - | -| **产品型号** | 亚克力-单-J1900-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥186 | -| **建议零售价** | - | ¥216 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-8G-128G.md deleted file mode 100644 index 821cc4f..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J1900-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J1900 | - | -| **产品型号** | 亚克力-单-J1900-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥266 | -| **建议零售价** | - | ¥296 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-128G.md deleted file mode 100644 index 5c65514..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J3160 | - | -| **产品型号** | 亚克力-单-J3160-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥229 | -| **建议零售价** | - | ¥259 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-32G.md deleted file mode 100644 index 7bcffc4..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J3160 | - | -| **产品型号** | 亚克力-单-J3160-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥181 | -| **建议零售价** | - | ¥211 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-64G.md deleted file mode 100644 index 317d74f..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J3160 | - | -| **产品型号** | 亚克力-单-J3160-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥196 | -| **建议零售价** | - | ¥226 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-8G-128G.md deleted file mode 100644 index fe67cf8..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-J3160-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 J3160 | - | -| **产品型号** | 亚克力-单-J3160-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥276 | -| **建议零售价** | - | ¥306 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-128G.md deleted file mode 100644 index 9c10551..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 i3-3代 | - | -| **产品型号** | 亚克力-单-i3-3代-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥229 | -| **建议零售价** | - | ¥279 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-32G.md deleted file mode 100644 index fdd5cd9..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 i3-3代 | - | -| **产品型号** | 亚克力-单-i3-3代-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥181 | -| **建议零售价** | - | ¥231 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-64G.md deleted file mode 100644 index 0a98148..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 i3-3代 | - | -| **产品型号** | 亚克力-单-i3-3代-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥196 | -| **建议零售价** | - | ¥246 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-8G-128G.md deleted file mode 100644 index 3eb995c..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱 - 单/sku/亚克力-单-i3-3代-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力单 i3-3代 | - | -| **产品型号** | 亚克力-单-i3-3代-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-单 | ¥20 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-单 | ¥4 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥276 | -| **建议零售价** | - | ¥326 | -| **备注** | 亚克力机箱,单SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-128G.md deleted file mode 100644 index 390f71f..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 1037U | - | -| **产品型号** | 亚克力-双-1037U-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | 1037U | ¥50 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥226 | -| **建议零售价** | - | ¥256 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-32G.md deleted file mode 100644 index 75131bd..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 1037U | - | -| **产品型号** | 亚克力-双-1037U-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | 1037U | ¥50 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥178 | -| **建议零售价** | - | ¥208 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-64G.md deleted file mode 100644 index 2efa480..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 1037U | - | -| **产品型号** | 亚克力-双-1037U-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | 1037U | ¥50 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥193 | -| **建议零售价** | - | ¥223 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-128G.md deleted file mode 100644 index dcc4feb..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 1037U | - | -| **产品型号** | 亚克力-双-1037U-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | 1037U | ¥50 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥273 | -| **建议零售价** | - | ¥303 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-64G.md deleted file mode 100644 index 1b8e87c..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-1037U-8G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 1037U | - | -| **产品型号** | 亚克力-双-1037U-8G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | 1037U | ¥50 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥240 | -| **建议零售价** | - | ¥270 | -| **备注** | 亚克力机箱,双SATA口 | - | \ No newline at end of file diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-128G.md deleted file mode 100644 index ecf3717..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-128G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J1900 | - | -| **产品型号** | 亚克力-双-J1900-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥274 | -| **建议零售价** | - | ¥324 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-32G.md deleted file mode 100644 index 560bc0c..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-32G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J1900 | - | -| **产品型号** | 亚克力-双-J1900-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥226 | -| **建议零售价** | - | ¥276 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-64G.md deleted file mode 100644 index 0584ba1..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-4G-64G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J1900 | - | -| **产品型号** | 亚克力-双-J1900-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥241 | -| **建议零售价** | - | ¥291 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-128G.md deleted file mode 100644 index b0f167b..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-128G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J1900 | - | -| **产品型号** | 亚克力-双-J1900-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥321 | -| **建议零售价** | - | ¥371 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-64G.md deleted file mode 100644 index b1ba700..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J1900-8G-64G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J1900 | - | -| **产品型号** | 亚克力-双-J1900-8G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J1900 | ¥70 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥288 | -| **建议零售价** | - | ¥338 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | \ No newline at end of file diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-128G.md deleted file mode 100644 index 42e2bdb..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-128G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J3160 | - | -| **产品型号** | 亚克力-双-J3160-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥284 | -| **建议零售价** | - | ¥354 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-32G.md deleted file mode 100644 index a6ad72b..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-32G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J3160 | - | -| **产品型号** | 亚克力-双-J3160-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥236 | -| **建议零售价** | - | ¥306 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-64G.md deleted file mode 100644 index bd695cc..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-4G-64G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J3160 | - | -| **产品型号** | 亚克力-双-J3160-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥251 | -| **建议零售价** | - | ¥321 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-128G.md deleted file mode 100644 index 911f81b..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-128G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J3160 | - | -| **产品型号** | 亚克力-双-J3160-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥331 | -| **建议零售价** | - | ¥401 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-64G.md deleted file mode 100644 index 09ee1a9..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-J3160-8G-64G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 J3160 | - | -| **产品型号** | 亚克力-双-J3160-8G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | J3160 | ¥80 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥298 | -| **建议零售价** | - | ¥368 | -| **备注** | 亚克力机箱,双SATA口,需转换器 | - | \ No newline at end of file diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-128G.md deleted file mode 100644 index df2d843..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 i3-3代 | - | -| **产品型号** | 亚克力-双-i3-3代-4G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥256 | -| **建议零售价** | - | ¥306 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-32G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-32G.md deleted file mode 100644 index e54b48f..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-32G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 i3-3代 | - | -| **产品型号** | 亚克力-双-i3-3代-4G-32G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-32G | ¥20 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥208 | -| **建议零售价** | - | ¥258 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-64G.md deleted file mode 100644 index f90fd45..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-4G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 i3-3代 | - | -| **产品型号** | 亚克力-双-i3-3代-4G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-4G | ¥18 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥223 | -| **建议零售价** | - | ¥273 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-128G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-128G.md deleted file mode 100644 index 92d1e41..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 i3-3代 | - | -| **产品型号** | 亚克力-双-i3-3代-8G-128G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥303 | -| **建议零售价** | - | ¥353 | -| **备注** | 亚克力机箱,双SATA口 | - | diff --git a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-64G.md b/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-64G.md deleted file mode 100644 index 085a4d9..0000000 --- a/产品/飞牛 NAS/归档/亚克力机箱-双/sku/亚克力-双-i3-3代-8G-64G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 亚克力双 i3-3代 | - | -| **产品型号** | 亚克力-双-i3-3代-8G-64G | - | -| **用途分类** | NAS/迷你主机 | - | -| **CPU** | i3-3代 | ¥80 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-64G | ¥35 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥270 | -| **建议零售价** | - | ¥320 | -| **备注** | 亚克力机箱,双SATA口 | - | \ No newline at end of file diff --git a/产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-3盘-i7-3代-8G-128G.md b/产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-3盘-i7-3代-8G-128G.md deleted file mode 100644 index 86ea6cc..0000000 --- a/产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-3盘-i7-3代-8G-128G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 金属机箱3.5寸大 3盘位 i7-3代 | - | -| **产品型号** | 3.5金大-3盘-i7-3代-8G-128G | - | -| **用途分类** | NAS | - | -| **CPU** | i7-3代 | ¥120 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-96W | ¥18.5 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥399.5 | -| **建议零售价** | - | ¥569.5 | -| **备注** | 3.5金属大,3盘位,需双SATA转换器 | - | \ No newline at end of file diff --git a/产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-4盘-i7-3代-8G-128G.md b/产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-4盘-i7-3代-8G-128G.md deleted file mode 100644 index a2120ab..0000000 --- a/产品/飞牛 NAS/归档/金属机箱3.5寸大-三或四盘位/3.5金大-4盘-i7-3代-8G-128G.md +++ /dev/null @@ -1,23 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 金属机箱3.5寸大 4盘位 i7-3代 | - | -| **产品型号** | 3.5金大-4盘-i7-3代-8G-128G | - | -| **用途分类** | NAS | - | -| **CPU** | i7-3代 | ¥120 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 金属机箱3.5寸大 | ¥68 | -| **电源** | 电源-96W | ¥18.5 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **双SATA转换器** | 双SATA转换器 | ¥28 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥399.5 | -| **建议零售价** | - | ¥599.5 | -| **备注** | 3.5金属大,4盘位,需双SATA转换器 | - | \ No newline at end of file diff --git a/产品/飞牛 NAS/归档/高性能-i5-i7/sku/亚克力-双-i5-2代-8G-128G.md b/产品/飞牛 NAS/归档/高性能-i5-i7/sku/亚克力-双-i5-2代-8G-128G.md deleted file mode 100644 index f6b2100..0000000 --- a/产品/飞牛 NAS/归档/高性能-i5-i7/sku/亚克力-双-i5-2代-8G-128G.md +++ /dev/null @@ -1,22 +0,0 @@ -# 产品信息 - -| 字段 | 配件名称 | 价格 | -|------|---------|------| -| **产品编号** | - | - | -| **产品名称** | 飞牛NAS 高性能-i5-i7 亚克力双 i5-2代 | - | -| **产品型号** | 亚克力-双-i5-2代-8G-128G | - | -| **用途分类** | NAS | - | -| **CPU** | i5-2代 | ¥85 | -| **内存** | D3-8G | ¥65 | -| **系统盘** | mSATA-128G | ¥68 | -| **机箱** | 亚-双 | ¥46 | -| **电源** | 电源-60W | ¥12 | -| **硬盘线** | 硬盘线-双 | ¥5 | -| **电池** | 电池 | ¥1 | -| **网线** | 网线 | ¥1 | -| **运费** | 运费 | ¥10 | -| **包装费** | 包装费 | ¥5 | -| **装机费** | 装机费 | ¥10 | -| **总成本** | - | ¥308 | -| **建议零售价** | - | ¥388 | -| **备注** | 高性能-i5-i7,亚克力双机箱,支持双SATA口 | - | diff --git a/产品/飞牛 NAS/订单/订单.md b/产品/飞牛 NAS/订单/订单.md deleted file mode 100644 index 93ebe8c..0000000 --- a/产品/飞牛 NAS/订单/订单.md +++ /dev/null @@ -1,47 +0,0 @@ -3.5-亚-单-有-a4-4G-32G 实收: 189.5元 -3.5-亚-单-有-a4-4G-64G 实收: 215.5元 -3.5-亚-单-有-a4-4G-128G 实收: 237.5元 -3.5-亚-单-有-a4-8G-64G 实收: 284.1元 -3.5-亚-单-有-a4-8G-128G 实收: 308.6元 -3.5-亚-单-有-j900-4G-32G 实收: 197.9元 -3.5-亚-单-有-j900-4G-64G 实收: 212.75元 -3.5-亚-单-有-j900-4G-128G 实收:255.1元 -3.5-亚-单-有-j900-8G-64G 实收: 313.5元 -3.5-亚-单-有-j900-8G-128G 实收: 338元 -3.5-亚-单-有-i3-4G-32G 实收: 218元 -3.5-亚-单-有-i3-4G-64G 实收: 244.9元 -3.5-亚-单-有-i3-4G-128G 实收: 269.4元 -3.5-亚-单-有-i3-8G-64G 实收: 313.5元 -3.5-亚-单-有-i3-8G-128G 实收: 338元 -3.5-亚-单-有-j3160-4G-32G 实收: 197.9元 -3.5-亚-单-有-j3160-4G-64G 实收: 212.75元 -3.5-亚-单-有-j3160-4G-128G 实收: 318.4元 -3.5-亚-单-有-j3160-8G-64G 实收: 362.5元 -3.5-亚-单-有-j3160-8G-128G 实收: 360元 -3.5-亚-双-有-1037u-4G-32G 实收: 208.5元 -3.5-亚-双-有-1037u-4G-64G 实收: 232.5元 -3.5-亚-双-有-1037u-4G-128G 实收: 257.3元 -3.5-亚-双-有-1037u-8G-64G 实收: 303.7元 -3.5-亚-双-有-1037u-8G-128G 实收: 328.2元 -3.5-亚-双-有-j1900-4G-32G 实收: 279.2元 -3.5-亚-双-有-j1900-4G-64G 实收: 279.75元 -3.5-亚-双-有-j1900-4G-128G 实收: 315元 -3.5-亚-双-有-j1900-8G-64G 实收: 362.5元 -3.5-亚-双-有-j1900-8G-128G 实收: 387元 -3.5-亚-双-有-i3-4G-32G 实收: 217.7元 -3.5-亚-双-有-i3-4G-64G 实收: 248.46元 -3.5-亚-双-有-i3-4G-128G 实收: 253元 -3.5-亚-双-有-i3-8G-64G 实收: 333.1元 -3.5-亚-双-有-i3-8G-128G 实收: 341.5元 -3.5-亚-双-有-j3160-4G-32G 实收: 315元 -3.5-亚-双-有-j3160-4G-64G 实收: 260元 -3.5-亚-双-有-j3160-4G-128G 实收: 285元 -3.5-亚-双-有-j3160-8G-64G 实收: 378元 -3.5-亚-双-有-j3160-8G-128G 实收: 411元 -3.5-亚-双-有-i5-4G-32G 实收: 328.2元 -3.5-亚-双-有-i5-4G-64G 实收: 342.9元 -3.5-亚-双-有-i5-4G-128G 实收: 367.4元 -3.5-亚-双-有-i5-8G-64G 实收: 411.5元 -3.5-亚-双-有-i5-8G-128G 实收: 412.38元 - -