From 7e2246fec56e15b47cfce65583ddcec8a70cce5b Mon Sep 17 00:00:00 2001 From: comlibmb <1844410276@qq.com> Date: Wed, 11 Feb 2026 16:59:38 +0800 Subject: [PATCH] feat(admin): full integration of order, product, and finance modules with real RPC data streams --- ...10__admin__product-module-repaired-full.md | 41 + ...11__admin__finance-module-repaired-full.md | 48 ++ docs/sql/10_schema/finance/ml_extract_v1.sql | 39 + docs/sql/10_schema/finance/ml_invoices_v1.sql | 36 + .../sql/10_schema/finance/ml_user_bill_v1.sql | 33 + .../10_schema/finance/ml_user_recharge_v1.sql | 32 + docs/sql/20_rls/finance/ml_extract_rls_v1.sql | 20 + .../sql/20_rls/finance/ml_invoices_rls_v1.sql | 19 + .../20_rls/finance/ml_user_bill_rls_v1.sql | 19 + .../finance/ml_user_recharge_rls_v1.sql | 19 + .../rpc_admin_balance_distribution_v1.sql | 78 ++ .../finance/rpc_admin_balance_stats_v1.sql | 48 ++ .../finance/rpc_admin_balance_trend_v1.sql | 46 ++ .../rpc_admin_finance_bill_summary_v1.sql | 56 ++ .../finance/rpc_admin_finance_overview_v1.sql | 72 ++ .../finance/rpc_admin_invoice_list_v1.sql | 93 +++ .../finance/rpc_admin_invoice_process_v1.sql | 45 + .../rpc_admin_product_analytics_v1.sql | 28 +- .../rpc_admin_product_count_stats_v1.sql | 38 + .../product/rpc_admin_product_trend_v1.sql | 44 + pages/mall/admin/finance/balance_record.uvue | 347 +++++--- pages/mall/admin/finance/balance_stats.uvue | 86 +- pages/mall/admin/finance/bill.uvue | 271 ++---- pages/mall/admin/finance/capital_flow.uvue | 354 ++++---- pages/mall/admin/finance/commission.uvue | 502 +++++------- pages/mall/admin/finance/invoice.uvue | 526 ++++++------ pages/mall/admin/finance/recharge.uvue | 380 +++++---- .../mall/admin/finance/transaction_stats.uvue | 772 ++++-------------- pages/mall/admin/finance/withdrawal.uvue | 207 +++-- .../product/product-management/index.uvue | 105 +-- .../product/product-statistics/index.uvue | 168 ++-- services/admin/financeService.uts | 15 + services/admin/productService.uts | 41 + 33 files changed, 2535 insertions(+), 2093 deletions(-) create mode 100644 docs/ops/2026-02-10__admin__product-module-repaired-full.md create mode 100644 docs/ops/2026-02-11__admin__finance-module-repaired-full.md create mode 100644 docs/sql/10_schema/finance/ml_extract_v1.sql create mode 100644 docs/sql/10_schema/finance/ml_invoices_v1.sql create mode 100644 docs/sql/10_schema/finance/ml_user_bill_v1.sql create mode 100644 docs/sql/10_schema/finance/ml_user_recharge_v1.sql create mode 100644 docs/sql/20_rls/finance/ml_extract_rls_v1.sql create mode 100644 docs/sql/20_rls/finance/ml_invoices_rls_v1.sql create mode 100644 docs/sql/20_rls/finance/ml_user_bill_rls_v1.sql create mode 100644 docs/sql/20_rls/finance/ml_user_recharge_rls_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_balance_distribution_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_balance_stats_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_balance_trend_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_finance_bill_summary_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_finance_overview_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_invoice_list_v1.sql create mode 100644 docs/sql/30_rpc/finance/rpc_admin_invoice_process_v1.sql create mode 100644 docs/sql/30_rpc/product/rpc_admin_product_count_stats_v1.sql create mode 100644 docs/sql/30_rpc/product/rpc_admin_product_trend_v1.sql diff --git a/docs/ops/2026-02-10__admin__product-module-repaired-full.md b/docs/ops/2026-02-10__admin__product-module-repaired-full.md new file mode 100644 index 00000000..c7c35b3c --- /dev/null +++ b/docs/ops/2026-02-10__admin__product-module-repaired-full.md @@ -0,0 +1,41 @@ +# 商品模块全量修复与统计补全报告 + +## 摘要 +本次对 Admin 商品模块进行了深度的端到端修复,重点解决了商品管理页面的搜索筛选失效、状态统计缺失以及商品统计页面的全量 Mock 问题。补齐了配套的后端 RPC 接口,并重构了前端 Service 与 UI 逻辑。 + +## 修复范围 + +### 1. 商品管理页 (Product Management) +- **搜索功能真实化**:接入了分类选择器数据,绑定了搜索关键字,实现了按名称、分类、状态的联动查询。 +- **状态统计同步**:接入了各状态商品数量汇总 RPC,确保 Tab 上的“出售中”、“仓库中”等数量真实准确。 +- **交互完善**:补全了分页翻页逻辑、状态开关(上架/下架)以及逻辑删除(回收站)的操作反馈。 + +### 2. 商品统计页 (Product Statistics) +- **数据源迁移**:彻底移除硬编码的静态数组,将 KPI 卡片、ECharts 趋势图及排行表格全部对接真实 RPC 数据流。 +- **动态图表**:趋势图现在能反映真实的浏览量、访客数及支付金额变化。 +- **全维度排行**:商品排行表支持加购、收藏、订单数、支付额及转化率的综合展示。 + +### 3. 商品分类页 (Classify) +- **代码核对**:确认已符合 RPC 访问规范,支持树形结构的 CRUD 与状态管理。 + +## 变更清单 + +### 数据库 / RPC (SQL) +- `docs/sql/30_rpc/product/rpc_admin_product_count_stats_v1.sql` (新增):商品状态汇总统计。 +- `docs/sql/30_rpc/product/rpc_admin_product_trend_v1.sql` (新增):商品营业趋势统计。 +- `docs/sql/30_rpc/product/rpc_admin_product_analytics_v1.sql` (升级):增强商品概况指标与全维度排行逻辑。 + +### 前端代码 +- `services/admin/productService.uts`:补齐了 stats/trend/ranking/counts 等 fetch 方法。 +- `pages/mall/admin/product/product-management/index.uvue`:重构逻辑与模板绑定。 +- `pages/mall/admin/product/product-statistics/index.uvue`:重构数据加载与图表驱动逻辑。 + +## 验证说明 +1. **数据库执行**:需依次执行 `docs/sql/30_rpc/product/` 下新增及修改的 SQL 脚本。 +2. **功能验证**: + - 进入商品管理:确认搜索栏分类可选,点击查询后列表及 Tab 数量能正确刷新。 + - 进入商品统计:确认顶部 6 个指标不再是固定值,折线图与饼图有动态交互。 + +## 关联规范 +- 遵循 `AGENT_PROJECT_SPEC.md` 关于 Admin 侧通过 RPC 访问数据的要求。 +- 遵循 SQL 分层归档规范。 diff --git a/docs/ops/2026-02-11__admin__finance-module-repaired-full.md b/docs/ops/2026-02-11__admin__finance-module-repaired-full.md new file mode 100644 index 00000000..f3feb7e8 --- /dev/null +++ b/docs/ops/2026-02-11__admin__finance-module-repaired-full.md @@ -0,0 +1,48 @@ +# 财务模块全量修复与数据库构建报告 + +## 摘要 +本次对 Admin 侧财务模块进行了深度的端到端修复,完成了核心财务表(提现、充值、流水)的数据库构建、行级安全策略(RLS)配置、管理端 RPC 接口补全,以及前端 5 个核心页面的全量重构。彻底解决了财务数据展示依赖 Mock 的问题。 + +## 修复范围 + +### 1. 数据库构建 (Schema & RLS) +- **`ml_extract` (提现表)**:支持支付宝/微信/银行卡多渠道快照,补齐手续费、余额快照及审核流字段。 +- **`ml_user_recharge` (充值表)**:支持支付状态追踪、渠道类型及订单关联。 +- **`ml_user_bill` (资金流水表)**:统一收支原子日志,支持业务大类与细分类型筛选。 +- **RLS 策略**:为上述表配置了行级安全,确保普通用户仅能访问个人数据,Admin 侧通过 RPC 访问。 + +### 2. RPC 接口升级 (SECURITY DEFINER) +- **列表类**:补全了提现、充值、流水的管理端分页查询,支持复杂的名称/订单号/时间筛选。 +- **操作类**:补全了提现审核(通过/驳回)、充值审计逻辑。 +- **统计类**: + - `rpc_admin_finance_overview`:提供营业额、充值、提现等核心 KPI。 + - `rpc_admin_finance_bill_summary`:支持日/周/月维度的收支聚合。 + +### 3. 前端页面重构 +- **提现申请 (`withdrawal.uvue`)**:接入审核流逻辑,展示账号快照,实现实时统计更新。 +- **充值记录 (`recharge.uvue`)**:接入真实充值流水,对齐支付状态。 +- **资金流水 (`capital_flow.uvue`)**:接入原子流水展示,支持收支筛选。 +- **账单记录 (`bill.uvue`)**:基于周期聚合 RPC 实现动态账单切换。 +- **交易统计 (`transaction_stats.uvue`)**:接入真实 KPI 指标,动态驱动趋势折线图。 + +## 变更清单 + +### 数据库 SQL +- `docs/sql/10_schema/finance/`:`ml_extract_v1.sql`, `ml_user_recharge_v1.sql`, `ml_user_bill_v1.sql` +- `docs/sql/20_rls/finance/`:`ml_extract_rls_v1.sql`, `ml_user_recharge_rls_v1.sql`, `ml_user_bill_rls_v1.sql` +- `docs/sql/30_rpc/finance/`:补齐了 `rpc_admin_finance_overview_v1.sql`, `rpc_admin_finance_bill_summary_v1.sql` 等共 7 个接口。 + +### 前端代码 +- `services/admin/financeService.uts`:补全 DTO 结构与汇总统计方法。 +- `pages/mall/admin/finance/` 目录下 5 个 `.uvue` 文件的逻辑与 UI 重构。 + +## 验证说明 +1. **数据库执行**:需依次执行 `10_schema` -> `20_rls` -> `30_rpc` 下的财务脚本。 +2. **功能验证**: + - 进入财务统计:确认营业额等指标不再是固定值。 + - 提现审核:确认点击通过/驳回能真实联动数据库状态。 + - 筛选/分页:确认所有财务列表的分页与日期筛选均真实生效。 + +## 关联规范 +- 遵循 `AGENT_PROJECT_SPEC.md` 中关于 Admin 数据访问必须走 RPC 的要求。 +- 遵循 SQL 分层归档与版本管理规范。 diff --git a/docs/sql/10_schema/finance/ml_extract_v1.sql b/docs/sql/10_schema/finance/ml_extract_v1.sql new file mode 100644 index 00000000..15f08dda --- /dev/null +++ b/docs/sql/10_schema/finance/ml_extract_v1.sql @@ -0,0 +1,39 @@ +-- ===================================================================================== +-- Schema: 用户提现申请表 +-- 位置:docs/sql/10_schema/finance/ +-- 对象类型:Schema (DDL) +-- 版本:v1 +-- 说明:管理用户发起的提现申请(佣金/余额),支持多种提现方式及快照信息 +-- ===================================================================================== + +CREATE TABLE IF NOT EXISTS public.ml_extract ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + uid UUID NOT NULL REFERENCES public.ak_users(id), + + real_name TEXT NULL, -- 提现人姓名快照 + extract_type TEXT NOT NULL, -- 提现方式: alipay, wechat, bank + + -- 账号快照信息 + alipay_code TEXT NULL, -- 支付宝账号 + wechat_code TEXT NULL, -- 微信账号 + bank_code TEXT NULL, -- 银行卡号 + bank_address TEXT NULL, -- 开户行地址 + + extract_price DECIMAL(12,2) NOT NULL DEFAULT 0, -- 申请提现金额 + service_fee DECIMAL(12,2) NOT NULL DEFAULT 0, -- 提现手续费 + balance DECIMAL(12,2) NOT NULL DEFAULT 0, -- 提现时的余额快照 + + status SMALLINT NOT NULL DEFAULT 0, -- 状态: 0:待审核, 1:已通过, -1:已驳回 + refusal_reason TEXT NULL, -- 驳回原因 + + admin_id UUID NULL REFERENCES public.ak_users(id), -- 审核人ID + payment_time TIMESTAMPTZ NULL, -- 打款/到账时间 + + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- 索引 +CREATE INDEX IF NOT EXISTS ml_extract_uid_idx ON public.ml_extract (uid); +CREATE INDEX IF NOT EXISTS ml_extract_status_idx ON public.ml_extract (status); +CREATE INDEX IF NOT EXISTS ml_extract_created_at_idx ON public.ml_extract (created_at DESC); diff --git a/docs/sql/10_schema/finance/ml_invoices_v1.sql b/docs/sql/10_schema/finance/ml_invoices_v1.sql new file mode 100644 index 00000000..0864fa0b --- /dev/null +++ b/docs/sql/10_schema/finance/ml_invoices_v1.sql @@ -0,0 +1,36 @@ +-- ===================================================================================== +-- Schema: 发票管理表 +-- 位置:docs/sql/10_schema/finance/ml_invoices_v1.sql +-- 对象类型:Schema (DDL) +-- 版本:v1 +-- 说明:记录用户提交的开票申请及其处理状态 +-- ===================================================================================== + +CREATE TABLE IF NOT EXISTS public.ml_invoices ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + uid UUID NOT NULL REFERENCES public.ak_users(id), + order_no TEXT NOT NULL, -- 关联订单号 + + order_amount DECIMAL(12,2) NOT NULL, -- 订单金额 + + invoice_type SMALLINT NOT NULL DEFAULT 1, -- 1: 电子普通发票, 2: 增值税专用发票 + header_type SMALLINT NOT NULL DEFAULT 1, -- 1: 个人, 2: 企业 + + header_name TEXT NOT NULL, -- 发票抬头 + tax_id TEXT NULL, -- 企业税号 + + email TEXT NULL, -- 接收邮箱 + remark TEXT NULL, -- 备注 + + status SMALLINT NOT NULL DEFAULT 0, -- 0: 待开票, 1: 已开票, -1: 已拒绝 + refusal_reason TEXT NULL, -- 驳回原因 + invoice_url TEXT NULL, -- 电子发票文件路径/URL + + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- 索引 +CREATE INDEX IF NOT EXISTS ml_invoices_uid_idx ON public.ml_invoices (uid); +CREATE INDEX IF NOT EXISTS ml_invoices_order_no_idx ON public.ml_invoices (order_no); +CREATE INDEX IF NOT EXISTS ml_invoices_status_idx ON public.ml_invoices (status); diff --git a/docs/sql/10_schema/finance/ml_user_bill_v1.sql b/docs/sql/10_schema/finance/ml_user_bill_v1.sql new file mode 100644 index 00000000..f8442677 --- /dev/null +++ b/docs/sql/10_schema/finance/ml_user_bill_v1.sql @@ -0,0 +1,33 @@ +-- ===================================================================================== +-- Schema: 用户资金流水表 +-- 位置:docs/sql/10_schema/finance/ +-- 对象类型:Schema (DDL) +-- 版本:v1 +-- 说明:记录用户余额、积分、佣金的所有增减流水(原子日志) +-- ===================================================================================== + +CREATE TABLE IF NOT EXISTS public.ml_user_bill ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + uid UUID NOT NULL REFERENCES public.ak_users(id), + + link_id TEXT NULL, -- 关联业务ID(订单号、提现ID、充值ID等) + pm SMALLINT NOT NULL DEFAULT 1, -- 0:支出, 1:收入 + + title TEXT NOT NULL, -- 流水标题(如:商品购买、充值、提现) + category TEXT NOT NULL, -- 业务大类(如:balance-余额, integral-积分, brokerage-佣金) + type TEXT NOT NULL, -- 业务子类型(如:recharge, extract, pay, refund, system_add, system_sub) + + number DECIMAL(12,2) NOT NULL DEFAULT 0, -- 变动金额 + balance DECIMAL(12,2) NOT NULL DEFAULT 0, -- 变动后的余额快照 + + mark TEXT NULL, -- 备注 + status SMALLINT NOT NULL DEFAULT 1, -- 状态(1:有效, 0:无效/冲正) + + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- 常用查询索引 +CREATE INDEX IF NOT EXISTS ml_user_bill_uid_idx ON public.ml_user_bill (uid); +CREATE INDEX IF NOT EXISTS ml_user_bill_category_type_idx ON public.ml_user_bill (category, type); +CREATE INDEX IF NOT EXISTS ml_user_bill_created_at_idx ON public.ml_user_bill (created_at DESC); diff --git a/docs/sql/10_schema/finance/ml_user_recharge_v1.sql b/docs/sql/10_schema/finance/ml_user_recharge_v1.sql new file mode 100644 index 00000000..490202e5 --- /dev/null +++ b/docs/sql/10_schema/finance/ml_user_recharge_v1.sql @@ -0,0 +1,32 @@ +-- ===================================================================================== +-- Schema: 用户充值记录表 +-- 位置:docs/sql/10_schema/finance/ +-- 对象类型:Schema (DDL) +-- 版本:v1 +-- 说明:记录用户主动发起的充值申请及支付状态 +-- ===================================================================================== + +CREATE TABLE IF NOT EXISTS public.ml_user_recharge ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + uid UUID NOT NULL REFERENCES public.ak_users(id), + + order_no TEXT UNIQUE NOT NULL, -- 充值订单号(cz开头) + recharge_type TEXT NOT NULL, -- 充值渠道: wechat, alipay, system (后台补单) + + price DECIMAL(12,2) NOT NULL DEFAULT 0, -- 实际充值金额 + give_price DECIMAL(12,2) NOT NULL DEFAULT 0, -- 赠送金额 + + paid SMALLINT NOT NULL DEFAULT 0, -- 支付状态: 0:未支付, 1:已支付 + pay_time TIMESTAMPTZ NULL, -- 支付时间 + + channel_trade_no TEXT NULL, -- 外部渠道流水号 + status SMALLINT NOT NULL DEFAULT 1, -- 记录状态: 1:正常, 0:逻辑删除 + + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- 索引 +CREATE INDEX IF NOT EXISTS ml_user_recharge_uid_idx ON public.ml_user_recharge (uid); +CREATE INDEX IF NOT EXISTS ml_user_recharge_order_no_idx ON public.ml_user_recharge (order_no); +CREATE INDEX IF NOT EXISTS ml_user_recharge_created_at_idx ON public.ml_user_recharge (created_at DESC); diff --git a/docs/sql/20_rls/finance/ml_extract_rls_v1.sql b/docs/sql/20_rls/finance/ml_extract_rls_v1.sql new file mode 100644 index 00000000..7831493f --- /dev/null +++ b/docs/sql/20_rls/finance/ml_extract_rls_v1.sql @@ -0,0 +1,20 @@ +-- ===================================================================================== +-- RLS: 用户提现申请表 +-- 位置:docs/sql/20_rls/finance/ +-- 对象类型:RLS 策略 +-- 版本:v1 +-- 说明:仅允许用户查看自己的提现记录;管理端通过 RPC 访问 +-- ===================================================================================== + +ALTER TABLE public.ml_extract ENABLE ROW LEVEL SECURITY; + +-- 策略 1: 允许用户读取自己的提现申请 +DROP POLICY IF EXISTS ml_extract_user_select ON public.ml_extract; +CREATE POLICY ml_extract_user_select + ON public.ml_extract + FOR SELECT + TO authenticated + USING (uid = auth.uid()); + +-- 默认不开放 INSERT/UPDATE/DELETE 给普通用户 +-- 提现申请通常由特定的 RPC 函数 (security definer) 创建,以确保业务逻辑(如冻结余额)的原子性 diff --git a/docs/sql/20_rls/finance/ml_invoices_rls_v1.sql b/docs/sql/20_rls/finance/ml_invoices_rls_v1.sql new file mode 100644 index 00000000..e2418cf0 --- /dev/null +++ b/docs/sql/20_rls/finance/ml_invoices_rls_v1.sql @@ -0,0 +1,19 @@ +-- ===================================================================================== +-- RLS: 发票管理表 +-- 位置:docs/sql/20_rls/finance/ml_invoices_rls_v1.sql +-- 对象类型:RLS 策略 +-- 版本:v1 +-- 说明:用户仅能查看自己的开票申请;管理端通过 RPC 访问 +-- ===================================================================================== + +ALTER TABLE public.ml_invoices ENABLE ROW LEVEL SECURITY; + +-- 策略 1: 允许用户读取自己的记录 +DROP POLICY IF EXISTS ml_invoices_user_select ON public.ml_invoices; +CREATE POLICY ml_invoices_user_select + ON public.ml_invoices + FOR SELECT + TO authenticated + USING (uid = auth.uid()); + +-- 默认不开放 INSERT/UPDATE/DELETE 给普通用户,通常由 RPC 或支付后逻辑触发 diff --git a/docs/sql/20_rls/finance/ml_user_bill_rls_v1.sql b/docs/sql/20_rls/finance/ml_user_bill_rls_v1.sql new file mode 100644 index 00000000..c629fec9 --- /dev/null +++ b/docs/sql/20_rls/finance/ml_user_bill_rls_v1.sql @@ -0,0 +1,19 @@ +-- ===================================================================================== +-- RLS: 用户资金流水表 +-- 位置:docs/sql/20_rls/finance/ +-- 对象类型:RLS 策略 +-- 版本:v1 +-- 说明:仅允许用户查看自己的流水记录;管理端通过 RPC 访问 +-- ===================================================================================== + +ALTER TABLE public.ml_user_bill ENABLE ROW LEVEL SECURITY; + +-- 策略 1: 允许用户读取自己的记录 +DROP POLICY IF EXISTS ml_user_bill_user_select ON public.ml_user_bill; +CREATE POLICY ml_user_bill_user_select + ON public.ml_user_bill + FOR SELECT + TO authenticated + USING (uid = auth.uid()); + +-- 默认不开放 INSERT/UPDATE/DELETE 给普通用户,由后端逻辑或 RPC 触发 diff --git a/docs/sql/20_rls/finance/ml_user_recharge_rls_v1.sql b/docs/sql/20_rls/finance/ml_user_recharge_rls_v1.sql new file mode 100644 index 00000000..6ba7eaa9 --- /dev/null +++ b/docs/sql/20_rls/finance/ml_user_recharge_rls_v1.sql @@ -0,0 +1,19 @@ +-- ===================================================================================== +-- RLS: 用户充值记录表 +-- 位置:docs/sql/20_rls/finance/ +-- 对象类型:RLS 策略 +-- 版本:v1 +-- 说明:仅允许用户查看自己的充值记录;管理端通过 RPC 访问 +-- ===================================================================================== + +ALTER TABLE public.ml_user_recharge ENABLE ROW LEVEL SECURITY; + +-- 策略 1: 允许用户读取自己的记录 +DROP POLICY IF EXISTS ml_user_recharge_user_select ON public.ml_user_recharge; +CREATE POLICY ml_user_recharge_user_select + ON public.ml_user_recharge + FOR SELECT + TO authenticated + USING (uid = auth.uid()); + +-- 默认不开放 INSERT/UPDATE/DELETE 给普通用户,写操作通常由业务逻辑或支付回调触发 diff --git a/docs/sql/30_rpc/finance/rpc_admin_balance_distribution_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_balance_distribution_v1.sql new file mode 100644 index 00000000..f8776fc9 --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_balance_distribution_v1.sql @@ -0,0 +1,78 @@ +-- ===================================================================================== +-- Admin 财务统计 - 余额收支分布统计 RPC +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:按业务子类型统计指定时间范围内的余额收入与支出分布 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_balance_distribution( + p_start_time TIMESTAMP WITH TIME ZONE, + p_end_time TIMESTAMP WITH TIME ZONE +) +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_total_income DECIMAL(12,2); + v_total_expense DECIMAL(12,2); + v_income_items JSONB; + v_expense_items JSONB; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 计算总收入与总支出 + SELECT + COALESCE(SUM(number) FILTER (WHERE pm = 1), 0), + COALESCE(SUM(number) FILTER (WHERE pm = 0), 0) + INTO v_total_income, v_total_expense + FROM public.ml_user_bill + WHERE category = 'balance' + AND created_at >= p_start_time + AND created_at <= p_end_time + AND status = 1; + + -- 3. 统计收入分布 (来源分析) + SELECT jsonb_agg(t) INTO v_income_items + FROM ( + SELECT + type AS name, + SUM(number) AS value, + CASE WHEN v_total_income > 0 THEN ROUND(SUM(number) / v_total_income * 100, 2) ELSE 0 END AS percent + FROM public.ml_user_bill + WHERE category = 'balance' AND pm = 1 AND status = 1 + AND created_at >= p_start_time AND created_at <= p_end_time + GROUP BY type + ORDER BY value DESC + ) t; + + -- 4. 统计支出分布 (消耗分析) + SELECT jsonb_agg(t) INTO v_expense_items + FROM ( + SELECT + type AS name, + SUM(number) AS value, + CASE WHEN v_total_expense > 0 THEN ROUND(SUM(number) / v_total_expense * 100, 2) ELSE 0 END AS percent + FROM public.ml_user_bill + WHERE category = 'balance' AND pm = 0 AND status = 1 + AND created_at >= p_start_time AND created_at <= p_end_time + GROUP BY type + ORDER BY value DESC + ) t; + + RETURN jsonb_build_object( + 'income', COALESCE(v_income_items, '[]'::jsonb), + 'expense', COALESCE(v_expense_items, '[]'::jsonb) + ); +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_balance_distribution IS '统计财务余额收支来源与消耗分布'; diff --git a/docs/sql/30_rpc/finance/rpc_admin_balance_stats_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_balance_stats_v1.sql new file mode 100644 index 00000000..23b9eb40 --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_balance_stats_v1.sql @@ -0,0 +1,48 @@ +-- ===================================================================================== +-- Admin 财务统计 - 余额核心指标 RPC +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:获取全站当前余额存量、累计增加总额及累计消耗总额 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_balance_stats() +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_current_balance DECIMAL(12,2); + v_total_accumulation DECIMAL(12,2); + v_total_consumption DECIMAL(12,2); +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 统计当前全站用户余额总存量 + SELECT COALESCE(SUM(now_money), 0) INTO v_current_balance FROM public.ak_users; + + -- 3. 统计累计增加 (pm=1) 和 累计消耗 (pm=0) + -- 基于 ml_user_bill 表中 category='balance' 的记录 + SELECT + COALESCE(SUM(number) FILTER (WHERE pm = 1), 0), + COALESCE(SUM(number) FILTER (WHERE pm = 0), 0) + INTO v_total_accumulation, v_total_consumption + FROM public.ml_user_bill + WHERE category = 'balance' AND status = 1; + + RETURN jsonb_build_object( + 'current_balance', v_current_balance, + 'total_accumulation', v_total_accumulation, + 'total_consumption', v_total_consumption + ); +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_balance_stats IS '获取全站余额存量及累计收支汇总'; diff --git a/docs/sql/30_rpc/finance/rpc_admin_balance_trend_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_balance_trend_v1.sql new file mode 100644 index 00000000..7e627578 --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_balance_trend_v1.sql @@ -0,0 +1,46 @@ +-- ===================================================================================== +-- Admin 财务统计 - 余额收支趋势 RPC +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:按日聚合指定时间范围内的余额积累 (pm=1) 与 余额消耗 (pm=0) 趋势 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_balance_trend( + p_start_time TIMESTAMP WITH TIME ZONE, + p_end_time TIMESTAMP WITH TIME ZONE +) +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_items JSONB; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 按日聚合统计 + SELECT jsonb_agg(t) INTO v_items + FROM ( + SELECT + to_char(date_trunc('day', gs.day), 'YYYY-MM-DD') AS date_group, + COALESCE(SUM(number) FILTER (WHERE pm = 1 AND category = 'balance'), 0) AS accumulation, + COALESCE(SUM(number) FILTER (WHERE pm = 0 AND category = 'balance'), 0) AS consumption + FROM generate_series(date_trunc('day', p_start_time), date_trunc('day', p_end_time), '1 day'::interval) gs(day) + LEFT JOIN public.ml_user_bill b ON date_trunc('day', b.created_at) = gs.day AND b.status = 1 + GROUP BY gs.day + ORDER BY gs.day ASC + ) t; + + RETURN COALESCE(v_items, '[]'::jsonb); +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_balance_trend IS '按日聚合财务余额收支趋势'; diff --git a/docs/sql/30_rpc/finance/rpc_admin_finance_bill_summary_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_finance_bill_summary_v1.sql new file mode 100644 index 00000000..f633f5c6 --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_finance_bill_summary_v1.sql @@ -0,0 +1,56 @@ +-- ===================================================================================== +-- Admin 财务功能 - 账单汇总统计 RPC +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:按日/周/月维度聚合财务收支数据,支撑账单列表展示 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_finance_bill_summary( + p_start_time TIMESTAMP WITH TIME ZONE, + p_end_time TIMESTAMP WITH TIME ZONE, + p_interval TEXT DEFAULT 'day' -- day, week, month +) +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_items JSONB; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 聚合统计 + SELECT jsonb_agg(t) INTO v_items + FROM ( + SELECT + to_char(date_trunc(p_interval, created_at), + CASE + WHEN p_interval = 'day' THEN 'YYYY-MM-DD' + WHEN p_interval = 'week' THEN 'IYYY-IW' + ELSE 'YYYY-MM' + END + ) AS date_group, + SUM(number) FILTER (WHERE pm = 1) AS income, + SUM(number) FILTER (WHERE pm = 0) AS expense, + SUM(CASE WHEN pm = 1 THEN number ELSE -number END) AS net_entry + FROM public.ml_user_bill + WHERE created_at >= p_start_time + AND created_at <= p_end_time + AND status = 1 + GROUP BY date_trunc(p_interval, created_at) + ORDER BY date_trunc(p_interval, created_at) DESC + ) t; + + RETURN COALESCE(v_items, '[]'::jsonb); +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_finance_bill_summary IS '按周期聚合财务收支账单'; diff --git a/docs/sql/30_rpc/finance/rpc_admin_finance_overview_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_finance_overview_v1.sql new file mode 100644 index 00000000..d3109c3b --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_finance_overview_v1.sql @@ -0,0 +1,72 @@ +-- ===================================================================================== +-- Admin 财务功能 - 财务概况统计 RPC +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:获取指定时间段内的财务核心 KPI(营业额、充值汇总、提现汇总、资金存量) +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_finance_overview( + p_start_time TIMESTAMP WITH TIME ZONE, + p_end_time TIMESTAMP WITH TIME ZONE +) +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_recharge_amount DECIMAL(12,2); + v_recharge_count BIGINT; + v_extract_amount DECIMAL(12,2); + v_extract_count BIGINT; + v_total_user_balance DECIMAL(12,2); + v_total_user_brokerage DECIMAL(12,2); +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 统计充值 (仅统计已支付) + SELECT + COALESCE(SUM(price + give_price), 0), + COUNT(*) + INTO v_recharge_amount, v_recharge_count + FROM public.ml_user_recharge + WHERE paid = 1 + AND created_at >= p_start_time + AND created_at <= p_end_time; + + -- 3. 统计提现 (仅统计已通过) + SELECT + COALESCE(SUM(extract_price), 0), + COUNT(*) + INTO v_extract_amount, v_extract_count + FROM public.ml_extract + WHERE status = 1 + AND created_at >= p_start_time + AND created_at <= p_end_time; + + -- 4. 统计全站资金存量 (实时快照) + SELECT + COALESCE(SUM(now_money), 0), + COALESCE(SUM(brokerage_price), 0) + INTO v_total_user_balance, v_total_user_brokerage + FROM public.ak_users; + + RETURN jsonb_build_object( + 'recharge_amount', v_recharge_amount, + 'recharge_count', v_recharge_count, + 'extract_amount', v_extract_amount, + 'extract_count', v_extract_count, + 'total_user_balance', v_total_user_balance, + 'total_user_brokerage', v_total_user_brokerage + ); +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_finance_overview IS '财务核心 KPI 概况统计'; diff --git a/docs/sql/30_rpc/finance/rpc_admin_invoice_list_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_invoice_list_v1.sql new file mode 100644 index 00000000..0915a8a5 --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_invoice_list_v1.sql @@ -0,0 +1,93 @@ +-- ===================================================================================== +-- RPC: rpc_admin_invoice_list +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数 (SECURITY DEFINER) +-- 版本:v1 +-- 说明:管理端分页获取发票申请列表,支持搜索、状态筛选及时间过滤 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_invoice_list( + p_page INTEGER DEFAULT 1, + p_page_size INTEGER DEFAULT 15, + p_status SMALLINT DEFAULT NULL, + p_start_time TIMESTAMP WITH TIME ZONE DEFAULT NULL, + p_end_time TIMESTAMP WITH TIME ZONE DEFAULT NULL, + p_search TEXT DEFAULT NULL +) +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_offset INTEGER; + v_total BIGINT; + v_items JSONB; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + v_offset := (p_page - 1) * p_page_size; + + -- 2. 获取总数 + SELECT COUNT(*) INTO v_total + FROM public.ml_invoices i + LEFT JOIN public.ak_users u ON u.id = i.uid + WHERE (p_status IS NULL OR i.status = p_status) + AND (p_start_time IS NULL OR i.created_at >= p_start_time) + AND (p_end_time IS NULL OR i.created_at <= p_end_time) + AND (p_search IS NULL OR ( + i.order_no ILIKE '%' || p_search || '%' OR + i.header_name ILIKE '%' || p_search || '%' OR + u.username ILIKE '%' || p_search || '%' + )); + + -- 3. 获取明细数据 + SELECT jsonb_agg(t) INTO v_items + FROM ( + SELECT + i.id, + i.uid, + i.order_no, + i.order_amount, + i.invoice_type, + i.header_type, + i.header_name, + i.tax_id, + i.email, + i.remark, + i.status, + i.refusal_reason, + i.invoice_url, + i.created_at, + i.updated_at, + u.username as user_name, + u.email as user_email + FROM public.ml_invoices i + LEFT JOIN public.ak_users u ON u.id = i.uid + WHERE (p_status IS NULL OR i.status = p_status) + AND (p_start_time IS NULL OR i.created_at >= p_start_time) + AND (p_end_time IS NULL OR i.created_at <= p_end_time) + AND (p_search IS NULL OR ( + i.order_no ILIKE '%' || p_search || '%' OR + i.header_name ILIKE '%' || p_search || '%' OR + u.username ILIKE '%' || p_search || '%' + )) + ORDER BY i.created_at DESC + LIMIT p_page_size + OFFSET v_offset + ) t; + + RETURN jsonb_build_object( + 'total', v_total, + 'items', COALESCE(v_items, '[]'::jsonb) + ); +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_invoice_list IS '管理员分页查询发票申请列表'; diff --git a/docs/sql/30_rpc/finance/rpc_admin_invoice_process_v1.sql b/docs/sql/30_rpc/finance/rpc_admin_invoice_process_v1.sql new file mode 100644 index 00000000..29d48a69 --- /dev/null +++ b/docs/sql/30_rpc/finance/rpc_admin_invoice_process_v1.sql @@ -0,0 +1,45 @@ +-- ===================================================================================== +-- RPC: rpc_admin_invoice_process +-- 位置:docs/sql/30_rpc/finance/ +-- 对象类型:RPC 函数 (SECURITY DEFINER) +-- 版本:v1 +-- 说明:管理端处理发票申请(开票或驳回) +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_invoice_process( + p_id UUID, + p_status SMALLINT, -- 1: 已开票, -1: 已拒绝 + p_invoice_url TEXT DEFAULT NULL, + p_refusal_reason TEXT DEFAULT NULL +) +RETURNS BOOLEAN +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_ok BOOLEAN; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 更新状态 + UPDATE public.ml_invoices + SET + status = p_status, + invoice_url = CASE WHEN p_status = 1 THEN p_invoice_url ELSE invoice_url END, + refusal_reason = CASE WHEN p_status = -1 THEN p_refusal_reason ELSE refusal_reason END, + updated_at = now() + WHERE id = p_id; + + GET DIAGNOSTICS v_ok = ROW_COUNT; + RETURN v_ok; +END; +$$; + +COMMENT ON FUNCTION public.rpc_admin_invoice_process IS '管理员处理发票开票申请'; diff --git a/docs/sql/30_rpc/product/rpc_admin_product_analytics_v1.sql b/docs/sql/30_rpc/product/rpc_admin_product_analytics_v1.sql index 270819a9..80d4ed4e 100644 --- a/docs/sql/30_rpc/product/rpc_admin_product_analytics_v1.sql +++ b/docs/sql/30_rpc/product/rpc_admin_product_analytics_v1.sql @@ -48,7 +48,7 @@ BEGIN 'refund_amount', refund_amount ) INTO v_stats FROM stats; - RETURN v_stats; + RETURN v_stats; END; $$; @@ -86,17 +86,29 @@ BEGIN p.main_image_url as image, COALESCE(p.view_count, 0) as views, (SELECT COUNT(DISTINCT user_id) FROM public.ml_browse_history bh WHERE bh.product_id = p.id AND bh.created_at BETWEEN p_start_time AND p_end_time) as visitors, - (SELECT COALESCE(SUM(quantity), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id - WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as sales, + (SELECT COALESCE(SUM(quantity), 0) FROM public.ml_shopping_cart sc WHERE sc.product_id = p.id AND sc.created_at BETWEEN p_start_time AND p_end_time) as cart_count, + (SELECT COUNT(DISTINCT o.id) FROM public.ml_orders o JOIN public.ml_order_items oi ON o.id = oi.order_id + WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time) as order_count, + (SELECT COALESCE(SUM(oi.quantity), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id + WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as pay_count, (SELECT COALESCE(SUM(oi.total_amount), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id - WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as amount + WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5)) as pay_amount, + (SELECT COUNT(*) FROM public.ml_user_favorites f WHERE f.target_id = p.id AND f.target_type = 1 AND f.created_at BETWEEN p_start_time AND p_end_time) as fav_count FROM public.ml_products p WHERE p.status != 4 ORDER BY - CASE WHEN p_sort_by = 'views' THEN 4 - WHEN p_sort_by = 'sales' THEN 6 - WHEN p_sort_by = 'amount' THEN 7 - ELSE 6 END DESC + CASE + WHEN p_sort_by = 'views' THEN COALESCE(p.view_count, 0) + WHEN p_sort_by = 'sales' THEN ( + SELECT COALESCE(SUM(oi.quantity), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id + WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5) + ) + WHEN p_sort_by = 'amount' THEN ( + SELECT COALESCE(SUM(oi.total_amount), 0) FROM public.ml_order_items oi JOIN public.ml_orders o ON oi.order_id = o.id + WHERE oi.product_id = p.id AND o.created_at BETWEEN p_start_time AND p_end_time AND o.order_status NOT IN (1, 5) + ) + ELSE COALESCE(p.view_count, 0) + END DESC LIMIT p_limit ) t; diff --git a/docs/sql/30_rpc/product/rpc_admin_product_count_stats_v1.sql b/docs/sql/30_rpc/product/rpc_admin_product_count_stats_v1.sql new file mode 100644 index 00000000..bf6e2d8d --- /dev/null +++ b/docs/sql/30_rpc/product/rpc_admin_product_count_stats_v1.sql @@ -0,0 +1,38 @@ +-- ===================================================================================== +-- Admin 商品管理 - 商品状态汇总统计 RPC +-- 位置:docs/sql/30_rpc/product/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:统计出售中、仓库中、草稿箱、回收站各状态的商品数量 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_product_count_stats() +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_result JSONB; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE auth_id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 统计各状态数量 + -- status 定义:1:上架(出售中), 2:下架(仓库中), 3:草稿, 4:逻辑删除(回收站) + SELECT jsonb_build_object( + 'selling', COUNT(*) FILTER (WHERE status = 1), + 'warehouse', COUNT(*) FILTER (WHERE status = 2), + 'draft', COUNT(*) FILTER (WHERE status = 3), + 'recycle', COUNT(*) FILTER (WHERE status = 4) + ) INTO v_result + FROM public.ml_products; + + RETURN v_result; +END; +$$; diff --git a/docs/sql/30_rpc/product/rpc_admin_product_trend_v1.sql b/docs/sql/30_rpc/product/rpc_admin_product_trend_v1.sql new file mode 100644 index 00000000..5ad2c9e2 --- /dev/null +++ b/docs/sql/30_rpc/product/rpc_admin_product_trend_v1.sql @@ -0,0 +1,44 @@ +-- ===================================================================================== +-- Admin 商品统计 - 营业趋势统计 RPC +-- 位置:docs/sql/30_rpc/product/ +-- 对象类型:RPC 函数(SECURITY DEFINER) +-- 版本:v1 +-- 说明:按天聚合指定时间范围内的商品浏览量、访客量、支付金额及退款金额 +-- ===================================================================================== + +CREATE OR REPLACE FUNCTION public.rpc_admin_product_trend( + p_start_time TIMESTAMP WITH TIME ZONE, + p_end_time TIMESTAMP WITH TIME ZONE +) +RETURNS JSONB +SECURITY DEFINER +SET search_path = public +LANGUAGE plpgsql +AS $$ +DECLARE + v_items JSONB; +BEGIN + -- 1. 权限检查 + IF NOT EXISTS ( + SELECT 1 FROM public.ak_users + WHERE auth_id = auth.uid() AND role IN ('admin', 'analytics') + ) THEN + RAISE EXCEPTION 'Permission denied'; + END IF; + + -- 2. 按日聚合统计 + SELECT jsonb_agg(t) INTO v_items + FROM ( + SELECT + to_char(date_trunc('day', gs.day), 'YYYY-MM-DD') AS date_group, + (SELECT COUNT(*) FROM public.ml_browse_history bh WHERE date_trunc('day', bh.created_at) = gs.day) as views, + (SELECT COUNT(DISTINCT user_id) FROM public.ml_browse_history bh WHERE date_trunc('day', bh.created_at) = gs.day) as visitors, + (SELECT COALESCE(SUM(total_amount), 0) FROM public.ml_orders o WHERE date_trunc('day', o.created_at) = gs.day AND o.order_status NOT IN (1, 5)) as pay_amount, + (SELECT COALESCE(SUM(total_amount), 0) FROM public.ml_orders o WHERE date_trunc('day', o.created_at) = gs.day AND o.order_status = 7) as refund_amount + FROM generate_series(date_trunc('day', p_start_time), date_trunc('day', p_end_time), '1 day'::interval) gs(day) + ORDER BY gs.day ASC + ) t; + + RETURN COALESCE(v_items, '[]'::jsonb); +END; +$$; diff --git a/pages/mall/admin/finance/balance_record.uvue b/pages/mall/admin/finance/balance_record.uvue index 17ab5e3b..dad6af02 100644 --- a/pages/mall/admin/finance/balance_record.uvue +++ b/pages/mall/admin/finance/balance_record.uvue @@ -3,19 +3,16 @@ - - 订单时间: - - 📅 - 开始日期 - 结束日期 - + + 流水搜索: + 交易类型: - - 请选择 - - + + + + 查询 @@ -23,114 +20,164 @@ - ID - 关联订单 + 序号 + 关联单据 交易时间 交易金额 用户 - 交易类型 + 业务类型 备注 操作 - - - {{ item.id }} - {{ item.order }} - {{ item.time }} + + + 加载中... + + + 暂无记录 + + + {{ (page - 1) * pageSize + index + 1 }} + {{ item.link_id || '-' }} + {{ item.created_at.substring(0, 16).replace('T', ' ') }} - {{ item.amount }} + + {{ item.pm === 1 ? '+' : '-' }}{{ item.number.toFixed(2) }} + - {{ item.user }} - {{ item.type }} - {{ item.remark }} + + + {{ item.user_name || '未知' }} + UID:{{ item.uid.substring(0, 8) }} + + + {{ getBillTypeText(item.type) }} + {{ item.mark || '-' }} - 备注 + 详情 - + + + + + + + 共 {{ total }} 条 + + + + < + + + {{ page }} + + + > + + + + 前往 + + + diff --git a/pages/mall/admin/finance/balance_stats.uvue b/pages/mall/admin/finance/balance_stats.uvue index 487852ff..ca19f772 100644 --- a/pages/mall/admin/finance/balance_stats.uvue +++ b/pages/mall/admin/finance/balance_stats.uvue @@ -7,7 +7,7 @@ 💰 - 1447117274.55 + {{ statsData.current_balance.toFixed(2) }} 当前余额 @@ -16,7 +16,7 @@ 🏦 - 1602611838.49 + {{ statsData.total_accumulation.toFixed(2) }} 累计余额 @@ -25,7 +25,7 @@ 💳 - 155494563.94 + {{ statsData.total_consumption.toFixed(2) }} 累计消耗余额 @@ -144,30 +144,31 @@ - - diff --git a/pages/mall/admin/finance/capital_flow.uvue b/pages/mall/admin/finance/capital_flow.uvue index 7c67848a..6f5b7a4e 100644 --- a/pages/mall/admin/finance/capital_flow.uvue +++ b/pages/mall/admin/finance/capital_flow.uvue @@ -4,24 +4,18 @@ - 订单时间: - - 📅 - 开始日期 - 结束日期 - + 交易类型: + - 交易类型: - - 请选择 - - + 收支类型: + 流水搜索: - + - + 查询 @@ -30,112 +24,170 @@ - 交易单号 - 关联订单 + 交易 ID + 关联单据 交易时间 交易金额 交易用户 - 支付方式 + 业务类型 备注 操作 - - {{ item.flowNo }} - {{ item.orderNo }} - {{ item.time }} - {{ item.amount }} - {{ item.user }} - {{ item.method }} - {{ item.remark }} + + 加载中... + + + 暂无流水记录 + + + {{ item.id.substring(0, 8) }}... + {{ item.link_id || '-' }} + {{ item.created_at.substring(0, 16).replace('T', ' ') }} + + + {{ item.pm === 1 ? '+' : '-' }}{{ item.number.toFixed(2) }} + + + + + {{ item.user_name || '未知' }} + UID:{{ item.uid.substring(0, 8) }} + + + {{ getBillTypeText(item.type) }} + {{ item.mark || '-' }} - 备注 + 详情 + + + + + 共 {{ total }} 条 + + + + < + + + {{ page }} + + + > + + + + 前往 + + + + diff --git a/pages/mall/admin/finance/commission.uvue b/pages/mall/admin/finance/commission.uvue index 55c6104b..41e58f45 100644 --- a/pages/mall/admin/finance/commission.uvue +++ b/pages/mall/admin/finance/commission.uvue @@ -3,11 +3,15 @@ - - 昵称/手机号/分销商ID: - + + 佣金搜索: + - + + 收支类型: + + + 查询 @@ -23,102 +27,159 @@ + 序号 + 关联单据 + 时间 + 变动金额 用户信息 - 总佣金金额 - - 提现佣金 + 业务类型 + 备注 - + + 加载中... + + + 暂无佣金记录 + + + {{ (page - 1) * pageSize + index + 1 }} + {{ item.link_id || '-' }} + {{ item.created_at.substring(0, 16).replace('T', ' ') }} + + + {{ item.pm === 1 ? '+' : '-' }}{{ item.number.toFixed(2) }} + + - {{ item.userInfo }} - - - {{ item.totalAmount }} - - - - {{ item.withdrawAmount }} + + {{ item.user_name || '未知' }} + UID:{{ item.uid.substring(0, 8) }} + + {{ getBillTypeText(item.type) }} + {{ item.mark || '-' }} + + + + + 共 {{ total }} 条 + + + + < + + + {{ page }} + + + > + + + + 前往 + + + + - - diff --git a/pages/mall/admin/finance/invoice.uvue b/pages/mall/admin/finance/invoice.uvue index 5f559853..7748b2b1 100644 --- a/pages/mall/admin/finance/invoice.uvue +++ b/pages/mall/admin/finance/invoice.uvue @@ -7,20 +7,14 @@ 创建时间: 📅 - 开始日期 - 结束日期 + 最近30天 - + 搜索: - - - 请选择 - - - - + - + 查询 @@ -33,134 +27,206 @@ :key="index" class="tab-item" :class="{ active: activeTab === index }" - @click="activeTab = index" + @click="handleTabChange(index)" > - {{ tab.name }} ({{ tab.count }}) + {{ tab.name }} - + 订单号 订单金额 发票类型 - 发票抬头类型 - 下单时间 + 抬头信息 + 申请时间 开票状态 - 订单状态 操作 - - {{ item.orderNo }} - ¥ {{ item.amount }} - {{ item.invoiceType }} - {{ item.headerType }} - {{ item.time }} - {{ item.invStatus }} - {{ item.orderStatus }} - - - 操作 - | - 订单信息 + + 加载中... + + + 暂无发票申请 + + + {{ item.order_no }} + ¥ {{ item.order_amount.toFixed(2) }} + {{ item.invoice_type == 1 ? '普通发票' : '专用发票' }} + + + {{ item.header_name }} + 税号: {{ item.tax_id }} + {{ item.created_at.substring(0, 16).replace('T', ' ') }} + + + {{ getStatusText(item.status) }} + + + + + 开票 + | + 驳回 + + - + + + + + + 共 {{ total }} 条 + + + + < + + + {{ page }} + + + > + + + + 前往 + + + + diff --git a/pages/mall/admin/finance/recharge.uvue b/pages/mall/admin/finance/recharge.uvue index c6af5b4d..dbb90cae 100644 --- a/pages/mall/admin/finance/recharge.uvue +++ b/pages/mall/admin/finance/recharge.uvue @@ -4,24 +4,14 @@ - 时间选择: - - 📅 - 开始日期 - 结束日期 - - - - 支付类型: - - 全部 - - + 支付状态: + 搜索: - + - + 查询 @@ -29,7 +19,7 @@ - + {{ item.icon }} @@ -51,8 +41,7 @@ ID - 头像 - 用户昵称 + 用户信息 订单号 支付金额 是否支付 @@ -62,102 +51,169 @@ - - {{ item.id }} - - - 🖼️ - + + 加载中... + + + 暂无充值记录 + + + {{ (page - 1) * pageSize + index + 1 }} + + + {{ item.user_name || '未知' }} + {{ item.user_email || '-' }} - {{ item.nickname }} - {{ item.orderNo }} - {{ item.amount }} - {{ item.isPaid }} - {{ item.type }} - {{ item.time }} + {{ item.order_no }} + + + ¥{{ item.price.toFixed(2) }} + 赠:¥{{ item.give_price.toFixed(2) }} + + + + + {{ item.paid == 1 ? '已支付' : '未支付' }} + + + {{ getRechargeTypeText(item.recharge_type) }} + {{ item.pay_time ? item.pay_time.substring(0, 16).replace('T', ' ') : '-' }} - 删除 + 详情 + + + + + 共 {{ total }} 条 + + + + < + + + {{ page }} + + + > + + + + 前往 + + + + diff --git a/pages/mall/admin/finance/transaction_stats.uvue b/pages/mall/admin/finance/transaction_stats.uvue index 18ea22cf..20beb1bb 100644 --- a/pages/mall/admin/finance/transaction_stats.uvue +++ b/pages/mall/admin/finance/transaction_stats.uvue @@ -8,16 +8,16 @@ :key="index" class="date-tab-item" :class="{ active: activeDateTab === index }" - @click="activeDateTab = index" + @click="handleDateTabChange(index)" >{{ item }} D - 2026-02-03 - 2026-02-03 + {{ displayDateRange }} - + @@ -25,11 +25,8 @@ ? - - 2026/01/05 - 2026/02/03 - - - + + @@ -41,10 +38,10 @@ 🕒 营业额 - {{ stats.revenue }} + ¥{{ stats.revenue }} - 环比增长: - 44275370% ▲ + 昨日对比: + {{ stats.revenueTrend }} @@ -52,10 +49,10 @@ ¥ 商品支付金额 - {{ stats.payAmount }} + ¥{{ stats.payAmount }} - 环比增长: - 43469352% ▲ + 交易笔数: + {{ stats.orderCount }} @@ -63,10 +60,10 @@ 🔒 购买会员金额 - {{ stats.memberAmount }} + ¥{{ stats.memberAmount }} - 环比增长: - 805918% ▲ + 占比: + - @@ -74,10 +71,10 @@ 💰 充值金额 - {{ stats.rechargeAmount }} + ¥{{ stats.rechargeAmount }} - 环比增长: - 0% - + 笔数: + {{ stats.rechargeCount }} @@ -85,10 +82,10 @@ 🛒 线下收银金额 - {{ stats.offlineAmount }} + ¥{{ stats.offlineAmount }} - 环比增长: - 100% ▲ + 占比: + - @@ -99,33 +96,33 @@ - 支出金额 - {{ stats.expenditure }} + 支出金额 (提现) + ¥{{ stats.expenditure }} - 环比增长: - 44275269% ▲ + 笔数: + {{ stats.extractCount }} 💳 - 余额支付金额 - {{ stats.balancePay }} + 全站余额存量 + ¥{{ stats.balancePay }} - 环比增长: - 5293.00% ▲ + 用户总数: + - - 支付佣金金额 - {{ stats.commissionPay }} + 佣金总存量 + ¥{{ stats.commissionPay }} - 环比增长: - 0% - + 待结算: + - @@ -133,147 +130,22 @@ 📦 商品退款金额 - {{ stats.refundAmount }} + ¥{{ stats.refundAmount }} - 环比增长: - 0% - + 退款率: + - - - - 营业额 - 商品支付金额 - 购买会员金额 - 充值金额 - 支出金额 - - - - - - - - - - - - 今日订单金额 - - - - ¥ - 0 - - - - - 今天 - - - - 昨天 - - - - - - - - - - - - - - - 今日订单数 - - - 0 - - 昨日: - 4 - - - 日环比: - -100% ▼ - - - - - - - - - - 本月订单数 - - - 12 - - 上月: - 206 - - - 月环比: - -94% ▼ - - - - - - - - - - - - - 今日支付人数 - - - 0 - - 昨日: - 4 - - - 日环比: - -100% ▼ - - - - - - - - - - 本月支付人数 - - - 7 - - 上月: - 134 - - - 月环比: - -94% ▼ - - - - - - + 统计加载中... + @@ -281,142 +153,129 @@ @@ -461,7 +315,6 @@ function initCharts() { min-height: 100vh; } -/* 头部筛选 */ .header-filters { background: #fff; padding: 12px 20px; @@ -487,15 +340,8 @@ function initCharts() { border-right: 1px solid #d9d9d9; cursor: pointer; - &:last-child { - border-right: none; - } - - &.active { - background-color: #1890ff; - color: #fff; - border-color: #1890ff; - } + &:last-child { border-right: none; } + &.active { background-color: #1890ff; color: #fff; border-color: #1890ff; } } .date-picker-wrap { @@ -503,167 +349,17 @@ function initCharts() { flex-direction: row; align-items: center; padding: 4px 12px; - border: 1px solid #d9d9d9; + border: 1px solid #dcdfe6; border-radius: 2px; } -.calendar-icon { - margin-right: 8px; - font-size: 14px; -} +.calendar-icon { margin-right: 8px; font-size: 14px; } +.date-range-text { font-size: 14px; color: #333; } -.date-range-text { - font-size: 14px; - color: #333; -} - -/* 统计区域布局 */ -.stats-section { - display: flex; - flex-direction: row; - gap: 16px; -} - -.stats-card-main { - flex: 3; - background: #fff; - border-radius: 4px; - padding: 24px; - min-height: 380px; -} - -.card-title { - font-size: 16px; - color: #333; - font-weight: 500; - margin-bottom: 20px; - display: block; -} - -.amount-wrap { - margin-top: 10px; -} - -.currency { - font-size: 24px; - color: #333; - margin-right: 8px; -} - -.amount-value { - font-size: 40px; - color: #333; - font-weight: bold; -} - -.chart-legend { - display: flex; - flex-direction: row; - margin-top: 16px; -} - -.legend-item { - display: flex; - flex-direction: row; - align-items: center; - margin-right: 20px; - font-size: 14px; - color: #666; -} - -.dot { - width: 8px; - height: 8px; - border-radius: 50%; - margin-right: 8px; - - &.blue { background-color: #1890ff; } - &.gray { background-color: #d9d9d9; } -} - -.chart-box { - width: 100%; - height: 220px; - margin-top: 20px; -} - -.stats-chart { - width: 100%; - height: 100%; -} - -/* 侧边网格 */ -.stats-side-grid { - flex: 2; - display: flex; - flex-direction: row; - gap: 16px; -} - -.side-column { - flex: 1; - display: flex; - flex-direction: column; - gap: 16px; -} - -.side-stat-card { - background: #fff; - border-radius: 4px; - padding: 24px; - display: flex; - flex-direction: column; -} - -.main-val { - font-size: 32px; - font-weight: bold; - color: #333; - margin-bottom: 20px; - display: block; -} - -.compare-row { - display: flex; - flex-direction: row; - margin-bottom: 8px; - font-size: 14px; -} - -.compare-row .label { - color: #999; - margin-right: 8px; -} - -.compare-row .val { - color: #333; - - &.down { color: #52c41a; } - &.up { color: #f5222d; } -} - -.mini-chart-placeholder { - margin-top: 20px; - height: 2px; - background-color: #f0f0f0; - position: relative; -} - -.blue-line { - position: absolute; - left: 0; - top: 0; - width: 60%; - height: 100%; - background-color: #1890ff; -} - -/* 交易概况复刻样式 */ .overview-card { background: #fff; border-radius: 4px; padding: 20px; - margin-bottom: 20px; } .overview-header { @@ -674,72 +370,22 @@ function initCharts() { margin-bottom: 24px; } -.overview-header .header-left { - display: flex; - flex-direction: row; - align-items: center; -} - -.section-title { - font-size: 16px; - font-weight: bold; - color: #333; -} - +.header-left { display: flex; flex-direction: row; align-items: center; } +.section-title { font-size: 16px; font-weight: bold; color: #333; } .info-tag { - width: 16px; - height: 16px; - border-radius: 50%; - background: #eee; - color: #999; - font-size: 11px; - display: flex; - align-items: center; - justify-content: center; - margin-left: 8px; -} - -.overview-header .header-right { - display: flex; - flex-direction: row; - gap: 12px; -} - -.date-picker-inline { - border: 1px solid #dcdfe6; - padding: 5px 15px; - border-radius: 4px; - display: flex; - align-items: center; -} - -.date-text { - font-size: 13px; - color: #606266; + width: 16px; height: 16px; border-radius: 50%; + background: #eee; color: #999; font-size: 11px; + display: flex; align-items: center; justify-content: center; margin-left: 8px; } +.header-right { display: flex; flex-direction: row; gap: 12px; } .btn-query, .btn-export { - padding: 0 16px; - height: 32px; - line-height: 32px; - font-size: 13px; - border-radius: 4px; - cursor: pointer; + padding: 0 16px; height: 32px; line-height: 32px; + font-size: 13px; border-radius: 4px; cursor: pointer; } +.btn-query { background-color: #1890ff; color: #fff; border: none; } +.btn-export { background: #fff; color: #1890ff; border: 1px solid #1890ff; } -.btn-query { - background-color: #1890ff; - color: #fff; - border: none; -} - -.btn-export { - background: #fff; - color: #1890ff; - border: 1px solid #1890ff; -} - -/* 指标网格 */ .overview-grid { display: flex; flex-direction: column; @@ -748,36 +394,14 @@ function initCharts() { border-bottom: 1px dashed #f0f0f0; } -.grid-row { - display: flex; - flex-direction: row; - justify-content: space-between; -} - -.overview-item { - flex: 1; - display: flex; - flex-direction: row; - align-items: center; -} - -.overview-item.transparent { - visibility: hidden; -} +.grid-row { display: flex; flex-direction: row; justify-content: space-between; } +.overview-item { flex: 1; display: flex; flex-direction: row; align-items: center; } +.overview-item.transparent { visibility: hidden; } .icon-box { - width: 44px; - height: 44px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - margin-right: 12px; -} - -.icon-box .icon { - font-size: 20px; - color: #fff; + width: 44px; height: 44px; border-radius: 50%; + display: flex; align-items: center; justify-content: center; margin-right: 12px; + text { color: #fff; font-size: 20px; } } .icon-box.blue { background-color: #2f54eb; } @@ -790,74 +414,14 @@ function initCharts() { .icon-box.red-purple { background-color: #eb2f96; } .icon-box.blue-gray { background-color: #4096ff; } -.item-info { - display: flex; - flex-direction: column; -} +.item-info { display: flex; flex-direction: column; } +.item-label { font-size: 13px; color: #999; margin-bottom: 4px; } +.item-value { font-size: 22px; font-weight: bold; color: #333; margin-bottom: 4px; } +.trend-row { display: flex; flex-direction: row; font-size: 12px; color: #999; } +.trend-value { margin-left: 4px; } -.item-label { - font-size: 13px; - color: #999; - margin-bottom: 4px; -} - -.item-value { - font-size: 24px; - font-weight: bold; - color: #333; - margin-bottom: 4px; -} - -.trend-row { - display: flex; - flex-direction: row; - font-size: 12px; - color: #999; -} - -.trend-value.up { - color: #f5222d; - margin-left: 4px; -} - -/* 图表区 */ -.overview-chart-section { - padding-top: 24px; -} - -.overview-chart-legend { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: 16px; - margin-bottom: 20px; -} - -.legend-dot { - width: 8px; - height: 8px; - border-radius: 50%; -} - -.legend-dot.blue { background: #1890ff; } -.legend-dot.green { background: #52c41a; } -.legend-dot.gray-blue { background: #607d8b; } -.legend-dot.red { background: #f44336; } -.legend-dot.orange { background: #fa8c16; } - -.legend-text { - font-size: 12px; - color: #666; -} - -.overview-chart-box { - width: 100%; - height: 400px; -} - -.main-trend-chart { - width: 100%; - height: 100%; -} +.overview-chart-section { padding-top: 24px; } +.overview-chart-box { width: 100%; height: 350px; } +.main-trend-chart { width: 100%; height: 100%; } +.chart-loading { height: 100%; display: flex; align-items: center; justify-content: center; color: #999; } diff --git a/pages/mall/admin/finance/withdrawal.uvue b/pages/mall/admin/finance/withdrawal.uvue index 5d9ef872..25eaec43 100644 --- a/pages/mall/admin/finance/withdrawal.uvue +++ b/pages/mall/admin/finance/withdrawal.uvue @@ -25,7 +25,7 @@ - + {{ item.icon }} @@ -43,73 +43,98 @@ - + ID 用户信息 提现金额 - 提现手续费 + 手续费 到账金额 提现方式 - 收款码 申请时间 - 备注 审核状态 操作 - - {{ item.id }} + + 加载中... + + + 暂无提现申请 + + + {{ (page - 1) * pageSize + index + 1 }} - {{ item.amount }} - {{ item.fee }} - {{ item.netAmount }} + ¥{{ item.extract_price.toFixed(2) }} + ¥{{ item.service_fee.toFixed(2) }} + ¥{{ (item.extract_price - item.service_fee).toFixed(2) }} - 姓名:{{ item.name }} - {{ item.type }}:{{ item.account }} - 银行开户地址:{{ item.bank }} + {{ getMethodText(item.extract_type) }} + 账号:{{ item.alipay_code || item.wechat_code || item.bank_code || '-' }} - - - - + {{ item.created_at.substring(0, 16).replace('T', ' ') }} + + + {{ getStatusText(item.status) }} + - {{ item.time }} - {{ item.remark || '' }} - 申请中 - - 编辑 + + 通过 | - 通过 - | - 驳回 + 驳回 + - + + + + + 共 {{ total }} 条 + + + + < + + + {{ page }} + + + > + + + + 前往 + + + + diff --git a/pages/mall/admin/product/product-management/index.uvue b/pages/mall/admin/product/product-management/index.uvue index 96987e1e..33ef86b9 100644 --- a/pages/mall/admin/product/product-management/index.uvue +++ b/pages/mall/admin/product/product-management/index.uvue @@ -5,7 +5,7 @@ 商品搜索: - + 商品类型: @@ -16,14 +16,19 @@ 商品分类: - - 请选择 - - + + + {{ categoryOptions[categoryIndex].label }} + + + - - + + 展开 @@ -49,7 +54,7 @@ :key="index" class="tab-item" :class="{ active: activeStatus === tab.key }" - @click="activeStatus = tab.key" + @click="changeStatus(tab.key)" > {{ tab.label }}({{ tab.count }}) @@ -115,7 +120,7 @@ {{ item.stock }} {{ item.sort }} - + {{ item.status === 1 ? '上架' : '下架' }} @@ -137,7 +142,7 @@ 查看评论 会员价管理 佣金管理 - {{ activeStatus === 'recycle' ? '恢复商品' : '移到回收站' }} + {{ activeStatus === 4 ? '恢复商品' : '移到回收站' }} @@ -149,10 +154,9 @@ 共 {{ total }} 条 - {"<"} - 1 - 2 - {">"} + {"<"} + {{ page }} + {">"} @@ -162,15 +166,21 @@