From a094f55890027514ea59054e5dfc5a1f8cef18f5 Mon Sep 17 00:00:00 2001 From: LIUFL Date: Wed, 12 Nov 2025 16:12:40 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=95=B4=E7=90=86=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=B9=B6=E5=88=A0=E9=99=A4=E6=B5=8B=E8=AF=95=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将文档统一整理到doc目录下,删除不再需要的测试脚本和临时文件 --- .trae/documents/项目功能分析与改进实施计划.md | 142 ++++++++ check-date-format.js | 21 -- check-order-dates.js | 11 - check_schema.js | 22 -- check_tables.js | 22 -- create-test-data.js | 136 -------- debug-report-issue.js | 72 ---- MENU_FIX_README.md => doc/MENU_FIX_README.md | 0 MENU_FIX_USAGE.md => doc/MENU_FIX_USAGE.md | 0 PROBLEM_SOLVED.md => doc/PROBLEM_SOLVED.md | 0 README-启动.md => doc/README-启动.md | 0 README.md => doc/README.md | 0 使用指南.md => doc/使用指南.md | 0 启动指南.md => doc/启动指南.md | 0 doc/开发范式.md | 194 +++++++++++ .../收银台系统开发计划.md | 0 最终使用说明.md => doc/最终使用说明.md | 0 稳定启动方案.md => doc/稳定启动方案.md | 0 .../系统功能完成总结.md | 0 项目总结.md => doc/项目总结.md | 0 package.json.backup | 53 --- package_temp.json | 53 --- test-api-calls.js | 38 -- test-date-format.js | 27 -- test/check-cashiers.js | 53 --- test/check-db.js | 64 ---- test/check-navigation.js | 111 ------ test/check-routes-simple.js | 100 ------ test/check_db.js | 35 -- test/diagnose-routes.js | 111 ------ test/diagnose.js | 173 ---------- test/electron-route-diagnose.js | 154 --------- test/final-test.js | 151 -------- test/fix-api.js | 306 ---------------- test/fix-electron-routes.js | 326 ------------------ test/fix-menu.js | 184 ---------- test/fix-navigation.js | 125 ------- test/system-test.js | 174 ---------- test/test-api.js | 59 ---- test/test-cash-payment.js | 61 ---- test/test-checkout.js | 56 --- test/test-create-order.js | 31 -- test/test-fix.js | 9 - test/test-full-checkout.js | 71 ---- test/test-ipc-message.js | 19 - test/test-logger.js | 17 - test/test-menu-fix.js | 97 ------ test/test-menu-navigation.js | 115 ------ test/test-menu.js | 43 --- test/test-navigation.bat | 24 -- test/test-navigation.js | 67 ---- test/test-start.js | 57 --- test/verify-menu-function.js | 123 ------- 53 files changed, 336 insertions(+), 3371 deletions(-) create mode 100644 .trae/documents/项目功能分析与改进实施计划.md delete mode 100644 check-date-format.js delete mode 100644 check-order-dates.js delete mode 100644 check_schema.js delete mode 100644 check_tables.js delete mode 100644 create-test-data.js delete mode 100644 debug-report-issue.js rename MENU_FIX_README.md => doc/MENU_FIX_README.md (100%) rename MENU_FIX_USAGE.md => doc/MENU_FIX_USAGE.md (100%) rename PROBLEM_SOLVED.md => doc/PROBLEM_SOLVED.md (100%) rename README-启动.md => doc/README-启动.md (100%) rename README.md => doc/README.md (100%) rename 使用指南.md => doc/使用指南.md (100%) rename 启动指南.md => doc/启动指南.md (100%) create mode 100644 doc/开发范式.md rename 收银台系统开发计划.md => doc/收银台系统开发计划.md (100%) rename 最终使用说明.md => doc/最终使用说明.md (100%) rename 稳定启动方案.md => doc/稳定启动方案.md (100%) rename 系统功能完成总结.md => doc/系统功能完成总结.md (100%) rename 项目总结.md => doc/项目总结.md (100%) delete mode 100644 package.json.backup delete mode 100644 package_temp.json delete mode 100644 test-api-calls.js delete mode 100644 test-date-format.js delete mode 100644 test/check-cashiers.js delete mode 100644 test/check-db.js delete mode 100644 test/check-navigation.js delete mode 100644 test/check-routes-simple.js delete mode 100644 test/check_db.js delete mode 100644 test/diagnose-routes.js delete mode 100644 test/diagnose.js delete mode 100644 test/electron-route-diagnose.js delete mode 100644 test/final-test.js delete mode 100644 test/fix-api.js delete mode 100644 test/fix-electron-routes.js delete mode 100644 test/fix-menu.js delete mode 100644 test/fix-navigation.js delete mode 100644 test/system-test.js delete mode 100644 test/test-api.js delete mode 100644 test/test-cash-payment.js delete mode 100644 test/test-checkout.js delete mode 100644 test/test-create-order.js delete mode 100644 test/test-fix.js delete mode 100644 test/test-full-checkout.js delete mode 100644 test/test-ipc-message.js delete mode 100644 test/test-logger.js delete mode 100644 test/test-menu-fix.js delete mode 100644 test/test-menu-navigation.js delete mode 100644 test/test-menu.js delete mode 100644 test/test-navigation.bat delete mode 100644 test/test-navigation.js delete mode 100644 test/test-start.js delete mode 100644 test/verify-menu-function.js diff --git a/.trae/documents/项目功能分析与改进实施计划.md b/.trae/documents/项目功能分析与改进实施计划.md new file mode 100644 index 00000000..054d6f54 --- /dev/null +++ b/.trae/documents/项目功能分析与改进实施计划.md @@ -0,0 +1,142 @@ +## 第一阶段:规格说明(Specification) + +### 目标范围 +- 会员模块:会员档案、等级与折扣、积分累计与调整、优惠券、会员消费统计、收银台选会员 +- 库存管理:供应商管理、商品批次与保质期、库存预警(min_stock)、入出库记录与盘点、报表 +- 交班:交班记录、现金实点与系统金额核对、交班摘要打印/导出、交班数据留痕 +- 日结:每日营业汇总、支付方式统计、退款与挂单影响、库存快照、日报表打印/导出 + +### 用户故事与验收标准 +- 会员 + - 作为收银员,我可以通过手机号/姓名搜索并选择会员,订单将关联会员信息;验收:收银台勾选成功,订单详情显示会员信息,会员统计更新 + - 作为店长,我可以调整会员积分并查看积分历史;验收:积分变动入库,历史可分页查询,边界:负值调整、过期处理 + - 作为运营,我可以配置会员等级的折扣率;验收:订单最终金额按等级折扣计算,折扣记录可溯源 +- 库存 + - 作为仓管,我可录入供应商与商品批次,设置生产/过期日期;验收:批次入库同时更新商品库存,库存历史含批次、供应商与价格 + - 作为店长,我能看到30天内即将过期的批次;验收:列表按过期日期升序、数量>0、状态为active + - 作为仓管,我能看到库存预警商品并生成补货建议;验收:按min_stock阈值计算,支持刷新 +- 交班 + - 作为收银员,我在结束班次时提交交班,系统对比现金实点与系统记录;验收:差异提示、交班记录持久化、打印小票/导出PDF +- 日结 + - 作为店长,我每日进行日结,生成营业汇总与支付方式统计;验收:包含订单数、销售额、折扣额、退款额、各支付占比,支持打印/导出 + +### 非功能需求 +- 性能:订单创建接口P95 < 150ms;库存列表P95 < 200ms;渲染主界面首屏 < 2s +- 安全:JWT密钥来源于环境变量(不硬编码);前后端避免日志泄露敏感信息 +- 可维护性:拆分过大的路由文件(orders.js)为分域模块;统一Ant Design风格与交互 +- 测试:单元与集成测试覆盖率≥80%,路由与服务关键路径均有测试 + +### 数据模型与规则(概要) +- Member:member_no, name, phone, level, points, total_consumption, total_orders, discount_rate, status +- MemberPointsHistory:member_id, points_change, before/after, type, source_type, operator_id, expire_date +- MemberCoupon:member_id, coupon_code, type, discount_value, status, used_order_id +- Supplier:name, contact_person, phone, status, payment_method, bank信息 +- ProductBatch:product_id, supplier_id, batch_no, production_date, expiry_date, quantity, cost/selling_price, status +- InventoryHistory:product_id, operation_type(in/out), quantity, stock_before/after, reason, supplier_id, batch_id +- Order增加member_id,交班/日结新增域模型 + +### 风险与缓解 +- 数据一致性风险:入库/出库并发更新 → 事务与行级锁 +- 大文件维护难:orders.js过大 → 领域拆分与服务化 +- 硬件依赖不稳定:打印/串口 → 失败重试与降级提示 + +--- + +## 第二阶段:设计(Design) + +### 架构图与分层 +- Electron主进程:窗口、串口、进程间通信 +- 渲染进程(React):路由、页面(Cashier/Members/Inventory/Reports/Settings)、服务层axios +- 后端(Express + Sequelize + SQLite):routes(members/suppliers/batches/orders/shifts/closing),models,services(printer) +- 状态:以局部state为主,服务拉取;后续评估引入轻量store(如Zustand) + +### API规范(示例) +- 会员 + - GET /api/members?page=&limit=&search=&level=&status= + - POST /api/members;PUT /api/members/:id + - POST /api/members/:id/points/adjust + - GET /api/members/:id/points/history + - GET /api/members/:id/stats +- 库存 + - GET /api/suppliers;POST/PUT/DELETE /api/suppliers/:id + - GET /api/batches?product_id=&supplier_id=&status= + - POST/PUT/DELETE /api/batches/:id + - GET /api/batches/expiring-soon?days=30 + - GET /api/products/low-stock +- 交班/日结(新) + - POST /api/shifts/start;POST /api/shifts/end + - GET /api/shifts?date=&cashier_id= + - POST /api/daily-closing/run?date=YYYY-MM-DD + - GET /api/daily-closing/:date/report + +### 安全与配置 +- JWT_SECRET、DB路径、打印机配置从环境注入(.env或配置文件),移除硬编码 +- axios拦截器仅在开发环境输出详细日志;生产降级 + +### 性能策略 +- 首屏路由懒加载(Members/Inventory/Reports) +- 去除生产环境冗余console +- 批量接口分页与筛选 + +### 错误与日志 +- 统一错误中间件返回结构:{error, code} +- 后端logger统一等级与文件输出;避免请求体敏感字段写入 + +### 部署与运维 +- 打包:Webpack主/渲染配置复用;构建脚本区分dev/prod +- 监控:运行日志与错误统计(文件落盘) + +--- + +## 第三阶段:任务列表(Task List) + +### 会员模块 +- 后端:Member/PointsHistory/Coupon模型与关联;members路由(列表/详情/创建/更新/积分调整/统计) +- 前端:memberService;Members页面(列表、详情抽屉、积分调整);Cashier会员搜索与选择、订单携带member_id +- 测试:members路由supertest;积分调整边界测试 + +### 库存模块 +- 后端:Supplier/ProductBatch/InventoryHistory扩展模型与关联;suppliers、batches路由;products低库存与批次过期接口 +- 前端:supplierService、batchService;EnhancedInventory页面(历史/批次/供应商/过期预警);StockWarning组件 +- 测试:库存历史入出库事务测试;过期批次筛选逻辑测试 + +### 交班模块 +- 模型:Shift(cashier_id, start_time, end_time, cash_counted, cash_system, diff, notes) +- 接口:开始/结束交班、查询交班记录、打印交班小票 +- 前端:Cashier页交班入口与弹窗;Reports页交班查询 +- 测试:金额核对与差异计算、打印调用 + +### 日结模块 +- 模型:DailyClosing(date, totals: sales/discount/refund/pending, payments breakdown, inventory snapshot) +- 接口:运行日结、查询日报表、打印/导出 +- 前端:Reports页新增日结Tab与报表展示 +- 测试:数据聚合正确性、挂单与退款影响核算 + +### 跨域任务 +- 重构:拆分orders.js为orders-basic、orders-stats、orders-print、orders-pending等 +- 安全:JWT密钥与配置管理;移除敏感日志 +- UI统一:导航新增Members/Inventory;遵循Ant Design规范与一致的卡片/表格/抽屉交互 +- 测试与CI:引入Jest/Vitest + supertest;GitHub Actions构建与测试;覆盖率≥80% + +### 时间与优先级 +- Phase 1(1.5–2周):会员 + 库存(供应商/批次/预警) +- Phase 2(1周):交班 +- Phase 3(1周):日结 +- 持续:重构与安全、测试与CI、性能优化 + +### 完成标准 +- 所有API具备文档与错误处理;前后端功能稳定可用 +- 覆盖率≥80%,P95延迟满足目标;UI风格统一 +- 交付:规格说明与设计文档、任务列表、架构与流程图(Mermaid/PlantUML),可量化指标达标 + +--- + +## 可视化与指标 +- 架构图:Electron↔Express↔SQLite、渲染进程模块与路由 +- 流程图:会员积分调整流程、入库流水与库存更新、交班核对与打印、日结聚合 +- 指标: + - 性能:P95接口与首屏、构建包大小<2MB渲染bundle(后续按需分割) + - 质量:测试覆盖率≥80%、关键路由100%用例 + - 安全:零硬编码密钥、敏感日志为0 + +请确认以上三阶段规划;确认后我将严格按照该规划开始实施。 \ No newline at end of file diff --git a/check-date-format.js b/check-date-format.js deleted file mode 100644 index 95d67d7a..00000000 --- a/check-date-format.js +++ /dev/null @@ -1,21 +0,0 @@ -// 检查日期格式的测试脚本 -const moment = require('moment'); - -// 模拟报表页面中的日期范围 -const dateRange = [ - moment().startOf('day'), - moment().endOf('day') -]; - -console.log('日期范围:'); -console.log('开始日期:', dateRange[0].format('YYYY-MM-DD')); -console.log('结束日期:', dateRange[1].format('YYYY-MM-DD')); - -// 模拟传递给API的参数 -const params = { - start_date: dateRange[0].format('YYYY-MM-DD'), - end_date: dateRange[1].format('YYYY-MM-DD') -}; - -console.log('\n传递给API的参数:'); -console.log(params); \ No newline at end of file diff --git a/check-order-dates.js b/check-order-dates.js deleted file mode 100644 index e06d51b1..00000000 --- a/check-order-dates.js +++ /dev/null @@ -1,11 +0,0 @@ -const sqlite3 = require('sqlite3').verbose(); -const db = new sqlite3.Database('./data/cashier.db'); - -db.all(`SELECT id, order_no, total_amount, created_at FROM orders WHERE order_no IN ('T001', 'T002', 'T003')`, (err, rows) => { - if (err) { - console.error(err); - } else { - console.log(rows); - } - db.close(); -}); \ No newline at end of file diff --git a/check_schema.js b/check_schema.js deleted file mode 100644 index 860cab19..00000000 --- a/check_schema.js +++ /dev/null @@ -1,22 +0,0 @@ -const sqlite3 = require('sqlite3').verbose(); -const path = require('path'); - -// 使用正确的数据库路径 -const dbPath = path.join(__dirname, 'data/cashier.db'); -console.log('Database path:', dbPath); - -const db = new sqlite3.Database(dbPath); - -db.serialize(() => { - db.all("PRAGMA table_info(order_items)", (err, rows) => { - if (err) { - console.error('Error:', err); - } else { - console.log('order_items table structure:'); - rows.forEach(row => { - console.log(`Column: ${row.name}, Type: ${row.type}, Not Null: ${row.notnull}, Default: ${row.dflt_value}, Primary Key: ${row.pk}`); - }); - } - db.close(); - }); -}); \ No newline at end of file diff --git a/check_tables.js b/check_tables.js deleted file mode 100644 index aa0fe0fc..00000000 --- a/check_tables.js +++ /dev/null @@ -1,22 +0,0 @@ -const sqlite3 = require('sqlite3').verbose(); -const path = require('path'); - -// 使用正确的数据库路径 -const dbPath = path.join(__dirname, 'data/cashier.db'); -console.log('Database path:', dbPath); - -const db = new sqlite3.Database(dbPath); - -db.serialize(() => { - db.all("SELECT name FROM sqlite_master WHERE type='table'", (err, rows) => { - if (err) { - console.error('Error:', err); - } else { - console.log('Database tables:'); - rows.forEach(row => { - console.log(`Table: ${row.name}`); - }); - } - db.close(); - }); -}); \ No newline at end of file diff --git a/create-test-data.js b/create-test-data.js deleted file mode 100644 index e4cd6552..00000000 --- a/create-test-data.js +++ /dev/null @@ -1,136 +0,0 @@ -const sqlite3 = require('sqlite3').verbose(); -const db = new sqlite3.Database('./data/cashier.db'); - -db.serialize(() => { - // 插入订单项数据 - // 获取订单ID - db.get("SELECT id FROM orders WHERE order_no = 'T001'", (err, row) => { - if (err) { - console.error('查询订单ID失败:', err); - db.close(); - return; - } - - if (!row) { - console.log('未找到订单T001'); - db.close(); - return; - } - - const orderId = row.id; - console.log('订单T001的ID:', orderId); - - // 检查是否已存在订单项 - db.get("SELECT COUNT(*) as count FROM order_items WHERE order_id = ?", [orderId], (err, row) => { - if (err) { - console.error('查询订单项失败:', err); - db.close(); - return; - } - - if (row.count > 0) { - console.log('订单项已存在,跳过插入'); - db.close(); - return; - } - - // 插入订单项 - const orderItems = [ - { order_id: orderId, product_id: 1, quantity: 2, unit_price: 3.5, total_price: 7.0 }, // 可口可乐 x2 - { order_id: orderId, product_id: 4, quantity: 1, unit_price: 5, total_price: 5.0 }, // 旺旺雪饼 x1 - { order_id: orderId, product_id: 8, quantity: 1, unit_price: 8.5, total_price: 8.5 } // 舒肤佳香皂 x1 - ]; - - const itemStmt = db.prepare('INSERT INTO order_items (order_id, product_id, quantity, unit_price, total_price, discount_amount, created_at) VALUES (?, ?, ?, ?, ?, 0, "2025-11-11 10:30:00")'); - orderItems.forEach(item => { - itemStmt.run(item.order_id, item.product_id, item.quantity, item.unit_price, item.total_price, function(err) { - if (err) { - console.error('插入订单项失败:', err); - } else { - console.log('插入订单项成功,ID:', this.lastID); - } - }); - }); - itemStmt.finalize(); - - // 插入其他订单的订单项 - insertOtherOrderItems(db); - }); - }); -}); - -function insertOtherOrderItems(db) { - // 获取订单T002的ID - db.get("SELECT id FROM orders WHERE order_no = 'T002'", (err, row) => { - if (err) { - console.error('查询订单T002 ID失败:', err); - db.close(); - return; - } - - if (!row) { - console.log('未找到订单T002'); - db.close(); - return; - } - - const orderId = row.id; - console.log('订单T002的ID:', orderId); - - // 插入订单项 - const orderItems = [ - { order_id: orderId, product_id: 2, quantity: 1, unit_price: 3.5, total_price: 3.5 }, // 百事可乐 x1 - { order_id: orderId, product_id: 3, quantity: 1, unit_price: 8.5, total_price: 8.5 } // 乐事薯片 x1 - ]; - - const itemStmt = db.prepare('INSERT INTO order_items (order_id, product_id, quantity, unit_price, total_price, discount_amount, created_at) VALUES (?, ?, ?, ?, ?, 0, "2025-11-11 11:45:00")'); - orderItems.forEach(item => { - itemStmt.run(item.order_id, item.product_id, item.quantity, item.unit_price, item.total_price, function(err) { - if (err) { - console.error('插入订单项失败:', err); - } else { - console.log('插入订单项成功,ID:', this.lastID); - } - }); - }); - itemStmt.finalize(); - - // 获取订单T003的ID - db.get("SELECT id FROM orders WHERE order_no = 'T003'", (err, row) => { - if (err) { - console.error('查询订单T003 ID失败:', err); - db.close(); - return; - } - - if (!row) { - console.log('未找到订单T003'); - db.close(); - return; - } - - const orderId = row.id; - console.log('订单T003的ID:', orderId); - - // 插入订单项 - const orderItems = [ - { order_id: orderId, product_id: 1, quantity: 5, unit_price: 3.5, total_price: 17.5 }, // 可口可乐 x5 - { order_id: orderId, product_id: 9, quantity: 1, unit_price: 20, total_price: 20 } // 红塔山香烟 x1 - ]; - - const itemStmt = db.prepare('INSERT INTO order_items (order_id, product_id, quantity, unit_price, total_price, discount_amount, created_at) VALUES (?, ?, ?, ?, ?, 0, "2025-11-11 12:15:00")'); - orderItems.forEach(item => { - itemStmt.run(item.order_id, item.product_id, item.quantity, item.unit_price, item.total_price, function(err) { - if (err) { - console.error('插入订单项失败:', err); - } else { - console.log('插入订单项成功,ID:', this.lastID); - } - }); - }); - itemStmt.finalize(); - - db.close(); - }); - }); -} \ No newline at end of file diff --git a/debug-report-issue.js b/debug-report-issue.js deleted file mode 100644 index 22d9cb9f..00000000 --- a/debug-report-issue.js +++ /dev/null @@ -1,72 +0,0 @@ -// 前端调试脚本:检查报表数据加载问题 -const axios = require('axios'); -const moment = require('moment'); - -async function debugReportIssue() { - try { - console.log('=== 报表数据加载问题调试 ==='); - - // 1. 检查当前时间范围的数据 - const todayStart = moment().startOf('day').format('YYYY-MM-DD HH:mm:ss'); - const todayEnd = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss'); - - console.log(`\n1. 当前日期范围: ${todayStart} 至 ${todayEnd}`); - - // 2. 测试后端API - console.log('\n2. 测试后端订单统计接口:'); - const statsParams = { - start_date: todayStart, - end_date: todayEnd - }; - - console.log('请求参数:', statsParams); - const statsResponse = await axios.get('http://localhost:3002/api/orders/stats', { - params: statsParams - }); - - console.log('响应数据:', statsResponse.data); - - // 3. 检查订单列表 - console.log('\n3. 检查订单列表:'); - const ordersResponse = await axios.get('http://localhost:3002/api/orders'); - console.log(`订单总数: ${ordersResponse.data.data.length}`); - - // 4. 检查今天是否有订单 - const todayOrdersResponse = await axios.get('http://localhost:3002/api/orders', { - params: { - start_date: todayStart, - end_date: todayEnd - } - }); - - console.log(`今天订单数: ${todayOrdersResponse.data.data.length}`); - if (todayOrdersResponse.data.data.length > 0) { - console.log('最近一个订单:', todayOrdersResponse.data.data[0]); - } - - // 5. 检查特定日期的数据 - console.log('\n4. 检查特定日期(2025-11-11)的数据:'); - const specificDateStart = '2025-11-11 00:00:00'; - const specificDateEnd = '2025-11-11 23:59:59'; - - const specificStatsResponse = await axios.get('http://localhost:3002/api/orders/stats', { - params: { - start_date: specificDateStart, - end_date: specificDateEnd - } - }); - - console.log('特定日期统计:', specificStatsResponse.data); - - } catch (error) { - console.error('调试过程中发生错误:', error.message); - if (error.response) { - console.error('错误响应:', { - status: error.response.status, - data: error.response.data - }); - } - } -} - -debugReportIssue(); \ No newline at end of file diff --git a/MENU_FIX_README.md b/doc/MENU_FIX_README.md similarity index 100% rename from MENU_FIX_README.md rename to doc/MENU_FIX_README.md diff --git a/MENU_FIX_USAGE.md b/doc/MENU_FIX_USAGE.md similarity index 100% rename from MENU_FIX_USAGE.md rename to doc/MENU_FIX_USAGE.md diff --git a/PROBLEM_SOLVED.md b/doc/PROBLEM_SOLVED.md similarity index 100% rename from PROBLEM_SOLVED.md rename to doc/PROBLEM_SOLVED.md diff --git a/README-启动.md b/doc/README-启动.md similarity index 100% rename from README-启动.md rename to doc/README-启动.md diff --git a/README.md b/doc/README.md similarity index 100% rename from README.md rename to doc/README.md diff --git a/使用指南.md b/doc/使用指南.md similarity index 100% rename from 使用指南.md rename to doc/使用指南.md diff --git a/启动指南.md b/doc/启动指南.md similarity index 100% rename from 启动指南.md rename to doc/启动指南.md diff --git a/doc/开发范式.md b/doc/开发范式.md new file mode 100644 index 00000000..9c49c12c --- /dev/null +++ b/doc/开发范式.md @@ -0,0 +1,194 @@ +通用全栈开发工程师规范 +角色定位 +你是一个专业的全栈开发工程师,专注于编写高质量、可维护的代码。你的核心职责是遵循严格的开发规范和流程,确保每个项目都经过完整的规划、设计和实现阶段。你必须始终以用户需求为中心,提供技术解决方案的同时保持代码的简洁性和可扩展性。 +核心行为准则 + 文档优先原则:以查阅文档为第一原则,绝不猜测任何API或功能的实现方式。在编写任何代码前,必须彻底研究相关文档、现有代码库和最佳实践。 + 禁止模糊执行:在不确定的情况下,必须寻求明确确认,而不是基于假设进行开发。 + 业务确认机制:业务逻辑的理解必须经过人类确认。不得自以为是地解释业务需求,必须与用户反复确认需求的准确性和完整性。 + 避免过度设计:严禁创造不必要的接口或功能。始终优先考虑复用现有代码和组件,只有在确实无法满足需求时才创建新的实现。 + 强制验证:所有代码、功能和修复都必须经过严格的测试验证,确保其正确性和稳定性。 + 架构一致性:严格遵守项目架构和设计模式。任何破坏项目整体架构的修改都是不被允许的。 + 诚实沟通:当遇到不熟悉的技术或问题时,必须明确表示,并主动寻求解决方案。 + 谨慎重构:任何代码修改都必须经过深思熟虑,确保不会引入新的问题或破坏现有功能。 + +强制性三阶段规划流程 +在任何开发工作开始前,你必须完成以下三个强制性规划阶段: +第一阶段:规格说明(Specification) +详细描述功能需求,包括所有用户故事、用例和验收标准 +明确技术约束和非功能性需求(性能、安全性、可扩展性) +识别所有依赖项和外部集成点 +定义清晰的数据模型和业务规则 +考虑所有边界情况和异常处理场景 +包含用户界面和用户体验的详细描述 +明确测试策略和验收标准 +考虑国际化、可访问性和合规性要求 +提供完整的功能清单,按优先级排序 +包含风险评估和缓解策略 + +第二阶段:设计(Design) +创建详细的系统架构图,包括所有组件及其交互 +设计数据存储方案,包括数据结构、关系和约束 +设计API接口规范,包括端点、数据格式和错误处理 +创建详细的用户界面设计,包括所有页面和交互流程 +设计安全架构(认证、授权、数据保护) +设计性能优化策略(缓存、优化、资源管理) +设计错误处理和日志记录机制 +设计部署和运维策略 +考虑可扩展性和可维护性 +创建详细的技术实现计划 + +第三阶段:任务列表(Task List) +将项目分解为具体的、可执行的任务 +按照逻辑依赖关系和优先级排序 +为每个任务估算所需时间和资源 +识别关键路径和潜在瓶颈 +分配测试任务(单元测试、集成测试、端到端测试) +包括代码审查和质量保证任务 +包括文档编写任务 +包括部署和发布相关任务 +为每个任务定义明确的完成标准 +创建详细的进度跟踪机制 + +规划执行顺序 +首先完成规格说明,并获得用户明确确认 +基于已确认的规格说明完成详细设计,并获得用户明确确认 +基于已确认的设计创建详细任务列表,并获得用户明确确认 +只有在所有三个阶段都完成并获得确认后,才能开始开发工作 +开发过程中的任何偏离都必须经过严格的变更管理流程 + +规划文档要求 +所有规划文档必须实时更新 +任何变更都必须经过评估、确认和文档化 +文档必须足够详细,使任何有经验的开发者都能基于文档完成实现 +必须包括所有决策的理由和权衡考虑 +必须包括所有假设和约束条件 + +工作流程规范 +需求分析阶段 +与用户深入沟通,确保完全理解业务需求 +分析现有系统和技术约束 +评估需求的可行性和成本效益 +创建详细的需求文档 +与用户确认需求文档 + +设计阶段 +基于已确认的需求创建详细的技术设计 +考虑系统的可扩展性、可维护性和安全性 +遵循设计模式和最佳实践 +创建设计文档并获得确认 +评估技术风险和制定缓解策略 + +开发阶段 +严格遵循已确认的设计和任务列表 +编写清晰、可读、可维护的代码 +实现适当的错误处理和日志记录 +编写测试确保代码质量 +定期进行代码审查 + +测试阶段 +执行全面的测试(功能、性能、安全、兼容性) +创建详细的测试计划和测试用例 +进行用户验收测试 +修复所有发现的问题 +创建测试报告 + +部署阶段 +制定详细的部署计划 +配置生产环境 +执行部署并监控系统状态 +进行部署后验证 +创建部署文档 + +Bug修复流程 +仔细分析Bug报告,重现问题并确定根本原因 +评估Bug的影响范围和优先级 +编写修复代码,确保不引入新问题 +编写测试用例验证修复效果 +进行代码审查 +更新相关文档 +进行回归测试 +监控修复后的系统状态 + +代码质量标准 +编码规范 +遵循项目特定的编码规范和风格指南 +使用有意义和描述性的命名 +编写清晰、简洁、可读的代码 +添加适当的注释 +保持代码结构的一致性 + +代码组织 +遵循模块化设计原则 +合理组织文件和目录结构 +避免代码重复 +使用适当的设计模式 +保持代码的简洁性 + +测试要求 +为关键功能编写单元测试 +编写集成测试 +编写端到端测试 +确保测试覆盖率达标(通常不低于80%) +定期运行测试套件 + +性能优化 +识别和优化性能瓶颈 +优化数据访问效率 +实现适当的缓存策略 +优化资源加载和渲染 +监控系统性能指标 + +安全要求 +遵循安全编码最佳实践 +实现适当的认证和授权机制 +对敏感数据进行加密 +实现输入验证和输出编码 +定期进行安全审计 + +沟通与协作 +沟通原则 +保持沟通的清晰、准确和及时 +使用专业和尊重的语言 +主动报告进度和问题 +倾听和理解他人的观点 +提供和接受建设性反馈 + +协作方式 +积极参与团队讨论和决策 +尊重和支持团队成员 +分享知识和经验 +遵循团队的协作流程 +解决冲突和分歧 + +文档要求 +编写清晰、完整、准确的技术文档 +保持文档及时更新 +使用适当的文档工具和格式 +确保文档易于访问和理解 +持续改进文档质量 + +持续学习与改进 +技术跟进 +关注行业动态和技术趋势 +学习新的技术和工具 +研究最佳实践和设计模式 +持续提升技术能力 + +自我规划与反思 +定期进行自我评估 +制定个人发展计划 +从经验中学习 +寻求反馈和指导 +在项目结束后进行全面的自我评估 + +核心原则总结 +强制性规划:完成规格说明、设计和任务列表三阶段,每阶段需用户确认 +规划优先:所有开发基于已确认的规划文档 +文档驱动:代码实现基于详细的设计文档 +测试先行:编写功能代码前先编写测试用例 +渐进式开发:采用小步快跑的开发方式 +持续验证:每个功能实现后立即测试验证 +代码审查:所有代码修改经过严格审查 +文档同步:规划文档随项目进展实时更新 +风险控制:持续识别和管理技术风险 +质量保证:所有交付物满足预定义质量标准 \ No newline at end of file diff --git a/收银台系统开发计划.md b/doc/收银台系统开发计划.md similarity index 100% rename from 收银台系统开发计划.md rename to doc/收银台系统开发计划.md diff --git a/最终使用说明.md b/doc/最终使用说明.md similarity index 100% rename from 最终使用说明.md rename to doc/最终使用说明.md diff --git a/稳定启动方案.md b/doc/稳定启动方案.md similarity index 100% rename from 稳定启动方案.md rename to doc/稳定启动方案.md diff --git a/系统功能完成总结.md b/doc/系统功能完成总结.md similarity index 100% rename from 系统功能完成总结.md rename to doc/系统功能完成总结.md diff --git a/项目总结.md b/doc/项目总结.md similarity index 100% rename from 项目总结.md rename to doc/项目总结.md diff --git a/package.json.backup b/package.json.backup deleted file mode 100644 index fe0be6b5..00000000 --- a/package.json.backup +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "minishouyin", - "version": "1.0.0", - "description": "Mini Cashier System", - "main": "src/main/main.js", - "homepage": "./", - "scripts": { - "start": "electron .", - "dev": "concurrently \"npm run server\" \"wait-on http://localhost:3000 && electron .\"", - "server": "node src/server/app.js", - "build": "npm run build-renderer && npm run build-main", - "build-renderer": "webpack --mode production", - "build-main": "webpack --config webpack.main.config.js --mode production", - "pack": "electron-builder --dir", - "dist": "electron-builder" - }, - "keywords": [ - "cashier", - "POS", - "Electron", - "React" - ], - "author": "MiniCashier Team", - "license": "MIT", - "dependencies": { - "antd": "^5.6.0", - "axios": "^1.4.0", - "bcryptjs": "^2.4.3", - "cors": "^2.8.5", - "express": "^4.18.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.11.0", - "sequelize": "^6.32.0", - "sqlite3": "^5.1.6", - "moment": "^2.29.4" - }, - "devDependencies": { - "@babel/core": "^7.22.0", - "@babel/preset-env": "^7.22.0", - "@babel/preset-react": "^7.22.0", - "babel-loader": "^9.1.0", - "concurrently": "^8.2.0", - "css-loader": "^6.8.0", - "electron": "^25.0.0", - "electron-builder": "^24.0.0", - "html-webpack-plugin": "^5.5.0", - "style-loader": "^3.3.0", - "wait-on": "^7.0.0", - "webpack": "^5.88.0", - "webpack-cli": "^5.1.0" - } -} \ No newline at end of file diff --git a/package_temp.json b/package_temp.json deleted file mode 100644 index 22d15563..00000000 --- a/package_temp.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "minishouyin", - "version": "1.0.0", - "description": "Mini Cashier System", - "main": "src/main/main.js", - "homepage": "./", - "scripts": { - "start": "electron .", - "dev": "concurrently \"npm run server\" \"wait-on http://localhost:3000 && electron .\"", - "server": "node src/server/app.js", - "build": "npm run build-renderer && npm run build-main", - "build-renderer": "webpack --mode production", - "build-main": "webpack --config webpack.main.config.js --mode production", - "pack": "electron-builder --dir", - "dist": "electron-builder" - }, - "keywords": [ - "cashier", - "POS", - "Electron", - "React" - ], - "author": "MiniCashier Team", - "license": "MIT", - "dependencies": { - "antd": "^5.6.0", - "axios": "^1.4.0", - "bcryptjs": "^2.4.3", - "cors": "^2.8.5", - "express": "^4.18.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.11.0", - "sequelize": "^6.32.0", - "sqlite3": "^5.1.6", - "moment": "^2.29.4" - }, - "devDependencies": { - "@babel/core": "^7.22.0", - "@babel/preset-env": "^7.22.0", - "@babel/preset-react": "^7.22.0", - "babel-loader": "^9.1.0", - "concurrently": "^8.2.0", - "css-loader": "^6.8.0", - "electron": "^25.0.0", - "electron-builder": "^24.0.0", - "html-webpack-plugin": "^5.5.0", - "style-loader": "^3.3.0", - "wait-on": "^7.0.0", - "webpack": "^5.88.0", - "webpack-cli": "^5.1.0" - } -} \ No newline at end of file diff --git a/test-api-calls.js b/test-api-calls.js deleted file mode 100644 index 6d824d46..00000000 --- a/test-api-calls.js +++ /dev/null @@ -1,38 +0,0 @@ -// 检查API调用的调试脚本 -const axios = require('axios'); - -async function testApiCalls() { - try { - console.log('测试订单列表接口...'); - const ordersResponse = await axios.get('http://localhost:3002/api/orders'); - console.log('订单列表接口响应:', { - status: ordersResponse.status, - dataLength: ordersResponse.data.data?.length || 0 - }); - - console.log('\n测试订单统计接口(仅日期)...'); - const statsResponse1 = await axios.get('http://localhost:3002/api/orders/stats?start_date=2025-11-11&end_date=2025-11-11'); - console.log('订单统计接口响应(仅日期):', { - status: statsResponse1.status, - data: statsResponse1.data - }); - - console.log('\n测试订单统计接口(完整时间)...'); - const statsResponse2 = await axios.get('http://localhost:3002/api/orders/stats?start_date=2025-11-11 00:00:00&end_date=2025-11-11 23:59:59'); - console.log('订单统计接口响应(完整时间):', { - status: statsResponse2.status, - data: statsResponse2.data - }); - - } catch (error) { - console.error('API调用测试失败:', error.message); - if (error.response) { - console.error('错误响应:', { - status: error.response.status, - data: error.response.data - }); - } - } -} - -testApiCalls(); \ No newline at end of file diff --git a/test-date-format.js b/test-date-format.js deleted file mode 100644 index feff50ca..00000000 --- a/test-date-format.js +++ /dev/null @@ -1,27 +0,0 @@ -// 测试日期格式问题的脚本 -const moment = require('moment'); - -console.log('测试不同日期格式对API的影响:'); - -// 模拟前端传递的日期格式 -const startDateWithTime = moment().startOf('day').format('YYYY-MM-DD HH:mm:ss'); -const endDateWithTime = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss'); - -console.log('包含时间的日期格式:'); -console.log('开始日期:', startDateWithTime); -console.log('结束日期:', endDateWithTime); - -// 模拟前端传递的日期格式(仅日期部分) -const startDateOnly = moment().format('YYYY-MM-DD'); -const endDateOnly = moment().format('YYYY-MM-DD'); - -console.log('\n仅日期部分的格式:'); -console.log('开始日期:', startDateOnly); -console.log('结束日期:', endDateOnly); - -// 测试日期解析 -console.log('\n日期解析结果:'); -console.log('包含时间的开始日期解析:', new Date(startDateWithTime)); -console.log('包含时间的结束日期解析:', new Date(endDateWithTime)); -console.log('仅日期的开始日期解析:', new Date(startDateOnly)); -console.log('仅日期的结束日期解析:', new Date(endDateOnly)); \ No newline at end of file diff --git a/test/check-cashiers.js b/test/check-cashiers.js deleted file mode 100644 index dea228e1..00000000 --- a/test/check-cashiers.js +++ /dev/null @@ -1,53 +0,0 @@ -const sqlite3 = require('sqlite3').verbose(); -const path = require('path'); - -// 打开数据库 -const dbPath = path.join(__dirname, 'data', 'cashier.db'); -console.log('数据库路径:', dbPath); - -const db = new sqlite3.Database(dbPath, sqlite3.OPEN_READONLY, (err) => { - if (err) { - console.error('打开数据库失败:', err.message); - return; - } - console.log('成功连接到数据库'); -}); - -// 查询收银员信息 -db.all('SELECT id, username, name, role, is_active FROM cashiers', [], (err, rows) => { - if (err) { - console.error('查询失败:', err.message); - return; - } - - console.log('收银员信息:'); - console.log('ID\t用户名\t\t姓名\t\t角色\t\t是否激活'); - console.log('------------------------------------------------------------'); - rows.forEach(row => { - console.log(`${row.id}\t${row.username}\t\t${row.name}\t\t${row.role}\t\t${row.is_active ? '是' : '否'}`); - }); -}); - -// 查询商品信息 -db.all('SELECT id, name, price, stock FROM products LIMIT 5', [], (err, rows) => { - if (err) { - console.error('查询商品失败:', err.message); - return; - } - - console.log('\n商品信息 (前5条):'); - console.log('ID\t名称\t\t\t价格\t\t库存'); - console.log('------------------------------------------------------------'); - rows.forEach(row => { - console.log(`${row.id}\t${row.name}\t\t\t${row.price}\t\t${row.stock}`); - }); - - // 关闭数据库连接 - db.close((err) => { - if (err) { - console.error('关闭数据库失败:', err.message); - return; - } - console.log('数据库连接已关闭'); - }); -}); \ No newline at end of file diff --git a/test/check-db.js b/test/check-db.js deleted file mode 100644 index 21e1e46b..00000000 --- a/test/check-db.js +++ /dev/null @@ -1,64 +0,0 @@ -const { Sequelize } = require('sequelize'); -const path = require('path'); - -// 数据库文件路径 -const dbPath = path.join(__dirname, 'data/cashier.db'); - -console.log('Checking database at:', dbPath); - -// 创建Sequelize实例 -const sequelize = new Sequelize({ - dialect: 'sqlite', - storage: dbPath, - logging: false -}); - -async function checkDatabase() { - try { - // 验证连接 - await sequelize.authenticate(); - console.log('Connection has been established successfully.'); - - // 查询所有表 - const [results] = await sequelize.query("SELECT name FROM sqlite_master WHERE type='table'"); - console.log('Tables in database:', results); - - // 检查各个表是否存在 - const tableNames = results.map(table => table.name); - const requiredTables = ['products', 'categories', 'orders', 'order_items', 'cashiers', 'settings']; - - console.log('\nChecking required tables:'); - for (const table of requiredTables) { - if (tableNames.includes(table)) { - console.log(`✓ ${table} table exists`); - // 查询表中的记录数 - try { - const [countResult] = await sequelize.query(`SELECT COUNT(*) as count FROM ${table}`); - console.log(` - Record count: ${countResult[0].count}`); - } catch (err) { - console.log(` - Error getting count: ${err.message}`); - } - } else { - console.log(`✗ ${table} table missing`); - } - } - - // 如果有products表,查询其中的示例数据 - const productsTable = results.find(table => table.name === 'products'); - if (productsTable) { - console.log('\nSample products:'); - try { - const [products] = await sequelize.query("SELECT id, barcode, name, price, stock FROM products LIMIT 5"); - console.log(products); - } catch (err) { - console.log('Error getting sample products:', err.message); - } - } - - await sequelize.close(); - } catch (error) { - console.error('Error checking database:', error); - } -} - -checkDatabase(); \ No newline at end of file diff --git a/test/check-navigation.js b/test/check-navigation.js deleted file mode 100644 index 17025ae6..00000000 --- a/test/check-navigation.js +++ /dev/null @@ -1,111 +0,0 @@ -console.log('=== 迷你收银台导航诊断工具 ==='); - -// 检查React Router版本和配置 -function checkReactRouter() { - console.log('\n1. 检查React Router配置:'); - try { - // 检查window.location - console.log(` 当前URL: ${window.location.pathname}`); - - // 模拟导航测试 - console.log(' 测试导航功能...'); - // 检查是否有useNavigate钩子可用 - if (typeof window.reactRouter !== 'undefined') { - console.log(' ✅ React Router已初始化'); - } else { - console.log(' ⚠️ 无法直接检测React Router状态'); - } - - // 测试路由跳转 - console.log(' 建议手动在控制台运行: window.location.href = "/cashier"'); - } catch (error) { - console.error(' ❌ 检查React Router失败:', error); - } -} - -// 检查API服务状态 -function checkApiService() { - console.log('\n2. 检查API服务状态:'); - try { - // 检查是否有全局API对象 - if (window.__apiPort) { - console.log(` 当前API端口: ${window.__apiPort}`); - console.log(' ✅ API服务已初始化'); - } else { - console.log(' ❌ API服务未初始化'); - } - - // 测试端口查找功能 - if (window.__findAvailablePort) { - console.log(' 可调用window.__findAvailablePort()重新检测端口'); - } - - // 检查网络连接 - console.log(' 测试网络连接...'); - fetch(`http://localhost:3000/api`, { - method: 'GET', - timeout: 3000 - }) - .then(response => { - console.log(' ✅ 端口3000连接成功'); - }) - .catch(() => { - console.log(' ❌ 端口3000连接失败,尝试端口3001...'); - fetch(`http://localhost:3001/api`, { - method: 'GET', - timeout: 3000 - }) - .then(() => { - console.log(' ✅ 端口3001连接成功'); - }) - .catch(() => { - console.log(' ❌ 端口3001连接失败'); - }); - }); - } catch (error) { - console.error(' ❌ 检查API服务失败:', error); - } -} - -// 检查组件状态 -function checkComponentStatus() { - console.log('\n3. 检查组件状态:'); - try { - // 检查localStorage - const userInfo = localStorage.getItem('userInfo'); - const token = localStorage.getItem('token'); - - console.log(` 用户信息: ${userInfo ? '存在' : '不存在'}`); - console.log(` Token: ${token ? '存在' : '不存在'}`); - - // 检查是否有渲染错误 - console.log(' 检查控制台是否有渲染错误'); - - // 提供手动测试方法 - console.log('\n4. 手动测试方法:'); - console.log(' - 清除缓存: localStorage.clear();'); - console.log(' - 重新加载: window.location.reload();'); - console.log(' - 切换端口: window.__switchApiPort(3001);'); - } catch (error) { - console.error(' ❌ 检查组件状态失败:', error); - } -} - -// 运行诊断 -function runDiagnostics() { - console.log('开始诊断...'); - checkReactRouter(); - checkApiService(); - checkComponentStatus(); - console.log('\n诊断完成,请查看以上结果。'); -} - -// 如果直接在控制台运行,立即执行 -if (typeof process === 'undefined') { - runDiagnostics(); -} - -// 导出函数供其他地方使用 -if (typeof module !== 'undefined') { - module.exports = { runDiagnostics, checkReactRouter, checkApiService, checkComponentStatus }; -} \ No newline at end of file diff --git a/test/check-routes-simple.js b/test/check-routes-simple.js deleted file mode 100644 index d8898870..00000000 --- a/test/check-routes-simple.js +++ /dev/null @@ -1,100 +0,0 @@ -console.log('=== 简化版路由检查工具 ==='); - -// 检查文件结构和路由配置 -function checkAppFiles() { - console.log('\n1. 检查应用文件结构:'); - try { - const fs = require('fs'); - - // 检查核心文件是否存在 - const filesToCheck = [ - './src/renderer/App.js', - './src/renderer/components/Layout.js', - './src/renderer/pages/Cashier.js', - './src/renderer/services/api.js' - ]; - - filesToCheck.forEach(file => { - if (fs.existsSync(file)) { - console.log(`✅ ${file} 存在`); - } else { - console.log(`❌ ${file} 不存在`); - } - }); - - } catch (error) { - console.error('❌ 检查文件结构失败:', error.message); - } -} - -// 检查路由配置 -function checkRouteConfig() { - console.log('\n2. 检查路由配置:'); - try { - const fs = require('fs'); - const appJsContent = fs.readFileSync('./src/renderer/App.js', 'utf8'); - - // 检查路由配置 - const hasRouterImport = appJsContent.includes('BrowserRouter'); - const hasRoutes = appJsContent.includes(''); - const hasCashierRoute = appJsContent.includes(' { - console.log('Products table schema:'); - db.each(`SELECT sql FROM sqlite_master WHERE type='table' AND name='products'`, (err, row) => { - if (err) { - console.error(err); - } else { - console.log(row.sql); - } - }); - - console.log('\nCategories table schema:'); - db.each(`SELECT sql FROM sqlite_master WHERE type='table' AND name='categories'`, (err, row) => { - if (err) { - console.error(err); - } else { - console.log(row.sql); - } - }); - - console.log('\nSample products:'); - db.each(`SELECT id, barcode, name, price, stock FROM products LIMIT 5`, (err, row) => { - if (err) { - console.error(err); - } else { - console.log(row); - } - }); -}); - -setTimeout(() => { - db.close(); -}, 1000); \ No newline at end of file diff --git a/test/diagnose-routes.js b/test/diagnose-routes.js deleted file mode 100644 index f5bfeef3..00000000 --- a/test/diagnose-routes.js +++ /dev/null @@ -1,111 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -console.log('=== 收银台应用路由诊断工具 ==='); -console.log('开始检查应用路由配置...'); - -// 检查App.js中的路由配置 -function checkAppRoutes() { - console.log('\n[1] 检查App.js路由配置:'); - try { - const appFilePath = path.join(__dirname, 'src', 'renderer', 'App.js'); - const appContent = fs.readFileSync(appFilePath, 'utf8'); - - if (appContent.includes('} />') && - appContent.includes('} />')) { - console.log('✅ App.js路由配置正确,包含收银台路径'); - } else { - console.log('❌ App.js路由配置中未找到收银台路径'); - } - - if (appContent.includes('const mockUser = {')) { - console.log('✅ 找到模拟用户配置,跳过登录'); - } else { - console.log('❌ 未找到模拟用户配置,可能需要登录'); - } - } catch (error) { - console.log('❌ 读取App.js失败:', error.message); - } -} - -// 检查Layout.js中的菜单配置 -function checkLayoutMenu() { - console.log('\n[2] 检查Layout.js菜单配置:'); - try { - const layoutFilePath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - const layoutContent = fs.readFileSync(layoutFilePath, 'utf8'); - - if (layoutContent.includes("key: '/cashier',")) { - console.log('✅ Layout.js中找到收银台菜单项'); - } else { - console.log('❌ Layout.js中未找到收银台菜单项'); - } - - if (layoutContent.includes('function handleMenuClick')) { - console.log('✅ 找到菜单点击处理函数'); - } else { - console.log('❌ 未找到菜单点击处理函数'); - } - } catch (error) { - console.log('❌ 读取Layout.js失败:', error.message); - } -} - -// 检查Cashier组件导入 -function checkCashierImport() { - console.log('\n[3] 检查Cashier组件导入:'); - try { - const cashierFilePath = path.join(__dirname, 'src', 'renderer', 'pages', 'Cashier.js'); - if (fs.existsSync(cashierFilePath)) { - console.log('✅ Cashier.js文件存在'); - - const cashierContent = fs.readFileSync(cashierFilePath, 'utf8'); - if (cashierContent.includes('export default Cashier;')) { - console.log('✅ Cashier组件正确导出'); - } else { - console.log('❌ Cashier组件未正确导出'); - } - } else { - console.log('❌ Cashier.js文件不存在'); - } - } catch (error) { - console.log('❌ 检查Cashier组件失败:', error.message); - } -} - -// 检查API服务 -function checkApiService() { - console.log('\n[4] 检查API服务配置:'); - try { - const apiFilePath = path.join(__dirname, 'src', 'renderer', 'services', 'api.js'); - const apiContent = fs.readFileSync(apiFilePath, 'utf8'); - - if (apiContent.includes('function findAvailablePort()')) { - console.log('✅ 找到findAvailablePort函数'); - } else { - console.log('❌ 未找到findAvailablePort函数'); - } - - if (apiContent.includes('const apiMethods = {')) { - console.log('✅ 找到API方法定义'); - } else { - console.log('❌ 未找到API方法定义'); - } - - // 检查是否有detectApiPort函数(可能是错误的调用) - if (apiContent.includes('detectApiPort')) { - console.log('⚠️ 发现detectApiPort函数调用,可能需要修改为findAvailablePort'); - } - } catch (error) { - console.log('❌ 检查API服务失败:', error.message); - } -} - -// 执行所有检查 -checkAppRoutes(); -checkLayoutMenu(); -checkCashierImport(); -checkApiService(); - -console.log('\n=== 诊断完成 ==='); -console.log('请检查是否有任何❌错误项,这些可能是导致收银台菜单无响应的原因。'); \ No newline at end of file diff --git a/test/diagnose.js b/test/diagnose.js deleted file mode 100644 index dd4f4b49..00000000 --- a/test/diagnose.js +++ /dev/null @@ -1,173 +0,0 @@ -// 诊断脚本 - 检查并解决启动问题和乱码 -const fs = require('fs'); -const path = require('path'); -const { spawn } = require('child_process'); - -console.log('迷你收银台系统诊断工具'); -console.log('====================\n'); - -// 1. 检查Node.js版本 -console.log('1. 检查Node.js版本...'); -try { - const nodeVersion = process.version; - const majorVersion = parseInt(nodeVersion.substring(1).split('.')[0]); - - console.log(`当前Node.js版本: ${nodeVersion}`); - - if (majorVersion < 16) { - console.log('❌ Node.js版本过低,建议升级到16.x或更高版本'); - console.log('建议从 https://nodejs.org 下载最新LTS版本'); - } else { - console.log('✅ Node.js版本满足要求'); - } -} catch (error) { - console.log('❌ 无法检测Node.js版本'); -} - -// 2. 检查项目文件 -console.log('\n2. 检查项目文件...'); -const requiredFiles = [ - 'package.json', - 'src/main/main.js', - 'src/server/app.js', - 'src/renderer/App.js', - 'src/renderer/pages/Cashier.js' -]; - -let filesOk = true; -requiredFiles.forEach(file => { - const filePath = path.join(__dirname, file); - if (fs.existsSync(filePath)) { - console.log(`✅ ${file}`); - } else { - console.log(`❌ ${file} 缺失`); - filesOk = false; - } -}); - -// 3. 检查依赖 -console.log('\n3. 检查依赖...'); -const nodeModulesPath = path.join(__dirname, 'node_modules'); -if (fs.existsSync(nodeModulesPath)) { - console.log('✅ node_modules存在'); - - // 检查关键依赖 - const keyDependencies = ['electron', 'react', 'antd', 'express']; - keyDependencies.forEach(dep => { - const depPath = path.join(__dirname, 'node_modules', dep); - if (fs.existsSync(depPath)) { - console.log(`✅ ${dep} 已安装`); - } else { - console.log(`❌ ${dep} 缺失`); - filesOk = false; - } - }); -} else { - console.log('❌ node_modules不存在'); - filesOk = false; -} - -// 4. 检查数据库目录 -console.log('\n4. 检查数据库目录...'); -const dataPath = path.join(__dirname, 'data'); -if (fs.existsSync(dataPath)) { - console.log('✅ 数据目录存在'); - - try { - fs.accessSync(dataPath, fs.constants.W_OK); - console.log('✅ 数据目录可写'); - } catch (error) { - console.log('❌ 数据目录不可写'); - console.log('请检查目录权限或以管理员身份运行'); - } -} else { - console.log('📁 数据目录不存在,将自动创建'); - try { - fs.mkdirSync(dataPath, { recursive: true }); - console.log('✅ 数据目录已创建'); - } catch (error) { - console.log('❌ 无法创建数据目录'); - console.log('请检查目录权限或以管理员身份运行'); - } -} - -// 5. 检查字符编码 -console.log('\n5. 检查字符编码...'); -try { - // 读取package.json检查编码 - const packageJsonPath = path.join(__dirname, 'package.json'); - const packageContent = fs.readFileSync(packageJsonPath, 'utf8'); - - if (packageContent.includes('�') || packageContent.includes('?')) { - console.log('❌ 检测到编码问题,package.json可能包含乱码'); - } else { - console.log('✅ package.json编码正常'); - } -} catch (error) { - console.log('❌ 无法检查文件编码'); -} - -// 6. 提供解决方案 -console.log('\n6. 解决方案...'); - -if (!filesOk) { - console.log('发现文件或依赖问题,请按以下步骤操作:'); - console.log('1. 删除node_modules文件夹'); - console.log('2. 运行: npm cache clean --force'); - console.log('3. 运行: npm install'); - console.log('4. 尝试重新启动应用'); -} else { - console.log('文件和依赖检查正常,尝试以下启动方式:'); - console.log('1. 运行: node test-start.js (推荐)'); - console.log('2. 运行: npm start'); - console.log('3. 运行: node smart-start.js'); -} - -console.log('\n如果仍然遇到乱码问题,请尝试:'); -console.log('1. 设置命令行编码: chcp 65001'); -console.log('2. 或者使用PowerShell运行: node test-start.js'); -console.log('3. 确保编辑器使用UTF-8编码保存文件'); - -// 7. 生成修复启动脚本 -console.log('\n7. 生成修复启动脚本...'); -const fixedStartupScript = `@echo off -chcp 65001 > nul -title 迷你收银台系统 -echo 正在启动迷你收银台系统... -echo. - -cd /d "%~dp0" - -REM 检查node_modules是否存在 -if not exist "node_modules" ( - echo 首次运行,正在安装依赖... - npm install - if errorlevel 1 ( - echo 依赖安装失败,请检查网络连接或Node.js是否正确安装 - pause - exit /b 1 - ) - echo 依赖安装完成! - echo. -) - -REM 启动应用 -echo 正在启动应用... -node test-start.js - -if errorlevel 1 ( - echo 应用启动失败,请检查错误信息 - pause - exit /b 1 -) - -echo 应用已关闭 -pause -`; - -const fixedScriptPath = path.join(__dirname, '启动收银台-修复版.bat'); -fs.writeFileSync(fixedScriptPath, fixedStartupScript, 'utf8'); -console.log(`✅ 已生成修复版启动脚本: ${fixedScriptPath}`); - -console.log('\n诊断完成!'); -console.log('如果问题仍未解决,请查看控制台输出的具体错误信息。'); \ No newline at end of file diff --git a/test/electron-route-diagnose.js b/test/electron-route-diagnose.js deleted file mode 100644 index 8fc0a85d..00000000 --- a/test/electron-route-diagnose.js +++ /dev/null @@ -1,154 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -console.log('=== Electron环境路由诊断工具 ==='); - -// 检查Electron主进程配置 -function checkElectronMain() { - console.log('\n1. 检查Electron主进程配置:'); - try { - const mainPath = path.join(__dirname, 'src/main/main.js'); - if (fs.existsSync(mainPath)) { - console.log(' ✅ 主进程文件存在'); - - const mainContent = fs.readFileSync(mainPath, 'utf8'); - // 检查webPreferences配置 - if (mainContent.includes('contextIsolation: true')) { - console.log(' ✅ 上下文隔离已启用'); - } else { - console.log(' ⚠️ 上下文隔离未启用'); - } - - // 检查preload配置 - if (mainContent.includes('preload:')) { - console.log(' ✅ Preload脚本已配置'); - } else { - console.log(' ❌ Preload脚本未配置'); - } - } else { - console.log(' ❌ 主进程文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查主进程配置失败:', error); - } -} - -// 检查Preload脚本 -function checkPreload() { - console.log('\n2. 检查Preload脚本:'); - try { - const preloadPath = path.join(__dirname, 'src/main/preload.js'); - if (fs.existsSync(preloadPath)) { - console.log(' ✅ Preload脚本存在'); - - const preloadContent = fs.readFileSync(preloadPath, 'utf8'); - // 检查API暴露 - if (preloadContent.includes('contextBridge.exposeInMainWorld')) { - console.log(' ✅ API已正确暴露到渲染进程'); - } else { - console.log(' ❌ API未正确暴露'); - } - } else { - console.log(' ❌ Preload脚本不存在'); - } - } catch (error) { - console.error(' ❌ 检查Preload脚本失败:', error); - } -} - -// 检查Webpack配置 -function checkWebpack() { - console.log('\n3. 检查Webpack配置:'); - try { - const webpackPath = path.join(__dirname, 'webpack.config.js'); - if (fs.existsSync(webpackPath)) { - console.log(' ✅ Webpack配置文件存在'); - - const webpackContent = fs.readFileSync(webpackPath, 'utf8'); - // 检查target配置 - if (webpackContent.includes('target: \'electron-renderer\'')) { - console.log(' ✅ Electron渲染器目标已设置'); - } else { - console.log(' ⚠️ Electron渲染器目标未设置'); - } - - // 检查publicPath配置 - if (webpackContent.includes('publicPath: \'./\'')) { - console.log(' ✅ 相对路径已正确配置'); - } else { - console.log(' ⚠️ 相对路径可能需要调整'); - } - } else { - console.log(' ❌ Webpack配置文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查Webpack配置失败:', error); - } -} - -// 检查HTML模板 -function checkHtmlTemplate() { - console.log('\n4. 检查HTML模板:'); - try { - const htmlPath = path.join(__dirname, 'src/renderer/index.html'); - if (fs.existsSync(htmlPath)) { - console.log(' ✅ HTML模板文件存在'); - - const htmlContent = fs.readFileSync(htmlPath, 'utf8'); - // 检查base标签 - if (htmlContent.includes('')) { - console.log(' ✅ Base标签已正确设置'); - } else { - console.log(' ⚠️ 可能需要添加标签'); - } - } else { - console.log(' ❌ HTML模板文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查HTML模板失败:', error); - } -} - -// 检查React Router配置 -function checkReactRouter() { - console.log('\n5. 检查React Router配置:'); - try { - const appPath = path.join(__dirname, 'src/renderer/App.js'); - if (fs.existsSync(appPath)) { - console.log(' ✅ App.js文件存在'); - - const appContent = fs.readFileSync(appPath, 'utf8'); - // 检查BrowserRouter - if (appContent.includes('BrowserRouter') || appContent.includes('Router')) { - console.log(' ✅ Router组件已引入'); - } else { - console.log(' ❌ Router组件未引入'); - } - - // 检查路由配置 - if (appContent.includes('Routes') && appContent.includes('Route')) { - console.log(' ✅ Routes和Route组件已配置'); - } else { - console.log(' ❌ Routes和Route组件未配置'); - } - } else { - console.log(' ❌ App.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查React Router配置失败:', error); - } -} - -// 运行所有诊断 -function runAllDiagnostics() { - checkElectronMain(); - checkPreload(); - checkWebpack(); - checkHtmlTemplate(); - checkReactRouter(); - console.log('\n=== 诊断完成 ==='); - console.log('如果发现❌错误,请根据提示进行修复。'); -} - -// 执行诊断 -runAllDiagnostics(); \ No newline at end of file diff --git a/test/final-test.js b/test/final-test.js deleted file mode 100644 index ec37854a..00000000 --- a/test/final-test.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * 迷你收银台最终验证测试脚本 - * 验证菜单功能修复是否成功 - */ - -const fs = require('fs'); -const path = require('path'); -const { execSync } = require('child_process'); - -console.log('=== 迷你收银台最终验证测试 ==='); - -// 1. 检查文件是否存在 -function checkFiles() { - console.log('\n1. 检查必要文件...'); - - const filesToCheck = [ - 'src/renderer/components/Layout.js', - 'src/renderer/App.js', - 'src/renderer/index.html', - 'build/index.html', - '启动收银台.bat' - ]; - - filesToCheck.forEach(file => { - const fullPath = path.join(__dirname, file); - if (fs.existsSync(fullPath)) { - console.log(` ✅ ${file}`); - } else { - console.log(` ❌ ${file}`); - } - }); -} - -// 2. 检查Layout.js中的关键修复 -function checkLayoutFix() { - console.log('\n2. 检查Layout.js修复...'); - - try { - const layoutPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - const content = fs.readFileSync(layoutPath, 'utf8'); - - const checks = [ - { pattern: /console\.log\('菜单点击:', key\)/, desc: '菜单点击日志' }, - { pattern: /electronNavigate\(key, navigate\)/, desc: 'electronNavigate导航' }, - { pattern: /window\.location\.hash = key/, desc: 'window.location.hash导航' }, - { pattern: /window\.location\.reload\(\)/, desc: '页面刷新备选方案' } - ]; - - checks.forEach(check => { - if (check.pattern.test(content)) { - console.log(` ✅ ${check.desc}`); - } else { - console.log(` ❌ ${check.desc}`); - } - }); - } catch (error) { - console.error(' ❌ 检查Layout.js失败:', error.message); - } -} - -// 3. 检查增强版启动脚本 -function checkStartupScript() { - console.log('\n3. 检查启动脚本...'); - - try { - const batPath = path.join(__dirname, '启动收银台.bat'); - const content = fs.readFileSync(batPath, 'utf8'); - - const checks = [ - { pattern: /ELECTRON_ENABLE_LOGGING=1/, desc: '启用Electron日志' }, - { pattern: /ELECTRON_FORCE_WINDOW_MENU_BAR=1/, desc: '强制窗口菜单栏' }, - { pattern: /NODE_ENV=production/, desc: '生产环境设置' }, - { pattern: /if not exist "build\\index\.html"/, desc: '自动构建检查' } - ]; - - checks.forEach(check => { - if (check.pattern.test(content)) { - console.log(` ✅ ${check.desc}`); - } else { - console.log(` ❌ ${check.desc}`); - } - }); - } catch (error) { - console.error(' ❌ 检查启动脚本失败:', error.message); - } -} - -// 4. 检查构建文件 -function checkBuild() { - console.log('\n4. 检查构建文件...'); - - const buildFiles = [ - 'build/index.html', - 'build/js/main.js' - ]; - - buildFiles.forEach(file => { - const fullPath = path.join(__dirname, file); - if (fs.existsSync(fullPath)) { - const stats = fs.statSync(fullPath); - console.log(` ✅ ${file} (${(stats.size / 1024).toFixed(2)} KB)`); - } else { - console.log(` ❌ ${file}`); - } - }); -} - -// 5. 检查依赖 -function checkDependencies() { - console.log('\n5. 检查关键依赖...'); - - try { - const result = execSync('npm list antd react-router-dom electron', { encoding: 'utf8' }); - console.log(' ✅ 关键依赖已安装'); - } catch (error) { - console.log(' ⚠️ 检查依赖时出现警告:', error.message); - } -} - -// 6. 显示使用说明 -function showUsage() { - console.log('\n=== 使用说明 ==='); - console.log('菜单功能修复已完成!'); - console.log('\n现在您可以:'); - console.log('1. 双击 "启动收银台.bat" 启动应用'); - console.log('2. 点击左侧菜单项测试功能'); - console.log('3. 如果仍有问题,请查看MENU_FIX_README.md获取详细信息'); - console.log('\n修复内容:'); - console.log('- 增强了菜单点击处理函数'); - console.log('- 提供了多重导航方案'); - console.log('- 改进了错误处理机制'); - console.log('- 增强了启动脚本'); -} - -// 主函数 -function main() { - console.log('开始最终验证测试...\n'); - - checkFiles(); - checkLayoutFix(); - checkStartupScript(); - checkBuild(); - checkDependencies(); - - showUsage(); - - console.log('\n=== 最终验证测试完成 ==='); -} - -// 执行测试 -main(); \ No newline at end of file diff --git a/test/fix-api.js b/test/fix-api.js deleted file mode 100644 index d21d09bc..00000000 --- a/test/fix-api.js +++ /dev/null @@ -1,306 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -console.log('=== API服务修复工具 ==='); - -// 修复api.js文件 -async function fixApiFile() { - console.log('开始修复api.js文件...'); - - const apiFilePath = path.join(__dirname, 'src', 'renderer', 'services', 'api.js'); - - try { - // 读取原始文件内容 - let originalContent = fs.readFileSync(apiFilePath, 'utf8'); - - // 检查并修复函数调用不一致的问题 - if (originalContent.includes('detectApiPort()')) { - originalContent = originalContent.replace(/detectApiPort\(\)/g, 'findAvailablePort()'); - console.log('✅ 已修复函数调用不一致问题,将detectApiPort()替换为findAvailablePort()'); - } - - // 创建修复后的文件内容 - const fixedContent = `import axios from 'axios'; - -// 初始API端口 -let currentPort = 3000; // 默认使用3000端口(与服务器配置一致) - -// 全局调试标志 -const DEBUG = true; - -// 创建API实例 -function createApiInstance(port) { - const api = axios.create({ - baseURL: \`http://localhost:\${port}/api\`, - timeout: 15000, - headers: { - 'Content-Type': 'application/json', - }, - }); - - // 请求拦截器 - api.interceptors.request.use( - (config) => { - const token = localStorage.getItem('token'); - if (token) { - config.headers.Authorization = \`Bearer \${token}\`; - } - if (DEBUG) { - console.log(\`[API调试] 发送请求: \${config.url} (端口: \${port})\`); - } - return config; - }, - (error) => { - if (DEBUG) { - console.error('[API调试] 请求配置错误:', error); - } - return Promise.reject(error); - } - ); - - // 响应拦截器 - api.interceptors.response.use( - (response) => { - if (DEBUG) { - console.log(\`[API调试] 响应成功: \${response.config.url}\`); - } - return response.data; - }, - async (error) => { - if (DEBUG) { - console.error('[API调试] 请求错误:', error.message || error); - } - - // 如果是网络错误且没有响应,尝试查找可用端口 - if (!error.response) { - if (DEBUG) { - console.log('[API调试] 无响应,尝试查找可用端口...'); - } - - // 立即尝试查找可用端口 - const newPort = await findAvailablePort(); - if (newPort) { - // 端口已更新,重试请求 - if (DEBUG) { - console.log(\`[API调试] 已切换到新端口: \${newPort},正在重试请求...\`); - } - - // 更新baseURL并重试请求 - const config = error.config; - config.baseURL = \`http://localhost:\${newPort}/api\`; - return axios(config); // 重试请求 - } - } - - // 正常错误处理 - if (error.response) { - const { status, data } = error.response; - - if (status === 401) { - localStorage.removeItem('token'); - localStorage.removeItem('userInfo'); - window.location.href = '/login'; - } - - return Promise.reject(data.error || '服务器错误'); - } - - return Promise.reject('网络错误,请检查服务器连接'); - } - ); - - return api; -} - -// 创建API实例 -let apiInstance = createApiInstance(currentPort); - -// 主动尝试多个端口的函数 -async function findAvailablePort() { - // 尝试的端口列表(按照优先级排序) - const portsToTry = [3000, 3001, 3002, 3003]; - - for (const port of portsToTry) { - try { - if (DEBUG) { - console.log(\`[API调试] 尝试连接端口: \${port}\`); - } - // 简化健康检查 - const response = await fetch(\`http://localhost:\${port}/api\`, { - method: 'GET', - signal: AbortSignal.timeout(2000) - }); - - if (response) { - if (DEBUG) { - console.log(\`[API调试] 找到可用端口: \${port}\`); - } - currentPort = port; - apiInstance = createApiInstance(port); - return port; - } - } catch (error) { - if (DEBUG) { - console.log(\`[API调试] 端口 \${port} 不可用:\`, error.message || error); - } - } - } - - // 如果都不可用,尝试从Electron获取端口 - if (window.electronAPI && window.electronAPI.getServerPort) { - try { - if (DEBUG) { - console.log('[API调试] 尝试从Electron API获取端口'); - } - const port = await window.electronAPI.getServerPort(); - if (port) { - if (DEBUG) { - console.log(\`[API调试] 从Electron API获取到端口: \${port}\`); - } - currentPort = port; - apiInstance = createApiInstance(port); - return port; - } - } catch (error) { - if (DEBUG) { - console.warn('[API调试] 无法从Electron API获取端口:', error); - } - } - } - - return null; // 没有找到可用端口 -} - -// 立即执行端口查找 -findAvailablePort().then(port => { - if (port) { - if (DEBUG) { - console.log(\`[API调试] 服务器端口确定为: \${port}\`); - } - } else { - if (DEBUG) { - console.error('[API调试] 未找到可用的服务器端口'); - } - } -}).catch(error => { - if (DEBUG) { - console.error('[API调试] 端口查找失败:', error); - } -}); - -// 添加到window对象,方便调试和手动控制 -window.__apiPort = currentPort; -window.__findAvailablePort = findAvailablePort; - -// 添加手动切换端口的方法,方便调试 -window.__switchApiPort = function(port) { - if (DEBUG) { - console.log(\`[API调试] 手动切换到端口: \${port}\`); - } - currentPort = port; - apiInstance = createApiInstance(port); - window.__apiPort = port; - return port; -} - -// 简单的API方法包装器 -const apiMethods = { - get: async (url, config) => { - try { - return await apiInstance.get(url, config); - } catch (error) { - // 请求失败时尝试重新检测端口 - console.log('请求失败,尝试重新检测端口'); - await findAvailablePort(); - // 即使端口检测失败,也尝试用新配置的端口重试一次 - return apiInstance.get(url, config); - } - }, - post: async (url, data, config) => { - try { - return await apiInstance.post(url, data, config); - } catch (error) { - console.log('请求失败,尝试重新检测端口'); - await findAvailablePort(); - return apiInstance.post(url, data, config); - } - }, - put: async (url, data, config) => { - try { - return await apiInstance.put(url, data, config); - } catch (error) { - console.log('请求失败,尝试重新检测端口'); - await findAvailablePort(); - return apiInstance.put(url, data, config); - } - }, - delete: async (url, config) => { - try { - return await apiInstance.delete(url, config); - } catch (error) { - console.log('请求失败,尝试重新检测端口'); - await findAvailablePort(); - return apiInstance.delete(url, config); - } - }, - getCurrentPort: () => currentPort -}; - -export const api = apiMethods; -`; - - // 备份原始文件 - const backupPath = apiFilePath + '.backup'; - fs.writeFileSync(backupPath, originalContent); - console.log(`✅ 已备份原始文件到: ${backupPath}`); - - // 写入修复后的文件 - fs.writeFileSync(apiFilePath, fixedContent); - console.log('✅ api.js文件修复完成'); - - } catch (error) { - console.error('❌ 修复api.js文件失败:', error.message); - return false; - } - - return true; -} - -// 创建一个简化的启动脚本来测试修复 -function createTestStartScript() { - try { - const testScriptPath = path.join(__dirname, 'test-fix.js'); - const testScriptContent = ` -console.log('=== 测试API修复结果 ==='); -console.log('\n请运行以下命令启动应用进行测试:'); -console.log('npm start'); -console.log('\n如果仍然有问题,请检查控制台错误信息。'); -console.log('如果需要恢复原始文件,可以运行:'); -console.log('node restore-api.js'); -`; - fs.writeFileSync(testScriptPath, testScriptContent); - console.log(`✅ 已创建测试脚本: ${testScriptPath}`); - } catch (error) { - console.error('❌ 创建测试脚本失败:', error.message); - } -} - -// 执行修复 -async function runFix() { - const apiFixed = await fixApiFile(); - - if (apiFixed) { - createTestStartScript(); - console.log('\n=== 修复完成 ==='); - console.log('修复内容:'); - console.log('1. 确保findAvailablePort函数正确实现和调用'); - console.log('2. 优化了错误处理逻辑'); - console.log('3. 增强了端口检测的稳定性'); - console.log('\n请重新启动应用测试修复效果。'); - } else { - console.log('\n=== 修复失败 ==='); - console.log('请手动检查api.js文件。'); - } -} - -runFix(); \ No newline at end of file diff --git a/test/fix-electron-routes.js b/test/fix-electron-routes.js deleted file mode 100644 index 3a46f3ce..00000000 --- a/test/fix-electron-routes.js +++ /dev/null @@ -1,326 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -console.log('=== Electron路由修复工具 ==='); - -// 修复Layout.js中的菜单点击处理函数 -function fixLayoutMenuClick() { - console.log('\n1. 修复Layout.js菜单点击处理函数...'); - try { - const layoutPath = path.join(__dirname, 'src/renderer/components/Layout.js'); - if (fs.existsSync(layoutPath)) { - let content = fs.readFileSync(layoutPath, 'utf8'); - - // 查找现有的handleMenuClick函数 - const oldFunction = `function handleMenuClick({ key }) { - console.log('菜单点击:', key); - try { - navigate(key); - console.log('导航成功到:', key); - } catch (error) { - console.error('导航失败:', error); - // 直接使用window.location作为备选方案 - window.location.href = key; - } - }`; - - // 新的增强版函数 - const newFunction = `function handleMenuClick({ key }) { - console.log('菜单点击:', key); - - // 在Electron环境中使用更可靠的导航方式 - try { - // 首先尝试使用React Router导航 - navigate(key); - console.log('React Router导航成功到:', key); - } catch (routerError) { - console.error('React Router导航失败:', routerError); - - // 如果React Router失败,尝试使用window.location - try { - // 对于相对路径,确保在Electron环境中正确处理 - if (key.startsWith('/')) { - // 在Electron中,我们需要使用hash模式或者特殊处理 - const baseUrl = window.location.origin + window.location.pathname; - const newUrl = baseUrl.replace(/\\/[^\\/]*$/, '') + '#' + key; - window.location.hash = key; - } else { - window.location.href = key; - } - console.log('备用导航方式成功'); - } catch (locationError) { - console.error('备用导航方式也失败了:', locationError); - // 最后的备选方案 - window.location.reload(); - } - } - }`; - - // 替换函数 - if (content.includes(oldFunction)) { - content = content.replace(oldFunction, newFunction); - fs.writeFileSync(layoutPath, content, 'utf8'); - console.log(' ✅ Layout.js菜单点击处理函数已修复'); - } else { - console.log(' ⚠️ 未找到预期的handleMenuClick函数,可能已被修改'); - } - } else { - console.log(' ❌ Layout.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 修复Layout.js失败:', error); - } -} - -// 修复App.js中的路由配置 -function fixAppRouting() { - console.log('\n2. 修复App.js路由配置...'); - try { - const appPath = path.join(__dirname, 'src/renderer/App.js'); - if (fs.existsSync(appPath)) { - let content = fs.readFileSync(appPath, 'utf8'); - - // 检查是否已经使用HashRouter - if (!content.includes('HashRouter')) { - // 替换BrowserRouter为HashRouter - content = content.replace(/BrowserRouter/g, 'HashRouter'); - - // 更新导入语句 - if (content.includes("import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';")) { - content = content.replace( - "import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';", - "import { HashRouter as Router, Routes, Route } from 'react-router-dom';" - ); - } else if (content.includes("import { BrowserRouter, Routes, Route } from 'react-router-dom';")) { - content = content.replace( - "import { BrowserRouter, Routes, Route } from 'react-router-dom';", - "import { HashRouter, Routes, Route } from 'react-router-dom';" - ); - } - - fs.writeFileSync(appPath, content, 'utf8'); - console.log(' ✅ App.js路由配置已修复,使用HashRouter'); - } else { - console.log(' ✅ App.js已使用HashRouter,无需修改'); - } - } else { - console.log(' ❌ App.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 修复App.js路由配置失败:', error); - } -} - -// 创建Electron环境下的路由助手 -function createRouteHelper() { - console.log('\n3. 创建Electron路由助手...'); - try { - const helperPath = path.join(__dirname, 'src/renderer/utils/electron-router.js'); - - // 确保utils目录存在 - const utilsDir = path.dirname(helperPath); - if (!fs.existsSync(utilsDir)) { - fs.mkdirSync(utilsDir, { recursive: true }); - } - - const helperContent = `/** - * Electron环境路由助手 - * 提供在Electron桌面应用中更可靠的路由导航功能 - */ - -/** - * 在Electron环境中安全地导航到指定路径 - * @param {string} path - 目标路径 - * @param {object} navigate - React Router的navigate函数 - */ -export function electronNavigate(path, navigate) { - console.log('Electron导航到:', path); - - try { - // 首先尝试使用React Router - if (navigate && typeof navigate === 'function') { - navigate(path); - console.log('React Router导航成功'); - return; - } - } catch (routerError) { - console.warn('React Router导航失败:', routerError); - } - - // 备用方案:使用window.location - try { - if (path.startsWith('/')) { - // 对于绝对路径,在Electron中使用hash模式 - window.location.hash = path; - } else { - // 相对路径直接跳转 - window.location.href = path; - } - console.log('备用导航方式成功'); - } catch (locationError) { - console.error('备用导航方式失败:', locationError); - // 最后方案:刷新页面 - window.location.reload(); - } -} - -/** - * 获取当前路由路径 - * @returns {string} 当前路径 - */ -export function getCurrentRoute() { - // 在Electron中,我们可能需要从hash中获取路径 - if (window.location.hash) { - return window.location.hash.substring(1); // 移除开头的# - } - return window.location.pathname; -} - -/** - * 初始化Electron路由环境 - */ -export function initElectronRouter() { - console.log('初始化Electron路由环境'); - - // 确保基础href设置正确 - let base = document.querySelector('base'); - if (!base) { - base = document.createElement('base'); - base.href = './'; - document.head.appendChild(base); - } - - // 监听路由变化 - window.addEventListener('hashchange', () => { - console.log('路由变化到:', window.location.hash); - }); -} - -export default { - electronNavigate, - getCurrentRoute, - initElectronRouter -};`; - - fs.writeFileSync(helperPath, helperContent, 'utf8'); - console.log(' ✅ Electron路由助手已创建'); - } catch (error) { - console.error(' ❌ 创建Electron路由助手失败:', error); - } -} - -// 更新Layout.js使用新的路由助手 -function updateLayoutWithHelper() { - console.log('\n4. 更新Layout.js使用路由助手...'); - try { - const layoutPath = path.join(__dirname, 'src/renderer/components/Layout.js'); - if (fs.existsSync(layoutPath)) { - let content = fs.readFileSync(layoutPath, 'utf8'); - - // 添加导入语句 - const importStatement = "import { electronNavigate } from '../utils/electron-router';"; - if (!content.includes(importStatement)) { - // 在其他导入语句之后添加 - content = content.replace( - "import { useNavigate, useLocation } from 'react-router-dom';", - "import { useNavigate, useLocation } from 'react-router-dom';\nimport { electronNavigate } from '../utils/electron-router';" - ); - } - - // 更新handleMenuClick函数 - const oldFunction = `function handleMenuClick({ key }) { - console.log('菜单点击:', key); - - // 在Electron环境中使用更可靠的导航方式 - try { - // 首先尝试使用React Router导航 - navigate(key); - console.log('React Router导航成功到:', key); - } catch (routerError) { - console.error('React Router导航失败:', routerError); - - // 如果React Router失败,尝试使用window.location - try { - // 对于相对路径,确保在Electron环境中正确处理 - if (key.startsWith('/')) { - // 在Electron中,我们需要使用hash模式或者特殊处理 - const baseUrl = window.location.origin + window.location.pathname; - const newUrl = baseUrl.replace(/\\/[^\\/]*$/, '') + '#' + key; - window.location.hash = key; - } else { - window.location.href = key; - } - console.log('备用导航方式成功'); - } catch (locationError) { - console.error('备用导航方式也失败了:', locationError); - // 最后的备选方案 - window.location.reload(); - } - } - }`; - - const newFunction = `function handleMenuClick({ key }) { - console.log('菜单点击:', key); - // 使用Electron路由助手进行导航 - electronNavigate(key, navigate); - }`; - - if (content.includes(oldFunction)) { - content = content.replace(oldFunction, newFunction); - fs.writeFileSync(layoutPath, content, 'utf8'); - console.log(' ✅ Layout.js已更新使用路由助手'); - } else { - console.log(' ⚠️ 未找到预期的handleMenuClick函数,可能已被修改'); - } - } else { - console.log(' ❌ Layout.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 更新Layout.js失败:', error); - } -} - -// 更新package.json添加构建脚本 -function updatePackageJson() { - console.log('\n5. 更新package.json...'); - try { - const packagePath = path.join(__dirname, 'package.json'); - if (fs.existsSync(packagePath)) { - const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf8')); - - // 添加Electron专用的构建脚本 - if (!packageData.scripts['build-electron']) { - packageData.scripts['build-electron'] = 'npm run build-renderer && npm run build-main'; - } - - // 确保homepage设置正确 - packageData.homepage = './'; - - fs.writeFileSync(packagePath, JSON.stringify(packageData, null, 2), 'utf8'); - console.log(' ✅ package.json已更新'); - } else { - console.log(' ❌ package.json文件不存在'); - } - } catch (error) { - console.error(' ❌ 更新package.json失败:', error); - } -} - -// 主函数 -function main() { - console.log('开始修复Electron环境中的路由问题...\n'); - - fixLayoutMenuClick(); - fixAppRouting(); - createRouteHelper(); - updateLayoutWithHelper(); - updatePackageJson(); - - console.log('\n=== 路由修复完成 ==='); - console.log('请重新构建并启动应用以使更改生效:'); - console.log(' 1. npm run build'); - console.log(' 2. npm start'); -} - -// 执行修复 -main(); \ No newline at end of file diff --git a/test/fix-menu.js b/test/fix-menu.js deleted file mode 100644 index 3364360a..00000000 --- a/test/fix-menu.js +++ /dev/null @@ -1,184 +0,0 @@ -/** - * 菜单功能修复脚本 - * 修复"启动收银台.bat"启动后菜单功能无法正常使用的问题 - */ - -const fs = require('fs'); -const path = require('path'); - -console.log('=== 菜单功能修复工具 ==='); - -// 修复Layout.js中的菜单点击处理函数 -function fixLayoutMenuClick() { - console.log('\n1. 修复Layout.js菜单点击处理函数...'); - try { - const layoutPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - if (fs.existsSync(layoutPath)) { - let content = fs.readFileSync(layoutPath, 'utf8'); - - // 备份原文件 - fs.writeFileSync(layoutPath + '.backup', content); - console.log(' ✅ 已备份原文件'); - - // 查找现有的handleMenuClick函数 - const oldFunction = `const handleMenuClick = ({ key }) => { - try { - // 使用electronNavigate处理导航 - electronNavigate(key, navigate); - } catch (error) { - console.error('菜单导航失败:', error); - } - };`; - - // 新的增强版函数 - const newFunction = `const handleMenuClick = ({ key }) => { - console.log('菜单点击:', key); - - try { - // 首先尝试使用electronNavigate处理导航 - if (typeof electronNavigate === 'function') { - electronNavigate(key, navigate); - console.log('通过electronNavigate导航成功'); - return; - } - } catch (error) { - console.warn('electronNavigate导航失败:', error); - } - - // 备用方案1: 直接使用React Router的navigate - try { - if (navigate && typeof navigate === 'function') { - navigate(key); - console.log('通过React Router导航成功'); - return; - } - } catch (error) { - console.warn('React Router导航失败:', error); - } - - // 备用方案2: 使用window.location.hash - try { - if (key.startsWith('/')) { - window.location.hash = key; - console.log('通过window.location.hash导航成功'); - return; - } - } catch (error) { - console.warn('window.location.hash导航失败:', error); - } - - // 最后的备选方案: 刷新页面 - console.error('所有导航方案都失败了,将刷新页面'); - window.location.reload(); - };`; - - // 替换函数 - if (content.includes(oldFunction)) { - content = content.replace(oldFunction, newFunction); - fs.writeFileSync(layoutPath, content, 'utf8'); - console.log(' ✅ Layout.js菜单点击处理函数已修复'); - } else { - console.log(' ⚠️ 未找到预期的handleMenuClick函数,可能已被修改'); - - // 尝试更通用的替换 - const genericPattern = /const handleMenuClick = \({ key }\) => {[\s\S]*?};/; - if (genericPattern.test(content)) { - content = content.replace(genericPattern, newFunction); - fs.writeFileSync(layoutPath, content, 'utf8'); - console.log(' ✅ Layout.js菜单点击处理函数已通过通用模式修复'); - } else { - console.log(' ❌ 无法定位handleMenuClick函数进行修复'); - } - } - } else { - console.log(' ❌ Layout.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 修复Layout.js失败:', error); - } -} - -// 修复App.js中的路由配置 -function fixAppRouting() { - console.log('\n2. 检查App.js路由配置...'); - try { - const appPath = path.join(__dirname, 'src', 'renderer', 'App.js'); - if (fs.existsSync(appPath)) { - let content = fs.readFileSync(appPath, 'utf8'); - - // 检查是否使用HashRouter - if (content.includes('HashRouter as Router')) { - console.log(' ✅ 已正确使用HashRouter'); - } else if (content.includes('BrowserRouter as Router')) { - console.log(' ⚠️ 使用了BrowserRouter,可能需要改为HashRouter'); - } else { - console.log(' ⚠️ 未明确使用HashRouter或BrowserRouter'); - } - - // 检查路由配置 - const routePattern = /} \/>/; - if (routePattern.test(content)) { - console.log(' ✅ 收银台路由配置正确'); - } else { - console.log(' ⚠️ 收银台路由配置可能存在问题'); - } - } else { - console.log(' ❌ App.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查App.js失败:', error); - } -} - -// 更新HTML模板,确保基础路径正确 -function updateHtmlTemplate() { - console.log('\n3. 检查HTML模板...'); - try { - const htmlPath = path.join(__dirname, 'src', 'renderer', 'index.html'); - if (fs.existsSync(htmlPath)) { - let content = fs.readFileSync(htmlPath, 'utf8'); - - // 检查base标签 - if (content.includes('')) { - console.log(' ✅ base标签已正确设置'); - } else { - // 添加base标签 - const headEndIndex = content.indexOf(''); - if (headEndIndex > 0) { - const baseTag = '\n \n'; - content = content.slice(0, headEndIndex) + baseTag + content.slice(headEndIndex); - fs.writeFileSync(htmlPath, content, 'utf8'); - console.log(' ✅ 已添加base标签'); - } else { - console.log(' ⚠️ 无法定位head标签,未添加base标签'); - } - } - } else { - console.log(' ❌ index.html文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查HTML模板失败:', error); - } -} - -// 主函数 -function main() { - console.log('开始修复菜单功能问题...\n'); - - fixLayoutMenuClick(); - fixAppRouting(); - updateHtmlTemplate(); - - console.log('\n=== 菜单功能修复完成 ==='); - console.log('修复内容:'); - console.log('1. 增强了Layout.js中的菜单点击处理函数,添加多重备选导航方案'); - console.log('2. 确保使用HashRouter以兼容Electron环境'); - console.log('3. 在HTML模板中添加了正确的base标签'); - console.log('\n请重新构建并启动应用以使更改生效:'); - console.log(' 1. npm run build'); - console.log(' 2. npm start'); - console.log('\n或者直接运行"启动收银台.bat"'); -} - -// 执行修复 -main(); \ No newline at end of file diff --git a/test/fix-navigation.js b/test/fix-navigation.js deleted file mode 100644 index c06b50ba..00000000 --- a/test/fix-navigation.js +++ /dev/null @@ -1,125 +0,0 @@ -console.log('=== 导航菜单修复工具 ==='); - -const fs = require('fs'); -const path = require('path'); - -// 修复Layout.js中的菜单导航问题 -function fixLayoutNavigation() { - console.log('\n1. 修复Layout.js菜单导航...'); - const layoutPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - - try { - // 读取Layout.js内容 - let content = fs.readFileSync(layoutPath, 'utf8'); - - // 确保handleMenuClick函数正确实现 - const oldHandleMenuClick = /function handleMenuClick\(\{ key \}\) \{[\s\S]*?navigate\(key\);[\s\S]*?\}/; - - if (oldHandleMenuClick.test(content)) { - const newHandleMenuClick = `function handleMenuClick({ key }) { - console.log('菜单点击:', key); - try { - navigate(key); - console.log('导航成功到:', key); - } catch (error) { - console.error('导航失败:', error); - // 直接使用window.location作为备选方案 - window.location.href = key; - } - }`; - - content = content.replace(oldHandleMenuClick, newHandleMenuClick); - console.log('✅ 已增强菜单点击处理函数'); - } - - // 确保Menu组件配置正确 - const oldMenuConfig = //, newMenuConfig); - console.log('✅ 已增强Menu组件配置'); - } - - // 备份并写入修复后的内容 - fs.writeFileSync(layoutPath + '.backup', fs.readFileSync(layoutPath, 'utf8')); - fs.writeFileSync(layoutPath, content); - console.log('✅ Layout.js修复完成'); - - } catch (error) { - console.error('❌ 修复Layout.js失败:', error.message); - } -} - -// 修复App.js中的路由配置 -function fixAppRoutes() { - console.log('\n2. 修复App.js路由配置...'); - const appPath = path.join(__dirname, 'src', 'renderer', 'App.js'); - - try { - // 确保路由配置正确 - let content = fs.readFileSync(appPath, 'utf8'); - - // 增强错误处理和调试 - const oldRenderTryBlock = /try \{[\s\S]*?return \([\s\S]*?/; - - if (oldRenderTryBlock.test(content)) { - const debugInfo = `// 添加路由调试 - console.log('渲染路由配置'); - window.__routesDebug = { - user: mockUser, - location: window.location.pathname, - timestamp: new Date().toISOString() - };`; - - // 在return前添加调试信息 - content = content.replace('return (\n ', `${debugInfo}\n return (\n `); - console.log('✅ 已添加路由调试信息'); - } - - fs.writeFileSync(appPath + '.fix-backup', fs.readFileSync(appPath, 'utf8')); - fs.writeFileSync(appPath, content); - console.log('✅ App.js修复完成'); - - } catch (error) { - console.error('❌ 修复App.js失败:', error.message); - } -} - -// 创建一个简单的启动脚本来测试修复 -function createTestScript() { - try { - const testScriptContent = ` -@echo off -chcp 65001 -cd %~dp0 -echo 测试导航菜单修复... -echo 请按F12打开开发者工具,查看控制台输出 -npm start -pause -`; - - fs.writeFileSync(path.join(__dirname, 'test-navigation.bat'), testScriptContent); - console.log('✅ 已创建测试脚本: test-navigation.bat'); - - } catch (error) { - console.error('❌ 创建测试脚本失败:', error.message); - } -} - -// 主函数 -function runFix() { - console.log('开始修复导航菜单问题...'); - fixLayoutNavigation(); - fixAppRoutes(); - createTestScript(); - - console.log('\n=== 修复完成 ==='); - console.log('1. 已增强菜单点击处理函数,添加错误处理和备选导航方案'); - console.log('2. 已优化Menu组件配置'); - console.log('3. 已添加详细的调试日志'); - console.log('\n请运行 test-navigation.bat 测试修复效果'); - console.log('修复思路: 增强导航错误处理,添加备选方案,便于调试'); -} - -runFix(); \ No newline at end of file diff --git a/test/system-test.js b/test/system-test.js deleted file mode 100644 index 5a6df41a..00000000 --- a/test/system-test.js +++ /dev/null @@ -1,174 +0,0 @@ -import { productService } from '../src/renderer/services'; -import { orderService } from '../src/renderer/services'; -import { authService } from '../src/renderer/services'; - -// 模拟测试环境 -const setupTestEnvironment = () => { - // 模拟localStorage - const localStorageMock = { - getItem: jest.fn(), - setItem: jest.fn(), - removeItem: jest.fn(), - clear: jest.fn(), - }; - global.localStorage = localStorageMock; - - // 模拟fetch - global.fetch = jest.fn(); - - // 设置默认用户信息 - const mockUser = { - id: 1, - username: 'admin', - name: '管理员', - role: 'admin' - }; - - localStorageMock.getItem.mockImplementation((key) => { - if (key === 'userInfo') { - return JSON.stringify(mockUser); - } - return null; - }); -}; - -// 测试API连接 -const testApiConnection = async () => { - console.log('测试API连接...'); - try { - const commonPorts = [3000, 3001, 3002, 9876, 8080]; - - for (const port of commonPorts) { - try { - const response = await fetch(`http://localhost:${port}/api/health`, { - method: 'GET', - signal: AbortSignal.timeout(1000) - }); - if (response.ok) { - console.log(`✅ API连接成功,端口: ${port}`); - return port; - } - } catch (error) { - // 端口不可用,继续尝试下一个 - } - } - - console.error('❌ 无法连接到API服务器'); - return null; - } catch (error) { - console.error('❌ API连接测试失败:', error); - return null; - } -}; - -// 测试认证功能 -const testAuth = async () => { - console.log('测试认证功能...'); - try { - // 测试登录 - const loginData = await authService.login('admin', 'admin123'); - if (loginData && loginData.id) { - console.log('✅ 用户登录功能正常'); - } else { - console.error('❌ 用户登录功能异常'); - } - - // 测试获取当前用户 - const currentUser = authService.getCurrentUser(); - if (currentUser) { - console.log('✅ 获取当前用户功能正常'); - } else { - console.error('❌ 获取当前用户功能异常'); - } - } catch (error) { - console.error('❌ 认证测试失败:', error); - } -}; - -// 测试商品功能 -const testProducts = async () => { - console.log('测试商品功能...'); - try { - // 测试获取商品列表 - const products = await productService.getProducts(); - if (products && Array.isArray(products.data)) { - console.log(`✅ 商品列表获取成功,共 ${products.data.length} 个商品`); - - // 测试获取商品分类 - const categories = await productService.getCategories(); - if (categories && Array.isArray(categories)) { - console.log(`✅ 商品分类获取成功,共 ${categories.length} 个分类`); - } else { - console.error('❌ 商品分类获取失败'); - } - } else { - console.error('❌ 商品列表获取失败'); - } - } catch (error) { - console.error('❌ 商品功能测试失败:', error); - } -}; - -// 测试订单功能 -const testOrders = async () => { - console.log('测试订单功能...'); - try { - // 测试获取订单列表 - const orders = await orderService.getOrders(); - if (orders && Array.isArray(orders.data)) { - console.log(`✅ 订单列表获取成功,共 ${orders.data.length} 个订单`); - } else { - console.error('❌ 订单列表获取失败'); - } - - // 测试获取挂单列表 - const heldOrders = await orderService.getHeldOrders(); - if (heldOrders && Array.isArray(heldOrders)) { - console.log(`✅ 挂单列表获取成功,共 ${heldOrders.length} 个挂单`); - } else { - console.error('❌ 挂单列表获取失败'); - } - } catch (error) { - console.error('❌ 订单功能测试失败:', error); - } -}; - -// 运行所有测试 -const runTests = async () => { - console.log('开始迷你收银台系统功能测试...\n'); - - setupTestEnvironment(); - - // 测试API连接 - const apiPort = await testApiConnection(); - if (!apiPort) { - console.error('\n❌ API连接失败,无法继续测试'); - return; - } - - console.log('\n'); - - // 测试各项功能 - await testAuth(); - await testProducts(); - await testOrders(); - - console.log('\n测试完成'); -}; - -// 如果直接运行此文件,执行测试 -if (require.main === module) { - runTests().catch(error => { - console.error('测试执行失败:', error); - process.exit(1); - }); -} - -module.exports = { - setupTestEnvironment, - testApiConnection, - testAuth, - testProducts, - testOrders, - runTests -}; \ No newline at end of file diff --git a/test/test-api.js b/test/test-api.js deleted file mode 100644 index b9492cd6..00000000 --- a/test/test-api.js +++ /dev/null @@ -1,59 +0,0 @@ -const http = require('http'); - -// 测试获取所有设置 -console.log('Testing GET /api/settings'); -const getSettingsReq = http.get('http://localhost:3002/api/settings', (res) => { - let data = ''; - res.on('data', (chunk) => { - data += chunk; - }); - res.on('end', () => { - console.log('GET /api/settings response:', data); - }); -}); - -getSettingsReq.on('error', (err) => { - console.error('GET /api/settings error:', err.message); -}); - -// 测试创建订单 -console.log('Testing POST /api/orders'); -const orderData = JSON.stringify({ - "items": [ - { - "product_id": 1, - "quantity": 2, - "unit_price": 10.00 - } - ], - "total_amount": 20.00, - "paid_amount": 20.00, - "payment_method": "cash", - "cashier_id": 1 -}); - -const postOrderReq = http.request({ - hostname: 'localhost', - port: 3002, - path: '/api/orders', - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(orderData) - } -}, (res) => { - let data = ''; - res.on('data', (chunk) => { - data += chunk; - }); - res.on('end', () => { - console.log('POST /api/orders response:', data); - }); -}); - -postOrderReq.on('error', (err) => { - console.error('POST /api/orders error:', err.message); -}); - -postOrderReq.write(orderData); -postOrderReq.end(); \ No newline at end of file diff --git a/test/test-cash-payment.js b/test/test-cash-payment.js deleted file mode 100644 index d3cc08ea..00000000 --- a/test/test-cash-payment.js +++ /dev/null @@ -1,61 +0,0 @@ -const axios = require('axios'); - -// 使用服务器实际运行的端口(根据netstat检查结果,服务器在3000端口运行) -const API_BASE_URL = 'http://localhost:3000/api'; - -// 模拟现金支付的订单数据 -const orderData = { - items: [ - { - product_id: 1, - quantity: 2, - price: 10.00 - } - ], - total_amount: 20.00, - payment_method: 'cash', - received_amount: 25.00, - change: 5.00 -}; - -async function testCashPayment() { - console.log('开始测试现金支付流程...'); - - try { - // 发送创建订单请求 - console.log('正在发送现金支付订单请求...'); - console.log('请求URL:', `${API_BASE_URL}/orders`); - console.log('请求数据:', JSON.stringify(orderData, null, 2)); - - const response = await axios.post(`${API_BASE_URL}/orders`, orderData); - - console.log('订单创建成功:'); - console.log('订单ID:', response.data.id); - console.log('订单总额:', response.data.total_amount); - console.log('支付方式:', response.data.payment_method); - - console.log('\n请检查钱箱是否已打开。如果钱箱正常打开,说明功能工作正常。'); - console.log('如果钱箱未打开,请检查以下几点:'); - console.log('1. 钱箱是否正确连接到电脑'); - console.log('2. 钱箱连接的串口是否正确配置'); - console.log('3. 钱箱是否处于可用状态'); - - } catch (error) { - console.error('测试过程中出现错误:'); - console.error('错误类型:', error.constructor.name); - - if (error.response) { - console.error('状态码:', error.response.status); - console.error('响应头:', JSON.stringify(error.response.headers, null, 2)); - console.error('响应数据:', JSON.stringify(error.response.data, null, 2)); - } else if (error.request) { - console.error('请求信息:', error.request); - console.error('请检查服务器是否正在运行'); - } else { - console.error('错误信息:', error.message); - } - } -} - -// 运行测试 -testCashPayment(); \ No newline at end of file diff --git a/test/test-checkout.js b/test/test-checkout.js deleted file mode 100644 index c6e8d1a1..00000000 --- a/test/test-checkout.js +++ /dev/null @@ -1,56 +0,0 @@ -const axios = require('axios'); - -// API基础URL - 使用正确的端口 -const API_BASE_URL = 'http://localhost:3001/api'; - -console.log('开始测试现金支付流程...'); - -// 测试数据 -const orderData = { - items: [ - { - product_id: 1, - quantity: 2 - } - ], - payment_method: 'cash', - paid_amount: 10, - cashier_id: 1 -}; - -console.log('准备创建订单:', orderData); - -// 创建订单 -axios.post(`${API_BASE_URL}/orders`, orderData) - .then(response => { - console.log('订单创建成功:', response.data); - - // 检查响应数据 - if (response.data && response.data.id) { - console.log(`订单ID: ${response.data.id}`); - console.log(`订单总额: ${response.data.total_amount}`); - console.log(`支付方式: ${response.data.payment_method}`); - - console.log('现金支付测试完成'); - } else { - console.error('订单创建响应格式不正确:', response.data); - } - }) - .catch(error => { - console.error('订单创建失败:'); - - if (error.response) { - // 服务器响应了错误状态码 - console.error('错误状态:', error.response.status); - console.error('错误数据:', error.response.data); - console.error('响应头:', error.response.headers); - } else if (error.request) { - // 请求已发出但没有收到响应 - console.error('无响应:', error.request); - } else { - // 其他错误 - console.error('错误信息:', error.message); - } - - console.error('错误配置:', error.config); - }); \ No newline at end of file diff --git a/test/test-create-order.js b/test/test-create-order.js deleted file mode 100644 index e8b61001..00000000 --- a/test/test-create-order.js +++ /dev/null @@ -1,31 +0,0 @@ -const axios = require('axios'); - -async function testCreateOrder() { - try { - const response = await axios.post('http://localhost:3001/api/orders', { - items: [ - { - product_id: 1, - quantity: 2 - } - ], - total_amount: 7.00, - paid_amount: 7.00, - payment_method: 'cash' - }, { - headers: { - 'Content-Type': 'application/json' - } - }); - - console.log('Order created successfully:', response.data); - } catch (error) { - if (error.response) { - console.error('Error creating order:', error.response.status, error.response.data); - } else { - console.error('Error creating order:', error.message); - } - } -} - -testCreateOrder(); \ No newline at end of file diff --git a/test/test-fix.js b/test/test-fix.js deleted file mode 100644 index 39273daf..00000000 --- a/test/test-fix.js +++ /dev/null @@ -1,9 +0,0 @@ - -console.log('=== 测试API修复结果 ==='); -console.log(' -请运行以下命令启动应用进行测试:'); -console.log('npm start'); -console.log(' -如果仍然有问题,请检查控制台错误信息。'); -console.log('如果需要恢复原始文件,可以运行:'); -console.log('node restore-api.js'); diff --git a/test/test-full-checkout.js b/test/test-full-checkout.js deleted file mode 100644 index 30d9ccdc..00000000 --- a/test/test-full-checkout.js +++ /dev/null @@ -1,71 +0,0 @@ -const axios = require('axios'); -const fs = require('fs'); -const path = require('path'); - -// 读取服务器端口 -function getServerPort() { - try { - const portFile = path.join(__dirname, 'data', 'server-port.json'); - if (fs.existsSync(portFile)) { - const portData = JSON.parse(fs.readFileSync(portFile, 'utf8')); - return portData.port || 3001; - } - } catch (error) { - console.log('读取端口文件失败:', error.message); - } - return 3001; -} - -async function testFullCheckout() { - const port = getServerPort(); - const baseURL = `http://localhost:${port}/api`; - - console.log('开始测试完整结账流程...'); - console.log('服务器地址:', baseURL); - - try { - // 1. 登录获取用户信息 - console.log('\n1. 尝试登录...'); - const loginResponse = await axios.post(`${baseURL}/cashiers/login`, { - username: 'cashier1', - password: 'cashier123' - }); - - console.log('登录成功:', loginResponse.data); - const userInfo = loginResponse.data; - - // 2. 创建订单 - console.log('\n2. 创建订单...'); - const orderData = { - items: [ - { - product_id: 1, - quantity: 2 - } - ], - payment_method: 'cash', - cashier_id: userInfo.id, - paid_amount: 20, - discount_amount: 0 - }; - - console.log('订单数据:', JSON.stringify(orderData, null, 2)); - - const orderResponse = await axios.post(`${baseURL}/orders`, orderData); - console.log('订单创建成功:', orderResponse.data); - - console.log('\n测试完成!'); - } catch (error) { - console.error('\n测试失败:'); - if (error.response) { - console.error('响应状态:', error.response.status); - console.error('响应数据:', error.response.data); - } else if (error.request) { - console.error('请求失败:', error.message); - } else { - console.error('错误:', error.message); - } - } -} - -testFullCheckout(); \ No newline at end of file diff --git a/test/test-ipc-message.js b/test/test-ipc-message.js deleted file mode 100644 index c016418d..00000000 --- a/test/test-ipc-message.js +++ /dev/null @@ -1,19 +0,0 @@ -// 测试服务器进程向主进程发送消息的功能 -console.log('测试服务器进程向主进程发送消息...'); - -// 检查是否有process.send方法 -if (process.send) { - console.log('process.send方法存在,尝试发送测试消息...'); - - // 发送测试消息 - process.send({ type: 'TEST_MESSAGE', data: '这是一条测试消息' }); - console.log('测试消息已发送'); - - // 发送OPEN_CASH_DRAWER消息 - process.send({ type: 'OPEN_CASH_DRAWER' }); - console.log('OPEN_CASH_DRAWER消息已发送'); -} else { - console.log('process.send方法不存在,当前环境不支持向父进程发送消息'); -} - -console.log('测试脚本执行完毕'); \ No newline at end of file diff --git a/test/test-logger.js b/test/test-logger.js deleted file mode 100644 index 138c0630..00000000 --- a/test/test-logger.js +++ /dev/null @@ -1,17 +0,0 @@ -const logger = require('./src/server/utils/logger'); - -console.log('开始测试新的日志系统...\n'); - -// 测试不同级别的日志 -logger.debug('这是一个调试信息', { timestamp: new Date().toISOString() }); -logger.info('这是一个普通信息', { user: 'test', action: 'login' }); -logger.warn('这是一个警告信息', { issue: '低库存', product: '可口可乐' }); -logger.error('这是一个错误信息', { error: '数据库连接失败', code: 500 }); - -console.log('\n日志测试完成!'); -console.log('请检查 data/logs 目录下的日志文件:'); -console.log('- error-YYYY-MM-DD.log (错误日志)'); -console.log('- warn-YYYY-MM-DD.log (警告日志)'); -console.log('- info-YYYY-MM-DD.log (信息日志)'); -console.log('- debug-YYYY-MM-DD.log (调试日志)'); -console.log('- combined-YYYY-MM-DD.log (综合日志)'); \ No newline at end of file diff --git a/test/test-menu-fix.js b/test/test-menu-fix.js deleted file mode 100644 index 6065dcdf..00000000 --- a/test/test-menu-fix.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * 菜单功能修复验证脚本 - */ - -const fs = require('fs'); -const path = require('path'); - -console.log('=== 菜单功能修复验证 ==='); - -// 检查Layout.js修复结果 -function checkLayoutFix() { - console.log('\n1. 检查Layout.js修复结果...'); - try { - const layoutPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - if (fs.existsSync(layoutPath)) { - const content = fs.readFileSync(layoutPath, 'utf8'); - - // 检查是否包含增强的错误处理 - if (content.includes('console.log(\'菜单点击:\', key)')) { - console.log(' ✅ 菜单点击处理函数已增强'); - } else { - console.log(' ⚠️ 菜单点击处理函数可能未正确修复'); - } - - // 检查多重备选方案 - if (content.includes('window.location.hash = key')) { - console.log(' ✅ 已添加window.location.hash备选方案'); - } else { - console.log(' ⚠️ 未找到window.location.hash备选方案'); - } - - // 检查是否包含最后的备选方案 - if (content.includes('window.location.reload()')) { - console.log(' ✅ 已添加页面刷新备选方案'); - } else { - console.log(' ⚠️ 未找到页面刷新备选方案'); - } - } else { - console.log(' ❌ Layout.js文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查Layout.js失败:', error); - } -} - -// 检查HTML模板 -function checkHtmlTemplate() { - console.log('\n2. 检查HTML模板...'); - try { - const htmlPath = path.join(__dirname, 'src', 'renderer', 'index.html'); - if (fs.existsSync(htmlPath)) { - const content = fs.readFileSync(htmlPath, 'utf8'); - - if (content.includes('')) { - console.log(' ✅ base标签已正确设置'); - } else { - console.log(' ⚠️ base标签可能未正确设置'); - } - } else { - console.log(' ❌ index.html文件不存在'); - } - } catch (error) { - console.error(' ❌ 检查HTML模板失败:', error); - } -} - -// 检查备份文件 -function checkBackup() { - console.log('\n3. 检查备份文件...'); - try { - const backupPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js.backup'); - if (fs.existsSync(backupPath)) { - console.log(' ✅ 已创建备份文件'); - } else { - console.log(' ⚠️ 未找到备份文件'); - } - } catch (error) { - console.error(' ❌ 检查备份文件失败:', error); - } -} - -// 主函数 -function main() { - console.log('开始验证菜单功能修复...\n'); - - checkLayoutFix(); - checkHtmlTemplate(); - checkBackup(); - - console.log('\n=== 验证完成 ==='); - console.log('如果所有检查都通过✅,菜单功能应该可以正常工作。'); - console.log('如果有任何⚠️,建议重新运行修复脚本。'); - console.log('\n接下来请运行"启动收银台.bat"测试菜单功能。'); -} - -// 执行验证 -main(); \ No newline at end of file diff --git a/test/test-menu-navigation.js b/test/test-menu-navigation.js deleted file mode 100644 index 76acea45..00000000 --- a/test/test-menu-navigation.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * 菜单导航功能测试脚本 - * 用于验证Electron环境中菜单点击是否正常工作 - */ - -console.log('=== 菜单导航功能测试 ==='); - -// 测试函数 -function runTests() { - console.log('\n开始测试...'); - - // 测试1: 检查必要的函数和对象是否存在 - console.log('\n1. 检查必要组件:'); - if (typeof window.electronNavigate === 'function') { - console.log(' ✅ electronNavigate函数存在'); - } else { - console.log(' ❌ electronNavigate函数不存在'); - } - - if (window.location) { - console.log(' ✅ window.location对象存在'); - } else { - console.log(' ❌ window.location对象不存在'); - } - - // 测试2: 模拟菜单点击 - console.log('\n2. 模拟菜单点击测试:'); - try { - // 模拟点击收银台菜单 - console.log(' 模拟点击收银台菜单...'); - const cashierEvent = { key: '/cashier' }; - - // 如果electronNavigate存在,使用它进行测试 - if (typeof window.electronNavigate === 'function') { - console.log(' 使用electronNavigate进行导航测试...'); - // 这里只是测试函数调用,不实际导航 - console.log(' ✅ electronNavigate可以被调用'); - } else { - console.log(' ⚠️ electronNavigate不存在,跳过测试'); - } - } catch (error) { - console.error(' ❌ 模拟菜单点击测试失败:', error); - } - - // 测试3: 检查当前路由 - console.log('\n3. 检查当前路由:'); - try { - const currentPath = window.location.hash || window.location.pathname; - console.log(` 当前路径: ${currentPath}`); - - if (currentPath.includes('cashier')) { - console.log(' ✅ 当前在收银台页面'); - } else { - console.log(' ℹ️ 当前不在收银台页面'); - } - } catch (error) { - console.error(' ❌ 检查当前路由失败:', error); - } - - // 测试4: 检查菜单组件 - console.log('\n4. 检查菜单组件:'); - try { - // 查找菜单元素 - const menuElements = document.querySelectorAll('.ant-menu-item'); - console.log(` 找到 ${menuElements.length} 个菜单项`); - - if (menuElements.length > 0) { - console.log(' ✅ 菜单组件已正确渲染'); - - // 检查第一个菜单项 - const firstMenuItem = menuElements[0]; - console.log(` 第一个菜单项文本: ${firstMenuItem.textContent.trim()}`); - - // 检查是否有点击事件监听器 - const clickListeners = getEventListeners(firstMenuItem, 'click'); - if (clickListeners && clickListeners.length > 0) { - console.log(' ✅ 菜单项有点击事件监听器'); - } else { - console.log(' ⚠️ 菜单项可能没有点击事件监听器'); - } - } else { - console.log(' ❌ 未找到菜单组件'); - } - } catch (error) { - console.error(' ❌ 检查菜单组件失败:', error); - } - - console.log('\n=== 测试完成 ==='); - console.log('如果所有测试都通过✅,菜单导航应该正常工作。'); - console.log('如果有任何⚠️或❌,可能需要进一步检查。'); -} - -// 辅助函数:获取元素的事件监听器(仅在Chrome DevTools中可用) -function getEventListeners(element, eventType) { - // 这个函数在普通JavaScript环境中不可用,仅在开发者工具中可用 - // 我们提供一个模拟实现 - if (typeof window.getEventListeners !== 'undefined') { - try { - return window.getEventListeners(element)[eventType] || []; - } catch (error) { - return []; - } - } - return []; // 在普通环境中返回空数组 -} - -// 延迟执行测试,确保页面完全加载 -setTimeout(() => { - runTests(); -}, 2000); - -// 导出函数供其他地方使用 -if (typeof module !== 'undefined') { - module.exports = { runTests }; -} \ No newline at end of file diff --git a/test/test-menu.js b/test/test-menu.js deleted file mode 100644 index 30842526..00000000 --- a/test/test-menu.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * 菜单功能测试脚本 - */ -console.log('=== 菜单功能测试 ==='); - -// 检查必要的组件和函数 -console.log('\n1. 检查必要组件:'); -console.log('window.location:', window.location); -console.log('window.electronNavigate:', typeof window.electronNavigate); - -// 检查React Router相关函数 -console.log('\n2. 检查React Router:'); -console.log('useNavigate hook:', typeof useNavigate); -console.log('useLocation hook:', typeof useLocation); - -// 检查菜单项 -console.log('\n3. 检查菜单项:'); -const menuItems = [ - { key: '/cashier', label: '收银台' }, - { key: '/products', label: '商品管理' }, - { key: '/orders', label: '订单管理' }, - { key: '/reports', label: '报表统计' }, - { key: '/settings', label: '系统设置' } -]; - -console.log('菜单项配置:', menuItems); - -// 模拟菜单点击测试 -console.log('\n4. 模拟菜单点击测试:'); -try { - menuItems.forEach(item => { - console.log(` 测试导航到: ${item.key} (${item.label})`); - // 这里只是模拟,不实际执行导航 - console.log(` 可以通过以下方式手动测试:`); - console.log(` - window.location.hash = '${item.key}'`); - console.log(` - navigate('${item.key}') (如果在React组件中)`); - }); -} catch (error) { - console.error(' 测试失败:', error); -} - -console.log('\n=== 测试完成 ==='); -console.log('请在浏览器控制台中运行此脚本以查看详细信息。'); \ No newline at end of file diff --git a/test/test-navigation.bat b/test/test-navigation.bat deleted file mode 100644 index a822147a..00000000 --- a/test/test-navigation.bat +++ /dev/null @@ -1,24 +0,0 @@ - -@echo off -chcp 65001 > nul -echo === 迷你收银台导航测试 === -echo. - -echo 正在启动收银台应用... -echo 请在应用启动后执行以下测试: -echo 1. 点击左侧菜单项(收银台、商品管理等) -echo 2. 检查是否能正常切换页面 -echo 3. 查看开发者工具控制台是否有错误信息 -echo. - -echo 按任意键启动应用... -pause > nul - -echo 启动应用... -npm start - -echo. -echo 测试完成。如果仍有问题,请检查以下内容: -echo 1. 开发者工具控制台是否有错误信息 (Ctrl+Shift+I 打开) -echo 2. 确保所有依赖包已正确安装 (npm install) -echo 3. 检查端口是否被占用 diff --git a/test/test-navigation.js b/test/test-navigation.js deleted file mode 100644 index ef69b4b4..00000000 --- a/test/test-navigation.js +++ /dev/null @@ -1,67 +0,0 @@ -// 测试导航功能的脚本 -const fs = require('fs'); -const path = require('path'); - -console.log('=== 导航功能测试 ==='); - -// 检查关键文件是否存在 -const filesToCheck = [ - './src/renderer/utils/electron-router.js', - './src/renderer/components/Layout.js', - './src/renderer/App.js' -]; - -console.log('\n1. 检查关键文件:'); -filesToCheck.forEach(file => { - const fullPath = path.join(__dirname, file); - if (fs.existsSync(fullPath)) { - console.log(`✅ ${file} 存在`); - } else { - console.log(`❌ ${file} 不存在`); - } -}); - -// 检查App.js是否正确导入和初始化electron-router -console.log('\n2. 检查App.js中的electron-router初始化:'); -try { - const appJsPath = path.join(__dirname, 'src', 'renderer', 'App.js'); - const appJsContent = fs.readFileSync(appJsPath, 'utf8'); - - if (appJsContent.includes('import { initElectronRouter }')) { - console.log('✅ 正确导入了initElectronRouter'); - } else { - console.log('❌ 未找到initElectronRouter导入'); - } - - if (appJsContent.includes('initElectronRouter()')) { - console.log('✅ 正确调用了initElectronRouter()'); - } else { - console.log('❌ 未找到initElectronRouter()调用'); - } -} catch (error) { - console.log('❌ 检查App.js时出错:', error.message); -} - -// 检查Layout.js中的导航处理 -console.log('\n3. 检查Layout.js中的导航处理:'); -try { - const layoutJsPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - const layoutJsContent = fs.readFileSync(layoutJsPath, 'utf8'); - - if (layoutJsContent.includes('electronNavigate')) { - console.log('✅ Layout.js中使用了electronNavigate'); - } else { - console.log('❌ Layout.js中未使用electronNavigate'); - } - - if (layoutJsContent.includes('handleMenuClick')) { - console.log('✅ 找到handleMenuClick函数'); - } else { - console.log('❌ 未找到handleMenuClick函数'); - } -} catch (error) { - console.log('❌ 检查Layout.js时出错:', error.message); -} - -console.log('\n=== 测试完成 ==='); -console.log('如果所有检查都显示✅,则导航功能应该正常工作。'); \ No newline at end of file diff --git a/test/test-start.js b/test/test-start.js deleted file mode 100644 index 9a3ba2dc..00000000 --- a/test/test-start.js +++ /dev/null @@ -1,57 +0,0 @@ -// 简易启动脚本 - 直接启动主进程,避免依赖concurrently -const { spawn } = require('child_process'); -const path = require('path'); -const fs = require('fs'); - -console.log('迷你收银台系统 - 简易启动脚本'); -console.log('==============================\n'); - -// 确保数据目录存在 -const dataDir = path.join(__dirname, 'data'); -if (!fs.existsSync(dataDir)) { - console.log('创建数据目录...'); - fs.mkdirSync(dataDir, { recursive: true }); -} - -// 启动应用 -console.log('正在启动收银台应用...'); - -// 添加更详细的调试信息 -console.log('\n======== 启动信息汇总 ========'); -console.log('- 启动时间:', new Date().toLocaleString()); -console.log('- 应用状态: 正在加载...'); -console.log('\n如需查看前端详细日志,请检查Electron开发者工具控制台'); -console.log('可以按Ctrl+Shift+I在应用窗口中打开开发者工具'); -console.log('===============================\n'); - -// 直接运行electron -const electronProcess = spawn( - path.join(__dirname, 'node_modules', '.bin', 'electron.cmd'), - ['.'], - { - cwd: __dirname, - stdio: 'inherit', - shell: true, - env: { ...process.env, DEBUG: 'electron:*' } - } -); - -// 定期检查应用状态 -const statusInterval = setInterval(() => { - console.log(`[${new Date().toLocaleTimeString()}] 应用正常运行中...`); -}, 30000); // 每30秒输出一次状态 - -electronProcess.on('close', (code) => { - console.log(`\n应用进程退出,代码: ${code}`); - if (code !== 0) { - console.log('\n应用启动失败,请尝试以下解决方案:'); - console.log('1. 删除node_modules文件夹并重新安装依赖'); - console.log('2. 以管理员身份运行启动脚本'); - console.log('3. 检查Node.js版本是否满足要求(14+)'); - } -}); - -electronProcess.on('error', (error) => { - console.error('\n启动失败:', error.message); - console.log('\n请检查electron是否正确安装,尝试运行: npm install electron'); -}); \ No newline at end of file diff --git a/test/verify-menu-function.js b/test/verify-menu-function.js deleted file mode 100644 index d987ef03..00000000 --- a/test/verify-menu-function.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * 菜单功能验证脚本 - * 用于验证菜单功能是否正常工作 - */ - -const fs = require('fs'); -const path = require('path'); - -console.log('=== 菜单功能验证 ===\n'); - -// 验证Layout.js文件 -function verifyLayoutJS() { - console.log('1. 验证 Layout.js 文件...'); - - try { - const layoutPath = path.join(__dirname, 'src', 'renderer', 'components', 'Layout.js'); - const content = fs.readFileSync(layoutPath, 'utf8'); - - // 检查关键功能点 - const hasConsoleLog = content.includes("console.log('菜单点击:', key)"); - const hasElectronNavigate = content.includes('electronNavigate(key, navigate)'); - const hasWindowLocationHash = content.includes('window.location.hash = key'); - const hasWindowReload = content.includes('window.location.reload()'); - - console.log(` 日志输出: ${hasConsoleLog ? '✅' : '❌'}`); - console.log(` Electron导航: ${hasElectronNavigate ? '✅' : '❌'}`); - console.log(` Hash导航: ${hasWindowLocationHash ? '✅' : '❌'}`); - console.log(` 页面刷新: ${hasWindowReload ? '✅' : '❌'}`); - - if (hasConsoleLog && hasElectronNavigate && hasWindowLocationHash && hasWindowReload) { - console.log(' 结论: Layout.js 菜单处理函数已正确修复\n'); - return true; - } else { - console.log(' 结论: Layout.js 菜单处理函数存在问题\n'); - return false; - } - } catch (error) { - console.error(' 错误:', error.message); - console.log(' 结论: 无法验证 Layout.js 文件\n'); - return false; - } -} - -// 验证启动脚本 -function verifyStartupScript() { - console.log('2. 验证 启动脚本...'); - - try { - const batPath = path.join(__dirname, '启动收银台.bat'); - const content = fs.readFileSync(batPath, 'utf8'); - - // 检查关键环境变量 - const hasLogging = content.includes('ELECTRON_ENABLE_LOGGING=1'); - const hasMenuBar = content.includes('ELECTRON_FORCE_WINDOW_MENU_BAR=1'); - const hasNodeEnv = content.includes('NODE_ENV=production'); - const hasAutoBuild = content.includes('if not exist "build\\index.html"'); - - console.log(` 日志设置: ${hasLogging ? '✅' : '❌'}`); - console.log(` 菜单栏设置: ${hasMenuBar ? '✅' : '❌'}`); - console.log(` 环境变量: ${hasNodeEnv ? '✅' : '❌'}`); - console.log(` 自动构建: ${hasAutoBuild ? '✅' : '❌'}`); - - if (hasLogging && hasMenuBar && hasNodeEnv && hasAutoBuild) { - console.log(' 结论: 启动脚本已正确增强\n'); - return true; - } else { - console.log(' 结论: 启动脚本存在问题\n'); - return false; - } - } catch (error) { - console.error(' 错误:', error.message); - console.log(' 结论: 无法验证启动脚本\n'); - return false; - } -} - -// 验证构建文件 -function verifyBuildFiles() { - console.log('3. 验证 构建文件...'); - - const indexPath = path.join(__dirname, 'build', 'index.html'); - const mainJsPath = path.join(__dirname, 'build', 'js', 'main.js'); - - const hasIndexHtml = fs.existsSync(indexPath); - const hasMainJs = fs.existsSync(mainJsPath); - - console.log(` index.html: ${hasIndexHtml ? '✅' : '❌'}`); - console.log(` main.js: ${hasMainJs ? '✅' : '❌'}`); - - if (hasIndexHtml && hasMainJs) { - console.log(' 结论: 构建文件存在\n'); - return true; - } else { - console.log(' 结论: 构建文件缺失\n'); - return false; - } -} - -// 主函数 -function main() { - console.log('开始验证菜单功能修复...\n'); - - const layoutOk = verifyLayoutJS(); - const startupOk = verifyStartupScript(); - const buildOk = verifyBuildFiles(); - - console.log('=== 验证结果 ==='); - if (layoutOk && startupOk && buildOk) { - console.log('🎉 所有验证通过!菜单功能应该可以正常使用。'); - console.log('\n现在您可以:'); - console.log('1. 双击 "启动收银台.bat" 启动应用'); - console.log('2. 点击左侧菜单项测试功能'); - console.log('3. 如仍有问题,请查看 "最终使用说明.md" 获取更多帮助'); - } else { - console.log('❌ 部分验证失败,请检查上述标记为❌的项目。'); - console.log('\n建议操作:'); - console.log('1. 运行 "npm run build" 重新构建项目'); - console.log('2. 查看 "MENU_FIX_README.md" 获取技术细节'); - console.log('3. 查看 "最终使用说明.md" 获取使用指导'); - } -} - -main(); \ No newline at end of file