From 6c0693d160b4b6e710289f9663babbf324871831 Mon Sep 17 00:00:00 2001 From: seagull Date: Sat, 12 Sep 2026 02:32:25 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=84=E5=BD=95A=E5=85=A8=E6=8E=A5=E5=85=A5:?= =?UTF-8?q?7=E6=96=B0=E9=A1=B5=E9=9D=A2+=E8=B7=AF=E7=94=B1=E8=8F=9C?= =?UTF-8?q?=E5=8D=95+=E5=BA=93=E5=AD=98=E5=A4=A7=E7=9B=98=E6=8A=BD?= =?UTF-8?q?=E5=B1=89=20/=20P1-2=E7=9C=9F=E6=9C=BA=E9=9D=9E=E6=B3=95?= =?UTF-8?q?=E5=80=BC=E6=8B=A6=E6=88=AA=E5=85=A8=E7=BB=BF=20/=20=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=BB=88=E7=89=88510+514?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PROGRESS_AGI_ITERATION_6.md | 28 +++- README.md | 2 +- frontend/src/layouts/MainLayout.vue | 7 + frontend/src/pages/Accounts.vue | 80 ++++++++++++ frontend/src/pages/AlertRules.vue | 158 +++++++++++++++++++++++ frontend/src/pages/Allocations.vue | 62 +++++++++ frontend/src/pages/Dashboard.vue | 38 +++++- frontend/src/pages/Movements.vue | 69 ++++++++++ frontend/src/pages/PriceLevels.vue | 149 +++++++++++++++++++++ frontend/src/pages/PrintTemplates.vue | 137 ++++++++++++++++++++ frontend/src/pages/ReportDefinitions.vue | 91 +++++++++++++ frontend/src/router/index.js | 7 + 12 files changed, 820 insertions(+), 8 deletions(-) create mode 100644 frontend/src/pages/Accounts.vue create mode 100644 frontend/src/pages/AlertRules.vue create mode 100644 frontend/src/pages/Allocations.vue create mode 100644 frontend/src/pages/Movements.vue create mode 100644 frontend/src/pages/PriceLevels.vue create mode 100644 frontend/src/pages/PrintTemplates.vue create mode 100644 frontend/src/pages/ReportDefinitions.vue diff --git a/PROGRESS_AGI_ITERATION_6.md b/PROGRESS_AGI_ITERATION_6.md index 8c3f338..1f13d52 100644 --- a/PROGRESS_AGI_ITERATION_6.md +++ b/PROGRESS_AGI_ITERATION_6.md @@ -82,17 +82,35 @@ seed_demo/demo 幂等兜底、两个测试侧 membership 修补、exceptions 去 补 `rules`(平台/店铺ID/店铺名必填,App Key 留空合法)+ 保存前 validate。 5. **文档数字**:README PG 口径 `499` → `514`(实跑)。 -## 最终验证(2026-09-12) +## 本轮新增(2026-09-12 续-3 · 附录 A #3–#10 全接入 + P1-2 真机验证) + +7 个新页面(路由+菜单已接线,构建 ✅ 6.37s): + +| # | 页面 | 路由 | 后端接口 | 真机数据 | +|---|---|---|---|---| +| 3 | 核销记录 `Allocations.vue`(只读) | `/finance/allocations` | `GET /finance/allocations/` | 30 行 | +| 4 | 库存流水 `Movements.vue`(只读) | `/stocks/movements` | `GET /inventory/movements/` | 50 行 | +| 5 | 预警规则 `AlertRules.vue`(CRUD+开关+init-default) | `/notify/rules` | `/notify/rules/` + `init-default` | 4 行 | +| 6 | 打印模板 `PrintTemplates.vue`(CRUD) | `/printing/templates` | `/printing/templates/` | 空态 200 ✅ | +| 7 | 自定义报表 `ReportDefinitions.vue`(init-system+run) | `/report/definitions` | `definitions/` + `init-system` + `run` | 空态 200 ✅ | +| 8 | 库存大盘 | Dashboard 库存卡片点击 → 明细抽屉 | `/report/dashboard/inventory-status/` | 2 仓/30734 件/¥131,509.92 | +| 9 | 科目管理 `Accounts.vue`(init-chart+启用开关) | `/finance/accounts` | `/finance/accounts/` + `init-chart` | 空态 200 ✅ | +| 10 | 价格等级/联系人 `PriceLevels.vue`(等级 CRUD + 联系人只读) | `/partner/price-levels` | `price-levels/` + `contacts/` | 空态 200 ✅ | + +P1-2 Playwright 真机(dev :18099 + demo 租户,0 console errors): +空提交被拦——Vouchers(请输入摘要)/ AlertRules(编码+名称)/ Channel(店铺ID+店铺名), +dialog 不关闭;抽屉字段曾与后端键名错位(`by_warehouse` vs 实际 `warehouses`/ +`grand_total_*`),已按实测键修好并复验出真数据。 + +## 最终验证(2026-09-12 终版) - 后端 SQLite:**510 passed / 4 skipped**(PG 专用并发用例) - 后端 PostgreSQL 5433:**514 passed / 0 skipped** -- 前端:`npm run build` ✅ 6.50s;`npm test` ✅ 11/11 +- 前端:`npm run build` ✅ 6.37s;`npm test` ✅ 11/11 - `manage.py check` 0 issues;`makemigrations --check` No changes -- Playwright Register 真机:空/非法被拦、合法 201 跳 dashboard、0 console errors +- Playwright:Register 空/非法被拦、合法 201 跳 dashboard;9 页渲染全过;3 页空提交被拦;抽屉真数据;全程 0 console errors ## 遗留(诚实记录) -- §附录 A #4–#10(库存流水/预警规则/打印模板/自定义报表/库存大盘/科目管理/价格等级页) - 仍是后端有、前端无——超出本轮 27 条真源范围,未动。 - P2-2 部署 readiness gate + 上线 192.168.5.7:需 Docker/服务器凭证,未动。 - P2-3/D2 移动开单、P3-1 行业专版:按客户驱动,未动。 diff --git a/README.md b/README.md index cf94813..1c1410e 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ python manage.py seed_full_finance ## 当前阶段 -**AGI 迭代基线(2026-09-12)**:进销存、财务、商城和扩展模块已形成可运行闭环,当前本地回归为 **509 passed / 4 skipped(SQLite)**,**513 passed(PostgreSQL 5433,含 4 并发用例)**,前端 `npm run build` ✅ + `npm test` ✅ 11/11(见 `PROGRESS_AGI_ITERATION_6.md`)。 +**AGI 迭代基线(2026-09-12)**:进销存、财务、商城和扩展模块已形成可运行闭环,当前本地回归为 **510 passed / 4 skipped(SQLite)**,**514 passed(PostgreSQL 5433,含 4 并发用例)**,前端 `npm run build` ✅ + `npm test` ✅ 11/11。附录 A 后端 10 项能力前端已全接入(收款/付款/核销/流水/预警规则/打印模板/自定义报表/库存大盘/科目/价格等级联系人),见 `PROGRESS_AGI_ITERATION_6.md`。 - ✅ Django + DRF + adrf + Granian 异步链路打通 - ✅ 多租户数据过滤、JWT 鉴权与审计日志 diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index ab3f66d..c1390eb 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -16,6 +16,7 @@ 商品中心 客户档案 库存查询 + 库存流水 批次效期 销售开单 采购开单 @@ -26,11 +27,17 @@ 应收账款 应付账款 财务报表 + 核销记录 + 科目管理 电商渠道 + 价格等级与联系人 消息预警 + 预警规则 + 打印模板 + 自定义报表 开放平台 套餐与用量 操作轨迹 diff --git a/frontend/src/pages/Accounts.vue b/frontend/src/pages/Accounts.vue new file mode 100644 index 0000000..8524fb5 --- /dev/null +++ b/frontend/src/pages/Accounts.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/frontend/src/pages/AlertRules.vue b/frontend/src/pages/AlertRules.vue new file mode 100644 index 0000000..ea4bb98 --- /dev/null +++ b/frontend/src/pages/AlertRules.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/frontend/src/pages/Allocations.vue b/frontend/src/pages/Allocations.vue new file mode 100644 index 0000000..213f63e --- /dev/null +++ b/frontend/src/pages/Allocations.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/frontend/src/pages/Dashboard.vue b/frontend/src/pages/Dashboard.vue index 94dfd63..e92d484 100644 --- a/frontend/src/pages/Dashboard.vue +++ b/frontend/src/pages/Dashboard.vue @@ -16,8 +16,8 @@ - -
库存资产估值
+ +
库存资产估值(点击看仓库明细)
¥ {{ fmt(inventory.valuation) }}
{{ inventory.sku_count }} 个 SKU / {{ fmt(inventory.total_quantity) }} 件
@@ -150,6 +150,25 @@ 提问 + + + +
+ + {{ inventoryDetail.grand_total_quantity ?? '—' }} + ¥ {{ fmt(inventoryDetail.grand_total_valuation) }} + {{ (inventoryDetail.warehouses || []).length }} + + + + + + + + + +
+
@@ -197,6 +216,21 @@ const purchase = computed(() => summary.value.month_purchase || {}) const inventory = computed(() => summary.value.inventory || {}) const finance = computed(() => summary.value.finance || {}) +// ---- 库存状态大盘明细(#8 inventory-status:各仓库分布与资产估值)---- +const inventoryDrawer = ref(false) +const inventoryDetail = ref({}) +const inventoryDetailLoading = ref(false) + +async function showInventoryDetail() { + inventoryDrawer.value = true + inventoryDetailLoading.value = true + try { + inventoryDetail.value = await api.get('/report/dashboard/inventory-status/') + } catch (e) { inventoryDetail.value = {} } finally { + inventoryDetailLoading.value = false + } +} + const levelMap = { high: '高风险', medium: '中风险', low: '低风险' } const levelText = (l) => levelMap[l] || l diff --git a/frontend/src/pages/Movements.vue b/frontend/src/pages/Movements.vue new file mode 100644 index 0000000..9926b17 --- /dev/null +++ b/frontend/src/pages/Movements.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/frontend/src/pages/PriceLevels.vue b/frontend/src/pages/PriceLevels.vue new file mode 100644 index 0000000..d1d9ceb --- /dev/null +++ b/frontend/src/pages/PriceLevels.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/frontend/src/pages/PrintTemplates.vue b/frontend/src/pages/PrintTemplates.vue new file mode 100644 index 0000000..d8a3b6b --- /dev/null +++ b/frontend/src/pages/PrintTemplates.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/frontend/src/pages/ReportDefinitions.vue b/frontend/src/pages/ReportDefinitions.vue new file mode 100644 index 0000000..d0b9f6a --- /dev/null +++ b/frontend/src/pages/ReportDefinitions.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index bef99db..ee70f7d 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -15,6 +15,7 @@ const routes = [ { path: 'products', name: 'products', component: () => import('../pages/Products.vue'), meta: { title: '商品中心' } }, { path: 'customers', name: 'customers', component: () => import('../pages/Customers.vue'), meta: { title: '客户档案' } }, { path: 'stocks', name: 'stocks', component: () => import('../pages/Stocks.vue'), meta: { title: '库存查询' } }, + { path: 'stocks/movements', name: 'movements', component: () => import('../pages/Movements.vue'), meta: { title: '库存流水' } }, { path: 'batches', name: 'batches', component: () => import('../pages/Batches.vue'), meta: { title: '批次效期' } }, { path: 'sales-bills', name: 'salesBills', component: () => import('../pages/SalesBills.vue'), meta: { title: '销售开单' } }, { path: 'purchase-bills', name: 'purchaseBills', component: () => import('../pages/PurchaseBills.vue'), meta: { title: '采购开单' } }, @@ -22,8 +23,14 @@ const routes = [ { path: 'finance/receivables', name: 'receivables', component: () => import('../pages/Receivables.vue'), meta: { title: '应收账款' } }, { path: 'finance/payables', name: 'payables', component: () => import('../pages/Payables.vue'), meta: { title: '应付账款' } }, { path: 'finance/reports', name: 'financeReports', component: () => import('../pages/FinanceReports.vue'), meta: { title: '财务报表' } }, + { path: 'finance/allocations', name: 'allocations', component: () => import('../pages/Allocations.vue'), meta: { title: '核销记录' } }, + { path: 'finance/accounts', name: 'accounts', component: () => import('../pages/Accounts.vue'), meta: { title: '科目管理' } }, { path: 'channel', name: 'channel', component: () => import('../pages/Channel.vue'), meta: { title: '电商渠道' } }, { path: 'notify', name: 'notify', component: () => import('../pages/Notify.vue'), meta: { title: '消息预警' } }, + { path: 'notify/rules', name: 'alertRules', component: () => import('../pages/AlertRules.vue'), meta: { title: '预警规则' } }, + { path: 'printing/templates', name: 'printTemplates', component: () => import('../pages/PrintTemplates.vue'), meta: { title: '打印模板' } }, + { path: 'report/definitions', name: 'reportDefinitions', component: () => import('../pages/ReportDefinitions.vue'), meta: { title: '自定义报表' } }, + { path: 'partner/price-levels', name: 'priceLevels', component: () => import('../pages/PriceLevels.vue'), meta: { title: '价格等级与联系人' } }, { path: 'openapi-keys', name: 'openapiKeys', component: () => import('../pages/OpenApiKeys.vue'), meta: { title: '开放平台' } }, { path: 'billing', name: 'billing', component: () => import('../pages/Billing.vue'), meta: { title: '套餐与用量' } }, { path: 'audit-logs', name: 'auditLogs', component: () => import('../pages/AuditLogs.vue'), meta: { title: '操作轨迹' } },