From 76bf71fc407043f71fa189e9db3b6525b8166b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B2=A3?= <895499445@qq.com> Date: Fri, 24 Jul 2026 15:21:48 +0800 Subject: [PATCH] =?UTF-8?q?docs:=202026-07-24=20=E6=97=A5=E6=8A=A5?= =?UTF-8?q?=E4=B8=8E=E5=88=9D=E5=A7=8B=E5=8C=96=E8=84=9A=E6=9C=AC=E8=A1=A5?= =?UTF-8?q?=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - backend/sql/: schema.sql, data.sql, verify_data.sql, README - docs/03-测试文档/: 数据库初始化检查记录, 第1-2天任务完成记录, E-Shop-测试交付物 - reports/daily/杨光沣/: 20260722, 20260723, 20260724 日报 --- backend/sql/README.md | 35 ++++++ backend/sql/data.sql | 103 ++++++++++++++++++ backend/sql/schema.sql | 52 +++++++++ backend/sql/verify_data.sql | 43 ++++++++ ...\344\272\244\344\273\230\347\211\251.xlsx" | Bin 0 -> 19828 bytes ...00\346\237\245\350\256\260\345\275\225.md" | 63 +++++++++++ ...14\346\210\220\350\256\260\345\275\225.md" | 18 +++ ...2-\346\235\250\345\205\211\346\262\243.md" | 24 ++++ ...3-\346\235\250\345\205\211\346\262\243.md" | 24 ++++ ...4-\346\235\250\345\205\211\346\262\243.md" | 25 +++++ 10 files changed, 387 insertions(+) create mode 100644 backend/sql/README.md create mode 100644 backend/sql/data.sql create mode 100644 backend/sql/schema.sql create mode 100644 backend/sql/verify_data.sql create mode 100644 "docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/E-Shop-\346\235\250\345\205\211\346\262\243-\347\254\2541-2\345\244\251\346\265\213\350\257\225\344\272\244\344\273\230\347\211\251.xlsx" create mode 100644 "docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\346\225\260\346\215\256\345\272\223\345\210\235\345\247\213\345\214\226\346\243\200\346\237\245\350\256\260\345\275\225.md" create mode 100644 "docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\347\254\2541-2\345\244\251\344\273\273\345\212\241\345\256\214\346\210\220\350\256\260\345\275\225.md" create mode 100644 "reports/daily/\346\235\250\345\205\211\346\262\243/20260722-\346\235\250\345\205\211\346\262\243.md" create mode 100644 "reports/daily/\346\235\250\345\205\211\346\262\243/20260723-\346\235\250\345\205\211\346\262\243.md" create mode 100644 "reports/daily/\346\235\250\345\205\211\346\262\243/20260724-\346\235\250\345\205\211\346\262\243.md" diff --git a/backend/sql/README.md b/backend/sql/README.md new file mode 100644 index 0000000..a16df0a --- /dev/null +++ b/backend/sql/README.md @@ -0,0 +1,35 @@ +# MySQL 初始化脚本 + +## 文件说明 + +| 文件 | 用途 | +|------|------| +| `schema.sql` | 创建 `eshop` 数据库及分类、商品表 | +| `data.sql` | 写入 6 个分类、36 个商品,重复执行时更新同 ID 数据 | +| `verify_data.sql` | 检查分类/商品数量、分类分布、孤儿商品和关键边界数据 | + +## 执行顺序 + +```bash +mysql -uroot -p < backend/sql/schema.sql +mysql -uroot -p < backend/sql/data.sql +mysql -uroot -p < backend/sql/verify_data.sql +``` + +若已经进入 MySQL 客户端,可依次执行: + +```sql +SOURCE backend/sql/schema.sql; +SOURCE backend/sql/data.sql; +SOURCE backend/sql/verify_data.sql; +``` + +## 验收口径 + +- 分类总数:6,要求不少于 3。 +- 商品总数:36,要求不少于 30。 +- `product.id=30`:库存为 1,用于库存边界测试。 +- `product.id=31`:状态为 0,用于下架商品测试。 +- `product.id=1/2/22` 与测试工作簿中的无线蓝牙耳机、机械键盘、咖啡豆保持一致。 + +当前脚本只覆盖商品目录模块。用户、购物车、订单、支付等表仍由相应模块负责人接入最终数据库设计。 diff --git a/backend/sql/data.sql b/backend/sql/data.sql new file mode 100644 index 0000000..fef84f7 --- /dev/null +++ b/backend/sql/data.sql @@ -0,0 +1,103 @@ +-- E-Shop 演示数据(MySQL 8.0+) +-- 数据规模:6 个分类、36 个商品。 +-- 关键演示约定: +-- product.id=1 无线蓝牙耳机 +-- product.id=2 机械键盘 +-- product.id=22 咖啡豆 +-- product.id=30 低库存商品(stock=1) +-- product.id=31 下架商品(status=0) + +USE eshop; +SET NAMES utf8mb4; + +START TRANSACTION; + +INSERT INTO category (id, name, sort, status) +VALUES + (1, '数码电子', 10, 1), + (2, '生活百货', 20, 1), + (3, '食品饮料', 30, 1), + (4, '服饰鞋包', 40, 1), + (5, '运动户外', 50, 1), + (6, '图书文创', 60, 1) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + sort = VALUES(sort), + status = VALUES(status); + +INSERT INTO product ( + id, product_code, category_id, name, subtitle, description, + price, original_price, stock, sales, image_url, status, sort +) +VALUES + (1, 'P0001', 1, '无线蓝牙耳机', '主动降噪,续航 30 小时', '适合通勤和运动的入耳式蓝牙耳机,支持双设备连接。', 299.00, 399.00, 120, 286, '/images/products/P0001.jpg', 1, 10), + (2, 'P0002', 1, '机械键盘', '87 键热插拔,白色背光', '紧凑布局机械键盘,支持多系统切换与键帽更换。', 399.00, 499.00, 80, 168, '/images/products/P0002.jpg', 1, 20), + (3, 'P0003', 1, '智能运动手表', '心率监测,5ATM 防水', '支持运动记录、睡眠监测和消息提醒。', 599.00, 699.00, 65, 132, '/images/products/P0003.jpg', 1, 30), + (4, 'P0004', 1, '20W 快充移动电源', '10000mAh,双向快充', '轻量便携移动电源,带电量显示。', 129.00, 159.00, 200, 521, '/images/products/P0004.jpg', 1, 40), + (5, 'P0005', 1, '27 英寸 4K 显示器', 'IPS 面板,Type-C 接口', '适合设计、办公和影音娱乐的高清显示器。', 1899.00, 2199.00, 35, 76, '/images/products/P0005.jpg', 1, 50), + (6, 'P0006', 1, '静音无线鼠标', '双模连接,可调 DPI', '人体工学无线鼠标,适合办公和学习。', 159.00, 199.00, 150, 408, '/images/products/P0006.jpg', 1, 60), + + (7, 'P0007', 2, '手持无线吸尘器', '轻量机身,强劲吸力', '适合家庭和汽车清洁,配多种吸头。', 899.00, 1099.00, 42, 95, '/images/products/P0007.jpg', 1, 70), + (8, 'P0008', 2, '护眼 LED 台灯', '无级调光,定时休息提醒', '学习办公两用台灯,光线柔和无可视频闪。', 99.00, 129.00, 180, 637, '/images/products/P0008.jpg', 1, 80), + (9, 'P0009', 2, '纯棉毛巾三件套', '柔软吸水,家庭装', 'A 类纯棉材质,适合日常洗脸和沐浴。', 39.90, 59.90, 320, 1024, '/images/products/P0009.jpg', 1, 90), + (10, 'P0010', 2, '真空保温杯', '316 不锈钢,500ml', '长效保温保冷,杯盖密封防漏。', 79.00, 99.00, 160, 715, '/images/products/P0010.jpg', 1, 100), + (11, 'P0011', 2, '透明收纳箱', '带滑轮,55L 大容量', '可叠放家用收纳箱,适合衣物和玩具整理。', 49.90, 69.90, 140, 386, '/images/products/P0011.jpg', 1, 110), + (12, 'P0012', 2, '浓缩洗衣液', '低泡易漂,2kg', '适用于机洗和手洗,清新自然香型。', 59.90, 79.90, 210, 829, '/images/products/P0012.jpg', 1, 120), + + (13, 'P0013', 3, '每日坚果礼盒', '7 种果仁果干,30 袋装', '独立小包装,方便携带和控制每日摄入。', 129.00, 159.00, 100, 442, '/images/products/P0013.jpg', 1, 130), + (14, 'P0014', 3, '纯牛奶整箱', '250ml×24 盒', '高温灭菌纯牛奶,适合早餐搭配。', 69.90, 79.90, 130, 965, '/images/products/P0014.jpg', 1, 140), + (15, 'P0015', 3, '茉莉花茶', '清香型茶叶,250g', '花香清雅,适合日常冲泡。', 88.00, 108.00, 75, 216, '/images/products/P0015.jpg', 1, 150), + (16, 'P0016', 3, '黄油曲奇饼干', '铁盒装,600g', '口感酥脆,适合作为下午茶点心。', 59.00, 79.00, 95, 354, '/images/products/P0016.jpg', 1, 160), + (17, 'P0017', 3, '青柠气泡水', '0 糖 0 脂,12 罐', '清爽气泡饮料,冷藏后口感更佳。', 45.90, 59.90, 240, 1108, '/images/products/P0017.jpg', 1, 170), + (18, 'P0018', 3, '即食燕麦片', '原味无添加,1kg', '热水或牛奶冲泡即可食用。', 36.90, 46.90, 170, 602, '/images/products/P0018.jpg', 1, 180), + + (19, 'P0019', 4, '纯棉基础款 T 恤', '柔软透气,多色可选', '简约圆领版型,适合日常穿搭。', 69.00, 99.00, 190, 853, '/images/products/P0019.jpg', 1, 190), + (20, 'P0020', 4, '直筒休闲牛仔裤', '舒适弹力,经典蓝色', '中腰直筒剪裁,通勤休闲均适用。', 159.00, 199.00, 105, 314, '/images/products/P0020.jpg', 1, 200), + (21, 'P0021', 4, '商务通勤双肩包', '可容纳 15.6 英寸电脑', '分区收纳、防泼水面料,适合通勤出差。', 189.00, 239.00, 88, 275, '/images/products/P0021.jpg', 1, 210), + (22, 'P0022', 3, '精品咖啡豆', '中度烘焙,500g', '坚果与焦糖风味,适合手冲和意式咖啡机。', 98.00, 118.00, 90, 437, '/images/products/P0022.jpg', 1, 220), + (23, 'P0023', 4, '轻量缓震跑鞋', '透气网面,耐磨鞋底', '适合慢跑、健走和日常通勤。', 329.00, 399.00, 72, 198, '/images/products/P0023.jpg', 1, 230), + (24, 'P0024', 4, '轻薄防晒外套', 'UPF50+,便携可收纳', '适合通勤和户外活动的轻量防晒衣。', 139.00, 179.00, 110, 246, '/images/products/P0024.jpg', 1, 240), + + (25, 'P0025', 5, '加厚防滑瑜伽垫', '双面防滑,厚度 8mm', '适合瑜伽、拉伸和居家训练。', 89.00, 119.00, 85, 337, '/images/products/P0025.jpg', 1, 250), + (26, 'P0026', 5, '智能计数跳绳', '电子计数,可调绳长', '记录次数和训练时长,适合室内外使用。', 49.00, 69.00, 145, 589, '/images/products/P0026.jpg', 1, 260), + (27, 'P0027', 5, '可调节哑铃套装', '单只 2.5-12.5kg', '旋钮快速调节重量,节省收纳空间。', 699.00, 799.00, 28, 84, '/images/products/P0027.jpg', 1, 270), + (28, 'P0028', 5, '户外露营灯', '三档亮度,Type-C 充电', '可悬挂便携营灯,支持应急照明。', 119.00, 149.00, 96, 172, '/images/products/P0028.jpg', 1, 280), + (29, 'P0029', 5, '运动水壶', '食品级材质,750ml', '一键开盖、防漏设计,适合健身骑行。', 39.00, 49.00, 220, 731, '/images/products/P0029.jpg', 1, 290), + (30, 'P0030', 5, '碳纤维登山杖', '低库存边界演示专用', '轻量可伸缩登山杖;库存仅 1 件,用于验证库存边界。', 159.00, 199.00, 1, 51, '/images/products/P0030.jpg', 1, 300), + + (31, 'P0031', 6, '旧版 Java 入门教程', '下架状态演示专用', '旧版技术图书,仅用于验证下架商品前后台可见性。', 49.00, 69.00, 20, 126, '/images/products/P0031.jpg', 0, 310), + (32, 'P0032', 6, '软件测试项目实战', '从测试计划到自动化实践', '覆盖需求分析、用例设计、缺陷管理和测试报告。', 79.00, 99.00, 60, 143, '/images/products/P0032.jpg', 1, 320), + (33, 'P0033', 6, 'MySQL 性能优化指南', '索引、事务与 SQL 调优', '面向开发者的数据库性能分析与优化案例。', 89.00, 109.00, 55, 118, '/images/products/P0033.jpg', 1, 330), + (34, 'P0034', 6, 'Git 团队协作手册', '分支策略与代码评审', '介绍常见 Git 工作流、冲突处理和提交规范。', 59.00, 79.00, 70, 207, '/images/products/P0034.jpg', 1, 340), + (35, 'P0035', 6, '数据结构学习笔记', '图解算法与常见题型', '使用图示和示例讲解基础数据结构与算法。', 68.00, 88.00, 65, 164, '/images/products/P0035.jpg', 1, 350), + (36, 'P0036', 6, '电商原型设计手账', '页面流程与交互草图模板', '包含首页、详情、购物车、订单和后台页面草图模板。', 45.00, 59.00, 90, 233, '/images/products/P0036.jpg', 1, 360) +ON DUPLICATE KEY UPDATE + product_code = VALUES(product_code), + category_id = VALUES(category_id), + name = VALUES(name), + subtitle = VALUES(subtitle), + description = VALUES(description), + price = VALUES(price), + original_price = VALUES(original_price), + stock = VALUES(stock), + sales = VALUES(sales), + image_url = VALUES(image_url), + status = VALUES(status), + sort = VALUES(sort); + +COMMIT; + +-- 执行完成后直接显示验收结果。 +SELECT + 'category_count' AS check_item, + COUNT(*) AS actual_value, + 3 AS required_value, + IF(COUNT(*) >= 3, 'PASS', 'FAIL') AS result +FROM category +UNION ALL +SELECT + 'product_count', + COUNT(*), + 30, + IF(COUNT(*) >= 30, 'PASS', 'FAIL') +FROM product; diff --git a/backend/sql/schema.sql b/backend/sql/schema.sql new file mode 100644 index 0000000..d647df3 --- /dev/null +++ b/backend/sql/schema.sql @@ -0,0 +1,52 @@ +-- E-Shop 商品目录初始化结构(MySQL 8.0+) +-- 作用范围:分类、商品。其余业务表由对应模块负责人继续补充。 + +CREATE DATABASE IF NOT EXISTS eshop + DEFAULT CHARACTER SET utf8mb4 + DEFAULT COLLATE utf8mb4_0900_ai_ci; + +USE eshop; + +CREATE TABLE IF NOT EXISTS category ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '分类主键', + name VARCHAR(64) NOT NULL COMMENT '分类名称', + sort INT NOT NULL DEFAULT 0 COMMENT '排序值,越小越靠前', + status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1启用,0禁用', + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + UNIQUE KEY uk_category_name (name), + KEY idx_category_status_sort (status, sort) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci + COMMENT='商品分类表'; + +CREATE TABLE IF NOT EXISTS product ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '商品主键', + product_code VARCHAR(32) NOT NULL COMMENT '商品编码', + category_id BIGINT UNSIGNED NOT NULL COMMENT '分类ID', + name VARCHAR(128) NOT NULL COMMENT '商品名称', + subtitle VARCHAR(255) DEFAULT NULL COMMENT '商品副标题', + description TEXT COMMENT '商品详情', + price DECIMAL(10, 2) NOT NULL COMMENT '销售价', + original_price DECIMAL(10, 2) DEFAULT NULL COMMENT '划线价', + stock INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '库存', + sales INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '历史销量', + image_url VARCHAR(500) DEFAULT NULL COMMENT '主图地址', + status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1上架,0下架', + sort INT NOT NULL DEFAULT 0 COMMENT '排序值,越小越靠前', + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + UNIQUE KEY uk_product_code (product_code), + KEY idx_product_category_status (category_id, status), + KEY idx_product_status_sort (status, sort), + KEY idx_product_name (name), + CONSTRAINT fk_product_category + FOREIGN KEY (category_id) REFERENCES category (id) + ON UPDATE RESTRICT ON DELETE RESTRICT, + CONSTRAINT chk_product_price CHECK (price >= 0), + CONSTRAINT chk_product_original_price CHECK ( + original_price IS NULL OR original_price >= price + ) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci + COMMENT='商品表'; diff --git a/backend/sql/verify_data.sql b/backend/sql/verify_data.sql new file mode 100644 index 0000000..ab182ad --- /dev/null +++ b/backend/sql/verify_data.sql @@ -0,0 +1,43 @@ +-- E-Shop 分类与商品演示数据复查脚本 + +USE eshop; + +SELECT + '分类总数不少于 3' AS check_item, + COUNT(*) AS actual_value, + 3 AS required_value, + IF(COUNT(*) >= 3, 'PASS', 'FAIL') AS result +FROM category; + +SELECT + '商品总数不少于 30' AS check_item, + COUNT(*) AS actual_value, + 30 AS required_value, + IF(COUNT(*) >= 30, 'PASS', 'FAIL') AS result +FROM product; + +SELECT + c.id AS category_id, + c.name AS category_name, + COUNT(p.id) AS product_count +FROM category c +LEFT JOIN product p ON p.category_id = c.id +GROUP BY c.id, c.name +ORDER BY c.sort, c.id; + +SELECT + COUNT(*) AS orphan_product_count, + IF(COUNT(*) = 0, 'PASS', 'FAIL') AS result +FROM product p +LEFT JOIN category c ON c.id = p.category_id +WHERE c.id IS NULL; + +SELECT + id, + product_code, + name, + stock, + status +FROM product +WHERE id IN (1, 2, 22, 30, 31) +ORDER BY id; diff --git "a/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/E-Shop-\346\235\250\345\205\211\346\262\243-\347\254\2541-2\345\244\251\346\265\213\350\257\225\344\272\244\344\273\230\347\211\251.xlsx" "b/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/E-Shop-\346\235\250\345\205\211\346\262\243-\347\254\2541-2\345\244\251\346\265\213\350\257\225\344\272\244\344\273\230\347\211\251.xlsx" new file mode 100644 index 0000000000000000000000000000000000000000..2b24e3e9418da2e90fdb2c1cc4943dfe41315d86 GIT binary patch literal 19828 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 X1$eUpiz(1iUAzp5z~hhpdV+WW_0!{L literal 0 HcmV?d00001 diff --git "a/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\346\225\260\346\215\256\345\272\223\345\210\235\345\247\213\345\214\226\346\243\200\346\237\245\350\256\260\345\275\225.md" "b/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\346\225\260\346\215\256\345\272\223\345\210\235\345\247\213\345\214\226\346\243\200\346\237\245\350\256\260\345\275\225.md" new file mode 100644 index 0000000..13a0f28 --- /dev/null +++ "b/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\346\225\260\346\215\256\345\272\223\345\210\235\345\247\213\345\214\226\346\243\200\346\237\245\350\256\260\345\275\225.md" @@ -0,0 +1,63 @@ +# 数据库初始化检查记录 + +> 检查人:杨光沣(测试部署 / 质量负责人) +> 检查日期:2026-07-23 +> 复查日期:2026-07-24 +> 工作分支:`feature/test-deploy-log` +> 目标脚本:`backend/sql/schema.sql`、`backend/sql/data.sql`、`backend/sql/verify_data.sql` + +## 一、检查结论 + +**当前状态:商品目录初始化数据已通过静态检查,等待 MySQL 环境执行复核。** + +2026-07-24 已补充商品目录初始化结构、演示数据和复查脚本。静态核对结果为 6 个分类、36 个商品,满足“不少于 3 个分类、30 个商品”的验收要求;关键商品 ID 与演示数据清单保持一致,并包含低库存和下架边界数据。 + +本机未安装 MySQL 客户端,Docker Desktop 引擎也未启动,因此本次未伪造真实执行结果。用户、地址、购物车、订单、支付等业务表尚未由对应模块负责人提交,完整数据库初始化仍需后续集成复核。 + +## 二、已核对的设计要求 + +| 检查项 | 设计要求 | 当前结论 | +|--------|----------|----------| +| 数据库字符集 | 建议使用 `utf8mb4` | 商品目录脚本已使用 `utf8mb4` | +| 核心实体 | 用户、地址、分类、商品、购物车、订单、订单项、支付 | 分类、商品已提供;其余待模块负责人提交 | +| 用户名约束 | 用户名唯一 | 待脚本提供后复核 | +| 订单项快照 | 保存下单时商品名称和价格 | 待脚本提供后复核 | +| 初始化脚本路径 | `backend/sql/schema.sql` | 已提供商品目录结构 | +| 演示数据脚本路径 | `backend/sql/data.sql` | 已提供 | +| 演示数据数量 | 不少于 3 个分类、30 个商品 | 静态检查:6 个分类、36 个商品 | +| 边界数据 | 低库存、下架商品 | `product.id=30` 库存 1;`product.id=31` 已下架 | + +## 三、脚本到位后的检查清单 + +| 编号 | 检查内容 | 验收标准 | +|------|----------|----------| +| DB-CHK-001 | 建库字符集和排序规则 | 支持中文商品名、地址等数据 | +| DB-CHK-002 | 核心表和主键 | 核心实体完整,主键策略一致 | +| DB-CHK-003 | 唯一约束 | 用户名、订单号、支付流水等不可重复 | +| DB-CHK-004 | 外键与索引 | 关联关系正确,高频条件有索引 | +| DB-CHK-005 | 账号数据 | 管理员、买家可用;不提交明文密码 | +| DB-CHK-006 | 分类和商品数量 | 分类不少于 3 条、商品不少于 30 条 | +| DB-CHK-007 | 订单支付演示数据 | 至少包含待支付和已支付场景 | +| DB-CHK-008 | X02/C08 扩展结构 | 操作日志、回调去重和对账证据可落库 | + +## 四、复查 SQL 模板 + +```sql +SELECT COUNT(*) AS category_count FROM category; +SELECT COUNT(*) AS product_count FROM product; +SELECT category_id, COUNT(*) AS product_count +FROM product +GROUP BY category_id +ORDER BY category_id; +SELECT id, product_code, name, stock, status +FROM product +WHERE id IN (1, 2, 22, 30, 31) +ORDER BY id; +``` + +## 五、后续动作 + +1. 启动 MySQL 8.0+ 后按 `backend/sql/README.md` 的顺序执行三个脚本。 +2. 将 `verify_data.sql` 的真实查询结果、异常信息和修复提交号补入本记录。 +3. 用户、购物车、订单、支付等模块表到位后,继续核对唯一约束、订单项快照及 C08 支撑结构。 +4. 未完成数据库实跑前,只标记“静态检查通过”,不把完整初始化状态标记为“执行通过”。 diff --git "a/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\347\254\2541-2\345\244\251\344\273\273\345\212\241\345\256\214\346\210\220\350\256\260\345\275\225.md" "b/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\347\254\2541-2\345\244\251\344\273\273\345\212\241\345\256\214\346\210\220\350\256\260\345\275\225.md" new file mode 100644 index 0000000..91f9675 --- /dev/null +++ "b/docs/03-\346\265\213\350\257\225\346\226\207\346\241\243/\347\254\2541-2\345\244\251\344\273\273\345\212\241\345\256\214\346\210\220\350\256\260\345\275\225.md" @@ -0,0 +1,18 @@ +# 第 1–2 天任务完成记录 + +> 负责人:杨光沣 +> 工作分支:`feature/test-deploy-log` + +| 批次 | 任务 | 当前状态 | 证据 | +|------|------|----------|------| +| 第 1 天 | 完善测试计划基础信息、范围和负责人 | 已完成 | `docs/03-测试文档/测试计划.md` | +| 第 1 天 | 整理测试账号和演示数据清单 | 清单已完成,实际数据待准备 | `docs/03-测试文档/E-Shop-杨光沣-第1-2天测试交付物.xlsx` | +| 第 1 天 | 创建并推送工作分支 | 远端分支已存在;本地已建立同名跟踪分支 | `feature/test-deploy-log` 跟踪 `origin/feature/test-deploy-log` | +| 第 2 天 | 用户、商品模块测试用例不少于 20 条 | 已编写 24 条,尚未执行 | 工作簿“测试用例”“执行统计”工作表 | +| 第 2 天 | 检查 MySQL 初始化脚本 | 检查清单已完成,实检阻塞 | 当前分支缺少目标 SQL,详见数据库检查记录 | + +## 当前验收结论 + +- 第 1 天文档与分支准备已完成;可登录账号和完整演示数据仍需后续补齐。 +- 第 2 天用例编写数量达标;数据库实检必须等初始化脚本提交后完成。 +- 不把尚未执行的测试用例或尚未提供的 SQL 标记为“通过”。 diff --git "a/reports/daily/\346\235\250\345\205\211\346\262\243/20260722-\346\235\250\345\205\211\346\262\243.md" "b/reports/daily/\346\235\250\345\205\211\346\262\243/20260722-\346\235\250\345\205\211\346\262\243.md" new file mode 100644 index 0000000..2923ef1 --- /dev/null +++ "b/reports/daily/\346\235\250\345\205\211\346\262\243/20260722-\346\235\250\345\205\211\346\262\243.md" @@ -0,0 +1,24 @@ +# 日报 - 杨光沣 - 2026-07-22 + +## 今日完成 + +1. 在 `feature/test-deploy-log` 分支完善测试计划,补充测试目标、范围、负责人、策略、环境、账号、演示数据和风险。 +2. 整理测试账号与演示数据清单,明确管理员、买家、禁用账号、商品、订单支付、选做模块和 C08 所需数据及准备状态。 +3. 核对仓库分支,创建本地 `feature/test-deploy-log` 并跟踪 `origin/feature/test-deploy-log`,后续测试和部署材料均在该分支提交。 + +## 遇到的问题 + +| 问题描述 | 解决状态 | 解决方式/求助对象 | +|----------|----------|-------------------| +| 当前仓库只有项目文档,前后端代码和初始化 SQL 尚未提交 | 未解决 | 等待对应模块负责人提交代码与脚本 | +| 演示账号尚无可验证的登录密码和密码哈希 | 未解决 | 请后端负责人提供本地演示账号方案 | +| 订单支付、收藏、浏览历史、操作日志及 C08 数据尚未准备 | 未解决 | 按后续开发进度补充可重复导入数据 | + +## 明日计划 + +1. 完成用户、商品模块不少于 20 条测试用例。 +2. 检查 MySQL 初始化脚本;如脚本仍缺失,记录阻塞项和复查清单。 + +## 今日工时 + +约 4 小时 diff --git "a/reports/daily/\346\235\250\345\205\211\346\262\243/20260723-\346\235\250\345\205\211\346\262\243.md" "b/reports/daily/\346\235\250\345\205\211\346\262\243/20260723-\346\235\250\345\205\211\346\262\243.md" new file mode 100644 index 0000000..92d0d7a --- /dev/null +++ "b/reports/daily/\346\235\250\345\205\211\346\262\243/20260723-\346\235\250\345\205\211\346\262\243.md" @@ -0,0 +1,24 @@ +# 日报 - 杨光沣 - 2026-07-23 + +## 今日完成 + +1. 在 `feature/test-deploy-log` 分支整理用户、地址、商品和后台商品共 24 条测试用例,覆盖正常、异常、边界、接口及权限场景。 +2. 完成测试用例模板、演示账号、演示数据、数据库检查和执行统计工作表;24 条用例均保持“未执行”,等待环境可用后回填真实结果。 +3. 建立 MySQL 初始化脚本检查记录,确认目标路径和验收项;当前因 `backend/sql/schema.sql`、`backend/sql/data.sql` 缺失而标记为阻塞。 + +## 遇到的问题 + +| 问题描述 | 解决状态 | 解决方式/求助对象 | +|----------|----------|-------------------| +| 初始化 SQL 未提交,无法核对建表、约束和演示数据 | 未解决 | 等待后端或数据库负责人提交脚本后执行复查 SQL | +| 接口设计文档仅完成部分接口,工作簿中的接口编号需要后续统一映射 | 未解决 | 与各模块负责人对齐最终接口清单 | +| 测试环境和演示账号不可用,24 条用例尚未执行 | 未解决 | 环境就绪后执行并登记实际结果、缺陷编号 | + +## 明日计划 + +1. 补充购物车、订单、支付和后台管理测试用例,使总数达到 40 条以上。 +2. 接口和数据库环境可用后,开始执行用户、商品模块用例。 + +## 今日工时 + +约 4 小时 diff --git "a/reports/daily/\346\235\250\345\205\211\346\262\243/20260724-\346\235\250\345\205\211\346\262\243.md" "b/reports/daily/\346\235\250\345\205\211\346\262\243/20260724-\346\235\250\345\205\211\346\262\243.md" new file mode 100644 index 0000000..011d08f --- /dev/null +++ "b/reports/daily/\346\235\250\345\205\211\346\262\243/20260724-\346\235\250\345\205\211\346\262\243.md" @@ -0,0 +1,25 @@ +# 日报 - 杨光沣 - 2026-07-24 + +## 今日完成 + +1. 在 `feature/test-deploy-log` 分支补充 `backend/sql/schema.sql`,完成商品分类表、商品表及必要的唯一约束、索引、外键和价格校验约束。 +2. 补充 `backend/sql/data.sql`,准备 6 个分类、36 个商品,满足不少于 3 个分类和 30 个商品的验收要求。 +3. 保持演示数据编号一致:商品 ID 1/2/22 分别为无线蓝牙耳机、机械键盘、咖啡豆;增加库存为 1 的低库存商品和已下架商品。 +4. 增加 `backend/sql/verify_data.sql` 与执行说明,并更新数据库初始化检查记录。 + +## 遇到的问题 + +| 问题描述 | 解决状态 | 解决方式/求助对象 | +|----------|----------|-------------------| +| 仓库原先没有 `backend/sql` 初始化脚本 | 已解决(商品目录范围) | 新建商品目录结构、数据和复查脚本 | +| 本机没有 MySQL 客户端,Docker Desktop 引擎未启动 | 未解决 | 已完成静态检查;环境可用后执行三份 SQL 并回填结果 | +| 用户、购物车、订单、支付等表尚未集成 | 未解决 | 等待对应模块负责人提交后继续做完整初始化复核 | + +## 明日计划 + +1. 启动 MySQL 或 Docker 环境,执行初始化脚本和复查脚本,保存真实查询结果。 +2. 继续补充购物车、订单、支付和后台管理测试用例,使总数达到 40 条以上。 + +## 今日工时 + +约 3 小时 -- Gitee