罗永浩 5 mēneši atpakaļ
vecāks
revīzija
e3229c9df6
54 mainītis faili ar 9469 papildinājumiem un 479 dzēšanām
  1. 1 0
      .nvmrc
  2. 61 0
      .windsurf/mcp.json
  3. 515 0
      README.md
  4. 1 0
      addons/admin/package.json
  5. 406 0
      addons/admin/src/views/agents/agents.vue
  6. 360 0
      addons/admin/src/views/financial/accountLog.vue
  7. 24 0
      addons/admin/src/views/financial/agentWithdraw.vue
  8. 439 0
      addons/admin/src/views/financial/balanceLogs.vue
  9. 162 0
      addons/admin/src/views/financial/components/StatisticsTable.vue
  10. 47 0
      addons/admin/src/views/financial/financial.vue
  11. 24 0
      addons/admin/src/views/financial/storesWithdraw.vue
  12. 63 27
      addons/admin/src/views/member/member/index.vue
  13. 997 0
      addons/admin/src/views/order/order.vue
  14. 269 0
      addons/admin/src/views/orders/afterType.vue
  15. 334 0
      addons/admin/src/views/orders/refundOrder.vue
  16. 286 0
      addons/admin/src/views/pay/components/MealsManage.vue
  17. 226 0
      addons/admin/src/views/pay/components/OrdersManage.vue
  18. 40 0
      addons/admin/src/views/pay/electricityBill.vue
  19. 40 0
      addons/admin/src/views/pay/gasBill.vue
  20. 40 0
      addons/admin/src/views/pay/phonebill.vue
  21. 1 2
      addons/admin/src/views/store/store.vue
  22. 0 0
      addons/admin/update_node_sass.bat
  23. 59 22
      app/Http/Controllers/Admin/AccountController.php
  24. 70 0
      app/Http/Controllers/Admin/AgentController.php
  25. 79 0
      app/Http/Controllers/Admin/AgentWithdrawController.php
  26. 80 0
      app/Http/Controllers/Admin/BalanceLogsController.php
  27. 29 0
      app/Http/Controllers/Admin/FinancialController.php
  28. 29 9
      app/Http/Controllers/Admin/MemberController.php
  29. 86 71
      app/Http/Controllers/Admin/OrderController.php
  30. 81 0
      app/Http/Controllers/Admin/PayMealsController.php
  31. 51 0
      app/Http/Controllers/Admin/PayOrdersController.php
  32. 0 80
      app/Http/Controllers/Admin/WithdrawController.php
  33. 29 0
      app/Models/AgentModel.php
  34. 61 19
      app/Models/BalanceLogModel.php
  35. 13 0
      app/Models/OrderGoodsModel.php
  36. 30 12
      app/Models/OrderModel.php
  37. 56 0
      app/Models/PayMealsModel.php
  38. 74 0
      app/Models/PayOrdersModel.php
  39. 366 56
      app/Services/Common/AccountService.php
  40. 246 0
      app/Services/Common/AgentService.php
  41. 324 0
      app/Services/Common/BalanceLogsService.php
  42. 406 0
      app/Services/Common/FinancialService.php
  43. 256 18
      app/Services/Common/MemberService.php
  44. 636 160
      app/Services/Common/OrderService.php
  45. 233 0
      app/Services/Common/PayMealsService.php
  46. 164 0
      app/Services/Common/PayOrdersService.php
  47. 1004 0
      database/lev_.sql
  48. 146 0
      database/seeders/AgentTestDataSeeder.php
  49. 7 1
      database/seeders/DatabaseSeeder.php
  50. 159 0
      database/seeders/OrderTestDataSeeder.php
  51. 68 0
      database/seeders/PayMealsSeeder.php
  52. 115 0
      database/seeders/PayOrdersSeeder.php
  53. 105 0
      database/seeders/README_PAY.md
  54. 71 2
      routes/web.php

+ 1 - 0
.nvmrc

@@ -0,0 +1 @@
+14.21.3

+ 61 - 0
.windsurf/mcp.json

@@ -0,0 +1,61 @@
+{
+  "mcpServers": {
+    "windows-mcp": {
+      "command": "uv",
+      "args": [
+        "--directory",
+        "C:/Windows-MCP",
+        "run",
+        "main.py"
+      ],
+      "env": {
+        "PYTHONUNBUFFERED": "1"
+      },
+      "metadata": {
+        "description": "Windows-MCP server for local system operations",
+        "homepage": "https://github.com/CursorTouch/Windows-MCP"
+      }
+    },
+    "filesystem": {
+      "command": "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v18.20.2\\node.exe",
+      "args": [
+        "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v18.20.2\\node_modules\\@modelcontextprotocol\\server-filesystem\\dist\\index.js",
+        "D:\\www"
+      ]
+    },
+    "mysqlyitongchengtest": {
+      "command": "npx",
+      "args": [
+        "-y",
+        "@bytebase/dbhub",
+        "--transport",
+        "stdio",
+        "--dsn",
+        "mysql://admin:wK7p16bw5z@123.57.137.186:3306/yitongchengtest?sslmode=disable"
+      ]
+    },
+    "mysql": {
+      "command": "npx",
+      "args": [
+        "-y",
+        "@bytebase/dbhub",
+        "--transport",
+        "stdio",
+        "--dsn",
+        "mysql://nn2025112501:kB8SXpiG7pa2iXe2@47.112.222.163:63306/nn2025112501?sslmode=disable"
+      ]
+    },
+    "fetch": {
+      "command": "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v20.19.5\\node.exe",
+      "args": [
+        "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v20.19.5\\node_modules\\fetch-mcp\\dist\\index.js"
+      ]
+    },
+    "windows-cli": {
+      "command": "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v20.19.5\\node.exe",
+      "args": [
+        "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v20.19.5\\windows-cli-mcp-server-main\\dist\\index.js"
+      ]
+    }
+  }
+}

+ 515 - 0
README.md

@@ -0,0 +1,515 @@
+# 共享平台商城系统开发
+
+## 项目概述
+
+这是一个基于 Laravel 8.0 框架开发的多商户共享平台商城系统,支持会员、商户、代理等多角色管理。
+
+## 技术栈
+
+### 后端
+- **框架**: Laravel 8.0
+- **数据库**: MySQL 5.6+
+- **缓存**: Redis
+- **语言**: PHP 7.4+
+
+### 前端
+- **框架**: Vue.js 2.x
+- **UI组件**: Element UI (element-admin)
+- **构建工具**: Webpack
+- **包管理**: npm
+
+## 技能要求 (Skills)
+
+### 后端开发技能
+
+#### 核心技术
+- ![PHP](https://img.shields.io/badge/PHP-7.4+-777BB4?style=flat&logo=php&logoColor=white) PHP 面向对象编程
+- ![Laravel](https://img.shields.io/badge/Laravel-8.0-FF2D20?style=flat&logo=laravel&logoColor=white) Laravel 框架精通
+- ![MySQL](https://img.shields.io/badge/MySQL-5.6+-4479A1?style=flat&logo=mysql&logoColor=white) MySQL 数据库设计与优化
+- ![Redis](https://img.shields.io/badge/Redis-5.0+-DC382D?style=flat&logo=redis&logoColor=white) Redis 缓存应用
+
+#### Laravel 核心能力
+- **Eloquent ORM** - 模型关联、查询构造器、软删除
+- **服务容器** - 依赖注入、服务提供者
+- **中间件** - 认证、授权、请求过滤
+- **验证器** - 表单验证、自定义规则
+- **事件系统** - 事件监听、队列任务
+- **数据库迁移** - Schema Builder、数据填充
+
+#### 架构设计
+- **MVC架构** - Model-View-Controller 分层
+- **服务层模式** - Service Layer 业务逻辑封装
+- **仓储模式** - Repository Pattern 数据访问抽象
+- **RESTful API** - 接口设计规范
+- **多商户架构** - 数据隔离、权限控制
+
+#### 数据库技能
+- **数据库设计** - ER图设计、范式应用
+- **索引优化** - 索引策略、查询优化
+- **事务处理** - ACID特性、锁机制
+- **关联查询** - JOIN、子查询、聚合函数
+- **数据迁移** - 版本控制、回滚机制
+
+#### 安全技能
+- **身份认证** - JWT、Session、OAuth
+- **权限控制** - RBAC、ACL、数据权限
+- **数据加密** - 密码哈希、敏感信息加密
+- **防护机制** - SQL注入、XSS、CSRF防护
+- **接口安全** - 签名验证、频率限制
+
+### 前端开发技能
+
+#### 核心技术
+- ![Vue.js](https://img.shields.io/badge/Vue.js-2.x-4FC08D?style=flat&logo=vue.js&logoColor=white) Vue.js 框架
+- ![Element UI](https://img.shields.io/badge/Element_UI-2.x-409EFF?style=flat&logo=element&logoColor=white) Element UI 组件库
+- ![JavaScript](https://img.shields.io/badge/JavaScript-ES6+-F7DF1E?style=flat&logo=javascript&logoColor=black) ES6+ 语法
+- ![Webpack](https://img.shields.io/badge/Webpack-4.x-8DD6F9?style=flat&logo=webpack&logoColor=black) Webpack 构建工具
+
+#### Vue.js 核心能力
+- **组件开发** - 单文件组件、组件通信、插槽
+- **状态管理** - Vuex、模块化、持久化
+- **路由管理** - Vue Router、路由守卫、动态路由
+- **生命周期** - 钩子函数、异步组件
+- **响应式原理** - 数据绑定、计算属性、侦听器
+
+#### Element UI 应用
+- **表格组件** - 数据展示、分页、排序、筛选
+- **表单组件** - 表单验证、动态表单、上传组件
+- **布局组件** - 栅格系统、容器布局
+- **导航组件** - 菜单、标签页、面包屑
+- **反馈组件** - 消息提示、对话框、加载状态
+
+#### 前端工程化
+- **模块化开发** - ES6 Module、组件化
+- **代码规范** - ESLint、Prettier
+- **构建优化** - 代码分割、懒加载、压缩
+- **调试工具** - Vue DevTools、Chrome DevTools
+- **版本控制** - Git、分支管理
+
+### 通用技能
+
+#### 开发工具
+- ![Git](https://img.shields.io/badge/Git-F05032?style=flat&logo=git&logoColor=white) Git 版本控制
+- ![Composer](https://img.shields.io/badge/Composer-885630?style=flat&logo=composer&logoColor=white) Composer 依赖管理
+- ![npm](https://img.shields.io/badge/npm-CB3837?style=flat&logo=npm&logoColor=white) npm 包管理
+- ![Postman](https://img.shields.io/badge/Postman-FF6C37?style=flat&logo=postman&logoColor=white) Postman API测试
+
+#### 软技能
+- **需求分析** - 业务理解、需求拆解
+- **系统设计** - 架构设计、数据建模
+- **代码审查** - Code Review、最佳实践
+- **文档编写** - API文档、技术文档
+- **团队协作** - 敏捷开发、沟通能力
+- **问题解决** - Debug能力、性能优化
+
+#### 业务理解
+- **电商系统** - 订单流程、支付流程、库存管理
+- **多商户平台** - 商户入驻、数据隔离、结算分账
+- **会员系统** - 等级体系、积分系统、推荐机制
+- **财务系统** - 账户管理、交易记录、对账结算
+- **权限系统** - 角色管理、菜单权限、数据权限
+
+### 进阶技能
+
+#### 性能优化
+- **数据库优化** - 慢查询分析、索引优化、分库分表
+- **缓存策略** - Redis缓存、页面缓存、对象缓存
+- **代码优化** - 算法优化、内存管理、并发控制
+- **前端优化** - 资源压缩、CDN加速、懒加载
+
+#### 高级特性
+- **消息队列** - Laravel Queue、异步任务
+- **定时任务** - Cron、任务调度
+- **文件存储** - 本地存储、云存储、OSS
+- **第三方集成** - 支付接口、短信服务、物流接口
+- **API开发** - RESTful、GraphQL、接口文档
+
+#### 测试能力
+- **单元测试** - PHPUnit、测试覆盖率
+- **功能测试** - Feature Test、集成测试
+- **接口测试** - Postman、自动化测试
+- **前端测试** - Jest、Vue Test Utils
+
+### 学习资源
+
+#### 官方文档
+- [Laravel 中文文档](https://learnku.com/docs/laravel/8.x)
+- [Vue.js 官方文档](https://cn.vuejs.org/)
+- [Element UI 文档](https://element.eleme.cn/)
+- [MySQL 官方文档](https://dev.mysql.com/doc/)
+
+#### 推荐书籍
+- 《Laravel 框架关键技术解析》
+- 《Vue.js 设计与实现》
+- 《高性能MySQL》
+- 《PHP核心技术与最佳实践》
+
+#### 在线课程
+- Laravel 从入门到精通
+- Vue.js 实战开发
+- MySQL 数据库优化
+- Redis 深度历险
+
+## 核心功能模块
+
+### 1. 用户管理
+- **会员管理** (`lev_member`)
+  - 用户注册、登录
+  - 会员等级管理
+  - 账户余额管理
+  - 推荐关系管理
+  - 设备信息记录
+
+- **后台用户** (`lev_user`)
+  - 管理员账号管理
+  - 角色权限分配
+  - 登录日志记录
+
+### 2. 商户管理
+- **商户信息** (`lev_store`)
+  - 商户入驻审核
+  - 商户资料管理
+  - 商户状态控制
+  - 多商户隔离
+
+### 3. 商品管理
+- **商品信息** (`lev_goods`)
+  - 商品发布
+  - 商品分类
+  - 库存管理
+  - 价格管理
+
+### 4. 订单管理
+- **订单处理** (`lev_order`)
+  - 订单创建
+  - 订单状态流转
+  - 订单支付
+  - 订单退款
+
+### 5. 财务管理
+- **账户明细** (`lev_account_logs`)
+  - 交易记录
+  - 收支明细
+  - 资金流水
+  - 统计报表
+
+- **充值套餐** (`lev_pay_meals`)
+  - 套餐配置
+  - 折扣设置
+  - 排序管理
+
+### 6. 权限管理
+- **角色管理** (`lev_role`)
+- **权限管理** (`lev_menu`)
+- **用户角色关联** (`lev_user_role`)
+
+## 数据表关系
+
+### 核心关联关系
+```
+store.user_id = user.user_id = member.id
+```
+
+### 主要数据表
+
+#### 用户相关
+- `lev_member` - 会员表(前台用户)
+- `lev_user` - 后台用户表
+- `lev_user_role` - 用户角色关联表
+
+#### 商户相关
+- `lev_store` - 商户表
+- 关联字段: `user_id` 关联到 `member.id`
+
+#### 商品相关
+- `lev_goods` - 商品表
+- `lev_goods_category` - 商品分类表
+
+#### 订单相关
+- `lev_order` - 订单表
+- `lev_order_goods` - 订单商品明细表
+
+#### 财务相关
+- `lev_account_logs` - 账户明细表
+- `lev_pay_meals` - 充值套餐表
+- `lev_balance_logs` - 余额变动记录表
+
+#### 系统相关
+- `lev_role` - 角色表
+- `lev_menu` - 菜单权限表
+- `lev_action_log` - 操作日志表
+- `lev_login_log` - 登录日志表
+
+## 目录结构
+
+```
+NN2025112501/
+├── addons/                    # 前端插件
+│   └── admin/                 # 后台管理前端
+│       ├── dist/              # 编译后的文件
+│       ├── public/            # 公共资源
+│       └── src/               # 源代码
+│           ├── components/    # 公共组件
+│           ├── views/         # 页面视图
+│           │   ├── financial/ # 财务管理
+│           │   ├── member/    # 会员管理
+│           │   ├── store/     # 商户管理
+│           │   ├── goods/     # 商品管理
+│           │   └── pay/       # 支付管理
+│           ├── router/        # 路由配置
+│           └── utils/         # 工具函数
+├── app/                       # 应用核心
+│   ├── Console/               # 命令行
+│   ├── Exceptions/            # 异常处理
+│   ├── Exports/               # 导出功能
+│   ├── Helpers/               # 辅助函数
+│   ├── Http/                  # HTTP层
+│   │   ├── Controllers/       # 控制器
+│   │   │   ├── Admin/         # 后台控制器
+│   │   │   └── Api/           # API控制器
+│   │   ├── Middleware/        # 中间件
+│   │   └── Validator/         # 验证器
+│   ├── Models/                # 数据模型
+│   └── Services/              # 业务逻辑层
+│       ├── Common/            # 公共服务
+│       └── Api/               # API服务
+├── config/                    # 配置文件
+├── database/                  # 数据库
+│   ├── migrations/            # 数据迁移
+│   ├── seeders/               # 数据填充
+│   └── *.sql                  # SQL文件
+├── public/                    # 公共资源
+├── resources/                 # 资源文件
+│   ├── certs/                 # 证书文件
+│   ├── lang/                  # 语言包
+│   └── views/                 # 视图模板
+├── routes/                    # 路由定义
+│   ├── api.php                # API路由
+│   └── web.php                # Web路由
+└── storage/                   # 存储目录
+```
+
+## 核心业务流程
+
+### 1. 会员注册流程
+1. 用户提交注册信息
+2. 验证手机号唯一性
+3. 创建会员记录 (`lev_member`)
+4. 生成推广码
+5. 记录推荐关系
+
+### 2. 商户入驻流程
+1. 会员申请成为商户
+2. 提交商户资料
+3. 后台审核
+4. 创建商户记录 (`lev_store`)
+5. 关联用户ID (`store.user_id = member.id`)
+
+### 3. 订单处理流程
+1. 用户下单
+2. 创建订单记录
+3. 扣减库存
+4. 支付处理
+5. 更新订单状态
+6. 记录账户明细
+
+### 4. 财务结算流程
+1. 订单完成
+2. 计算佣金
+3. 更新账户余额
+4. 记录账户明细 (`lev_account_logs`)
+5. 生成财务报表
+
+## 权限系统
+
+### 权限配置
+- 基于 RBAC (Role-Based Access Control)
+- 菜单权限控制
+- 接口权限控制
+- 数据权限控制(多商户隔离)
+
+### 权限标识格式
+```
+模块:功能:操作
+例如: sys:member:add
+```
+
+### 常用权限
+- `sys:member:view` - 查看会员
+- `sys:member:add` - 添加会员
+- `sys:member:edit` - 编辑会员
+- `sys:member:delete` - 删除会员
+- `financial:accountLog:view` - 查看财务明细
+- `store:store:view` - 查看商户
+
+## API接口规范
+
+### 请求格式
+```json
+{
+  "page": 1,
+  "limit": 20,
+  "keyword": "搜索关键词",
+  "status": 1
+}
+```
+
+### 响应格式
+```json
+{
+  "code": 0,
+  "msg": "操作成功",
+  "data": [],
+  "count": 100
+}
+```
+
+### 状态码
+- `0` - 成功
+- `1` - 失败
+- `-1` - 异常
+
+## 数据字典
+
+### 交易类型 (account_logs.type)
+- `1` - 商城消费
+- `2` - 充值缴费
+- `3` - 商城退款
+- `4` - 佣金提现
+- `5` - 提现驳回
+- `6` - 平台入款
+
+### 订单状态 (order.status)
+- `1` - 待支付
+- `2` - 已支付
+- `3` - 配送中
+- `4` - 已完成
+- `5` - 已取消
+
+### 用户状态 (member.status)
+- `1` - 正常
+- `2` - 冻结
+
+### 商户状态 (store.status)
+- `1` - 启用
+- `2` - 禁用
+
+## 环境配置
+
+### 开发环境要求
+- PHP >= 7.4
+- MySQL >= 5.6
+- Redis >= 5.0
+- Composer
+- Node.js >= 12.x
+- npm >= 6.x
+
+### 安装步骤
+
+1. **克隆项目**
+```bash
+git clone [repository-url]
+cd NN2025112501
+```
+
+2. **安装后端依赖**
+```bash
+composer install
+```
+
+3. **配置环境变量**
+```bash
+cp .env.example .env
+# 编辑 .env 文件,配置数据库等信息
+```
+
+4. **生成应用密钥**
+```bash
+php artisan key:generate
+```
+
+5. **导入数据库**
+```bash
+# 导入 database/lev_.sql 文件
+```
+
+6. **安装前端依赖**
+```bash
+cd addons/admin
+npm install
+```
+
+7. **编译前端资源**
+```bash
+npm run dev   # 开发环境
+npm run build # 生产环境
+```
+
+8. **启动服务**
+```bash
+php artisan serve
+```
+
+## 开发规范
+
+### 代码规范
+- 遵循 PSR-12 编码规范
+- 使用 Laravel 最佳实践
+- 代码注释完整
+- 变量命名语义化
+
+### Git 提交规范
+```
+feat: 新功能
+fix: 修复bug
+docs: 文档更新
+style: 代码格式调整
+refactor: 重构
+test: 测试相关
+chore: 构建/工具链
+```
+
+### 数据库规范
+- 表名使用 `lev_` 前缀
+- 字段名使用下划线命名
+- 必须包含 `create_time`、`update_time`、`mark` 字段
+- 软删除使用 `mark` 字段(1-有效,0-删除)
+
+## 安全措施
+
+### 数据安全
+- 密码加密存储
+- SQL注入防护
+- XSS攻击防护
+- CSRF令牌验证
+
+### 接口安全
+- JWT身份验证
+- 接口签名验证
+- 请求频率限制
+- IP白名单
+
+### 数据隔离
+- 多商户数据隔离
+- 基于 `store_id` 的数据过滤
+- 权限级别控制
+
+## 常见问题
+
+### Q: 如何添加新的权限?
+A: 在 `lev_menu` 表中添加权限记录,然后在角色管理中分配权限。
+
+### Q: 如何实现多商户数据隔离?
+A: 在控制器中获取 `$this->storeId`,在查询时添加 `store_id` 条件。
+
+### Q: 如何自定义交易类型?
+A: 修改 `config/payment.php` 中的 `accountTypes` 配置。
+
+## 更新日志
+
+### v1.0.0 (2025-01-25)
+- ✅ 完成会员管理模块
+- ✅ 完成财务明细模块
+- ✅ 完成充值套餐模块
+- ✅ 完成权限管理系统
+- ✅ 完成多商户数据隔离

+ 1 - 0
addons/admin/package.json

@@ -4,6 +4,7 @@
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",
+    "dev:v14": "C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v12.22.12\\npm run dev",
     "build": "vue-cli-service build",
     "lint": "vue-cli-service lint"
   },

+ 406 - 0
addons/admin/src/views/agents/agents.vue

@@ -0,0 +1,406 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<!-- 状态tabs -->
+			<el-tabs v-model="activeStatus" @tab-click="handleTabClick" style="margin-bottom: 15px;">
+				<el-tab-pane v-for="item in statusTabs" :key="item.value" :name="item.value">
+					<span slot="label"><i :class="item.icon"></i> {{ item.label }}</span>
+				</el-tab-pane>
+			</el-tabs>
+
+			<!-- 搜索表单 -->
+			<el-form :model="table.where" label-width="90px" class="ele-form-search"
+				@keyup.enter.native="$refs.table.reload()" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="6" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="table.where.keyword" placeholder="姓名/电话" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :md="12" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="$refs.table.reload()" icon="el-icon-search"
+								class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset()">重置</el-button>
+
+							<!-- 待审核状态下显示批量操作按钮 -->
+							<template v-if="activeStatus === '2'">
+								<el-button type="success" icon="el-icon-check" @click="handleBatchAudit" :disabled="!choose.length"
+									v-if="permission.includes('sys:agents:edit')">批量通过</el-button>
+								<el-button type="danger" icon="el-icon-close" @click="handleBatchReject" :disabled="!choose.length"
+									v-if="permission.includes('sys:agents:edit')">批量驳回</el-button>
+							</template>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 数据表格 -->
+			<ele-data-table ref="table" :config="table" :choose.sync="choose" height="calc(100vh - 315px)">
+				<template slot-scope="{index}">
+					<el-table-column type="selection" width="45" align="center" fixed="left" />
+					<el-table-column type="index" :index="index" label="编号" width="60" align="center" fixed="left"
+						show-overflow-tooltip />
+					<el-table-column prop="id" label="ID" sortable="custom" show-overflow-tooltip min-width="80" align="center" />
+					<el-table-column prop="real_name" label="代理姓名" show-overflow-tooltip min-width="120" align="center" />
+					<el-table-column prop="phone" label="电话" show-overflow-tooltip min-width="130" align="center" />
+					<el-table-column prop="idcard" label="身份证号" show-overflow-tooltip min-width="180" align="center" />
+					<el-table-column prop="team_count" label="团队人数" show-overflow-tooltip min-width="100" align="center" />
+					<el-table-column prop="order_count" label="代理订单" show-overflow-tooltip min-width="100" align="center" />
+					<el-table-column prop="income" label="总佣金" show-overflow-tooltip min-width="120" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #f56c6c;">¥{{ row.income }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="balance" label="可提现余额" show-overflow-tooltip min-width="120" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #67c23a;">¥{{ row.balance }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="create_time" label="申请时间" show-overflow-tooltip min-width="160" align="center" />
+					<el-table-column label="状态" show-overflow-tooltip min-width="100" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.status === 1" type="success" size="small">已审核</el-tag>
+							<el-tag v-else-if="row.status === 2" type="warning" size="small">待审核</el-tag>
+							<el-tag v-else-if="row.status === 3" type="danger" size="small">已驳回</el-tag>
+							<el-tag v-else-if="row.status === 4" type="info" size="small">已冻结</el-tag>
+						</template>
+					</el-table-column>
+					<el-table-column label="操作" width="380" align="center" :resizable="false" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="handleView(row)" icon="el-icon-view" type="primary" :underline="false"
+								v-if="permission.includes('sys:agents:index')">查看</el-link>
+							<el-divider direction="vertical" />
+
+							<!-- 待审核状态显示审核按钮 -->
+							<template v-if="row.status === 2">
+								<el-popconfirm title="确定要通过此代理申请吗?" @confirm="quickAudit(row, 1)">
+									<el-link slot="reference" icon="el-icon-check" type="success" :underline="false"
+										v-if="permission.includes('sys:agents:edit')">通过</el-link>
+								</el-popconfirm>
+								<el-divider direction="vertical" />
+								<el-link @click="handleReject(row)" icon="el-icon-close" type="danger" :underline="false"
+									v-if="permission.includes('sys:agents:edit')">驳回</el-link>
+								<el-divider direction="vertical" />
+							</template>
+
+							<!-- 已审核状态显示冻结按钮 -->
+							<template v-if="row.status === 1">
+								<el-popconfirm title="确定要冻结此代理吗?" @confirm="quickFreeze(row, 4)">
+									<el-link slot="reference" icon="el-icon-lock" type="warning" :underline="false"
+										v-if="permission.includes('sys:agents:status')">冻结</el-link>
+								</el-popconfirm>
+								<el-divider direction="vertical" />
+							</template>
+
+							<!-- 已冻结状态显示解冻按钮 -->
+							<template v-if="row.status === 4">
+								<el-popconfirm title="确定要解冻此代理吗?" @confirm="quickFreeze(row, 1)">
+									<el-link slot="reference" icon="el-icon-unlock" type="success" :underline="false"
+										v-if="permission.includes('sys:agents:status')">解冻</el-link>
+								</el-popconfirm>
+								<el-divider direction="vertical" />
+							</template>
+
+							<el-popconfirm title="确定要删除此代理吗?" @confirm="handleDelete(row)">
+								<el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false"
+									v-if="permission.includes('sys:agents:delete')">删除</el-link>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 查看详情弹窗 -->
+		<el-dialog :title="'代理详情'" :visible.sync="detailVisible" width="800px" :lock-scroll="false"
+			:destroy-on-close="true">
+			<el-descriptions :column="2" border v-loading="detailLoading">
+				<el-descriptions-item label="ID">{{ agentInfo.id }}</el-descriptions-item>
+				<el-descriptions-item label="代理姓名">{{ agentInfo.real_name }}</el-descriptions-item>
+				<el-descriptions-item label="联系电话">{{ agentInfo.phone }}</el-descriptions-item>
+				<el-descriptions-item label="身份证号">{{ agentInfo.idcard }}</el-descriptions-item>
+				<el-descriptions-item label="团队人数">{{ agentInfo.team_count || 0 }}</el-descriptions-item>
+				<el-descriptions-item label="代理订单">{{ agentInfo.order_count }}</el-descriptions-item>
+				<el-descriptions-item label="总佣金">
+					<span style="color: #f56c6c;">¥{{ agentInfo.income }}</span>
+				</el-descriptions-item>
+				<el-descriptions-item label="可提现余额">
+					<span style="color: #67c23a;">¥{{ agentInfo.balance }}</span>
+				</el-descriptions-item>
+				<el-descriptions-item label="累计提现">¥{{ agentInfo.withdraw_total }}</el-descriptions-item>
+				<el-descriptions-item label="申请时间">{{ agentInfo.create_time }}</el-descriptions-item>
+				<el-descriptions-item label="状态">
+					<el-tag v-if="agentInfo.status === 1" type="success" size="small">已审核</el-tag>
+					<el-tag v-else-if="agentInfo.status === 2" type="warning" size="small">待审核</el-tag>
+					<el-tag v-else-if="agentInfo.status === 3" type="danger" size="small">已驳回</el-tag>
+					<el-tag v-else-if="agentInfo.status === 4" type="info" size="small">已冻结</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="审核备注" :span="2">
+					{{ agentInfo.confirm_remark || '无' }}
+				</el-descriptions-item>
+			</el-descriptions>
+
+			<!-- 审核操作按钮 -->
+			<div slot="footer" class="dialog-footer" v-if="agentInfo.status === 2">
+				<el-button @click="detailVisible = false">关闭</el-button>
+				<el-button type="danger" @click="handleRejectInDetail"
+					v-if="permission.includes('sys:agents:edit')">驳回申请</el-button>
+				<el-button type="success" @click="handleAuditInDetail"
+					v-if="permission.includes('sys:agents:edit')">通过审核</el-button>
+			</div>
+			<div slot="footer" class="dialog-footer" v-else>
+				<el-button @click="detailVisible = false">关闭</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+export default {
+	name: "Agents",
+	computed: {
+		...mapGetters(["permission"]),
+	},
+	data() {
+		return {
+			table: {
+				url: '/agent/index',
+				where: {
+					status: 0  // 默认全部
+				}
+			},
+			choose: [],
+			statusTabs: [
+				{ value: '0', label: '全部', icon: 'el-icon-s-grid' },
+				{ value: '2', label: '待审核', icon: 'el-icon-warning' },
+				{ value: '1', label: '已审核', icon: 'el-icon-circle-check' },
+				{ value: '3', label: '已驳回', icon: 'el-icon-circle-close' },
+				{ value: '4', label: '已冻结', icon: 'el-icon-lock' },
+			],
+			activeStatus: '0',
+			detailVisible: false,
+			detailLoading: false,
+			agentInfo: {}
+		}
+	},
+	mounted() {
+		// 调试:输出权限信息
+		console.log('=== 代理管理权限调试 ===');
+		console.log('当前权限列表:', this.permission);
+		console.log('是否有查看权限:', this.permission.includes('sys:agents:index'));
+		console.log('是否有编辑权限:', this.permission.includes('sys:agents:edit'));
+		console.log('是否有状态权限:', this.permission.includes('sys:agents:status'));
+		console.log('是否有删除权限:', this.permission.includes('sys:agents:delete'));
+	},
+	methods: {
+		handleTabClick(tab) {
+			this.activeStatus = tab.name;
+			this.table.where.status = parseInt(tab.name);
+			this.$refs.table.reload();
+		},
+		handleReset() {
+			this.activeStatus = '0';
+			this.table.where = { status: 0 };
+			this.$refs.table.reload();
+		},
+		handleView(row) {
+			this.detailVisible = true;
+			this.detailLoading = true;
+			this.$http.get('/agent/info', { params: { id: row.id } }).then(res => {
+				this.detailLoading = false;
+				if (res.data.code === 0) {
+					this.agentInfo = res.data.data;
+					// 计算团队人数
+					this.agentInfo.team_count = row.team_count;
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(() => {
+				this.detailLoading = false;
+				this.$message.error('获取详情失败');
+			});
+		},
+		// 列表快捷通过审核
+		quickAudit(row, status) {
+			this.submitAudit(row.id, status, '审核通过');
+		},
+		// 列表驳回操作
+		handleReject(row) {
+			this.$prompt('请输入驳回原因', '驳回代理申请', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPattern: /.+/,
+				inputErrorMessage: '请输入驳回原因'
+			}).then(({ value }) => {
+				this.submitAudit(row.id, 3, value);
+			}).catch(() => { });
+		},
+		// 详情弹窗中的通过审核
+		handleAuditInDetail() {
+			this.$confirm('确定要通过此代理申请吗?', '审核通过', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'success'
+			}).then(() => {
+				this.submitAudit(this.agentInfo.id, 1, '审核通过');
+			}).catch(() => { });
+		},
+		// 详情弹窗中的驳回
+		handleRejectInDetail() {
+			this.$prompt('请输入驳回原因', '驳回代理申请', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPattern: /.+/,
+				inputErrorMessage: '请输入驳回原因'
+			}).then(({ value }) => {
+				this.submitAudit(this.agentInfo.id, 3, value);
+			}).catch(() => { });
+		},
+		submitAudit(id, status, remark) {
+			this.$http.post('/agent/audit', {
+				id: id,
+				status: status,
+				confirm_remark: remark
+			}).then(res => {
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.detailVisible = false;
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(() => {
+				this.$message.error('操作失败');
+			});
+		},
+		// 列表快捷冻结/解冻
+		quickFreeze(row, status) {
+			this.submitFreeze(row.id, status);
+		},
+		submitFreeze(id, status) {
+			this.$http.post('/agent/freeze', {
+				id: id,
+				status: status
+			}).then(res => {
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(() => {
+				this.$message.error('操作失败');
+			});
+		},
+		handleDelete(row) {
+			this.$http.post('/agent/delete', { id: row.id }).then(res => {
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(() => {
+				this.$message.error('删除失败');
+			});
+		},
+		// 批量通过审核
+		handleBatchAudit() {
+			if (!this.choose.length) {
+				this.$message.warning('请选择要审核的代理');
+				return;
+			}
+			this.$confirm(`确定要通过选中的 ${this.choose.length} 个代理申请吗?`, '批量审核', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'success'
+			}).then(() => {
+				let successCount = 0;
+				let failCount = 0;
+				const promises = this.choose.map(agent => {
+					return this.$http.post('/agent/audit', {
+						id: agent.id,
+						status: 1,
+						confirm_remark: '批量审核通过'
+					}).then(res => {
+						if (res.data.code === 0) {
+							successCount++;
+						} else {
+							failCount++;
+						}
+					}).catch(() => {
+						failCount++;
+					});
+				});
+
+				Promise.all(promises).then(() => {
+					if (successCount > 0) {
+						this.$message.success(`成功通过 ${successCount} 个代理申请${failCount > 0 ? `,失败 ${failCount} 个` : ''}`);
+					} else {
+						this.$message.error('批量审核失败');
+					}
+					this.$refs.table.reload();
+				});
+			}).catch(() => { });
+		},
+		// 批量驳回
+		handleBatchReject() {
+			if (!this.choose.length) {
+				this.$message.warning('请选择要驳回的代理');
+				return;
+			}
+			this.$prompt('请输入驳回原因', '批量驳回', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPattern: /.+/,
+				inputErrorMessage: '请输入驳回原因'
+			}).then(({ value }) => {
+				let successCount = 0;
+				let failCount = 0;
+				const promises = this.choose.map(agent => {
+					return this.$http.post('/agent/audit', {
+						id: agent.id,
+						status: 3,
+						confirm_remark: value
+					}).then(res => {
+						if (res.data.code === 0) {
+							successCount++;
+						} else {
+							failCount++;
+						}
+					}).catch(() => {
+						failCount++;
+					});
+				});
+
+				Promise.all(promises).then(() => {
+					if (successCount > 0) {
+						this.$message.success(`成功驳回 ${successCount} 个代理申请${failCount > 0 ? `,失败 ${failCount} 个` : ''}`);
+					} else {
+						this.$message.error('批量驳回失败');
+					}
+					this.$refs.table.reload();
+				});
+			}).catch(() => { });
+		}
+	}
+}
+</script>
+
+<style scoped>
+.ele-form-search {
+	margin-bottom: 15px;
+}
+
+/* 操作列按钮样式优化 */
+.el-link {
+	margin: 0 4px;
+}
+
+.el-divider--vertical {
+	margin: 0 6px;
+}
+</style>

+ 360 - 0
addons/admin/src/views/financial/accountLog.vue

@@ -0,0 +1,360 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<!-- 搜索表单 -->
+			<el-form :model="table.where" label-width="90px" class="ele-form-search" @keyup.enter.native="$refs.table.reload()" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="4" :sm="12">
+						<el-form-item label="交易类型:">
+							<el-select v-model="table.where.type" placeholder="请选择类型" clearable class="ele-fluid">
+								<el-option label="商城消费" :value="1"/>
+								<el-option label="充值缴费" :value="2"/>
+								<el-option label="商城退款" :value="3"/>
+								<el-option label="佣金提现" :value="4"/>
+								<el-option label="提现驳回" :value="5"/>
+								<el-option label="平台入款" :value="6"/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="4" :sm="12">
+						<el-form-item label="状态:">
+							<el-select v-model="table.where.status" placeholder="请选择状态" clearable class="ele-fluid">
+								<el-option label="已完成" :value="1"/>
+								<el-option label="待处理" :value="2"/>
+								<el-option label="失败/取消" :value="3"/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="5" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="table.where.keyword" placeholder="用户昵称/手机号" clearable/>
+						</el-form-item>
+					</el-col>
+					<el-col :md="5" :sm="12">
+						<el-form-item label="订单号:">
+							<el-input v-model="table.where.order_no" placeholder="请输入订单号" clearable/>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="$refs.table.reload()" icon="el-icon-search" class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset">重置</el-button>
+							<el-button @click="openEdit()" type="primary" icon="el-icon-plus" class="ele-btn-icon"
+								v-if="permission.includes('sys:accountLog:add')">添加</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 统计信息 -->
+			<div class="stat-cards" v-if="counts">
+				<el-row :gutter="15">
+					<el-col :span="12">
+						<div class="stat-card">
+							<div class="stat-label">总记录数</div>
+							<div class="stat-value">{{ counts.count || 0 }}</div>
+						</div>
+					</el-col>
+					<el-col :span="12">
+						<div class="stat-card">
+							<div class="stat-label">总金额</div>
+							<div class="stat-value amount">¥{{ counts.total || 0 }}</div>
+						</div>
+					</el-col>
+				</el-row>
+			</div>
+
+			<!-- 数据表格 -->
+			<ele-data-table
+				ref="table"
+				:config="table"
+				:choose.sync="selection"
+				:parse-data="parseData"
+				height="calc(100vh - 400px)">
+				<template slot-scope="{index}">
+					<el-table-column type="selection" width="45" align="center" fixed="left"/>
+					<el-table-column prop="id" label="ID" width="60" align="center" sortable="custom"/>
+					<el-table-column prop="mobile" label="用户手机" min-width="120" align="center"/>
+					<el-table-column prop="nickname" label="用户昵称" min-width="120" align="center"/>
+					<el-table-column prop="source_order_no" label="订单号" min-width="180" align="center" show-overflow-tooltip/>
+					
+					<!-- 交易类型 -->
+					<el-table-column label="交易类型" width="120" align="center">
+						<template slot-scope="{row}">
+							<el-tag :type="getTypeColor(row.type)" size="mini">{{ row.type_text }}</el-tag>
+						</template>
+					</el-table-column>
+					
+					<!-- 金额 -->
+					<el-table-column label="交易金额" width="120" align="center">
+						<template slot-scope="{row}">
+							<span :style="{color: getMoneyColor(row.type), fontWeight: 'bold'}">
+								{{ getMoneyPrefix(row.type) }}¥{{ row.money }}
+							</span>
+						</template>
+					</el-table-column>
+					
+					<el-table-column label="变更前金额" width="120" align="center">
+						<template slot-scope="{row}">
+							<span>¥{{ row.before_money }}</span>
+						</template>
+					</el-table-column>
+					
+					<!-- 状态 -->
+					<el-table-column label="状态" width="100" align="center">
+						<template slot-scope="{row}">
+							<el-tag :type="getStatusColor(row.status)" size="mini">{{ row.status_text }}</el-tag>
+						</template>
+					</el-table-column>
+					
+					<el-table-column prop="remark" label="备注" min-width="150" align="center" show-overflow-tooltip/>
+					<el-table-column prop="create_time_text" label="创建时间" min-width="160" align="center" show-overflow-tooltip/>
+					
+					<!-- 操作 -->
+					<el-table-column label="操作" width="180" align="center" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="openEdit(row)" icon="el-icon-edit" type="primary" :underline="false" 
+								v-if="permission.includes('sys:accountLog:edit')" style="margin-right: 10px;">修改</el-link>
+							<el-popconfirm title="确定要删除此记录吗?" @confirm="remove(row)" 
+								v-if="permission.includes('sys:accountLog:delete')">
+								<el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false">删除</el-link>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 编辑弹窗 -->
+		<el-dialog :title="editForm.id ? '修改财务明细' : '添加财务明细'" :visible.sync="editVisible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
+			<el-form :model="editForm" :rules="editRules" ref="editForm" label-width="120px">
+				<el-form-item label="用户ID:" prop="user_id">
+					<el-input-number v-model="editForm.user_id" :min="1" controls-position="right" class="ele-fluid" placeholder="请输入用户ID"/>
+				</el-form-item>
+				<el-form-item label="订单号:">
+					<el-input v-model="editForm.source_order_no" placeholder="请输入关联订单号" clearable/>
+				</el-form-item>
+				<el-form-item label="交易类型:" prop="type">
+					<el-select v-model="editForm.type" placeholder="请选择交易类型" class="ele-fluid">
+						<el-option label="商城消费" :value="1"/>
+						<el-option label="充值缴费" :value="2"/>
+						<el-option label="商城退款" :value="3"/>
+						<el-option label="佣金提现" :value="4"/>
+						<el-option label="提现驳回" :value="5"/>
+						<el-option label="平台入款" :value="6"/>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="交易金额:" prop="money">
+					<el-input-number v-model="editForm.money" :min="0" :precision="2" controls-position="right" class="ele-fluid" placeholder="请输入交易金额"/>
+					<div class="el-form-item__tip">单位:元</div>
+				</el-form-item>
+				<el-form-item label="变更前金额:" prop="before_money">
+					<el-input-number v-model="editForm.before_money" :min="0" :precision="2" controls-position="right" class="ele-fluid" placeholder="请输入变更前金额"/>
+					<div class="el-form-item__tip">单位:元</div>
+				</el-form-item>
+				<el-form-item label="备注:">
+					<el-input v-model="editForm.remark" type="textarea" :rows="3" placeholder="请输入备注信息" maxlength="150"/>
+				</el-form-item>
+				<el-form-item label="状态:" prop="status">
+					<el-radio-group v-model="editForm.status">
+						<el-radio :label="1">已完成</el-radio>
+						<el-radio :label="2">待处理</el-radio>
+						<el-radio :label="3">失败/取消</el-radio>
+					</el-radio-group>
+				</el-form-item>
+			</el-form>
+			<div slot="footer">
+				<el-button @click="editVisible = false">取消</el-button>
+				<el-button type="primary" @click="save" :loading="saveLoading">保存</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+export default {
+	name: "AccountLog",
+	computed: {
+		...mapGetters(["permission"]),
+	},
+	data() {
+		return {
+			// 表格配置
+			table: {
+				url: '/account/index',
+				where: {
+					type: '',
+					status: '',
+					keyword: '',
+					order_no: ''
+				}
+			},
+			selection: [], // 表格选中数据
+			counts: null, // 统计数据
+			editVisible: false, // 是否显示编辑弹窗
+			saveLoading: false, // 保存按钮loading
+			editForm: {}, // 编辑表单数据
+			editRules: {
+				user_id: [
+					{ required: true, message: '请输入用户ID', trigger: 'blur' }
+				],
+				type: [
+					{ required: true, message: '请选择交易类型', trigger: 'change' }
+				],
+				money: [
+					{ required: true, message: '请输入交易金额', trigger: 'blur' }
+				],
+				before_money: [
+					{ required: true, message: '请输入变更前金额', trigger: 'blur' }
+				],
+				status: [
+					{ required: true, message: '请选择状态', trigger: 'change' }
+				]
+			}
+		};
+	},
+	methods: {
+		/* 解析表格数据 */
+		parseData(res) {
+			if (res.data && res.data.counts) {
+				this.counts = res.data.counts;
+			}
+			return res;
+		},
+		
+		/* 重置搜索 */
+		handleReset() {
+			this.table.where = {
+				type: '',
+				status: '',
+				keyword: '',
+				order_no: ''
+			};
+			this.$refs.table.reload();
+		},
+		
+		/* 打开编辑弹窗 */
+		openEdit(row) {
+			if (row && row.id) {
+				this.editForm = Object.assign({}, row);
+			} else {
+				this.editForm = {
+					user_id: null,
+					source_order_no: '',
+					type: 1,
+					money: 0,
+					before_money: 0,
+					remark: '',
+					status: 1
+				};
+			}
+			this.editVisible = true;
+		},
+		
+		/* 保存 */
+		save() {
+			this.$refs.editForm.validate((valid) => {
+				if (valid) {
+					this.saveLoading = true;
+					const url = this.editForm.id ? '/account/edit' : '/account/add';
+					this.$http.post(url, this.editForm).then(res => {
+						this.saveLoading = false;
+						if (res.data.code === 0) {
+							this.$message.success(res.data.msg);
+							this.editVisible = false;
+							this.$refs.table.reload();
+						} else {
+							this.$message.error(res.data.msg);
+						}
+					}).catch(e => {
+						this.saveLoading = false;
+						this.$message.error(e.message);
+					});
+				}
+			});
+		},
+		
+		/* 删除 */
+		remove(row) {
+			const loading = this.$loading({ lock: true });
+			this.$http.post('/account/delete', { id: row.id }).then(res => {
+				loading.close();
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(e => {
+				loading.close();
+				this.$message.error(e.message);
+			});
+		},
+		
+		/* 获取类型颜色 */
+		getTypeColor(type) {
+			const colors = {
+				1: 'danger',    // 商城消费
+				2: 'success',   // 充值缴费
+				3: 'warning',   // 商城退款
+				4: 'primary',   // 佣金提现
+				5: 'info',      // 提现驳回
+				6: 'success'    // 平台入款
+			};
+			return colors[type] || '';
+		},
+		
+		/* 获取金额颜色 */
+		getMoneyColor(type) {
+			// 1-商城消费,4-佣金提现 为支出(红色)
+			// 2-充值缴费,3-商城退款,5-提现驳回,6-平台入款 为收入(绿色)
+			return [1, 4].includes(type) ? '#F56C6C' : '#67C23A';
+		},
+		
+		/* 获取金额前缀 */
+		getMoneyPrefix(type) {
+			return [1, 4].includes(type) ? '-' : '+';
+		},
+		
+		/* 获取状态颜色 */
+		getStatusColor(status) {
+			const colors = {
+				1: 'success',  // 已完成
+				2: 'warning',  // 待处理
+				3: 'danger'    // 失败/取消
+			};
+			return colors[status] || '';
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.stat-cards {
+	margin-bottom: 15px;
+	
+	.stat-card {
+		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+		border-radius: 8px;
+		padding: 20px;
+		color: white;
+		
+		.stat-label {
+			font-size: 14px;
+			opacity: 0.9;
+			margin-bottom: 8px;
+		}
+		
+		.stat-value {
+			font-size: 28px;
+			font-weight: bold;
+			
+			&.amount {
+				color: #ffd700;
+			}
+		}
+	}
+}
+</style>

+ 24 - 0
addons/admin/src/views/financial/agentWithdraw.vue

@@ -0,0 +1,24 @@
+<template>
+	<balance-logs 
+		:default-account-type="2" 
+		:default-type="2"
+		:show-account-type-filter="false"
+		:show-type-filter="false"
+		title="代理提现管理"
+		permission-prefix="sys:agentWithdraw"
+	/>
+</template>
+
+<script>
+import BalanceLogs from './balanceLogs.vue';
+
+export default {
+	name: "AgentWithdraw",
+	components: {
+		BalanceLogs
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 439 - 0
addons/admin/src/views/financial/balanceLogs.vue

@@ -0,0 +1,439 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<!-- 状态 Tab 标签页 -->
+			<el-tabs v-model="activeTab" @tab-click="handleTabClick" class="ele-tabs-card">
+				<el-tab-pane label="全部" name="all"></el-tab-pane>
+				<el-tab-pane label="待审核" name="1"></el-tab-pane>
+				<el-tab-pane label="已审核/到账" name="2"></el-tab-pane>
+				<el-tab-pane label="审核失败" name="3"></el-tab-pane>
+				<el-tab-pane label="已取消" name="-1"></el-tab-pane>
+			</el-tabs>
+
+			<!-- 搜索表单 -->
+			<el-form :model="table.where" label-width="80px" class="ele-form-search" @keyup.enter.native="$refs.table.reload()" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="4" :sm="12" v-if="showAccountTypeFilter">
+						<el-form-item label="账户类型:">
+							<el-select clearable v-model="table.where.account_type" placeholder="请选择账户类型" class="ele-fluid">
+								<el-option label="会员账户" :value="1"/>
+								<el-option label="代理账户" :value="2"/>
+								<el-option label="商户账户" :value="3"/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="4" :sm="12" v-if="showTypeFilter">
+						<el-form-item label="类型:">
+							<el-select clearable v-model="table.where.type" placeholder="请选择类型" class="ele-fluid">
+								<el-option label="充值" :value="1"/>
+								<el-option label="提现" :value="2"/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input clearable v-model="table.where.keyword" placeholder="订单号/姓名/手机号"/>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<el-form-item label="时间范围:">
+							<el-date-picker
+								v-model="dateRange"
+								type="daterange"
+								range-separator="至"
+								start-placeholder="开始日期"
+								end-placeholder="结束日期"
+								value-format="yyyy-MM-dd"
+								class="ele-fluid">
+							</el-date-picker>
+						</el-form-item>
+					</el-col>
+					<el-col :md="4" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" icon="el-icon-search" class="ele-btn-icon" @click="$refs.table.reload()">查询</el-button>
+							<el-button @click="reset">重置</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 数据表格 -->
+			<ele-data-table
+				ref="table"
+				:config="table"
+				:choose.sync="selection"
+				height="calc(100vh - 350px)">
+				<template slot-scope="{index}">
+					<el-table-column type="selection" width="45" align="center" fixed="left"/>
+					<el-table-column prop="id" label="ID" width="60" align="center" sortable="custom"/>
+					<el-table-column prop="order_no" label="订单号" min-width="180" align="center" show-overflow-tooltip/>
+					
+					<!-- 账户类型 -->
+					<el-table-column label="账户类型" width="100" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.account_type === 1" type="success" size="mini">会员</el-tag>
+							<el-tag v-else-if="row.account_type === 2" type="warning" size="mini">代理</el-tag>
+							<el-tag v-else-if="row.account_type === 3" type="info" size="mini">商户</el-tag>
+						</template>
+					</el-table-column>
+					
+					<!-- 类型 -->
+					<el-table-column label="类型" width="80" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.type === 1" type="success" size="mini">充值</el-tag>
+							<el-tag v-else-if="row.type === 2" type="primary" size="mini">提现</el-tag>
+						</template>
+					</el-table-column>
+					
+					<el-table-column prop="realname" label="姓名/商户" min-width="120" align="center" show-overflow-tooltip/>
+					
+					<!-- 金额 -->
+					<el-table-column label="金额" min-width="120" align="center">
+						<template slot-scope="{row}">
+							<span :style="{color: row.type === 1 ? '#67C23A' : '#F56C6C', fontWeight: 'bold'}">
+								{{ row.type === 1 ? '+' : '-' }}¥{{ row.money }}
+							</span>
+						</template>
+					</el-table-column>
+					
+					<!-- 实际到账 -->
+					<el-table-column label="实际到账" min-width="120" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #409EFF; font-weight: bold;">¥{{ row.actual_money }}</span>
+						</template>
+					</el-table-column>
+					
+					<!-- 支付方式 -->
+					<el-table-column label="支付方式" width="100" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.pay_type === 10" type="success" size="mini">微信</el-tag>
+							<el-tag v-else-if="row.pay_type === 20" type="primary" size="mini">支付宝</el-tag>
+							<el-tag v-else-if="row.pay_type === 50" type="info" size="mini">银行卡</el-tag>
+						</template>
+					</el-table-column>
+					
+					<!-- 状态 -->
+					<el-table-column label="状态" width="120" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.status === -1" type="info" size="mini">已取消</el-tag>
+							<el-tag v-else-if="row.status === 1" type="warning" size="mini">待审核</el-tag>
+							<el-tag v-else-if="row.status === 2" type="success" size="mini">已审核/到账</el-tag>
+							<el-tag v-else-if="row.status === 3" type="danger" size="mini">审核失败</el-tag>
+						</template>
+					</el-table-column>
+					
+					<el-table-column prop="create_time_text" label="申请时间" min-width="160" align="center" show-overflow-tooltip/>
+					
+					<!-- 操作 -->
+					<el-table-column label="操作" width="240" align="center" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="openDetail(row)" icon="el-icon-view" type="primary" :underline="false" style="margin-right: 10px;">查看</el-link>
+							<el-link v-if="row.status === 1 && row.type === 2 && permission.includes(permissionPrefix + ':edit')" 
+								@click="openAudit(row)" icon="el-icon-check" type="success" :underline="false" style="margin-right: 10px;">审核</el-link>
+							<el-popconfirm title="确定要删除此记录吗?" @confirm="remove(row)" 
+								v-if="row.status !== 1 && permission.includes(permissionPrefix + ':delete')">
+								<el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false">删除</el-link>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 详情弹窗 -->
+		<el-dialog :visible.sync="detailVisible" title="详情" width="700px" :destroy-on-close="true">
+			<el-descriptions :column="2" border v-if="detailData">
+				<el-descriptions-item label="订单号">{{ detailData.order_no }}</el-descriptions-item>
+				<el-descriptions-item label="账户类型">
+					<el-tag v-if="detailData.account_type === 1" type="success" size="mini">会员</el-tag>
+					<el-tag v-else-if="detailData.account_type === 2" type="warning" size="mini">代理</el-tag>
+					<el-tag v-else-if="detailData.account_type === 3" type="info" size="mini">商户</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="类型">
+					<el-tag v-if="detailData.type === 1" type="success" size="mini">充值</el-tag>
+					<el-tag v-else-if="detailData.type === 2" type="primary" size="mini">提现</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="姓名">{{ detailData.realname }}</el-descriptions-item>
+				<el-descriptions-item label="金额">
+					<span :style="{color: detailData.type === 1 ? '#67C23A' : '#F56C6C', fontWeight: 'bold'}">
+						{{ detailData.type === 1 ? '+' : '-' }}¥{{ detailData.money }}
+					</span>
+				</el-descriptions-item>
+				<el-descriptions-item label="实际到账金额">
+					<span style="color: #409EFF; font-weight: bold;">¥{{ detailData.actual_money }}</span>
+				</el-descriptions-item>
+				<el-descriptions-item label="支付方式">
+					<el-tag v-if="detailData.pay_type === 10" type="success" size="mini">微信</el-tag>
+					<el-tag v-else-if="detailData.pay_type === 20" type="primary" size="mini">支付宝</el-tag>
+					<el-tag v-else-if="detailData.pay_type === 50" type="info" size="mini">银行卡</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="支付状态">
+					<el-tag v-if="detailData.pay_status === 10" type="warning" size="mini">待支付</el-tag>
+					<el-tag v-else-if="detailData.pay_status === 20" type="success" size="mini">已支付</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="提现账号" v-if="detailData.type === 2">{{ detailData.account }}</el-descriptions-item>
+				<el-descriptions-item label="账号备注" v-if="detailData.type === 2">{{ detailData.account_remark }}</el-descriptions-item>
+				<el-descriptions-item label="状态">
+					<el-tag v-if="detailData.status === -1" type="info" size="mini">已取消</el-tag>
+					<el-tag v-else-if="detailData.status === 1" type="warning" size="mini">待审核</el-tag>
+					<el-tag v-else-if="detailData.status === 2" type="success" size="mini">已审核/到账</el-tag>
+					<el-tag v-else-if="detailData.status === 3" type="danger" size="mini">审核失败</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="申请时间">{{ detailData.create_time_text }}</el-descriptions-item>
+				<el-descriptions-item label="处理时间">{{ detailData.update_time_text }}</el-descriptions-item>
+				<el-descriptions-item label="付款时间" v-if="detailData.pay_at">{{ detailData.pay_at }}</el-descriptions-item>
+				<el-descriptions-item label="支付交易号" v-if="detailData.transaction_id">{{ detailData.transaction_id }}</el-descriptions-item>
+				<el-descriptions-item label="打款凭证" :span="2" v-if="detailData.pay_img">
+					<el-image :src="detailData.pay_img" style="width: 200px; height: 200px;" :preview-src-list="[detailData.pay_img]"></el-image>
+				</el-descriptions-item>
+				<el-descriptions-item label="审核备注" :span="2" v-if="detailData.confirm_remark">{{ detailData.confirm_remark }}</el-descriptions-item>
+			</el-descriptions>
+		</el-dialog>
+
+		<!-- 审核弹窗 -->
+		<el-dialog :visible.sync="auditVisible" title="审核" width="500px" :destroy-on-close="true">
+			<el-form :model="auditForm" :rules="auditRules" ref="auditForm" label-width="100px">
+				<el-form-item label="金额:">
+					<span style="color: #F56C6C; font-weight: bold; font-size: 18px;">¥{{ auditForm.money }}</span>
+				</el-form-item>
+				<el-form-item label="审核结果:" prop="status">
+					<el-radio-group v-model="auditForm.status">
+						<el-radio :label="2">通过</el-radio>
+						<el-radio :label="3">驳回</el-radio>
+					</el-radio-group>
+				</el-form-item>
+				<el-form-item label="审核备注:" prop="remark">
+					<el-input type="textarea" v-model="auditForm.remark" :rows="3" placeholder="请输入审核备注"/>
+				</el-form-item>
+				<el-form-item label="打款凭证:" v-if="auditForm.status === 2">
+					<upload-image v-model="auditForm.pay_img" :limit="1" />
+					<div class="el-form-item__tip">建议尺寸:800x600像素,支持jpg、png格式</div>
+				</el-form-item>
+			</el-form>
+			<div slot="footer">
+				<el-button @click="auditVisible = false">取消</el-button>
+				<el-button type="primary" @click="submitAudit" :loading="auditLoading">提交</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+import UploadImage from "@/components/uploadImage";
+
+export default {
+	name: "BalanceLogs",
+	components: {
+		UploadImage
+	},
+	props: {
+		// 默认账户类型(1-会员,2-代理,3-商户)
+		defaultAccountType: {
+			type: Number,
+			default: null
+		},
+		// 默认类型(1-充值,2-提现)
+		defaultType: {
+			type: Number,
+			default: 2
+		},
+		// 是否显示账户类型筛选
+		showAccountTypeFilter: {
+			type: Boolean,
+			default: true
+		},
+		// 是否显示类型筛选
+		showTypeFilter: {
+			type: Boolean,
+			default: true
+		},
+		// 页面标题
+		title: {
+			type: String,
+			default: ''
+		},
+		// 权限前缀(如:sys:agentWithdraw, sys:storesWithdraw, sys:balanceLogs)
+		permissionPrefix: {
+			type: String,
+			default: 'sys:balanceLogs'
+		}
+	},
+	computed: {
+		...mapGetters(["permission"])
+	},
+	data() {
+		return {
+			// 表格配置
+			table: {
+				url: '/financial/balanceLogs/index',
+				where: {}
+			},
+			// 当前激活的 Tab
+			activeTab: 'all',
+			// 日期范围
+			dateRange: [],
+			// 表格选中数据
+			selection: [],
+			// 详情弹窗
+			detailVisible: false,
+			detailData: null,
+			// 审核弹窗
+			auditVisible: false,
+			auditForm: {
+				id: null,
+				account_type: null,
+				money: '',
+				status: 2,
+				remark: '',
+				pay_img: ''
+			},
+			auditRules: {
+				status: [
+					{required: true, message: '请选择审核结果', trigger: 'change'}
+				]
+			},
+			auditLoading: false
+		}
+	},
+	mounted() {
+		// 初始化默认筛选条件
+		if (this.defaultAccountType !== null) {
+			this.table.where.account_type = this.defaultAccountType;
+		}
+		if (this.defaultType !== null) {
+			this.table.where.type = this.defaultType;
+		}
+	},
+	watch: {
+		dateRange(val) {
+			if (val && val.length === 2) {
+				this.table.where.start_time = val[0];
+				this.table.where.end_time = val[1];
+			} else {
+				this.table.where.start_time = '';
+				this.table.where.end_time = '';
+			}
+		}
+	},
+	methods: {
+		/* Tab 切换 */
+		handleTabClick(tab) {
+			if (this.activeTab === 'all') {
+				// 全部 - 不筛选状态
+				delete this.table.where.status;
+			} else {
+				// 按状态筛选
+				this.table.where.status = parseInt(this.activeTab);
+			}
+			this.$refs.table.reload();
+		},
+		/* 重置搜索 */
+		reset() {
+			this.table.where = {};
+			this.activeTab = 'all';
+			// 重置时恢复默认值
+			if (this.defaultAccountType !== null) {
+				this.table.where.account_type = this.defaultAccountType;
+			}
+			if (this.defaultType !== null) {
+				this.table.where.type = this.defaultType;
+			}
+			this.dateRange = [];
+			this.$refs.table.reload();
+		},
+		/* 打开详情 */
+		openDetail(row) {
+			this.$http.get('/financial/balanceLogs/info', {params: {id: row.id}}).then(res => {
+				if (res.data.code === 0) {
+					this.detailData = res.data.data;
+					this.detailVisible = true;
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			});
+		},
+		/* 打开审核弹窗 */
+		openAudit(row) {
+			this.auditForm = {
+				id: row.id,
+				account_type: row.account_type,
+				money: row.money,
+				status: 2,
+				remark: '',
+				pay_img: ''
+			};
+			this.auditVisible = true;
+		},
+		/* 提交审核 */
+		submitAudit() {
+			this.$refs.auditForm.validate(valid => {
+				if (valid) {
+					this.auditLoading = true;
+					this.$http.post('/financial/balanceLogs/audit', this.auditForm).then(res => {
+						this.auditLoading = false;
+						if (res.data.code === 0) {
+							this.$message.success(res.data.msg);
+							this.auditVisible = false;
+							this.$refs.table.reload();
+						} else {
+							this.$message.error(res.data.msg);
+						}
+					}).catch(() => {
+						this.auditLoading = false;
+					});
+				}
+			});
+		},
+		/* 删除 */
+		remove(row) {
+			if (!row) {
+				// 批量删除
+				if (!this.selection.length) {
+					this.$message.error('请至少选择一条数据');
+					return;
+				}
+				const ids = this.selection.map(d => d.id);
+				this.$confirm('确定要删除选中的记录吗?', '提示', {type: 'warning'}).then(() => {
+					this.$http.post('/financial/balanceLogs/deleteAll', {ids}).then(res => {
+						if (res.data.code === 0) {
+							this.$message.success(res.data.msg);
+							this.$refs.table.reload();
+						} else {
+							this.$message.error(res.data.msg);
+						}
+					});
+				}).catch(() => {});
+			} else {
+				// 单个删除
+				this.$http.post('/financial/balanceLogs/delete', {id: row.id}).then(res => {
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				});
+			}
+		}
+	}
+}
+</script>
+
+<style scoped>
+/* Tab 标签页样式 */
+.ele-tabs-card {
+	margin-bottom: 15px;
+}
+.ele-tabs-card >>> .el-tabs__header {
+	margin: 0 0 15px;
+}
+.ele-tabs-card >>> .el-tabs__item {
+	height: 40px;
+	line-height: 40px;
+	font-size: 14px;
+}
+.ele-tabs-card >>> .el-tabs__nav-wrap::after {
+	height: 1px;
+}
+</style>

+ 162 - 0
addons/admin/src/views/financial/components/StatisticsTable.vue

@@ -0,0 +1,162 @@
+<template>
+	<div style="margin-top: 20px;">
+		<!-- 筛选条件 -->
+		<el-form :model="query" inline class="filter-form">
+			<el-form-item label="分组方式">
+				<el-select v-model="query.group_by" @change="loadData" style="width: 120px;">
+					<el-option label="按年" value="year"></el-option>
+					<el-option label="按月" value="month"></el-option>
+					<el-option label="按日" value="day"></el-option>
+				</el-select>
+			</el-form-item>
+			<el-form-item label="时间范围">
+				<el-date-picker v-model="query.date_range" type="daterange" range-separator="至" start-placeholder="开始日期"
+					end-placeholder="结束日期" value-format="yyyy-MM-dd" @change="loadData">
+				</el-date-picker>
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary" icon="el-icon-search" @click="loadData">查询</el-button>
+				<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
+			</el-form-item>
+		</el-form>
+
+		<!-- 统计表格 -->
+		<el-table :data="tableData" v-loading="loading" border stripe>
+			<el-table-column prop="date" label="时间" min-width="150" align="center" />
+			<template v-if="type === 'order'">
+				<el-table-column prop="count" label="订单数" min-width="120" align="center" />
+			</template>
+			<template v-else-if="type === 'revenue'">
+				<el-table-column prop="amount" label="营业额" min-width="150" align="center">
+					<template slot-scope="{row}">
+						<span style="color: #67C23A; font-weight: bold;">¥{{ row.amount }}</span>
+					</template>
+				</el-table-column>
+			</template>
+			<template v-else-if="type === 'refund'">
+				<el-table-column prop="count" label="退款订单数" min-width="120" align="center" />
+				<el-table-column prop="amount" label="退款金额" min-width="150" align="center">
+					<template slot-scope="{row}">
+						<span style="color: #F56C6C; font-weight: bold;">¥{{ row.amount }}</span>
+					</template>
+				</el-table-column>
+			</template>
+			<template v-else-if="type === 'settlement'">
+				<el-table-column prop="amount" label="结算金额" min-width="150" align="center">
+					<template slot-scope="{row}">
+						<span style="color: #409EFF; font-weight: bold;">¥{{ row.amount }}</span>
+					</template>
+				</el-table-column>
+			</template>
+			<template v-else-if="type === 'member'">
+				<el-table-column prop="count" label="新增会员数" min-width="120" align="center" />
+			</template>
+		</el-table>
+
+		<!-- 分页 -->
+		<el-pagination v-if="total > 0" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+			:current-page="query.page" :page-sizes="[10, 20, 50, 100]" :page-size="query.limit" :total="total"
+			layout="total, sizes, prev, pager, next, jumper" style="margin-top: 20px; text-align: right;">
+		</el-pagination>
+	</div>
+</template>
+
+<script>
+export default {
+	name: 'StatisticsTable',
+	props: {
+		type: {
+			type: String,
+			required: true
+		}
+	},
+	data() {
+		return {
+			loading: false,
+			query: {
+				group_by: 'day',
+				date_range: [],
+				page: 1,
+				limit: 20
+			},
+			tableData: [],
+			total: 0
+		}
+	},
+	mounted() {
+		// 默认查询最近30天
+		const end = new Date();
+		const start = new Date();
+		start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+		this.query.date_range = [
+			this.formatDate(start),
+			this.formatDate(end)
+		];
+		this.loadData();
+	},
+	methods: {
+		loadData() {
+			this.loading = true;
+			const params = {
+				type: this.type,
+				group_by: this.query.group_by,
+				page: this.query.page,
+				limit: this.query.limit
+			};
+
+			if (this.query.date_range && this.query.date_range.length === 2) {
+				params.start_date = this.query.date_range[0];
+				params.end_date = this.query.date_range[1];
+			}
+
+			this.$http.get('/financial/list', { params }).then(res => {
+				this.loading = false;
+				if (res.data.code === 0) {
+					this.tableData = res.data.data || [];
+					this.total = res.data.count || 0;
+				} else {
+					this.$message.error(res.data.msg || '数据加载失败');
+				}
+			}).catch(() => {
+				this.loading = false;
+				this.$message.error('数据加载失败');
+			});
+		},
+		handleReset() {
+			const end = new Date();
+			const start = new Date();
+			start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+			this.query = {
+				group_by: 'day',
+				date_range: [
+					this.formatDate(start),
+					this.formatDate(end)
+				],
+				page: 1,
+				limit: 20
+			};
+			this.loadData();
+		},
+		handleSizeChange(val) {
+			this.query.limit = val;
+			this.loadData();
+		},
+		handleCurrentChange(val) {
+			this.query.page = val;
+			this.loadData();
+		},
+		formatDate(date) {
+			const year = date.getFullYear();
+			const month = String(date.getMonth() + 1).padStart(2, '0');
+			const day = String(date.getDate()).padStart(2, '0');
+			return `${year}-${month}-${day}`;
+		}
+	}
+}
+</script>
+
+<style scoped>
+.filter-form {
+	margin-bottom: 20px;
+}
+</style>

+ 47 - 0
addons/admin/src/views/financial/financial.vue

@@ -0,0 +1,47 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<!-- Tab 切换 -->
+			<el-tabs v-model="activeTab">
+				<el-tab-pane label="订单统计" name="order">
+					<statistics-table type="order" />
+				</el-tab-pane>
+				<el-tab-pane label="营业额统计" name="revenue">
+					<statistics-table type="revenue" />
+				</el-tab-pane>
+				<el-tab-pane label="退款统计" name="refund">
+					<statistics-table type="refund" />
+				</el-tab-pane>
+				<el-tab-pane label="结算统计" name="settlement">
+					<statistics-table type="settlement" />
+				</el-tab-pane>
+				<el-tab-pane label="会员统计" name="member">
+					<statistics-table type="member" />
+				</el-tab-pane>
+			</el-tabs>
+		</el-card>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+import StatisticsTable from "./components/StatisticsTable.vue";
+
+export default {
+	name: "Financial",
+	components: {
+		StatisticsTable
+	},
+	computed: {
+		...mapGetters(["permission"]),
+	},
+	data() {
+		return {
+			activeTab: 'order'
+		}
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 24 - 0
addons/admin/src/views/financial/storesWithdraw.vue

@@ -0,0 +1,24 @@
+<template>
+	<balance-logs 
+		:default-account-type="3" 
+		:default-type="2"
+		:show-account-type-filter="false"
+		:show-type-filter="false"
+		title="商家提现管理"
+		permission-prefix="sys:storesWithdraw"
+	/>
+</template>
+
+<script>
+import BalanceLogs from './balanceLogs.vue';
+
+export default {
+	name: "StoresWithdraw",
+	components: {
+		BalanceLogs
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 63 - 27
addons/admin/src/views/member/member/index.vue

@@ -52,18 +52,27 @@
               <el-image v-else shape="square" style="width: 60px;height: 60px;border-radius: 4px;" :src="avatar" lazy/>
             </template>
           </el-table-column>
-          <el-table-column prop="mobile" label="号" min-width="120"/>
+          <el-table-column prop="mobile" label="手机号" min-width="120"/>
           <el-table-column prop="nickname" label="昵称" min-width="120"/>
           <el-table-column prop="realname" label="姓名" min-width="100"/>
-          <el-table-column prop="balance" label="余额" sortable="custom" min-width="120">
-            <template  slot-scope="{row}">
-              <span class="ele-text-warning">{{row.balance}}</span>
+          <el-table-column prop="gender_text" label="性别" width="80" align="center"/>
+          <el-table-column prop="member_level" label="会员等级" width="90" align="center">
+            <template slot-scope="{row}">
+              <el-tag v-if="row.member_level > 0" type="warning" size="mini">LV{{ row.member_level }}</el-tag>
+              <span v-else>-</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="balance" label="余额" sortable="custom" width="120" align="center">
+            <template slot-scope="{row}">
+              <span class="ele-text-warning">¥{{ row.balance }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="status" label="状态" min-width="100">
+          <el-table-column prop="user_type_text" label="用户类型" width="100" align="center"/>
+          <el-table-column prop="login_time_text" label="最近登录" min-width="160" align="center" show-overflow-tooltip/>
+          <el-table-column prop="status" label="状态" width="100" align="center">
             <template slot-scope="{row}">
               <ele-dot :type="['danger', 'success'][row.status]" :ripple="row.status===0"
-                       :text="['禁用','正常'][row.status]"/>
+                       :text="['冻结','正常'][row.status]"/>
             </template>
           </el-table-column>
           <el-table-column label="操作" width="200px" align="center" :resizable="false"  fixed="right">
@@ -71,7 +80,6 @@
               <el-link @click="edit(row)" icon="el-icon-edit" type="primary" :underline="false" v-if="permission.includes('sys:member:edit')">修改</el-link>
               <el-link @click="showOrder(row)" icon="el-icon-view" type="success" :underline="false" v-if="permission.includes('sys:member:edit')">订单</el-link>
               <el-link @click="showAccount(row)" icon="el-icon-view" type="primary" :underline="false" v-if="permission.includes('sys:member:edit')">账户</el-link>
-              <el-link @click="showDeposit(row)" icon="el-icon-view" type="warning" :underline="false" v-if="permission.includes('sys:member:edit')">保证金</el-link>
               <el-popconfirm title="确定要删除此用户吗?" @confirm="remove(row)" class="ele-action" v-if="permission.includes('sys:member:delete')">
                 <el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false" >删除</el-link>
               </el-popconfirm>
@@ -92,31 +100,52 @@
             <el-form-item label="手机号:" prop="mobile">
               <el-input v-model="editForm.mobile" placeholder="请输入手机号" maxlength="11" clearable/>
             </el-form-item>
-            <el-form-item v-if="editForm.id"  label="登录密码:" prop="password1">
-              <el-input v-model="editForm.password" type="password" maxlength="20" placeholder="请输入登录密码(空不修改)" clearable>
-              </el-input>
+            <el-form-item v-if="editForm.id" label="登录密码:" prop="password1">
+              <el-input v-model="editForm.password" type="password" maxlength="20" placeholder="请输入登录密码(空不修改)" clearable/>
             </el-form-item>
-            <el-form-item v-else  label="登录密码:" prop="password">
-              <el-input v-model="editForm.password" type="password" maxlength="20" placeholder="请输入登录密码" clearable>
-              </el-input>
+            <el-form-item v-else label="登录密码:" prop="password">
+              <el-input v-model="editForm.password" type="password" maxlength="20" placeholder="请输入登录密码" clearable/>
             </el-form-item>
             <el-form-item label="昵称:" prop="nickname">
               <el-input v-model="editForm.nickname" placeholder="请输入账号昵称" maxlength="30" clearable/>
             </el-form-item>
+            <el-form-item label="真实姓名:" prop="realname">
+              <el-input v-model="editForm.realname" placeholder="请输入真实姓名" maxlength="20" clearable/>
+            </el-form-item>
+            <el-form-item label="性别:">
+              <el-radio-group v-model="editForm.gender">
+                <el-radio :label="1">男</el-radio>
+                <el-radio :label="2">女</el-radio>
+                <el-radio :label="3">未知</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="会员等级:">
+              <el-input-number v-model="editForm.member_level" :min="0" :max="99" controls-position="right" class="ele-fluid"/>
+            </el-form-item>
           </el-col>
           <el-col :sm="12">
-            <el-row>
-              <el-form-item  label="姓名:" prop="realname">
-                <el-input v-model="editForm.realname" placeholder="请输入真实姓名" maxlength="20" clearable>
-                </el-input>
-              </el-form-item>
-              <el-form-item label="状态:" prop="status">
-                <el-radio-group v-model="editForm.status">
-                  <el-radio :label="1">正常</el-radio>
-                  <el-radio :label="2">已冻结</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-row>
+            <el-form-item label="账户余额:">
+              <el-input-number v-model="editForm.balance" :min="0" :precision="2" controls-position="right" class="ele-fluid"/>
+              <div class="el-form-item__tip">单位:元</div>
+            </el-form-item>
+            <el-form-item label="个性签名:">
+              <el-input v-model="editForm.signature" placeholder="请输入个性签名" maxlength="30" clearable/>
+            </el-form-item>
+            <el-form-item label="个人简介:">
+              <el-input v-model="editForm.intro" type="textarea" :rows="3" placeholder="请输入个人简介" maxlength="200"/>
+            </el-form-item>
+            <el-form-item label="用户类型:">
+              <el-radio-group v-model="editForm.user_type">
+                <el-radio :label="1">用户</el-radio>
+                <el-radio :label="2">其他</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="状态:" prop="status">
+              <el-radio-group v-model="editForm.status">
+                <el-radio :label="1">正常</el-radio>
+                <el-radio :label="2">已冻结</el-radio>
+              </el-radio-group>
+            </el-form-item>
           </el-col>
         </el-row>
 
@@ -147,7 +176,7 @@ import account from '../../system/account/index'
 import { mapGetters } from "vuex";
 export default {
   name: "SysFreightPackage",
-  components: {uploadImage,order,account,deposit},
+  components: {uploadImage,order,account},
   data() {
     return {
       cityData: cityData,  // 省市区数据
@@ -160,7 +189,14 @@ export default {
       showEdit: false,  // 是否显示表单弹窗
       showOrderEdit: false,  // 是否显示表单弹窗
       showAccountEdit: false,  // 是否显示表单弹窗
-      editForm: {confirm_status: 1,status:1},  // 表单数据
+      editForm: {
+        confirm_status: 1,
+        status: 1,
+        gender: 3,
+        user_type: 1,
+        member_level: 0,
+        balance: 0
+      },  // 表单数据
       editRules: {  // 表单验证规则
         mobile: [
           {required: true, message: '请输入手机账号', trigger: 'blur'},

+ 997 - 0
addons/admin/src/views/order/order.vue

@@ -0,0 +1,997 @@
+<template>
+	<div class="ele-body">
+		<!-- 统计卡片 -->
+		<el-row :gutter="15" style="margin-bottom: 15px;">
+			<el-col :xs="12" :sm="6">
+				<el-card shadow="hover" class="stat-card">
+					<div class="stat-content">
+						<div class="stat-icon" style="background: #409EFF;">
+							<i class="el-icon-s-order"></i>
+						</div>
+						<div class="stat-info">
+							<div class="stat-label">总订单数</div>
+							<div class="stat-value">{{ statistics.total || 0 }}</div>
+						</div>
+					</div>
+				</el-card>
+			</el-col>
+			<el-col :xs="12" :sm="6">
+				<el-card shadow="hover" class="stat-card">
+					<div class="stat-content">
+						<div class="stat-icon" style="background: #67C23A;">
+							<i class="el-icon-money"></i>
+						</div>
+						<div class="stat-info">
+							<div class="stat-label">总交易额</div>
+							<div class="stat-value">¥{{ statistics.totalAmount || 0 }}</div>
+						</div>
+					</div>
+				</el-card>
+			</el-col>
+			<el-col :xs="12" :sm="6">
+				<el-card shadow="hover" class="stat-card">
+					<div class="stat-content">
+						<div class="stat-icon" style="background: #E6A23C;">
+							<i class="el-icon-time"></i>
+						</div>
+						<div class="stat-info">
+							<div class="stat-label">待处理</div>
+							<div class="stat-value">{{ statistics.pending || 0 }}</div>
+						</div>
+					</div>
+				</el-card>
+			</el-col>
+			<el-col :xs="12" :sm="6">
+				<el-card shadow="hover" class="stat-card">
+					<div class="stat-content">
+						<div class="stat-icon" style="background: #F56C6C;">
+							<i class="el-icon-warning"></i>
+						</div>
+						<div class="stat-info">
+							<div class="stat-label">待退款</div>
+							<div class="stat-value">{{ statistics.refunding || 0 }}</div>
+						</div>
+					</div>
+				</el-card>
+			</el-col>
+		</el-row>
+
+		<el-card shadow="never">
+			<!-- 状态tabs -->
+			<el-tabs v-model="activeStatus" @tab-click="handleTabClick">
+				<el-tab-pane v-for="item in statusTabs" :key="item.value" :name="item.value">
+					<span slot="label"><i :class="item.icon"></i> {{ item.label }}</span>
+				</el-tab-pane>
+			</el-tabs>
+			<!-- 搜索表单 -->
+			<el-form style="margin-top: 15px;" :model="table.where" label-width="90px" class="ele-form-search"
+				@keyup.enter.native="$refs.table.reload()" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="8" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="table.where.keyword" placeholder="订单号/商品名称" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :md="16" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="$refs.table.reload()" icon="el-icon-search"
+								class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset()">重置</el-button>
+							<el-button type="warning" icon="el-icon-download" @click="handleExport"
+								v-if="permission.includes('sys:order:index')">导出</el-button>
+							<el-button type="danger" icon="el-icon-delete" @click="removeBatch"
+								v-if="permission.includes('sys:order:delete')">批量删除</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+			<!-- 数据表格 -->
+			<ele-data-table ref="table" :config="table" :choose.sync="choose" height="calc(100vh - 380px)"
+				highlight-current-row>
+				<template>
+					<el-table-column type="selection" width="45" align="center" fixed="left" />
+					<el-table-column prop="id" label="ID" width="60" align="center" fixed="left" />
+					<el-table-column prop="order_no" label="订单号" min-width="180" />
+					<el-table-column prop="user" label="下单用户" min-width="120">
+						<template slot-scope="{row}">
+							<span>{{ row.user ? row.user.realname || row.user.nickname : '' }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="goods" label="商品信息" min-width="200">
+						<template slot-scope="{row}">
+							<div v-if="row.goods" style="display:flex;align-items:center;">
+								<el-image :src="row.goods.thumb" style="width:50px;height:50px;margin-right:10px;" fit="cover" />
+								<span>{{ row.goods.goods_name }}</span>
+							</div>
+						</template>
+					</el-table-column>
+					<el-table-column prop="total" label="订单金额" width="100" align="center">
+						<template slot-scope="{row}">
+							<span>¥{{ row.total }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="receiver_address" label="收货地址" min-width="200" />
+					<el-table-column prop="status" label="订单状态" width="160" align="center">
+						<template slot-scope="{row}">
+							<div style="display: flex; flex-direction: column; gap: 5px; align-items: center;">
+								<div style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">订单:</span>
+									<el-tag :type="getStatusType(row.status)" size="small">{{ getStatusText(row.status) }}</el-tag>
+								</div>
+								<div v-if="row.refund_status == 3" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="warning" size="mini">
+										<i class="el-icon-warning"></i> 待审核
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 1" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="success" size="mini">
+										<i class="el-icon-circle-check"></i> 已退款
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 4" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="danger" size="mini">
+										<i class="el-icon-circle-close"></i> 已驳回
+									</el-tag>
+								</div>
+							</div>
+						</template>
+					</el-table-column>
+					<el-table-column prop="create_time" label="下单时间" min-width="160" align="center" />
+					<el-table-column label="操作" width="280px" align="center" :resizable="false" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="viewDetail(row)" icon="el-icon-view" type="primary" :underline="false">查看</el-link>
+
+							<!-- 待付款:完成支付 -->
+							<el-link @click="quickCompletePay(row)" icon="el-icon-check" type="success" :underline="false"
+								v-if="row.status == 1 && permission.includes('sys:order:status')" class="ele-action">支付</el-link>
+
+							<!-- 已付款:发货 -->
+							<el-link @click="quickDeliver(row)" icon="el-icon-truck" type="warning" :underline="false"
+								v-if="row.status == 2 && permission.includes('sys:order:status')" class="ele-action">发货</el-link>
+
+							<!-- 已发货:完成 -->
+							<el-link @click="quickComplete(row)" icon="el-icon-circle-check" type="success" :underline="false"
+								v-if="row.status == 3 && permission.includes('sys:order:status')" class="ele-action">完成</el-link>
+
+							<!-- 删除 -->
+							<el-popconfirm title="确定要删除此订单吗?" @confirm="remove(row)" class="ele-action">
+								<el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false"
+									v-if="permission.includes('sys:order:delete')">删除</el-link>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 发货弹窗 -->
+		<el-dialog title="订单发货" :visible.sync="deliverVisible" width="500px" :close-on-click-modal="false">
+			<el-form :model="deliverForm" label-width="100px">
+				<el-form-item label="快递单号" required>
+					<el-input v-model="deliverForm.delivery_no" placeholder="请输入快递单号" clearable />
+				</el-form-item>
+				<el-form-item label="快递公司" required>
+					<el-select v-model="deliverForm.delivery_company" placeholder="请选择快递公司" clearable filterable
+						style="width: 100%;">
+						<el-option label="顺丰速运" value="顺丰速运"></el-option>
+						<el-option label="圆通速递" value="圆通速递"></el-option>
+						<el-option label="中通快递" value="中通快递"></el-option>
+						<el-option label="韵达快递" value="韵达快递"></el-option>
+						<el-option label="申通快递" value="申通快递"></el-option>
+						<el-option label="百世快递" value="百世快递"></el-option>
+						<el-option label="京东物流" value="京东物流"></el-option>
+						<el-option label="邮政EMS" value="邮政EMS"></el-option>
+						<el-option label="德邦快递" value="德邦快递"></el-option>
+						<el-option label="天天快递" value="天天快递"></el-option>
+					</el-select>
+				</el-form-item>
+			</el-form>
+			<div slot="footer">
+				<el-button @click="deliverVisible = false">取消</el-button>
+				<el-button type="primary" @click="confirmDeliver">确认发货</el-button>
+			</div>
+		</el-dialog>
+
+		<!-- 订单详情弹窗 -->
+		<el-dialog title="订单详情" :visible.sync="detailVisible" width="85%" top="3vh" :close-on-click-modal="false"
+			custom-class="order-detail-dialog">
+			<div v-loading="detailLoading" class="order-detail-content">
+				<!-- 订单状态卡片 -->
+				<el-card shadow="hover" class="status-card">
+					<div class="status-header">
+						<div class="status-info">
+							<span class="order-no">订单号:{{ orderInfo.order_no }}</span>
+							<div class="status-tags">
+								<div class="status-item">
+									<span class="status-label">订单状态:</span>
+									<el-tag :type="getStatusType(orderInfo.status)" size="medium" class="status-tag">
+										{{ getStatusText(orderInfo.status) }}
+									</el-tag>
+								</div>
+								<div v-if="orderInfo.refund_status > 0" class="status-item">
+									<span class="status-label">退款状态:</span>
+									<el-tag v-if="orderInfo.refund_status == 3" type="warning" size="medium" class="status-tag">
+										<i class="el-icon-warning"></i> 待审核
+									</el-tag>
+									<el-tag v-if="orderInfo.refund_status == 1" type="success" size="medium" class="status-tag">
+										<i class="el-icon-circle-check"></i> 已退款
+									</el-tag>
+									<el-tag v-if="orderInfo.refund_status == 4" type="danger" size="medium" class="status-tag">
+										<i class="el-icon-circle-close"></i> 已驳回
+									</el-tag>
+								</div>
+							</div>
+						</div>
+						<div class="amount-info">
+							<div class="amount-item">
+								<span class="label">订单金额</span>
+								<span class="value total">¥{{ orderInfo.total }}</span>
+							</div>
+							<div class="amount-item">
+								<span class="label">实付金额</span>
+								<span class="value paid">¥{{ orderInfo.pay_total }}</span>
+							</div>
+							<div class="amount-item" v-if="orderInfo.bonus > 0">
+								<span class="label">商家佣金</span>
+								<span class="value bonus">¥{{ orderInfo.bonus }}</span>
+							</div>
+						</div>
+					</div>
+				</el-card>
+
+				<!-- 订单基本信息 -->
+				<el-card shadow="hover" class="info-card">
+					<div slot="header" class="card-header">
+						<i class="el-icon-document"></i> 订单信息
+					</div>
+					<el-row :gutter="20">
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">下单用户:</span>
+								<span class="info-value">{{ orderInfo.user ? (orderInfo.user.realname || orderInfo.user.nickname) : '-'
+								}}</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">用户手机:</span>
+								<span class="info-value">{{ orderInfo.user ? orderInfo.user.mobile : '-' }}</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">所属店铺:</span>
+								<span class="info-value">{{ orderInfo.store ? orderInfo.store.store_name : '-' }}</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">交易单号:</span>
+								<span class="info-value">{{ orderInfo.transaction_id || '-' }}</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">下单时间:</span>
+								<span class="info-value">{{ orderInfo.create_time }}</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">更新时间:</span>
+								<span class="info-value">{{ orderInfo.update_time }}</span>
+							</div>
+						</el-col>
+					</el-row>
+				</el-card>
+
+				<!-- 收货信息 -->
+				<el-card shadow="hover" class="info-card">
+					<div slot="header" class="card-header">
+						<i class="el-icon-location"></i> 收货信息
+					</div>
+					<el-row :gutter="20">
+						<el-col :span="8">
+							<div class="info-item">
+								<span class="info-label">收货人:</span>
+								<span class="info-value">{{ orderInfo.receiver_name }}</span>
+							</div>
+						</el-col>
+						<el-col :span="16">
+							<div class="info-item">
+								<span class="info-label">所在地区:</span>
+								<span class="info-value">{{ orderInfo.receiver_area }}</span>
+							</div>
+						</el-col>
+						<el-col :span="24">
+							<div class="info-item">
+								<span class="info-label">详细地址:</span>
+								<span class="info-value">{{ orderInfo.receiver_address }}</span>
+							</div>
+						</el-col>
+					</el-row>
+				</el-card>
+
+				<!-- 物流信息 -->
+				<el-card shadow="hover" class="info-card" v-if="orderInfo.delivery_no">
+					<div slot="header" class="card-header">
+						<i class="el-icon-truck"></i> 物流信息
+					</div>
+					<el-row :gutter="20">
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">快递公司:</span>
+								<span class="info-value">{{ orderInfo.delivery_company }}</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">快递单号:</span>
+								<span class="info-value highlight">{{ orderInfo.delivery_no }}</span>
+							</div>
+						</el-col>
+					</el-row>
+				</el-card>
+
+				<!-- 商品信息 -->
+				<el-card shadow="hover" class="info-card">
+					<div slot="header" class="card-header">
+						<i class="el-icon-goods"></i> 商品信息
+					</div>
+					<el-table :data="orderInfo.order_goods" border stripe style="width: 100%">
+						<el-table-column label="商品图片" width="100" align="center">
+							<template slot-scope="{row}">
+								<el-image :src="row.thumb" style="width: 60px; height: 60px; border-radius: 4px;" fit="cover"
+									:preview-src-list="[row.thumb]" />
+							</template>
+						</el-table-column>
+						<el-table-column prop="goods_name" label="商品名称" min-width="200" show-overflow-tooltip />
+						<el-table-column prop="price" label="单价" width="100" align="center">
+							<template slot-scope="{row}">
+								<span class="price-text">¥{{ row.price }}</span>
+							</template>
+						</el-table-column>
+						<el-table-column prop="stock" label="数量" width="80" align="center">
+							<template slot-scope="{row}">
+								<el-tag type="info" size="small">{{ row.stock }}</el-tag>
+							</template>
+						</el-table-column>
+						<el-table-column prop="unit" label="单位" width="80" align="center" />
+						<el-table-column prop="weight" label="重量(KG)" width="100" align="center" />
+						<el-table-column label="小计" width="120" align="center">
+							<template slot-scope="{row}">
+								<span class="subtotal-text">¥{{ (row.price * row.stock).toFixed(2) }}</span>
+							</template>
+						</el-table-column>
+					</el-table>
+				</el-card>
+
+				<!-- 售后/退款信息 -->
+				<el-card shadow="hover" class="info-card" v-if="orderInfo.after_type > 0 || orderInfo.refund_status > 0">
+					<div slot="header" class="card-header">
+						<i class="el-icon-warning"></i> 售后/退款信息
+					</div>
+					<el-row :gutter="20">
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">售后类型:</span>
+								<el-tag v-if="orderInfo.after_type == 1" type="warning" size="small">售后</el-tag>
+								<el-tag v-else-if="orderInfo.after_type == 2" type="danger" size="small">退款</el-tag>
+								<span v-else class="info-value">无</span>
+							</div>
+						</el-col>
+						<el-col :span="12">
+							<div class="info-item">
+								<span class="info-label">退款状态:</span>
+								<el-tag :type="getRefundStatusType(orderInfo.refund_status)" size="small">
+									{{ getRefundStatusText(orderInfo.refund_status) }}
+								</el-tag>
+							</div>
+						</el-col>
+						<el-col :span="12" v-if="orderInfo.after_realname">
+							<div class="info-item">
+								<span class="info-label">联系人:</span>
+								<span class="info-value">{{ orderInfo.after_realname }}</span>
+							</div>
+						</el-col>
+						<el-col :span="12" v-if="orderInfo.after_phone">
+							<div class="info-item">
+								<span class="info-label">联系电话:</span>
+								<span class="info-value">{{ orderInfo.after_phone }}</span>
+							</div>
+						</el-col>
+						<el-col :span="24" v-if="orderInfo.after_remark">
+							<div class="info-item">
+								<span class="info-label">用户反馈:</span>
+								<span class="info-value">{{ orderInfo.after_remark }}</span>
+							</div>
+						</el-col>
+						<el-col :span="24" v-if="orderInfo.refund_remark">
+							<div class="info-item">
+								<span class="info-label">审核备注:</span>
+								<span class="info-value">{{ orderInfo.refund_remark }}</span>
+							</div>
+						</el-col>
+					</el-row>
+				</el-card>
+			</div>
+
+			<div slot="footer">
+				<el-button @click="detailVisible = false">关闭</el-button>
+				<!-- 待付款:完成支付、取消订单 -->
+				<el-button type="success" @click="handleCompletePay"
+					v-if="orderInfo.status == 1 && permission.includes('sys:order:status')">
+					完成支付
+				</el-button>
+				<el-button type="info" @click="handleCancel"
+					v-if="orderInfo.status == 1 && permission.includes('sys:order:delete')">
+					取消订单
+				</el-button>
+				<!-- 已付款:发货 -->
+				<el-button type="primary" @click="handleDeliver"
+					v-if="orderInfo.status == 2 && permission.includes('sys:order:status')">
+					订单发货
+				</el-button>
+				<!-- 已发货:确认完成 -->
+				<el-button type="success" @click="handleComplete"
+					v-if="orderInfo.status == 3 && permission.includes('sys:order:status')">
+					确认完成
+				</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+export default {
+	name: "Order",
+	data() {
+		return {
+			table: { url: '/order/index', where: { status: 0 } },
+			choose: [],
+			statusTabs: [
+				{ value: '0', label: '全部订单', icon: 'el-icon-s-grid' },
+				{ value: '1', label: '待付款', icon: 'el-icon-time' },
+				{ value: '2', label: '已付款', icon: 'el-icon-check' },
+				{ value: '3', label: '已发货', icon: 'el-icon-truck' },
+				{ value: '4', label: '已完成', icon: 'el-icon-circle-check' },
+			],
+			activeStatus: '0',
+			detailVisible: false,
+			detailLoading: false,
+			orderInfo: {
+				user: {},
+				store: {},
+				order_goods: []
+			},
+			statistics: {
+				total: 0,
+				totalAmount: 0,
+				pending: 0,
+				refunding: 0
+			},
+			deliverVisible: false,
+			deliverForm: {
+				id: 0,
+				delivery_no: '',
+				delivery_company: ''
+			}
+		}
+	},
+	mounted() {
+		this.loadStatistics();
+	},
+	computed: {
+		...mapGetters(["permission"]),
+	},
+	methods: {
+		handleTabClick(tab) {
+			this.activeStatus = tab.name;
+			this.table.where.status = parseInt(tab.name);
+			this.$refs.table.reload();
+		},
+		handleReset() {
+			this.activeStatus = '0';
+			this.table.where = { status: 0 };
+			this.$refs.table.reload();
+		},
+		// 加载统计数据
+		loadStatistics() {
+			this.$http.get('/order/statistics').then(res => {
+				if (res.data.code === 0) {
+					this.statistics = res.data.data;
+				}
+			}).catch(e => {
+				console.error('加载统计数据失败:', e);
+			});
+		},
+		viewDetail(row) {
+			this.detailVisible = true;
+			this.loadOrderDetail(row.id);
+		},
+		loadOrderDetail(id) {
+			this.detailLoading = true;
+			this.$http.get('/order/info', { params: { id } }).then(res => {
+				this.detailLoading = false;
+				if (res.data.code === 0) {
+					this.orderInfo = res.data.data;
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(e => {
+				this.detailLoading = false;
+				this.$message.error(e.message);
+			});
+		},
+		remove(row) {
+			const loading = this.$loading({ lock: true });
+			this.$http.post('/order/delete', { id: row.id }).then(res => {
+				loading.close();
+				if (res.data.code === 0) {
+					this.$message({ type: 'success', message: res.data.msg });
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(e => {
+				loading.close();
+				this.$message.error(e.message);
+			});
+		},
+		// 批量删除
+		removeBatch() {
+			if (!this.choose.length) {
+				this.$message.error('请至少选择一条数据');
+				return;
+			}
+			this.$confirm('确定要删除选中的 ' + this.choose.length + ' 条订单吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				const ids = this.choose.map(item => item.id);
+				this.$http.post('/order/delete', { id: ids }).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		// 导出订单
+		handleExport() {
+			this.$confirm('确定要导出当前筛选条件下的订单数据吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true, text: '正在导出...' });
+				// 构建导出参数
+				const params = { ...this.table.where, export: 1 };
+				const queryString = Object.keys(params)
+					.map(key => `${key}=${encodeURIComponent(params[key])}`)
+					.join('&');
+
+				// 创建隐藏的下载链接
+				const link = document.createElement('a');
+				link.href = `/order/export?${queryString}`;
+				link.download = `订单列表_${new Date().getTime()}.xlsx`;
+				document.body.appendChild(link);
+				link.click();
+				document.body.removeChild(link);
+
+				setTimeout(() => {
+					loading.close();
+					this.$message.success('导出成功');
+				}, 1000);
+			}).catch(() => { });
+		},
+		// 完成支付
+		handleCompletePay() {
+			this.$confirm('确定要将此订单标记为已支付吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/completePay', { id: this.orderInfo.id }).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.loadOrderDetail(this.orderInfo.id);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		// 订单发货
+		handleDeliver() {
+			this.deliverForm = {
+				id: this.orderInfo.id,
+				delivery_no: '',
+				delivery_company: ''
+			};
+			this.deliverVisible = true;
+		},
+		// 确认发货
+		confirmDeliver() {
+			if (!this.deliverForm.delivery_no) {
+				this.$message.error('请输入快递单号');
+				return;
+			}
+			if (!this.deliverForm.delivery_company) {
+				this.$message.error('请选择快递公司');
+				return;
+			}
+			const loading = this.$loading({ lock: true });
+			this.$http.post('/order/deliver', this.deliverForm).then(res => {
+				loading.close();
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.deliverVisible = false;
+					// 如果详情弹窗打开,则刷新详情
+					if (this.detailVisible) {
+						this.loadOrderDetail(this.deliverForm.id);
+					}
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(e => {
+				loading.close();
+				this.$message.error(e.message);
+			});
+		},
+		// 确认完成
+		handleComplete() {
+			this.$confirm('确定要将此订单标记为已完成吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/complete', { id: this.orderInfo.id }).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.loadOrderDetail(this.orderInfo.id);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		// 取消订单
+		handleCancel() {
+			this.$confirm('确定要取消此订单吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/cancel', { id: this.orderInfo.id }).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.detailVisible = false;
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		getStatusText(status) {
+			const map = { 1: '待付款', 2: '已付款', 3: '已发货', 4: '已完成' };
+			return map[status] || '未知';
+		},
+		getStatusType(status) {
+			const map = { 1: 'info', 2: 'warning', 3: 'primary', 4: 'success' };
+			return map[status] || '';
+		},
+		getRefundStatusText(status) {
+			const map = { 0: '无', 1: '已退款', 2: '已审核', 3: '待审核', 4: '审核驳回' };
+			return map[status] || '未知';
+		},
+		getRefundStatusType(status) {
+			const map = { 0: 'info', 1: 'success', 2: 'primary', 3: 'warning', 4: 'danger' };
+			return map[status] || '';
+		},
+		// 快捷完成支付
+		quickCompletePay(row) {
+			this.$confirm('确定要将此订单标记为已支付吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/completePay', { id: row.id }).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		// 快捷发货
+		quickDeliver(row) {
+			this.deliverForm = {
+				id: row.id,
+				delivery_no: '',
+				delivery_company: ''
+			};
+			this.deliverVisible = true;
+		},
+		// 快捷完成订单
+		quickComplete(row) {
+			this.$confirm('确定要将此订单标记为已完成吗?', '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/complete', { id: row.id }).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		// 快捷申请退款
+		quickApplyRefund(row) {
+			this.refundForm = {
+				id: row.id,
+				after_type: 2,
+				after_realname: '',
+				after_phone: '',
+				after_remark: ''
+			};
+			this.refundVisible = true;
+		},
+	}
+}
+</script>
+
+<style scoped>
+.el-descriptions {
+	margin-bottom: 20px;
+}
+
+.stat-card {
+	cursor: pointer;
+	transition: all 0.3s;
+}
+
+.stat-card:hover {
+	transform: translateY(-5px);
+}
+
+.stat-content {
+	display: flex;
+	align-items: center;
+}
+
+.stat-icon {
+	width: 60px;
+	height: 60px;
+	border-radius: 10px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	font-size: 28px;
+	color: #fff;
+	margin-right: 15px;
+}
+
+.stat-info {
+	flex: 1;
+}
+
+.stat-label {
+	font-size: 14px;
+	color: #909399;
+	margin-bottom: 5px;
+}
+
+.stat-value {
+	font-size: 24px;
+	font-weight: bold;
+	color: #303133;
+}
+
+/* 订单详情弹窗样式 */
+.order-detail-content {
+	max-height: 75vh;
+	overflow-y: auto;
+	padding: 10px;
+}
+
+.status-card {
+	margin-bottom: 20px;
+	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+	color: #fff;
+}
+
+.status-card>>>.el-card__body {
+	padding: 20px;
+}
+
+.status-header {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	flex-wrap: wrap;
+	gap: 15px;
+}
+
+.status-info {
+	display: flex;
+	align-items: center;
+	gap: 15px;
+	flex-wrap: wrap;
+}
+
+.order-no {
+	font-size: 16px;
+	font-weight: bold;
+	color: #fff;
+}
+
+.status-tags {
+	display: flex;
+	gap: 15px;
+	flex-wrap: wrap;
+	align-items: center;
+}
+
+.status-item {
+	display: flex;
+	align-items: center;
+	gap: 8px;
+}
+
+.status-label {
+	font-size: 14px;
+	color: rgba(255, 255, 255, 0.9);
+	font-weight: 500;
+}
+
+.status-tag {
+	font-size: 14px;
+	padding: 2px 16px;
+}
+
+.status-tag i {
+	margin-right: 3px;
+}
+
+.amount-info {
+	display: flex;
+	gap: 30px;
+}
+
+.amount-item {
+	display: flex;
+	flex-direction: column;
+	align-items: flex-end;
+}
+
+.amount-item .label {
+	font-size: 12px;
+	color: rgba(255, 255, 255, 0.8);
+	margin-bottom: 5px;
+}
+
+.amount-item .value {
+	font-size: 20px;
+	font-weight: bold;
+	color: #fff;
+}
+
+.amount-item .total {
+	color: #ffd700;
+}
+
+.amount-item .paid {
+	color: #67c23a;
+}
+
+.amount-item .bonus {
+	color: #409eff;
+}
+
+.info-card {
+	margin-bottom: 20px;
+}
+
+.info-card>>>.el-card__header {
+	background: #f5f7fa;
+	padding: 15px 20px;
+}
+
+.card-header {
+	font-size: 16px;
+	font-weight: bold;
+	color: #303133;
+}
+
+.card-header i {
+	margin-right: 8px;
+	color: #409eff;
+}
+
+.info-item {
+	padding: 10px 0;
+	display: flex;
+	align-items: center;
+}
+
+.info-label {
+	font-size: 14px;
+	color: #606266;
+	min-width: 90px;
+	font-weight: 500;
+}
+
+.info-value {
+	font-size: 14px;
+	color: #303133;
+	flex: 1;
+}
+
+.info-value.highlight {
+	color: #409eff;
+	font-weight: bold;
+}
+
+.price-text {
+	color: #f56c6c;
+	font-weight: 500;
+}
+
+.subtotal-text {
+	color: #f56c6c;
+	font-weight: bold;
+	font-size: 15px;
+}
+
+/* 滚动条样式 */
+.order-detail-content::-webkit-scrollbar {
+	width: 6px;
+}
+
+.order-detail-content::-webkit-scrollbar-thumb {
+	background: #dcdfe6;
+	border-radius: 3px;
+}
+
+.order-detail-content::-webkit-scrollbar-thumb:hover {
+	background: #c0c4cc;
+}
+
+.order-detail-content::-webkit-scrollbar-track {
+	background: #f5f7fa;
+}
+</style>

+ 269 - 0
addons/admin/src/views/orders/afterType.vue

@@ -0,0 +1,269 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<div slot="header" class="clearfix">
+				<span style="font-size: 18px; font-weight: bold;">
+					<i class="el-icon-service"></i> 售后订单管理
+				</span>
+			</div>
+
+			<!-- 提示信息 -->
+			<el-alert title="售后订单说明" type="info" :closable="false" style="margin-bottom: 15px;">
+				<div slot>
+					<p>售后订单是指用户申请售后服务的订单</p>
+					<p>包括商品质量问题、商品损坏、商品缺失等需要售后处理的订单</p>
+				</div>
+			</el-alert>
+
+			<!-- 搜索表单 -->
+			<el-form style="margin-top: 15px;" :model="table.where" label-width="90px" class="ele-form-search"
+				@keyup.enter.native="$refs.table.reload()" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="8" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="table.where.keyword" placeholder="订单号/商品名称" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<el-form-item label="退款状态:">
+							<el-select v-model="table.where.refund_status" placeholder="全部" clearable style="width: 100%;">
+								<el-option label="待审核" :value="3"></el-option>
+								<el-option label="已退款" :value="1"></el-option>
+								<el-option label="已驳回" :value="4"></el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="10" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="$refs.table.reload()" icon="el-icon-search"
+								class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset()">重置</el-button>
+							<el-button type="warning" icon="el-icon-download" @click="handleExport"
+								v-if="permission.includes('sys:afterType:index')">导出</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 数据表格 -->
+			<ele-data-table ref="table" :config="table" :choose.sync="choose" height="calc(100vh - 450px)"
+				highlight-current-row>
+				<template>
+					<el-table-column type="selection" width="45" align="center" fixed="left" />
+					<el-table-column prop="id" label="ID" width="60" align="center" fixed="left" />
+					<el-table-column prop="order_no" label="订单号" min-width="180" />
+					<el-table-column prop="user" label="下单用户" min-width="120">
+						<template slot-scope="{row}">
+							<span>{{ row.user ? row.user.realname || row.user.nickname : '' }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="goods" label="商品信息" min-width="200">
+						<template slot-scope="{row}">
+							<div v-if="row.goods" style="display:flex;align-items:center;">
+								<el-image :src="row.goods.thumb" style="width:50px;height:50px;margin-right:10px;" fit="cover" />
+								<span>{{ row.goods.goods_name }}</span>
+							</div>
+						</template>
+					</el-table-column>
+					<el-table-column prop="after_realname" label="联系人" width="100" align="center" />
+					<el-table-column prop="after_phone" label="联系电话" width="120" align="center" />
+					<el-table-column prop="status" label="状态" width="160" align="center">
+						<template slot-scope="{row}">
+							<div style="display: flex; flex-direction: column; gap: 5px; align-items: center;">
+								<div style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">订单:</span>
+									<el-tag :type="getStatusType(row.status)" size="small">{{ getStatusText(row.status) }}</el-tag>
+								</div>
+								<div v-if="row.refund_status == 3" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">售后:</span>
+									<el-tag type="warning" size="mini">
+										<i class="el-icon-warning"></i> 待审核
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 1" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">售后:</span>
+									<el-tag type="success" size="mini">
+										<i class="el-icon-circle-check"></i> 已处理
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 4" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">售后:</span>
+									<el-tag type="danger" size="mini">
+										<i class="el-icon-circle-close"></i> 已驳回
+									</el-tag>
+								</div>
+							</div>
+						</template>
+					</el-table-column>
+					<el-table-column prop="create_time" label="申请时间" min-width="160" align="center" />
+					<el-table-column label="操作" width="200px" align="center" :resizable="false" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="viewDetail(row)" icon="el-icon-view" type="primary" :underline="false">查看</el-link>
+
+							<!-- 待审核:同意、拒绝 -->
+							<el-link @click="handleAgree(row)" icon="el-icon-check" type="success" :underline="false"
+								v-if="row.refund_status == 3 && permission.includes('sys:afterType:status')"
+								class="ele-action">同意</el-link>
+							<el-link @click="handleReject(row)" icon="el-icon-close" type="danger" :underline="false"
+								v-if="row.refund_status == 3 && permission.includes('sys:afterType:status')"
+								class="ele-action">驳回</el-link>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 订单详情弹窗(引用共用组件的详情部分) -->
+		<el-dialog title="售后订单详情" :visible.sync="detailVisible" width="85%" top="3vh" :close-on-click-modal="false"
+			custom-class="order-detail-dialog">
+			<div v-loading="detailLoading" class="order-detail-content">
+				<!-- 这里可以复用订单详情的内容 -->
+				<el-alert title="售后申请信息" type="warning" :closable="false" style="margin-bottom: 20px;">
+					<div>
+						<p><strong>联系人:</strong>{{ orderInfo.after_realname }}</p>
+						<p><strong>联系电话:</strong>{{ orderInfo.after_phone }}</p>
+						<p><strong>售后原因:</strong>{{ orderInfo.after_remark }}</p>
+						<p v-if="orderInfo.refund_remark"><strong>处理备注:</strong>{{ orderInfo.refund_remark }}</p>
+					</div>
+				</el-alert>
+
+				<p style="text-align: center; color: #909399;">详细订单信息请查看订单管理</p>
+			</div>
+			<div slot="footer">
+				<el-button @click="detailVisible = false">关闭</el-button>
+				<el-button type="success" @click="handleAgreeDetail"
+					v-if="orderInfo.refund_status == 3 && permission.includes('sys:afterType:status')">
+					同意售后
+				</el-button>
+				<el-button type="danger" @click="handleRejectDetail"
+					v-if="orderInfo.refund_status == 3 && permission.includes('sys:afterType:status')">
+					驳回售后
+				</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+export default {
+	name: "AfterType",
+	data() {
+		return {
+			table: {
+				url: '/order/index',
+				where: {
+					after_type: 1  // 售后类型
+				}
+			},
+			choose: [],
+			detailVisible: false,
+			detailLoading: false,
+			orderInfo: {}
+		}
+	},
+	computed: {
+		...mapGetters(["permission"]),
+	},
+	methods: {
+		handleReset() {
+			this.table.where = { after_type: 1 };
+			this.$refs.table.reload();
+		},
+		viewDetail(row) {
+			this.detailVisible = true;
+			this.loadOrderDetail(row.id);
+		},
+		loadOrderDetail(id) {
+			this.detailLoading = true;
+			this.$http.get('/order/info', { params: { id } }).then(res => {
+				this.detailLoading = false;
+				if (res.data.code === 0) {
+					this.orderInfo = res.data.data;
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(e => {
+				this.detailLoading = false;
+				this.$message.error(e.message);
+			});
+		},
+		handleAgree(row) {
+			this.$prompt('请输入处理备注', '同意售后', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPlaceholder: '请输入处理备注'
+			}).then(({ value }) => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/agreeRefund', {
+					id: row.id,
+					refund_remark: value || '售后申请已通过'
+				}).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		handleReject(row) {
+			this.$prompt('请输入驳回原因', '驳回售后', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPattern: /.+/,
+				inputErrorMessage: '请输入驳回原因'
+			}).then(({ value }) => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/rejectRefund', {
+					id: row.id,
+					refund_remark: value
+				}).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		handleAgreeDetail() {
+			this.handleAgree(this.orderInfo);
+			this.detailVisible = false;
+		},
+		handleRejectDetail() {
+			this.handleReject(this.orderInfo);
+			this.detailVisible = false;
+		},
+		handleExport() {
+			this.$message.info('导出功能开发中...');
+		},
+		getStatusText(status) {
+			const map = { 1: '待付款', 2: '已付款', 3: '已发货', 4: '已完成' };
+			return map[status] || '未知';
+		},
+		getStatusType(status) {
+			const map = { 1: 'info', 2: 'warning', 3: 'primary', 4: 'success' };
+			return map[status] || '';
+		},
+	}
+}
+</script>
+
+<style scoped>
+.order-detail-content {
+	max-height: 70vh;
+	overflow-y: auto;
+	padding: 10px;
+}
+</style>

+ 334 - 0
addons/admin/src/views/orders/refundOrder.vue

@@ -0,0 +1,334 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<div slot="header" class="clearfix">
+				<span style="font-size: 18px; font-weight: bold;">
+					<i class="el-icon-money"></i> 退款订单管理
+				</span>
+			</div>
+
+			<!-- 提示信息 -->
+			<el-alert title="退款订单说明" type="warning" :closable="false" style="margin-bottom: 15px;">
+				<div slot>
+					<p>退款订单是指用户申请退款的订单</p>
+					<p>包括不想要了、商品不符、价格问题等需要退款处理的订单</p>
+				</div>
+			</el-alert>
+
+			<!-- 退款状态tabs -->
+			<el-tabs v-model="activeRefundStatus" @tab-click="handleTabClick" style="margin-top: 15px;">
+				<el-tab-pane v-for="item in refundStatusTabs" :key="item.value" :name="item.value">
+					<span slot="label"><i :class="item.icon"></i> {{ item.label }}</span>
+				</el-tab-pane>
+			</el-tabs>
+
+			<!-- 搜索表单 -->
+			<el-form style="margin-top: 15px;" :model="table.where" label-width="90px" class="ele-form-search"
+				@keyup.enter.native="$refs.table.reload()" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="8" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="table.where.keyword" placeholder="订单号/商品名称" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :md="10" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="$refs.table.reload()" icon="el-icon-search"
+								class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset()">重置</el-button>
+							<el-button type="warning" icon="el-icon-download" @click="handleExport"
+								v-if="permission.includes('sys:refundOrder:index')">导出</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 数据表格 -->
+			<ele-data-table ref="table" :config="table" :choose.sync="choose" height="calc(100vh - 450px)"
+				highlight-current-row>
+				<template>
+					<el-table-column type="selection" width="45" align="center" fixed="left" />
+					<el-table-column prop="id" label="ID" width="60" align="center" fixed="left" />
+					<el-table-column prop="order_no" label="订单号" min-width="180" />
+					<el-table-column prop="user" label="下单用户" min-width="120">
+						<template slot-scope="{row}">
+							<span>{{ row.user ? row.user.realname || row.user.nickname : '' }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="goods" label="商品信息" min-width="200">
+						<template slot-scope="{row}">
+							<div v-if="row.goods" style="display:flex;align-items:center;">
+								<el-image :src="row.goods.thumb" style="width:50px;height:50px;margin-right:10px;" fit="cover" />
+								<span>{{ row.goods.goods_name }}</span>
+							</div>
+						</template>
+					</el-table-column>
+					<el-table-column prop="pay_total" label="退款金额" width="100" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #f56c6c; font-weight: bold;">¥{{ row.pay_total }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="after_realname" label="联系人" width="100" align="center" />
+					<el-table-column prop="after_phone" label="联系电话" width="120" align="center" />
+					<el-table-column prop="status" label="状态" width="160" align="center">
+						<template slot-scope="{row}">
+							<div style="display: flex; flex-direction: column; gap: 5px; align-items: center;">
+								<div style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">订单:</span>
+									<el-tag :type="getStatusType(row.status)" size="small">{{ getStatusText(row.status) }}</el-tag>
+								</div>
+								<div v-if="row.refund_status == 3" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="warning" size="mini">
+										<i class="el-icon-warning"></i> 待审核
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 2" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="primary" size="mini">
+										<i class="el-icon-s-order"></i> 已审核
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 1" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="success" size="mini">
+										<i class="el-icon-circle-check"></i> 已退款
+									</el-tag>
+								</div>
+								<div v-if="row.refund_status == 4" style="display: flex; align-items: center; gap: 5px;">
+									<span style="font-size: 12px; color: #909399;">退款:</span>
+									<el-tag type="danger" size="mini">
+										<i class="el-icon-circle-close"></i> 已驳回
+									</el-tag>
+								</div>
+							</div>
+						</template>
+					</el-table-column>
+					<el-table-column prop="create_time" label="申请时间" min-width="160" align="center" />
+					<el-table-column label="操作" width="250px" align="center" :resizable="false" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="viewDetail(row)" icon="el-icon-view" type="primary" :underline="false">查看</el-link>
+
+							<!-- 待审核:同意、拒绝 -->
+							<el-link @click="handleAgree(row)" icon="el-icon-check" type="success" :underline="false"
+								v-if="row.refund_status == 3 && permission.includes('sys:refundOrder:status')"
+								class="ele-action">同意</el-link>
+							<el-link @click="handleReject(row)" icon="el-icon-close" type="danger" :underline="false"
+								v-if="row.refund_status == 3 && permission.includes('sys:refundOrder:status')"
+								class="ele-action">驳回</el-link>
+
+							<!-- 已审核:确认退款 -->
+							<el-link @click="handleConfirmRefund(row)" icon="el-icon-money" type="warning" :underline="false"
+								v-if="row.refund_status == 2 && permission.includes('sys:refundOrder:status')"
+								class="ele-action">确认退款</el-link>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 订单详情弹窗 -->
+		<el-dialog title="退款订单详情" :visible.sync="detailVisible" width="85%" top="3vh" :close-on-click-modal="false"
+			custom-class="order-detail-dialog">
+			<div v-loading="detailLoading" class="order-detail-content">
+				<!-- 退款申请信息 -->
+				<el-alert title="退款申请信息" type="error" :closable="false" style="margin-bottom: 20px;">
+					<div>
+						<p><strong>退款金额:</strong><span style="color: #f56c6c; font-size: 18px; font-weight: bold;">¥{{
+							orderInfo.pay_total }}</span></p>
+						<p><strong>联系人:</strong>{{ orderInfo.after_realname }}</p>
+						<p><strong>联系电话:</strong>{{ orderInfo.after_phone }}</p>
+						<p><strong>退款原因:</strong>{{ orderInfo.after_remark }}</p>
+						<p v-if="orderInfo.refund_remark"><strong>处理备注:</strong>{{ orderInfo.refund_remark }}</p>
+					</div>
+				</el-alert>
+
+				<p style="text-align: center; color: #909399;">详细订单信息请查看订单管理</p>
+			</div>
+			<div slot="footer">
+				<el-button @click="detailVisible = false">关闭</el-button>
+				<el-button type="success" @click="handleAgreeDetail"
+					v-if="orderInfo.refund_status == 3 && permission.includes('sys:refundOrder:status')">
+					同意退款
+				</el-button>
+				<el-button type="danger" @click="handleRejectDetail"
+					v-if="orderInfo.refund_status == 3 && permission.includes('sys:refundOrder:status')">
+					驳回退款
+				</el-button>
+				<el-button type="warning" @click="handleConfirmRefundDetail"
+					v-if="orderInfo.refund_status == 2 && permission.includes('sys:refundOrder:status')">
+					确认退款
+				</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+export default {
+	name: "RefundOrder",
+	data() {
+		return {
+			table: {
+				url: '/order/index',
+				where: {
+					after_type: 2,  // 退款类型
+					refund_status: 0  // 默认全部
+				}
+			},
+			choose: [],
+			refundStatusTabs: [
+				{ value: '0', label: '全部', icon: 'el-icon-s-grid' },
+				{ value: '3', label: '待审核', icon: 'el-icon-warning' },
+				{ value: '2', label: '已审核', icon: 'el-icon-s-order' },
+				{ value: '1', label: '已退款', icon: 'el-icon-circle-check' },
+				{ value: '4', label: '已驳回', icon: 'el-icon-circle-close' },
+			],
+			activeRefundStatus: '0',
+			detailVisible: false,
+			detailLoading: false,
+			orderInfo: {}
+		}
+	},
+	computed: {
+		...mapGetters(["permission"]),
+	},
+	methods: {
+		handleTabClick(tab) {
+			this.activeRefundStatus = tab.name;
+			this.table.where.refund_status = parseInt(tab.name);
+			this.$refs.table.reload();
+		},
+		handleReset() {
+			this.activeRefundStatus = '0';
+			this.table.where = { after_type: 2, refund_status: 0 };
+			this.$refs.table.reload();
+		},
+		viewDetail(row) {
+			this.detailVisible = true;
+			this.loadOrderDetail(row.id);
+		},
+		loadOrderDetail(id) {
+			this.detailLoading = true;
+			this.$http.get('/order/info', { params: { id } }).then(res => {
+				this.detailLoading = false;
+				if (res.data.code === 0) {
+					this.orderInfo = res.data.data;
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			}).catch(e => {
+				this.detailLoading = false;
+				this.$message.error(e.message);
+			});
+		},
+		handleAgree(row) {
+			this.$confirm('同意退款后,退款状态将变为"已审核",需要再次确认退款才会完成退款流程。确定要同意吗?', '同意退款', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning'
+			}).then(() => {
+				this.$prompt('请输入审核备注', '同意退款', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					inputPlaceholder: '请输入审核备注(选填)'
+				}).then(({ value }) => {
+					const loading = this.$loading({ lock: true });
+					this.$http.post('/order/agreeRefund', {
+						id: row.id,
+						refund_remark: value || '退款申请已通过,待确认退款'
+					}).then(res => {
+						loading.close();
+						if (res.data.code === 0) {
+							this.$message.success(res.data.msg);
+							this.$refs.table.reload();
+						} else {
+							this.$message.error(res.data.msg);
+						}
+					}).catch(e => {
+						loading.close();
+						this.$message.error(e.message);
+					});
+				}).catch(() => { });
+			}).catch(() => { });
+		},
+		handleConfirmRefund(row) {
+			this.$confirm(`确定要确认退款 ¥${row.pay_total} 吗?此操作表示已完成退款流程。`, '确认退款', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/confirmRefund', {
+					id: row.id
+				}).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		handleReject(row) {
+			this.$prompt('请输入驳回原因', '驳回退款', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPattern: /.+/,
+				inputErrorMessage: '请输入驳回原因'
+			}).then(({ value }) => {
+				const loading = this.$loading({ lock: true });
+				this.$http.post('/order/rejectRefund', {
+					id: row.id,
+					refund_remark: value
+				}).then(res => {
+					loading.close();
+					if (res.data.code === 0) {
+						this.$message.success(res.data.msg);
+						this.$refs.table.reload();
+					} else {
+						this.$message.error(res.data.msg);
+					}
+				}).catch(e => {
+					loading.close();
+					this.$message.error(e.message);
+				});
+			}).catch(() => { });
+		},
+		handleAgreeDetail() {
+			this.handleAgree(this.orderInfo);
+		},
+		handleRejectDetail() {
+			this.handleReject(this.orderInfo);
+		},
+		handleConfirmRefundDetail() {
+			this.handleConfirmRefund(this.orderInfo);
+		},
+		handleExport() {
+			this.$message.info('导出功能开发中...');
+		},
+		getStatusText(status) {
+			const map = { 1: '待付款', 2: '已付款', 3: '已发货', 4: '已完成' };
+			return map[status] || '未知';
+		},
+		getStatusType(status) {
+			const map = { 1: 'info', 2: 'warning', 3: 'primary', 4: 'success' };
+			return map[status] || '';
+		},
+	}
+}
+</script>
+
+<style scoped>
+.order-detail-content {
+	max-height: 70vh;
+	overflow-y: auto;
+	padding: 10px;
+}
+</style>

+ 286 - 0
addons/admin/src/views/pay/components/MealsManage.vue

@@ -0,0 +1,286 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<!-- 搜索表单 -->
+			<el-form :model="where" label-width="80px" class="ele-form-search" @keyup.enter.native="query" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="6" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="where.keyword" placeholder="请输入金额/备注/产品ID" clearable/>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<el-form-item label="状态:">
+							<el-select v-model="where.status" placeholder="请选择状态" clearable class="ele-fluid">
+								<el-option label="有效" :value="1"/>
+								<el-option label="无效" :value="2"/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="12" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="query" icon="el-icon-search" class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset">重置</el-button>
+							<el-button @click="openEdit()" type="primary" icon="el-icon-plus" class="ele-btn-icon"
+								v-if="permission.includes(permissionPrefix + ':add')">添加</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 数据表格 -->
+			<ele-data-table
+				ref="table"
+				:config="table"
+				:choose.sync="selection"
+				height="calc(100vh - 315px)">
+				<template slot-scope="{index}">
+					<el-table-column type="selection" width="45" align="center" fixed="left"/>
+					<el-table-column prop="id" label="ID" width="60" align="center" sortable="custom"/>
+					<el-table-column prop="product_id" label="产品ID" width="100" align="center"/>
+					<el-table-column prop="money" label="面值金额" width="100" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #F56C6C; font-weight: bold;">¥{{ row.money }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="discount" label="折扣(%)" width="100" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.discount > 0" type="success" size="mini">{{ row.discount }}%</el-tag>
+							<span v-else>-</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="pay_money" label="实付金额" width="100" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #67C23A; font-weight: bold;">¥{{ row.pay_money }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="remark" label="备注" min-width="150" show-overflow-tooltip/>
+					<el-table-column prop="sort" label="排序" width="80" align="center"/>
+					<el-table-column label="状态" width="80" align="center">
+						<template slot-scope="{row}">
+							<el-switch
+								v-model="row.status"
+								:active-value="1"
+								:inactive-value="2"
+								@change="changeStatus(row)"
+								:disabled="!permission.includes(permissionPrefix + ':status')">
+							</el-switch>
+						</template>
+					</el-table-column>
+					<el-table-column prop="create_time_text" label="创建时间" min-width="160" align="center" show-overflow-tooltip/>
+
+					<!-- 操作 -->
+					<el-table-column label="操作" width="180" align="center" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="openEdit(row)" icon="el-icon-edit" type="primary" :underline="false"
+								v-if="permission.includes(permissionPrefix + ':edit')" style="margin-right: 10px;">修改</el-link>
+							<el-popconfirm title="确定要删除此记录吗?" @confirm="remove(row)"
+								v-if="permission.includes(permissionPrefix + ':delete')">
+								<el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false">删除</el-link>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 编辑弹窗 -->
+		<el-dialog :title="editForm.id ? '修改套餐' : '添加套餐'" :visible.sync="editVisible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
+			<el-form :model="editForm" :rules="editRules" ref="editForm" label-width="100px">
+				<el-form-item label="产品ID:" prop="product_id">
+					<el-input v-model.number="editForm.product_id" placeholder="请输入产品ID" clearable/>
+					<div class="el-form-item__tip">从充值平台获取的产品ID</div>
+				</el-form-item>
+				<el-form-item label="面值金额:" prop="money">
+					<el-input v-model.number="editForm.money" placeholder="请输入面值金额" clearable>
+						<template slot="prepend">¥</template>
+					</el-input>
+				</el-form-item>
+				<el-form-item label="折扣:" prop="discount">
+					<el-input v-model.number="editForm.discount" placeholder="请输入折扣,0表示无折扣" clearable>
+						<template slot="append">%</template>
+					</el-input>
+					<div class="el-form-item__tip">0-100,0表示无折扣,100表示原价</div>
+				</el-form-item>
+				<el-form-item label="备注:">
+					<el-input v-model="editForm.remark" type="textarea" :rows="3" placeholder="请输入备注"/>
+				</el-form-item>
+				<el-form-item label="排序:">
+					<el-input-number v-model="editForm.sort" :min="0" :max="9999" controls-position="right" class="ele-fluid"/>
+					<div class="el-form-item__tip">数字越大越靠前</div>
+				</el-form-item>
+				<el-form-item label="状态:" prop="status">
+					<el-radio-group v-model="editForm.status">
+						<el-radio :label="1">有效</el-radio>
+						<el-radio :label="2">无效</el-radio>
+					</el-radio-group>
+				</el-form-item>
+			</el-form>
+			<div slot="footer">
+				<el-button @click="editVisible = false">取消</el-button>
+				<el-button type="primary" @click="save" :loading="saveLoading">保存</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+export default {
+	name: "MealsManage",
+	props: {
+		// 充值类型(1-话费,2-电费,3-燃气)
+		type: {
+			type: Number,
+			required: true
+		},
+		// 权限前缀
+		permissionPrefix: {
+			type: String,
+			required: true
+		}
+	},
+	computed: {
+		...mapGetters(["permission"])
+	},
+	data() {
+		return {
+			// 表格配置
+			table: {
+				url: '/pay/meals/index',
+				where: {
+					type: this.type
+				}
+			},
+			// 搜索条件
+			where: {
+				keyword: '',
+				status: ''
+			},
+			// 表格选中数据
+			selection: [],
+			// 编辑弹窗
+			editVisible: false,
+			editForm: {
+				id: null,
+				product_id: '',
+				money: '',
+				discount: 0,
+				remark: '',
+				sort: 0,
+				status: 1,
+				type: this.type
+			},
+			editRules: {
+				product_id: [
+					{required: true, message: '请输入产品ID', trigger: 'blur'}
+				],
+				money: [
+					{required: true, message: '请输入面值金额', trigger: 'blur'},
+					{type: 'number', message: '金额必须为数字', trigger: 'blur'}
+				],
+				discount: [
+					{type: 'number', message: '折扣必须为数字', trigger: 'blur'}
+				],
+				status: [
+					{required: true, message: '请选择状态', trigger: 'change'}
+				]
+			},
+			saveLoading: false
+		}
+	},
+	methods: {
+		/* 查询 */
+		query() {
+			this.$refs.table.reload({where: this.where});
+		},
+		/* 重置 */
+		handleReset() {
+			this.where = {
+				keyword: '',
+				status: ''
+			};
+			this.query();
+		},
+		/* 打开编辑弹窗 */
+		openEdit(row) {
+			if (row) {
+				this.editForm = {
+					id: row.id,
+					product_id: row.product_id,
+					money: parseFloat(row.money),
+					discount: parseFloat(row.discount),
+					remark: row.remark,
+					sort: row.sort,
+					status: row.status,
+					type: this.type
+				};
+			} else {
+				this.editForm = {
+					id: null,
+					product_id: '',
+					money: '',
+					discount: 0,
+					remark: '',
+					sort: 0,
+					status: 1,
+					type: this.type
+				};
+			}
+			this.editVisible = true;
+		},
+		/* 保存 */
+		save() {
+			this.$refs.editForm.validate(valid => {
+				if (valid) {
+					this.saveLoading = true;
+					const url = this.editForm.id ? '/pay/meals/edit' : '/pay/meals/add';
+					this.$http.post(url, this.editForm).then(res => {
+						this.saveLoading = false;
+						if (res.data.code === 0) {
+							this.$message.success(res.data.msg);
+							this.editVisible = false;
+							this.$refs.table.reload();
+						} else {
+							this.$message.error(res.data.msg);
+						}
+					}).catch(() => {
+						this.saveLoading = false;
+					});
+				}
+			});
+		},
+		/* 修改状态 */
+		changeStatus(row) {
+			this.$http.post('/pay/meals/status', {
+				id: row.id,
+				status: row.status
+			}).then(res => {
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+				} else {
+					this.$message.error(res.data.msg);
+					row.status = row.status === 1 ? 2 : 1;
+				}
+			}).catch(() => {
+				row.status = row.status === 1 ? 2 : 1;
+			});
+		},
+		/* 删除 */
+		remove(row) {
+			this.$http.post('/pay/meals/delete', {id: row.id}).then(res => {
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			});
+		}
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 226 - 0
addons/admin/src/views/pay/components/OrdersManage.vue

@@ -0,0 +1,226 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<!-- 搜索表单 -->
+			<el-form :model="where" label-width="80px" class="ele-form-search" @keyup.enter.native="query" @submit.native.prevent>
+				<el-row :gutter="15">
+					<el-col :md="6" :sm="12">
+						<el-form-item label="关键词:">
+							<el-input v-model="where.keyword" placeholder="订单号/充值号码/昵称" clearable/>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<el-form-item label="状态:">
+							<el-select v-model="where.status" placeholder="请选择状态" clearable class="ele-fluid">
+								<el-option label="待付款" :value="1"/>
+								<el-option label="已付款" :value="2"/>
+								<el-option label="充值中" :value="3"/>
+								<el-option label="充值成功" :value="4"/>
+								<el-option label="充值失败" :value="5"/>
+								<el-option label="已退款" :value="6"/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<el-form-item label="时间范围:">
+							<el-date-picker
+								v-model="dateRange"
+								type="daterange"
+								range-separator="至"
+								start-placeholder="开始日期"
+								end-placeholder="结束日期"
+								value-format="yyyy-MM-dd"
+								class="ele-fluid">
+							</el-date-picker>
+						</el-form-item>
+					</el-col>
+					<el-col :md="6" :sm="12">
+						<div class="ele-form-actions">
+							<el-button type="primary" @click="query" icon="el-icon-search" class="ele-btn-icon">查询</el-button>
+							<el-button @click="handleReset">重置</el-button>
+						</div>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<!-- 数据表格 -->
+			<ele-data-table
+				ref="table"
+				:config="table"
+				:choose.sync="selection"
+				height="calc(100vh - 315px)">
+				<template slot-scope="{index}">
+					<el-table-column type="selection" width="45" align="center" fixed="left"/>
+					<el-table-column prop="id" label="ID" width="60" align="center" sortable="custom"/>
+					<el-table-column prop="order_no" label="订单号" min-width="180" align="center" show-overflow-tooltip/>
+					<el-table-column prop="account" label="充值号码" width="130" align="center"/>
+					<el-table-column prop="total" label="充值金额" width="100" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #F56C6C; font-weight: bold;">¥{{ row.total }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="discount" label="折扣(%)" width="90" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.discount > 0" type="success" size="mini">{{ row.discount }}%</el-tag>
+							<span v-else>-</span>
+						</template>
+					</el-table-column>
+					<el-table-column prop="pay_total" label="实付金额" width="100" align="center">
+						<template slot-scope="{row}">
+							<span style="color: #67C23A; font-weight: bold;">¥{{ row.pay_total }}</span>
+						</template>
+					</el-table-column>
+					<el-table-column label="用户昵称" width="120" align="center">
+						<template slot-scope="{row}">
+							{{ row.user_nickname || '-' }}
+						</template>
+					</el-table-column>
+					<el-table-column label="状态" width="100" align="center">
+						<template slot-scope="{row}">
+							<el-tag v-if="row.status === 1" type="info" size="mini">待付款</el-tag>
+							<el-tag v-else-if="row.status === 2" type="primary" size="mini">已付款</el-tag>
+							<el-tag v-else-if="row.status === 3" type="warning" size="mini">充值中</el-tag>
+							<el-tag v-else-if="row.status === 4" type="success" size="mini">充值成功</el-tag>
+							<el-tag v-else-if="row.status === 5" type="danger" size="mini">充值失败</el-tag>
+							<el-tag v-else-if="row.status === 6" type="info" size="mini">已退款</el-tag>
+						</template>
+					</el-table-column>
+					<el-table-column prop="create_time_text" label="创建时间" min-width="160" align="center" show-overflow-tooltip/>
+					
+					<!-- 操作 -->
+					<el-table-column label="操作" width="180" align="center" fixed="right">
+						<template slot-scope="{row}">
+							<el-link @click="openDetail(row)" icon="el-icon-view" type="primary" :underline="false" style="margin-right: 10px;">查看</el-link>
+							<el-popconfirm title="确定要删除此记录吗?" @confirm="remove(row)" 
+								v-if="permission.includes(permissionPrefix + ':delete')">
+								<el-link slot="reference" icon="el-icon-delete" type="danger" :underline="false">删除</el-link>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</template>
+			</ele-data-table>
+		</el-card>
+
+		<!-- 详情弹窗 -->
+		<el-dialog title="充值记录详情" :visible.sync="detailVisible" width="600px" :destroy-on-close="true">
+			<el-descriptions :column="2" border v-if="detailData">
+				<el-descriptions-item label="订单号" :span="2">{{ detailData.order_no }}</el-descriptions-item>
+				<el-descriptions-item label="充值号码" :span="2">{{ detailData.account }}</el-descriptions-item>
+				<el-descriptions-item label="充值金额">¥{{ detailData.total }}</el-descriptions-item>
+				<el-descriptions-item label="折扣">{{ detailData.discount > 0 ? detailData.discount + '%' : '无' }}</el-descriptions-item>
+				<el-descriptions-item label="实付金额">¥{{ detailData.pay_total }}</el-descriptions-item>
+				<el-descriptions-item label="状态">
+					<el-tag v-if="detailData.status === 1" type="info" size="mini">待付款</el-tag>
+					<el-tag v-else-if="detailData.status === 2" type="primary" size="mini">已付款</el-tag>
+					<el-tag v-else-if="detailData.status === 3" type="warning" size="mini">充值中</el-tag>
+					<el-tag v-else-if="detailData.status === 4" type="success" size="mini">充值成功</el-tag>
+					<el-tag v-else-if="detailData.status === 5" type="danger" size="mini">充值失败</el-tag>
+					<el-tag v-else-if="detailData.status === 6" type="info" size="mini">已退款</el-tag>
+				</el-descriptions-item>
+				<el-descriptions-item label="用户昵称">{{ detailData.user_nickname || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="用户手机">{{ detailData.user_mobile || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="交易单号" :span="2">{{ detailData.transaction_id || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="平台订单号" :span="2">{{ detailData.out_trade_num || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="产品ID">{{ detailData.product_id || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="套餐ID">{{ detailData.meal_id || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="备注" :span="2">{{ detailData.remark || '-' }}</el-descriptions-item>
+				<el-descriptions-item label="创建时间" :span="2">{{ detailData.create_time_text }}</el-descriptions-item>
+				<el-descriptions-item label="更新时间" :span="2">{{ detailData.update_time_text }}</el-descriptions-item>
+			</el-descriptions>
+			<div slot="footer">
+				<el-button @click="detailVisible = false">关闭</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+export default {
+	name: "OrdersManage",
+	props: {
+		// 充值类型(1-话费,2-电费,3-燃气)
+		type: {
+			type: Number,
+			required: true
+		},
+		// 权限前缀
+		permissionPrefix: {
+			type: String,
+			required: true
+		}
+	},
+	computed: {
+		...mapGetters(["permission"])
+	},
+	data() {
+		return {
+			// 表格配置
+			table: {
+				url: '/pay/orders/index',
+				where: {
+					type: this.type
+				}
+			},
+			// 搜索条件
+			where: {
+				keyword: '',
+				status: ''
+			},
+			// 日期范围
+			dateRange: [],
+			// 表格选中数据
+			selection: [],
+			// 详情弹窗
+			detailVisible: false,
+			detailData: null
+		}
+	},
+	watch: {
+		dateRange(val) {
+			if (val && val.length === 2) {
+				this.where.start_time = val[0];
+				this.where.end_time = val[1];
+			} else {
+				this.where.start_time = '';
+				this.where.end_time = '';
+			}
+		}
+	},
+	methods: {
+		/* 查询 */
+		query() {
+			this.$refs.table.reload({where: this.where});
+		},
+		/* 重置 */
+		handleReset() {
+			this.where = {
+				keyword: '',
+				status: ''
+			};
+			this.dateRange = [];
+			this.query();
+		},
+		/* 打开详情 */
+		openDetail(row) {
+			this.detailData = row;
+			this.detailVisible = true;
+		},
+		/* 删除 */
+		remove(row) {
+			this.$http.post('/pay/orders/delete', {id: row.id}).then(res => {
+				if (res.data.code === 0) {
+					this.$message.success(res.data.msg);
+					this.$refs.table.reload();
+				} else {
+					this.$message.error(res.data.msg);
+				}
+			});
+		}
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 40 - 0
addons/admin/src/views/pay/electricityBill.vue

@@ -0,0 +1,40 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<el-tabs v-model="activeTab" @tab-click="handleTabClick">
+				<el-tab-pane label="套餐管理" name="meals">
+					<meals-manage :type="2" permission-prefix="sys:electricityBill" />
+				</el-tab-pane>
+				<el-tab-pane label="充值记录" name="orders">
+					<orders-manage :type="2" permission-prefix="sys:electricityBill" />
+				</el-tab-pane>
+			</el-tabs>
+		</el-card>
+	</div>
+</template>
+
+<script>
+import MealsManage from './components/MealsManage';
+import OrdersManage from './components/OrdersManage';
+
+export default {
+	name: "ElectricityBill",
+	components: {
+		MealsManage,
+		OrdersManage
+	},
+	data() {
+		return {
+			activeTab: 'meals'
+		}
+	},
+	methods: {
+		handleTabClick(tab) {
+			// Tab 切换时的处理
+		}
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 40 - 0
addons/admin/src/views/pay/gasBill.vue

@@ -0,0 +1,40 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<el-tabs v-model="activeTab" @tab-click="handleTabClick">
+				<el-tab-pane label="套餐管理" name="meals">
+					<meals-manage :type="3" permission-prefix="sys:gasBill" />
+				</el-tab-pane>
+				<el-tab-pane label="充值记录" name="orders">
+					<orders-manage :type="3" permission-prefix="sys:gasBill" />
+				</el-tab-pane>
+			</el-tabs>
+		</el-card>
+	</div>
+</template>
+
+<script>
+import MealsManage from './components/MealsManage';
+import OrdersManage from './components/OrdersManage';
+
+export default {
+	name: "GasBill",
+	components: {
+		MealsManage,
+		OrdersManage
+	},
+	data() {
+		return {
+			activeTab: 'meals'
+		}
+	},
+	methods: {
+		handleTabClick(tab) {
+			// Tab 切换时的处理
+		}
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 40 - 0
addons/admin/src/views/pay/phonebill.vue

@@ -0,0 +1,40 @@
+<template>
+	<div class="ele-body">
+		<el-card shadow="never">
+			<el-tabs v-model="activeTab" @tab-click="handleTabClick">
+				<el-tab-pane label="套餐管理" name="meals">
+					<meals-manage :type="1" permission-prefix="sys:phonebill" />
+				</el-tab-pane>
+				<el-tab-pane label="充值记录" name="orders">
+					<orders-manage :type="1" permission-prefix="sys:phonebill" />
+				</el-tab-pane>
+			</el-tabs>
+		</el-card>
+	</div>
+</template>
+
+<script>
+import MealsManage from './components/MealsManage';
+import OrdersManage from './components/OrdersManage';
+
+export default {
+	name: "PhoneBill",
+	components: {
+		MealsManage,
+		OrdersManage
+	},
+	data() {
+		return {
+			activeTab: 'meals'
+		}
+	},
+	methods: {
+		handleTabClick(tab) {
+			// Tab 切换时的处理
+		}
+	}
+}
+</script>
+
+<style scoped>
+</style>

+ 1 - 2
addons/admin/src/views/store/store.vue

@@ -222,7 +222,7 @@ import {
 	DEFAULT_STATUS
 } from "@/constants/storeConstants";
 
-import { STATUS, STATUS_TEXT, STATUS_TYPE } from "@/constants/commonConstants";
+import { STATUS, STATUS_TYPE } from "@/constants/commonConstants";
 
 export default {
 	name: "StoreManage",
@@ -234,7 +234,6 @@ export default {
 			CONFIRM_STATUS,
 			DEFAULT_STATUS,
 			STATUS,
-			STATUS_TEXT,
 			STATUS_TYPE,
 			// 当前选中的状态 tab(使用字符串类型,因为 el-tabs 的 v-model 需要字符串)
 			activeStatus: DEFAULT_STATUS,

+ 0 - 0
addons/admin/update_node_sass.bat


+ 59 - 22
app/Http/Controllers/Admin/AccountController.php

@@ -34,30 +34,67 @@ class AccountController extends Backend
         $this->service = new AccountService();
     }
 
-    // 记录
+    /**
+     * 列表
+     */
     public function index()
     {
-        try {
-            $pageSize = request()->get('limit', 15);
-            $list = $this->service->getDataList(request()->all(), $pageSize);
-            $message = array(
-                "msg" => '操作成功',
-                "code" => 0,
-                "data" => isset($list['list'])? $list['list']:[],
-                "counts" => isset($list['counts'])? $list['counts']:[],
-                "count" => isset($list['total'])? $list['total']:0,
-            );
-            return $message;
-        } catch (\Exception $exception){
-            $message = array(
-                "msg" => '失败:'.$exception->getMessage(),
-                "code" => -1,
-                "counts" => [],
-                "data" => [],
-                "count" => 0,
-            );
-            return $message;
-        }
+        $pageSize = request()->get('limit', 15);
+        $params = request()->all();
+        $params['store_id'] = $this->storeId;
+        $list = $this->service->getDataList($params, $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list']) ? $list['list'] : [],
+            "counts" => isset($list['counts']) ? $list['counts'] : [],
+            "count" => isset($list['total']) ? $list['total'] : 0,
+        );
+        return $message;
+    }
+
+    /**
+     * 获取详情
+     */
+    public function read()
+    {
+        $result = $this->service->getInfo();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? []);
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        $result = $this->service->add();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit()
+    {
+        $result = $this->service->edit();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
 
+    /**
+     * 设置状态
+     */
+    public function status()
+    {
+        $result = $this->service->status();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 删除
+     */
+    public function delete()
+    {
+        $result = $this->service->delete();
+        return showJson($result['msg'], $result['code'] == 0);
     }
 }

+ 70 - 0
app/Http/Controllers/Admin/AgentController.php

@@ -0,0 +1,70 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\AgentService;
+
+/**
+ * 代理管理控制器
+ */
+class AgentController extends Backend
+{
+    /**
+     * 获取代理列表
+     */
+    public function index()
+    {
+        $agentService = new AgentService();
+        $pageSize = request()->get('limit', 15);
+        return $agentService->getDataList(request()->all(), $pageSize);
+    }
+
+    /**
+     * 获取代理详情
+     */
+    public function info()
+    {
+        $id = request()->get('id');
+        if (!$id) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+        $agentService = new AgentService();
+        return $agentService->getInfo($id);
+    }
+
+    /**
+     * 删除代理
+     */
+    public function delete()
+    {
+        $agentService = new AgentService();
+        return $agentService->delete();
+    }
+
+    /**
+     * 更新状态(禁用/启用)
+     */
+    public function status()
+    {
+        $agentService = new AgentService();
+        return $agentService->status();
+    }
+
+    /**
+     * 审核代理
+     */
+    public function audit()
+    {
+        $agentService = new AgentService();
+        return $agentService->audit();
+    }
+
+    /**
+     * 冻结/解冻代理
+     */
+    public function freeze()
+    {
+        $agentService = new AgentService();
+        return $agentService->freeze();
+    }
+}

+ 79 - 0
app/Http/Controllers/Admin/AgentWithdrawController.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\AgentWithdrawService;
+
+/**
+ * 代理提现管理控制器
+ */
+class AgentWithdrawController extends Backend
+{
+    /**
+     * 获取提现列表
+     */
+    public function index()
+    {
+        $service = new AgentWithdrawService();
+        return $service->getList(request()->all());
+    }
+
+    /**
+     * 获取提现详情
+     */
+    public function info()
+    {
+        $id = request()->input('id');
+        if (empty($id)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new AgentWithdrawService();
+        return $service->getInfo($id);
+    }
+
+    /**
+     * 审核提现
+     */
+    public function audit()
+    {
+        $id = request()->input('id');
+        $status = request()->input('status'); // 2-通过,3-驳回
+        $remark = request()->input('remark', '');
+
+        if (empty($id) || !in_array($status, [2, 3])) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new AgentWithdrawService();
+        return $service->audit($id, $status, $remark);
+    }
+
+    /**
+     * 删除提现记录
+     */
+    public function delete()
+    {
+        $id = request()->input('id');
+        if (empty($id)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new AgentWithdrawService();
+        return $service->delete($id);
+    }
+
+    /**
+     * 批量删除
+     */
+    public function deleteAll()
+    {
+        $ids = request()->input('ids');
+        if (empty($ids) || !is_array($ids)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new AgentWithdrawService();
+        return $service->deleteAll($ids);
+    }
+}

+ 80 - 0
app/Http/Controllers/Admin/BalanceLogsController.php

@@ -0,0 +1,80 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\BalanceLogsService;
+
+/**
+ * 统一余额日志管理控制器(充值/提现)
+ */
+class BalanceLogsController extends Backend
+{
+    /**
+     * 获取列表(支持所有账户类型)
+     */
+    public function index()
+    {
+        $service = new BalanceLogsService();
+        return $service->getList(request()->all());
+    }
+
+    /**
+     * 获取详情
+     */
+    public function info()
+    {
+        $id = request()->input('id');
+        if (empty($id)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new BalanceLogsService();
+        return $service->getInfo($id);
+    }
+
+    /**
+     * 审核(仅提现)
+     */
+    public function audit()
+    {
+        $id = request()->input('id');
+        $status = request()->input('status'); // 2-通过,3-驳回
+        $remark = request()->input('remark', '');
+        $payImg = request()->input('pay_img', '');
+
+        if (empty($id) || !in_array($status, [2, 3])) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new BalanceLogsService();
+        return $service->audit($id, $status, $remark, $payImg);
+    }
+
+    /**
+     * 删除记录
+     */
+    public function delete()
+    {
+        $id = request()->input('id');
+        if (empty($id)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new BalanceLogsService();
+        return $service->delete($id);
+    }
+
+    /**
+     * 批量删除
+     */
+    public function deleteAll()
+    {
+        $ids = request()->input('ids');
+        if (empty($ids) || !is_array($ids)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $service = new BalanceLogsService();
+        return $service->deleteAll($ids);
+    }
+}

+ 29 - 0
app/Http/Controllers/Admin/FinancialController.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\FinancialService;
+
+/**
+ * 财务管理控制器
+ */
+class FinancialController extends Backend
+{
+    /**
+     * 获取数据统计
+     */
+    public function statistics()
+    {
+        $financialService = new FinancialService();
+        return $financialService->getStatistics();
+    }
+
+    /**
+     * 获取统计列表(按年月日分组)
+     */
+    public function getList()
+    {
+        $financialService = new FinancialService();
+        return $financialService->getStatisticsList(request()->all());
+    }
+}

+ 29 - 9
app/Http/Controllers/Admin/MemberController.php

@@ -41,15 +41,8 @@ class MemberController extends Backend
      */
     public function index()
     {
-        $pageSize = request()->get('limit', 10);
-        $list = $this->service->getDataList(request()->all(), $pageSize);
-        $message = array(
-            "msg" => '操作成功',
-            "code" => 0,
-            "data" => isset($list['list'])? $list['list']:[],
-            "count" => isset($list['total'])? $list['total']:0,
-        );
-        return $message;
+        $result = $this->service->getList();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? [], $result['count'] ?? 0);
     }
 
     /**
@@ -80,4 +73,31 @@ class MemberController extends Backend
         $result = $this->service->options();
         return message(1002,true, $result);
     }
+
+    /**
+     * 获取详情
+     */
+    public function read()
+    {
+        $result = $this->service->getInfo();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? []);
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        $result = $this->service->add();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 设置状态
+     */
+    public function status()
+    {
+        $result = $this->service->status();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
 }

+ 86 - 71
app/Http/Controllers/Admin/OrderController.php

@@ -1,110 +1,125 @@
 <?php
-// +----------------------------------------------------------------------
-// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
-// +----------------------------------------------------------------------
-// | 版权所有 2017~2021 LARAVEL研发中心
-// +----------------------------------------------------------------------
-// | 官方网站: http://www.laravel.cn
-// +----------------------------------------------------------------------
-// | Author: laravel开发员 <laravel.qq.com>
-// +----------------------------------------------------------------------
 
 namespace App\Http\Controllers\Admin;
 
-use App\Http\Validator\OrderValidator;
 use App\Services\Common\OrderService;
 
 /**
- * 订单管理-控制器
- * @author laravel开发员
- * @since 2020/11/11
- * Class OrderController
- * @package App\Http\Controllers
+ * 订单控制器
  */
 class OrderController extends Backend
 {
-    /**
-     * 构造函数
-     * @author laravel开发员
-     * @since 2020/11/11
-     * OrderController constructor.
-     */
     public function __construct()
     {
         parent::__construct();
         $this->service = new OrderService();
     }
 
+    /**
+     * 列表
+     */
     public function index()
     {
         $params = request()->all();
-        $pageSize = isset($params['pageSize'])? $params['pageSize'] : 10;
-        $list = OrderService::make()->getDataList($params, $pageSize);
-        $message = array(
-            "msg" => '操作成功',
-            "code" => 0,
-            "data" => isset($list['list'])? $list['list']:[],
-            "count" => isset($list['total'])? $list['total']:0,
-        );
-        return $message;
+        $pageSize = isset($params['limit']) ? intval($params['limit']) : PERPAGE;
+        $params['store_id'] =  $this->storeId || 0;
+        return $this->service->getDataList($params, $pageSize);
+    }
+
+    /**
+     * 删除
+     */
+    public function delete()
+    {
+        return $this->service->delete();
+    }
+
+    /**
+     * 修改状态
+     */
+    public function status()
+    {
+        return $this->service->status();
+    }
+
+    /**
+     * 获取详情
+     */
+    public function info()
+    {
+        $id = request()->get('id');
+        return $this->service->getInfo($id);
     }
 
     /**
-     * 审核订单
-     * @return array
+     * 完成支付
      */
-    public function confirm(OrderValidator $validator)
+    public function completePay()
     {
-        $params = request()->post();
-        $params = $validator->check($params, 'confirm');
-        if (!is_array($params)) {
-            return message($params, false);
-        }
-
-        if(OrderService::make()->confirm($this->userId, $params)){
-            return message(OrderService::make()->getError(), true);
-        }else{
-            return message(OrderService::make()->getError(), false);
-        }
+        return $this->service->completePay();
     }
 
+    /**
+     * 订单发货
+     */
+    public function deliver()
+    {
+        return $this->service->deliverOrder();
+    }
+
+    /**
+     * 订单完成
+     */
+    public function complete()
+    {
+        return $this->service->completeOrder();
+    }
 
     /**
      * 取消订单
-     * @return array
      */
-    public function cancel(OrderValidator $validator)
+    public function cancel()
+    {
+        return $this->service->cancelOrder();
+    }
+
+    /**
+     * 申请退款
+     */
+    public function applyRefund()
     {
-        $params = request()->post();
-        $params = $validator->check($params, 'cancel');
-        if (!is_array($params)) {
-            return message($params, false);
-        }
-
-        if(OrderService::make()->cancel($this->userId, $params)){
-            return message(OrderService::make()->getError(), true);
-        }else{
-            return message(OrderService::make()->getError(), false);
-        }
+        return $this->service->applyRefund();
     }
 
     /**
-     * 完成订单
-     * @return array
+     * 同意退款
      */
-    public function complete(OrderValidator $validator)
+    public function agreeRefund()
     {
-        $params = request()->post();
-        $params = $validator->check($params, 'complete');
-        if (!is_array($params)) {
-            return message($params, false);
-        }
-
-        if(OrderService::make()->complete($this->userId, $params)){
-            return message(OrderService::make()->getError(), true);
-        }else{
-            return message(OrderService::make()->getError(), false);
-        }
+        return $this->service->agreeRefund();
     }
 
+    /**
+     * 确认退款
+     */
+    public function confirmRefund()
+    {
+        return $this->service->confirmRefund();
+    }
+
+    /**
+     * 拒绝退款
+     */
+    public function rejectRefund()
+    {
+        return $this->service->rejectRefund();
+    }
+
+    /**
+     * 订单统计
+     */
+    public function statistics()
+    {
+        return $this->service->getStatistics();
+    }
 }

+ 81 - 0
app/Http/Controllers/Admin/PayMealsController.php

@@ -0,0 +1,81 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\PayMealsService;
+
+/**
+ * 缴费充值套餐控制器
+ */
+class PayMealsController extends Backend
+{
+    /**
+     * 获取列表
+     */
+    public function index()
+    {
+        $service = new PayMealsService();
+        $result = $service->getList();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? [], $result['count'] ?? 0);
+    }
+
+    /**
+     * 获取详情
+     */
+    public function read()
+    {
+        $service = new PayMealsService();
+        $result = $service->getInfo();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? []);
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        $service = new PayMealsService();
+        $result = $service->add();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit()
+    {
+        $service = new PayMealsService();
+        $result = $service->edit();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 删除
+     */
+    public function delete()
+    {
+        $service = new PayMealsService();
+        $result = $service->delete();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 批量删除
+     */
+    public function dall()
+    {
+        $service = new PayMealsService();
+        $result = $service->deleteAll();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 设置状态
+     */
+    public function status()
+    {
+        $service = new PayMealsService();
+        $result = $service->status();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+}

+ 51 - 0
app/Http/Controllers/Admin/PayOrdersController.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\PayOrdersService;
+
+/**
+ * 充值缴费订单控制器
+ */
+class PayOrdersController extends Backend
+{
+    /**
+     * 获取列表
+     */
+    public function index()
+    {
+        $service = new PayOrdersService();
+        $result = $service->getList();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? [], $result['count'] ?? 0);
+    }
+
+    /**
+     * 获取详情
+     */
+    public function read()
+    {
+        $service = new PayOrdersService();
+        $result = $service->getInfo();
+        return showJson($result['msg'], $result['code'] == 0, $result['data'] ?? []);
+    }
+
+    /**
+     * 删除
+     */
+    public function delete()
+    {
+        $service = new PayOrdersService();
+        $result = $service->delete();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+
+    /**
+     * 批量删除
+     */
+    public function dall()
+    {
+        $service = new PayOrdersService();
+        $result = $service->deleteAll();
+        return showJson($result['msg'], $result['code'] == 0);
+    }
+}

+ 0 - 80
app/Http/Controllers/Admin/WithdrawController.php

@@ -1,80 +0,0 @@
-<?php
-// +----------------------------------------------------------------------
-// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
-// +----------------------------------------------------------------------
-// | 版权所有 2017~2021 LARAVEL研发中心
-// +----------------------------------------------------------------------
-// | 官方网站: http://www.laravel.cn
-// +----------------------------------------------------------------------
-// | Author: laravel开发员 <laravel.qq.com>
-// +----------------------------------------------------------------------
-
-namespace App\Http\Controllers\Admin;
-
-use App\Services\Common\BalanceLogService;
-
-/**
- * 提现管理-控制器
- * @author laravel开发员
- * @since 2020/11/11
- * @package App\Http\Controllers
- */
-class WithdrawController extends Backend
-{
-    /**
-     * 构造函数
-     * @author laravel开发员
-     * @since 2020/11/11
-     */
-    public function __construct()
-    {
-        parent::__construct();
-        $this->service = new  BalanceLogService();
-    }
-
-
-    /**
-     * 列表
-     * @return array
-     */
-    public function index()
-    {
-        $pageSize = request()->get('limit', 10);
-        $list = $this->service->getDataList(request()->all(), $pageSize);
-        $message = array(
-            "msg" => '操作成功',
-            "code" => 0,
-            "data" => isset($list['list'])? $list['list']:[],
-            "counts" => isset($list['counts'])? $list['counts']:[],
-            "count" => isset($list['total'])? $list['total']:0,
-        );
-        return $message;
-    }
-
-
-    /**
-     * 审核
-     * @return mixed
-     */
-    public function confirm(){
-        $params = request()->post();
-        if(BalanceLogService::make()->confirm($this->userId,$params)){
-            return message(BalanceLogService::make()->getError(), true);
-        }else{
-            return message(BalanceLogService::make()->getError(), false);
-        }
-    }
-
-    /**
-     * 更新打款状态
-     * @return mixed
-     */
-    public function payment(){
-        $params = request()->post();
-        if(BalanceLogService::make()->payment($this->userId,$params)){
-            return message(BalanceLogService::make()->getError(), true);
-        }else{
-            return message(BalanceLogService::make()->getError(), false);
-        }
-    }
-}

+ 29 - 0
app/Models/AgentModel.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Models;
+
+/**
+ * 代理模型
+ */
+class AgentModel extends BaseModel
+{
+    protected $table = 'agents';
+
+    /**
+     * 关联用户
+     */
+    public function user()
+    {
+        return $this->hasOne(MemberModel::class, 'id', 'user_id');
+    }
+
+    /**
+     * 获取团队人数
+     */
+    public function getTeamCountAttribute()
+    {
+        // 这里可以根据实际业务逻辑计算团队人数
+        // 例如:查询该代理推荐的下级用户数量
+        return 0;
+    }
+}

+ 61 - 19
app/Models/BalanceLogModel.php

@@ -1,34 +1,76 @@
 <?php
-// +----------------------------------------------------------------------
-// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
-// +----------------------------------------------------------------------
-// | 版权所有 2017~2021 LARAVEL研发中心
-// +----------------------------------------------------------------------
-// | 官方网站: http://www.laravel.cn
-// +----------------------------------------------------------------------
-// | Author: laravel开发员 <laravel.qq.com>
-// +----------------------------------------------------------------------
 
 namespace App\Models;
 
+use Illuminate\Database\Eloquent\Model;
+
 /**
- * 余额明细-模型
- * @author laravel开发员
- * @since 2020/11/11
- * @package App\Models
+ * 充值/提现记录模型 - 统一余额日志表
+ * 用于会员、代理、商户的充值和提现记录
  */
-class BalanceLogModel extends BaseModel
+class BalanceLogModel extends Model
 {
-    // 设置数据表
     protected $table = 'balance_logs';
+    protected $primaryKey = 'id';
+    public $timestamps = false;
+
+    protected $fillable = [
+        'order_no',
+        'user_id',
+        'type',
+        'account_type',
+        'realname',
+        'money',
+        'actual_money',
+        'pay_type',
+        'pay_status',
+        'pay_at',
+        'pay_img',
+        'transaction_id',
+        'account',
+        'account_remark',
+        'date',
+        'create_time',
+        'update_time',
+        'confirm_remark',
+        'status',
+        'mark'
+    ];
+
+    protected $casts = [
+        'money' => 'decimal:2',
+        'actual_money' => 'decimal:2',
+    ];
 
     /**
-     * 用户
-     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     * 关联用户(会员、代理、商家都在 member 表)
+     */
+    public function user()
+    {
+        return $this->belongsTo(MemberModel::class, 'user_id', 'id');
+    }
+
+    /**
+     * 关联会员(别名,向后兼容)
      */
     public function member()
     {
-        return $this->hasOne(MemberModel::class, 'id','user_id')
-            ->select(['id','mobile','nickname','balance','status']);
+        return $this->user();
+    }
+
+    /**
+     * 关联代理(别名,向后兼容)
+     */
+    public function agent()
+    {
+        return $this->user();
+    }
+
+    /**
+     * 关联商家(别名,向后兼容)
+     */
+    public function store()
+    {
+        return $this->user();
     }
 }

+ 13 - 0
app/Models/OrderGoodsModel.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Models;
+
+/**
+ * 订单商品-模型
+ */
+class OrderGoodsModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'orders_goods';
+}
+

+ 30 - 12
app/Models/OrderModel.php

@@ -25,13 +25,33 @@ class OrderModel extends BaseModel
 
 
     /**
-     * 接单人员
+     * 下单用户
      * @return \Illuminate\Database\Eloquent\Relations\HasOne
      */
     public function user()
     {
-        return $this->hasOne(MemberModel::class, 'id','user_id')
-            ->select(['id','mobile','nickname','realname','balance','picker_order_num','picker_status','confirm_status','status']);
+        return $this->hasOne(MemberModel::class, 'id', 'user_id')
+            ->select(['id', 'mobile', 'nickname', 'realname', 'status']);
+    }
+
+    /**
+     * 订单商品
+     * @return \Illuminate\Database\Eloquent\Relations\HasMany
+     */
+    public function orderGoods()
+    {
+        return $this->hasMany(OrderGoodsModel::class, 'order_id', 'id')
+            ->where('mark', 1);
+    }
+
+    /**
+     * 店铺
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function store()
+    {
+        return $this->hasOne(StoreModel::class, 'id', 'store_id')
+            ->select(['id', 'name']);
     }
 
     /**
@@ -40,8 +60,8 @@ class OrderModel extends BaseModel
      */
     public function adminUser()
     {
-        return $this->hasOne(UserModel::class, 'id','confirm_admin_id')
-            ->select(['id','nickname','mobile','realname','status']);
+        return $this->hasOne(UserModel::class, 'id', 'confirm_admin_id')
+            ->select(['id', 'nickname', 'mobile', 'realname', 'status']);
     }
 
     /**
@@ -50,11 +70,11 @@ class OrderModel extends BaseModel
      */
     public function confirm()
     {
-        return $this->hasOne(OrderModel::class, 'goods_id','goods_id')
+        return $this->hasOne(OrderModel::class, 'goods_id', 'goods_id')
             ->with(['user'])
-            ->whereIn('status',[2,3])
-            ->where(['mark'=>1])
-            ->select(['id','order_no','goods_id','confirm_at','status']);
+            ->whereIn('status', [2, 3])
+            ->where(['mark' => 1])
+            ->select(['id', 'order_no', 'goods_id', 'confirm_at', 'status']);
     }
 
     /**
@@ -63,8 +83,6 @@ class OrderModel extends BaseModel
      */
     public function goods()
     {
-        return $this->hasOne(GoodsModel::class, 'id','goods_id')->with(['shipperCity','shipperDistrict','receiverCity','receiverDistrict']);
+        return $this->hasOne(GoodsModel::class, 'id', 'goods_id')->with(['shipperCity', 'shipperDistrict', 'receiverCity', 'receiverDistrict']);
     }
-
-
 }

+ 56 - 0
app/Models/PayMealsModel.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace App\Models;
+
+/**
+ * 缴费充值套餐模型
+ */
+class PayMealsModel extends BaseModel
+{
+    protected $table = 'pay_meals';
+
+    protected $fillable = [
+        'product_id',
+        'money',
+        'discount',
+        'remark',
+        'type',
+        'sort',
+        'create_time',
+        'update_time',
+        'status',
+        'mark'
+    ];
+
+    /**
+     * 获取类型文本
+     */
+    public function getTypeTextAttribute()
+    {
+        $typeMap = [
+            1 => '话费充值',
+            2 => '电费充值',
+            3 => '燃气充值'
+        ];
+        return $typeMap[$this->type] ?? '未知';
+    }
+
+    /**
+     * 获取状态文本
+     */
+    public function getStatusTextAttribute()
+    {
+        return $this->status == 1 ? '有效' : '无效';
+    }
+
+    /**
+     * 获取实付金额
+     */
+    public function getPayMoneyAttribute()
+    {
+        if ($this->discount > 0) {
+            return round($this->money * $this->discount / 100, 2);
+        }
+        return $this->money;
+    }
+}

+ 74 - 0
app/Models/PayOrdersModel.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Models;
+
+/**
+ * 充值缴费订单模型
+ */
+class PayOrdersModel extends BaseModel
+{
+    protected $table = 'pay_orders';
+
+    protected $fillable = [
+        'order_no',
+        'total',
+        'type',
+        'discount',
+        'pay_total',
+        'account',
+        'transaction_id',
+        'meal_id',
+        'product_id',
+        'out_trade_num',
+        'remark',
+        'create_time',
+        'update_time',
+        'status',
+        'mark'
+    ];
+
+    /**
+     * 关联用户
+     */
+    public function user()
+    {
+        return $this->belongsTo(MemberModel::class, 'user_id', 'id');
+    }
+
+    /**
+     * 关联套餐
+     */
+    public function meal()
+    {
+        return $this->belongsTo(PayMealsModel::class, 'meal_id', 'id');
+    }
+
+    /**
+     * 获取类型文本
+     */
+    public function getTypeTextAttribute()
+    {
+        $typeMap = [
+            1 => '话费',
+            2 => '电费',
+            3 => '燃气'
+        ];
+        return $typeMap[$this->type] ?? '未知';
+    }
+
+    /**
+     * 获取状态文本
+     */
+    public function getStatusTextAttribute()
+    {
+        $statusMap = [
+            1 => '待付款',
+            2 => '已付款',
+            3 => '充值中',
+            4 => '充值成功',
+            5 => '充值失败',
+            6 => '已退款'
+        ];
+        return $statusMap[$this->status] ?? '未知';
+    }
+}

+ 366 - 56
app/Services/Common/AccountService.php

@@ -56,37 +56,99 @@ class AccountService extends BaseService
      */
     public function getDataList($params, $pageSize = 15)
     {
-        $query = $this->getQuery($params);
+        $status = $params['status'] ?? '';
+        $type = $params['type'] ?? '';
+        $keyword = $params['keyword'] ?? '';
+        $orderNo = $params['order_no'] ?? '';
+        $userId = $params['user_id'] ?? '';
+        $date = $params['date'] ?? [];
 
+        $query = AccountLogModel::from('account_logs as a')
+            ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
+            ->where('a.mark', 1);
+
+        // 状态筛选
+        if ($status !== '' && $status != 0) {
+            $query->where('a.status', $status);
+        }
+
+        // 类型筛选
+        if ($type !== '' && $type != 0) {
+            $query->where('a.type', $type);
+        }
+
+        // 用户ID筛选
+        if ($userId) {
+            $query->where('a.user_id', $userId);
+        }
+
+        // 订单号搜索
+        if (!empty($orderNo)) {
+            $query->where('a.source_order_no', 'like', "%{$orderNo}%");
+        }
+
+        // 关键词搜索(用户昵称/手机号)
+        if (!empty($keyword)) {
+            $query->where(function ($q) use ($keyword) {
+                $q->where('b.nickname', 'like', "%{$keyword}%")
+                    ->orWhere('b.mobile', 'like', "%{$keyword}%");
+            });
+        }
+
+        // 日期筛选
+        if (!empty($date) && is_array($date)) {
+            $start = $date[0] ?? '';
+            $end = $date[1] ?? '';
+            if ($start) {
+                $query->where('a.create_time', '>=', strtotime($start));
+            }
+            if ($end && $start < $end) {
+                $query->where('a.create_time', '<=', strtotime($end));
+            }
+        }
+
+        // 统计数据
         $model = clone $query;
         $counts = [
-            'count'=> $model->count('a.id'),
-            'total'=> $model->sum('a.money'),
+            'count' => $model->count('a.id'),
+            'total' => $model->sum('a.money')
         ];
 
-        $list = $query->select(['a.*'])
-            ->orderBy('a.create_time','desc')
-            ->orderBy('a.id','desc')
+        // 分页查询
+        $list = $query->select(['a.*', 'b.mobile', 'b.nickname'])
+            ->orderBy('a.create_time', 'desc')
+            ->orderBy('a.id', 'desc')
             ->paginate($pageSize > 0 ? $pageSize : 9999999);
-        $list = $list? $list->toArray() :[];
-        if($list){
-            $accountTypes = config('payment.accountTypes');
-            foreach($list['data'] as &$item){
-                $item['create_time'] = $item['create_time']? datetime($item['create_time'],'Y-m-d H.i.s') : '';
-                $type = isset($item['type'])? intval($item['type']) : 0;
-                $item['type_text'] = isset($item['remark'])? trim($item['remark']) : '';
-                $item['member'] = isset($item['member'])? $item['member'] : [];
-                if(empty($item['type_text'])){
-                    $item['type_text'] = isset($accountTypes[$type])? $accountTypes[$type] : '收支明细';
-                }
+        
+        $list = $list ? $list->toArray() : [];
+
+        // 格式化数据
+        if ($list && isset($list['data'])) {
+            $accountTypes = config('payment.accountTypes', [
+                1 => '商城消费',
+                2 => '充值缴费',
+                3 => '商城退款',
+                4 => '佣金提现',
+                5 => '提现驳回',
+                6 => '平台入款'
+            ]);
+
+            foreach ($list['data'] as &$item) {
+                $item['create_time'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H.i.s') : '';
+                $item['create_time_text'] = date('Y-m-d H:i:s', (int)$item['create_time']);
+                $type = isset($item['type']) ? intval($item['type']) : 0;
+                $item['type_text'] = $item['remark'] ?: ($accountTypes[$type] ?? '收支明细');
+                $item['money'] = number_format($item['money'], 2, '.', '');
+                $item['before_money'] = number_format($item['before_money'], 2, '.', '');
+                $item['status_text'] = ['', '已完成', '待处理', '失败/取消'][$item['status']] ?? '未知';
             }
         }
 
         return [
-            'pageSize'=> $pageSize,
-            'total'=>isset($list['total'])? $list['total'] : 0,
-            'counts'=>$counts,
-            'list'=> isset($list['data'])? $list['data'] : []
+            'pageSize' => $pageSize,
+            'total' => isset($list['total']) ? $list['total'] : 0,
+            'counts' => $counts,
+            'list' => isset($list['data']) ? $list['data'] : []
         ];
     }
 
@@ -98,66 +160,288 @@ class AccountService extends BaseService
     public function getQuery($params)
     {
         $where = ['a.mark' => 1];
-        $status = isset($params['status'])? $params['status'] : 0;
-        $type = isset($params['type'])? $params['type'] : 0;
-        if($status>0){
+        $status = isset($params['status']) ? $params['status'] : 0;
+        $type = isset($params['type']) ? $params['type'] : 0;
+        if ($status > 0) {
             $where['a.status'] = $status;
         }
-        if($type>0){
+        if ($type > 0) {
             $where['a.type'] = $type;
         }
 
-       return $this->model->with(['member'])->from("account_logs as a")
-            ->leftJoin('member as b','b.id','=','a.user_id')
+        return $this->model->with(['member'])->from("account_logs as a")
+            ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
             ->where($where)
-            ->where(function ($query) use($params) {
+            ->where(function ($query) use ($params) {
                 $keyword = isset($params['keyword']) ? $params['keyword'] : '';
-                $userId = isset($params['user_id'])? $params['user_id'] : 0;
-                if($userId){
-                    $query->where('a.user_id',$userId);
+                $userId = isset($params['user_id']) ? $params['user_id'] : 0;
+                if ($userId) {
+                    $query->where('a.user_id', $userId);
                 }
 
                 if ($keyword) {
-                    $query->where(function($query) use($keyword){
-                        $query->where('b.nickname','like',"%{$keyword}%")
-                            ->orWhere('b.mobile','like',"%{$keyword}%");
+                    $query->where(function ($query) use ($keyword) {
+                        $query->where('b.nickname', 'like', "%{$keyword}%")
+                            ->orWhere('b.mobile', 'like', "%{$keyword}%");
                     });
                 }
 
-                $orderNo = isset($params['order_no'])? trim($params['order_no']) : '';
-                if($orderNo){
-                    $query->where(function($query) use($orderNo){
-                        $query->where('a.source_order_no','like',"%{$orderNo}%");
+                $orderNo = isset($params['order_no']) ? trim($params['order_no']) : '';
+                if ($orderNo) {
+                    $query->where(function ($query) use ($orderNo) {
+                        $query->where('a.source_order_no', 'like', "%{$orderNo}%");
                     });
                 }
             })
-            ->where(function ($query) use($params){
+            ->where(function ($query) use ($params) {
 
                 // 日期
                 $date = isset($params['date']) ? $params['date'] : [];
-                $start = isset($date[0])? $date[0] : '';
-                $end = isset($date[1])? $date[1] : '';
-                $end = $start>=$end? '' : $end;
+                $start = isset($date[0]) ? $date[0] : '';
+                $end = isset($date[1]) ? $date[1] : '';
+                $end = $start >= $end ? '' : $end;
                 if ($start) {
-                    $query->where('a.create_time','>=', strtotime($start));
+                    $query->where('a.create_time', '>=', strtotime($start));
                 }
-                if($end){
-                    $query->where('a.create_time','<=', strtotime($end));
+                if ($end) {
+                    $query->where('a.create_time', '<=', strtotime($end));
                 }
             });
     }
 
 
     /**
-     * 添加或编辑
-     * @return array
-     * @since 2020/11/11
-     * @author laravel开发员
+     * 获取列表
+     */
+    public function getList()
+    {
+        $params = request()->all();
+
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 20;
+        $status = $params['status'] ?? '';
+        $type = $params['type'] ?? '';
+        $keyword = $params['keyword'] ?? '';
+        $orderNo = $params['order_no'] ?? '';
+        $userId = $params['user_id'] ?? '';
+        $date = $params['date'] ?? [];
+
+        $query = AccountLogModel::from('account_logs as a')
+            ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
+            ->where('a.mark', 1);
+
+        // 状态筛选
+        if ($status !== '' && $status != 0) {
+            $query->where('a.status', $status);
+        }
+
+        // 类型筛选
+        if ($type !== '' && $type != 0) {
+            $query->where('a.type', $type);
+        }
+
+        // 用户ID筛选
+        if ($userId) {
+            $query->where('a.user_id', $userId);
+        }
+
+        // 订单号搜索
+        if (!empty($orderNo)) {
+            $query->where('a.source_order_no', 'like', "%{$orderNo}%");
+        }
+
+        // 关键词搜索(用户昵称/手机号)
+        if (!empty($keyword)) {
+            $query->where(function ($q) use ($keyword) {
+                $q->where('b.nickname', 'like', "%{$keyword}%")
+                    ->orWhere('b.mobile', 'like', "%{$keyword}%");
+            });
+        }
+
+        // 日期筛选
+        if (!empty($date) && is_array($date)) {
+            $start = $date[0] ?? '';
+            $end = $date[1] ?? '';
+            if ($start) {
+                $query->where('a.create_time', '>=', strtotime($start));
+            }
+            if ($end && $start < $end) {
+                $query->where('a.create_time', '<=', strtotime($end));
+            }
+        }
+
+        // 统计数据
+        $counts = [
+            'count' => $query->count('a.id'),
+            'total' => $query->sum('a.money')
+        ];
+
+        $total = $counts['count'];
+        $list = $query->select(['a.*', 'b.mobile', 'b.nickname'])
+            ->orderBy('a.create_time', 'desc')
+            ->orderBy('a.id', 'desc')
+            ->offset(($page - 1) * $limit)
+            ->limit($limit)
+            ->get()
+            ->toArray();
+
+        // 格式化数据
+        $accountTypes = config('payment.accountTypes', [
+            1 => '商城消费',
+            2 => '充值缴费',
+            3 => '商城退款',
+            4 => '佣金提现',
+            5 => '提现驳回',
+            6 => '平台入款'
+        ]);
+
+        foreach ($list as &$item) {
+            $item['create_time_text'] = date('Y-m-d H:i:s', (int)$item['create_time']);
+            $item['type_text'] = $item['remark'] ?: ($accountTypes[$item['type']] ?? '收支明细');
+            $item['money'] = number_format($item['money'], 2, '.', '');
+            $item['before_money'] = number_format($item['before_money'], 2, '.', '');
+            $item['status_text'] = ['', '已完成', '待处理', '失败/取消'][$item['status']] ?? '未知';
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total,
+            'counts' => $counts
+        ];
+    }
+
+    /**
+     * 获取详情
+     */
+    public function getInfo($id = null)
+    {
+        if ($id === null) {
+            $id = request()->input('id');
+        }
+
+        $info = AccountLogModel::from('account_logs as a')
+            ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
+            ->where('a.id', $id)
+            ->where('a.mark', 1)
+            ->select(['a.*', 'b.mobile', 'b.nickname'])
+            ->first();
+
+        if (!$info) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $info = $info->toArray();
+        $info['create_time_text'] = date('Y-m-d H:i:s', (int)$info['create_time']);
+        $info['money'] = number_format($info['money'], 2, '.', '');
+        $info['before_money'] = number_format($info['before_money'], 2, '.', '');
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $info
+        ];
+    }
+
+    /**
+     * 添加账户明细
+     */
+    public function add()
+    {
+        $params = request()->all();
+
+        $data = [
+            'user_id' => (int)($params['user_id'] ?? 0),
+            'source_order_no' => $params['source_order_no'] ?? '',
+            'type' => (int)($params['type'] ?? 1),
+            'money' => (float)($params['money'] ?? 0),
+            'before_money' => (float)($params['before_money'] ?? 0),
+            'remark' => $params['remark'] ?? '',
+            'status' => (int)($params['status'] ?? 1),
+            'create_time' => time(),
+            'update_time' => time(),
+            'mark' => 1
+        ];
+
+        $result = AccountLogModel::insert($data);
+
+        if ($result) {
+            return ['code' => 0, 'msg' => '添加成功'];
+        }
+
+        return ['code' => 1, 'msg' => '添加失败'];
+    }
+
+    /**
+     * 编辑账户明细
      */
     public function edit()
     {
-        $data = request()->all();
-        return parent::edit($data); // TODO: Change the autogenerated stub
+        $params = request()->all();
+        $id = $params['id'] ?? 0;
+
+        $log = AccountLogModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$log) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        if (isset($params['user_id'])) {
+            $log->user_id = (int)$params['user_id'];
+        }
+        if (isset($params['source_order_no'])) {
+            $log->source_order_no = $params['source_order_no'];
+        }
+        if (isset($params['type'])) {
+            $log->type = (int)$params['type'];
+        }
+        if (isset($params['money'])) {
+            $log->money = (float)$params['money'];
+        }
+        if (isset($params['before_money'])) {
+            $log->before_money = (float)$params['before_money'];
+        }
+        if (isset($params['remark'])) {
+            $log->remark = $params['remark'];
+        }
+        if (isset($params['status'])) {
+            $log->status = (int)$params['status'];
+        }
+
+        $log->update_time = time();
+        $log->save();
+
+        ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => '修改账户明细', 'content' => json_encode($params, 256), 'module' => 'admin']);
+        ActionLogModel::record();
+
+        return ['code' => 0, 'msg' => '修改成功'];
+    }
+
+    /**
+     * 设置状态
+     */
+    public function status()
+    {
+        $params = request()->all();
+        $id = $params['id'] ?? 0;
+        $status = $params['status'] ?? 1;
+
+        $log = AccountLogModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$log) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $log->status = $status;
+        $log->update_time = time();
+        $log->save();
+
+        return ['code' => 0, 'msg' => '设置成功'];
     }
 
     /**
@@ -166,10 +450,36 @@ class AccountService extends BaseService
      */
     public function delete()
     {
-        // 设置日志标题
-        ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "删除账户明细", 'content' => json_encode(request()->post(), 256), 'module' => 'admin']);
-        ActionLogModel::record();
-        $this->model->where('mark', 0)->where('update_time', '<=', time() - 7 * 86400)->delete();
-        return parent::delete(); // TODO: Change the autogenerated stub
+        $id = request()->input('id');
+
+        if (is_array($id)) {
+            // 批量删除
+            $count = AccountLogModel::whereIn('id', $id)
+                ->where('mark', 1)
+                ->update(['mark' => 0, 'update_time' => time()]);
+
+            ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "批量删除账户明细", 'content' => json_encode($id, 256), 'module' => 'admin']);
+            ActionLogModel::record();
+
+            return ['code' => 0, 'msg' => "成功删除{$count}条记录"];
+        } else {
+            // 单个删除
+            $log = AccountLogModel::where('id', $id)
+                ->where('mark', 1)
+                ->first();
+
+            if (!$log) {
+                return ['code' => 1, 'msg' => '记录不存在'];
+            }
+
+            $log->mark = 0;
+            $log->update_time = time();
+            $log->save();
+
+            ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "删除账户明细", 'content' => json_encode(['id' => $id], 256), 'module' => 'admin']);
+            ActionLogModel::record();
+
+            return ['code' => 0, 'msg' => '删除成功'];
+        }
     }
 }

+ 246 - 0
app/Services/Common/AgentService.php

@@ -0,0 +1,246 @@
+<?php
+
+namespace App\Services\Common;
+
+use App\Models\AgentModel;
+use App\Models\ActionLogModel;
+use App\Services\BaseService;
+use App\Services\RedisService;
+
+/**
+ * 代理服务
+ */
+class AgentService extends BaseService
+{
+    public function __construct()
+    {
+        $this->model = new AgentModel();
+    }
+
+    /**
+     * 获取代理列表
+     */
+    public function getDataList($params, $pageSize = 15)
+    {
+        $query = $this->model->where('mark', 1);
+
+        // 审核状态筛选:1-已审核,2-待审核,3-驳回,4-冻结
+        if (isset($params['status']) && $params['status'] > 0) {
+            $query->where('status', $params['status']);
+        }
+
+        // 关键词搜索(姓名、电话)
+        if (isset($params['keyword']) && $params['keyword']) {
+            $keyword = $params['keyword'];
+            $query->where(function ($q) use ($keyword) {
+                $q->where('real_name', 'like', '%' . $keyword . '%')
+                    ->orWhere('phone', 'like', '%' . $keyword . '%');
+            });
+        }
+
+        $list = $query->with(['user'])
+            ->orderBy('create_time', 'desc')
+            ->orderBy('id', 'desc')
+            ->paginate($pageSize);
+
+        $list = $list ? $list->toArray() : [];
+        if ($list && isset($list['data'])) {
+            foreach ($list['data'] as &$item) {
+                // 确保 status 是整数类型
+                $item['status'] = (int)$item['status'];
+                
+                // 时间格式化:如果是时间戳则直接格式化,否则先转时间戳
+                $item['create_time'] = $item['create_time'] ? (is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : date('Y-m-d H:i:s', strtotime($item['create_time']))) : '';
+                $item['update_time'] = $item['update_time'] ? (is_numeric($item['update_time']) ? date('Y-m-d H:i:s', $item['update_time']) : date('Y-m-d H:i:s', strtotime($item['update_time']))) : '';
+                $item['user'] = $item['user'] ?? [];
+
+                // 计算团队人数(这里简化处理,实际应该查询下级用户)
+                $item['team_count'] = 0;
+                if (isset($item['user_id']) && $item['user_id']) {
+                    $item['team_count'] = \App\Models\MemberModel::where('parent_id', $item['user_id'])
+                        ->where('mark', 1)
+                        ->count();
+                }
+            }
+        }
+
+        return [
+            'msg' => '操作成功',
+            'code' => 0,
+            'data' => $list['data'] ?? [],
+            'count' => $list['total'] ?? 0,
+        ];
+    }
+
+    /**
+     * 获取代理详情
+     */
+    public function getInfo($id)
+    {
+        $info = $this->model->where('id', $id)->where('mark', 1)
+            ->with(['user'])
+            ->first();
+
+        if (!$info) {
+            return ['code' => 1, 'msg' => '代理不存在'];
+        }
+
+        $info = $info->toArray();
+        
+        // 确保 status 是整数类型
+        $info['status'] = (int)$info['status'];
+        
+        // 时间格式化:如果是时间戳则直接格式化,否则先转时间戳
+        $info['create_time'] = $info['create_time'] ? (is_numeric($info['create_time']) ? date('Y-m-d H:i:s', $info['create_time']) : date('Y-m-d H:i:s', strtotime($info['create_time']))) : '';
+        $info['update_time'] = $info['update_time'] ? (is_numeric($info['update_time']) ? date('Y-m-d H:i:s', $info['update_time']) : date('Y-m-d H:i:s', strtotime($info['update_time']))) : '';
+
+        // 计算团队人数
+        $info['team_count'] = 0;
+        if (isset($info['user_id']) && $info['user_id']) {
+            $info['team_count'] = \App\Models\MemberModel::where('parent_id', $info['user_id'])
+                ->where('mark', 1)
+                ->count();
+        }
+
+        return ['code' => 0, 'msg' => '操作成功', 'data' => $info];
+    }
+
+    /**
+     * 删除代理
+     */
+    public function delete()
+    {
+        $id = request()->post('id');
+        if (!$id) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        if (is_array($id)) {
+            $result = $this->model->whereIn('id', $id)->update([
+                'mark' => 0,
+                'update_time' => time()
+            ]);
+        } else {
+            $result = $this->model->where('id', $id)->update([
+                'mark' => 0,
+                'update_time' => time()
+            ]);
+        }
+
+        if ($result) {
+            ActionLogModel::setTitle("删除代理");
+            ActionLogModel::record();
+            RedisService::keyDel("caches:agents:*");
+            return ['code' => 0, 'msg' => '删除成功'];
+        }
+
+        return ['code' => 1, 'msg' => '删除失败'];
+    }
+
+    /**
+     * 更新状态
+     */
+    public function status()
+    {
+        $id = request()->post('id');
+        $status = request()->post('status');
+
+        if (!$id || !isset($status)) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $result = $this->model->where('id', $id)->update([
+            'status' => $status,
+            'update_time' => time()
+        ]);
+
+        if ($result !== false) {
+            ActionLogModel::setTitle("更新代理状态");
+            ActionLogModel::record();
+            RedisService::keyDel("caches:agents:*");
+            return ['code' => 0, 'msg' => '操作成功'];
+        }
+
+        return ['code' => 1, 'msg' => '操作失败'];
+    }
+
+    /**
+     * 审核代理
+     */
+    public function audit()
+    {
+        $id = request()->post('id');
+        $status = request()->post('status'); // 1-已审核(通过),3-驳回
+        $confirmRemark = request()->post('confirm_remark', '');
+
+        if (!$id || !$status) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $agent = $this->model->find($id);
+        if (!$agent) {
+            return ['code' => 1, 'msg' => '代理不存在'];
+        }
+
+        if ($agent->status != 2) {
+            return ['code' => 1, 'msg' => '该代理不是待审核状态'];
+        }
+
+        if ($status == 3 && !$confirmRemark) {
+            return ['code' => 1, 'msg' => '请填写驳回原因'];
+        }
+
+        $updateData = [
+            'status' => $status,
+            'confirm_remark' => $confirmRemark,
+            'update_time' => time()
+        ];
+
+        $result = $this->model->where('id', $id)->update($updateData);
+
+        if ($result) {
+            $statusText = $status == 1 ? '通过' : '驳回';
+            ActionLogModel::setTitle("审核代理-{$statusText}");
+            ActionLogModel::record();
+            RedisService::keyDel("caches:agents:*");
+            return ['code' => 0, 'msg' => "审核{$statusText}"];
+        }
+
+        return ['code' => 1, 'msg' => '操作失败'];
+    }
+
+    /**
+     * 冻结/解冻代理
+     */
+    public function freeze()
+    {
+        $id = request()->post('id');
+        $status = request()->post('status'); // 4-冻结,1-解冻
+
+        if (!$id || !$status) {
+            return ['code' => 1, 'msg' => '参数错误'];
+        }
+
+        $agent = $this->model->find($id);
+        if (!$agent) {
+            return ['code' => 1, 'msg' => '代理不存在'];
+        }
+
+        $updateData = [
+            'status' => $status,
+            'update_time' => time()
+        ];
+
+        $result = $this->model->where('id', $id)->update($updateData);
+
+        if ($result) {
+            $statusText = $status == 4 ? '冻结' : '解冻';
+            ActionLogModel::setTitle("{$statusText}代理");
+            ActionLogModel::record();
+            RedisService::keyDel("caches:agents:*");
+            return ['code' => 0, 'msg' => "{$statusText}成功"];
+        }
+
+        return ['code' => 1, 'msg' => '操作失败'];
+    }
+}

+ 324 - 0
app/Services/Common/BalanceLogsService.php

@@ -0,0 +1,324 @@
+<?php
+
+namespace App\Services\Common;
+
+use App\Models\BalanceLogModel;
+use App\Models\MemberModel;
+use App\Services\BaseService;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 统一余额日志服务(充值/提现)
+ * 支持会员、代理、商户的充值和提现记录
+ */
+class BalanceLogsService extends BaseService
+{
+    /**
+     * 获取列表
+     */
+    public function getList()
+    {
+        // 获取参数
+        $params = request()->all();
+        
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 20;
+        $keyword = $params['keyword'] ?? '';
+        $status = $params['status'] ?? '';
+        $type = $params['type'] ?? ''; // 1-充值,2-提现
+        $accountType = $params['account_type'] ?? ''; // 1-会员,2-代理,3-商户
+        $startTime = $params['start_time'] ?? '';
+        $endTime = $params['end_time'] ?? '';
+
+        $query = BalanceLogModel::where('mark', 1);
+
+        // 类型筛选
+        if ($type !== '') {
+            $query->where('type', $type);
+        }
+
+        // 账户类型筛选
+        if ($accountType !== '') {
+            $query->where('account_type', $accountType);
+        }
+
+        // 关键词搜索(订单号、姓名、手机号)
+        if (!empty($keyword)) {
+            $query->where(function($q) use ($keyword) {
+                $q->where('order_no', 'like', "%{$keyword}%")
+                  ->orWhere('realname', 'like', "%{$keyword}%")
+                  ->orWhereHas('user', function($sq) use ($keyword) {
+                      $sq->where('realname', 'like', "%{$keyword}%")
+                        ->orWhere('nickname', 'like', "%{$keyword}%")
+                        ->orWhere('mobile', 'like', "%{$keyword}%");
+                  });
+            });
+        }
+
+        // 状态筛选
+        if ($status !== '') {
+            $query->where('status', $status);
+        }
+
+        // 时间范围
+        if (!empty($startTime)) {
+            $query->where('create_time', '>=', strtotime($startTime));
+        }
+        if (!empty($endTime)) {
+            $query->where('create_time', '<=', strtotime($endTime . ' 23:59:59'));
+        }
+
+        $total = $query->count();
+        $list = $query->with(['user:id,realname,nickname,mobile,user_type'])
+            ->orderBy('create_time', 'desc')
+            ->offset(($page - 1) * $limit)
+            ->limit($limit)
+            ->get()
+            ->toArray();
+
+        // 格式化数据
+        foreach ($list as &$item) {
+            $item['money'] = number_format($item['money'], 2, '.', '');
+            $item['actual_money'] = number_format($item['actual_money'], 2, '.', '');
+            $item['create_time_text'] = date('Y-m-d H:i:s', $item['create_time']);
+            $item['update_time_text'] = date('Y-m-d H:i:s', $item['update_time']);
+            $item['status_text'] = $this->getStatusText($item['status']);
+            $item['pay_type_text'] = $this->getPayTypeText($item['pay_type']);
+            $item['account_type_text'] = $this->getAccountTypeText($item['account_type']);
+            $item['type_text'] = $item['type'] == 1 ? '充值' : '提现';
+            
+            // 根据账户类型添加额外信息
+            if (isset($item['user'])) {
+                $item['user_realname'] = $item['user']['realname'] ?? '';
+                $item['user_nickname'] = $item['user']['nickname'] ?? '';
+                $item['user_mobile'] = $item['user']['mobile'] ?? '';
+                $item['user_type'] = $item['user']['user_type'] ?? 0;
+            }
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 获取详情
+     */
+    public function getInfo($id = null)
+    {
+        // 如果没有传入ID,从请求中获取
+        if ($id === null) {
+            $id = request()->input('id');
+        }
+        
+        $info = BalanceLogModel::where('id', $id)
+            ->where('mark', 1)
+            ->with(['user:id,realname,nickname,mobile,user_type'])
+            ->first();
+
+        if (!$info) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $info = $info->toArray();
+        $info['money'] = number_format($info['money'], 2, '.', '');
+        $info['actual_money'] = number_format($info['actual_money'], 2, '.', '');
+        $info['create_time_text'] = date('Y-m-d H:i:s', $info['create_time']);
+        $info['update_time_text'] = date('Y-m-d H:i:s', $info['update_time']);
+        $info['status_text'] = $this->getStatusText($info['status']);
+        $info['pay_type_text'] = $this->getPayTypeText($info['pay_type']);
+        $info['account_type_text'] = $this->getAccountTypeText($info['account_type']);
+        $info['type_text'] = $info['type'] == 1 ? '充值' : '提现';
+
+        // 根据账户类型添加额外信息
+        if (isset($info['user'])) {
+            $info['user_realname'] = $info['user']['realname'] ?? '';
+            $info['user_nickname'] = $info['user']['nickname'] ?? '';
+            $info['user_mobile'] = $info['user']['mobile'] ?? '';
+            $info['user_type'] = $info['user']['user_type'] ?? 0;
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $info
+        ];
+    }
+
+    /**
+     * 审核(仅提现)
+     */
+    public function audit($id = null, $status = null, $remark = '', $payImg = '')
+    {
+        // 如果没有传入参数,从请求中获取
+        if ($id === null) {
+            $params = request()->all();
+            $id = $params['id'] ?? null;
+            $status = $params['status'] ?? null;
+            $remark = $params['remark'] ?? '';
+            $payImg = $params['pay_img'] ?? '';
+        }
+        
+        DB::beginTransaction();
+        try {
+            $record = BalanceLogModel::where('id', $id)
+                ->where('mark', 1)
+                ->where('type', 2) // 必须是提现
+                ->lockForUpdate()
+                ->first();
+
+            if (!$record) {
+                throw new \Exception('提现记录不存在');
+            }
+
+            if ($record->status != 1) {
+                throw new \Exception('该记录已处理');
+            }
+
+            // 更新状态
+            $record->status = $status;
+            $record->confirm_remark = $remark;
+            $record->update_time = time();
+            
+            // 如果是通过,更新支付状态和打款凭证
+            if ($status == 2) {
+                $record->pay_status = 20; // 20-已支付
+                $record->pay_at = date('Y-m-d H:i:s');
+                if (!empty($payImg)) {
+                    $record->pay_img = $payImg;
+                }
+            }
+            
+            $record->save();
+
+            // 如果是驳回,退回金额
+            if ($status == 3) {
+                $this->refundBalance($record);
+            }
+
+            DB::commit();
+            return ['code' => 0, 'msg' => '操作成功'];
+        } catch (\Exception $e) {
+            DB::rollBack();
+            return ['code' => 1, 'msg' => $e->getMessage()];
+        }
+    }
+
+    /**
+     * 退回余额
+     */
+    private function refundBalance($record)
+    {
+        // 所有用户(会员、代理、商户)都在 member 表中
+        $user = MemberModel::find($record->user_id);
+        
+        if ($user) {
+            // 退回余额
+            $user->balance = bcadd($user->balance, $record->money, 2);
+            $user->save();
+        }
+    }
+
+    /**
+     * 删除记录
+     */
+    public function delete()
+    {
+        // 获取参数
+        $id = request()->input('id');
+        
+        $record = BalanceLogModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$record) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        if ($record->status == 1) {
+            return ['code' => 1, 'msg' => '待审核的记录不能删除'];
+        }
+
+        $record->mark = 0;
+        $record->save();
+
+        return ['code' => 0, 'msg' => '删除成功'];
+    }
+
+    /**
+     * 批量删除
+     */
+    public function deleteAll($ids = null)
+    {
+        // 如果没有传入参数,从请求中获取
+        if ($ids === null) {
+            $ids = request()->input('ids', []);
+        }
+        
+        $count = BalanceLogModel::whereIn('id', $ids)
+            ->where('mark', 1)
+            ->where('status', '!=', 1)
+            ->update(['mark' => 0]);
+
+        return [
+            'code' => 0,
+            'msg' => "成功删除{$count}条记录"
+        ];
+    }
+
+    /**
+     * 获取状态文本
+     */
+    private function getStatusText($status)
+    {
+        $statusMap = [
+            -1 => '已取消',
+            1 => '待审核',
+            2 => '已审核/到账',
+            3 => '审核失败'
+        ];
+        return $statusMap[$status] ?? '未知';
+    }
+
+    /**
+     * 获取支付方式文本
+     */
+    private function getPayTypeText($payType)
+    {
+        $payTypeMap = [
+            10 => '微信',
+            20 => '支付宝',
+            50 => '银行卡'
+        ];
+        return $payTypeMap[$payType] ?? '未知';
+    }
+
+    /**
+     * 获取账户类型文本
+     */
+    private function getAccountTypeText($accountType)
+    {
+        $accountTypeMap = [
+            1 => '会员',
+            2 => '代理',
+            3 => '商户'
+        ];
+        return $accountTypeMap[$accountType] ?? '未知';
+    }
+
+    /**
+     * 获取代理等级文本
+     */
+    private function getAgentLevelText($level)
+    {
+        $levelMap = [
+            1 => '一级代理',
+            2 => '二级代理',
+            3 => '三级代理'
+        ];
+        return $levelMap[$level] ?? '未知';
+    }
+}

+ 406 - 0
app/Services/Common/FinancialService.php

@@ -0,0 +1,406 @@
+<?php
+
+namespace App\Services\Common;
+
+use App\Models\OrderModel;
+use App\Models\MemberModel;
+use App\Models\WithdrawModel;
+use App\Models\AccountLogModel;
+use App\Services\BaseService;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 财务服务
+ */
+class FinancialService extends BaseService
+{
+    /**
+     * 获取数据统计
+     */
+    public function getStatistics()
+    {
+        try {
+            // 获取当前时间范围
+            $today = date('Y-m-d');
+            $todayStart = strtotime($today . ' 00:00:00');
+            $todayEnd = strtotime($today . ' 23:59:59');
+            
+            $monthStart = strtotime(date('Y-m-01 00:00:00'));
+            $monthEnd = strtotime(date('Y-m-t 23:59:59'));
+
+            // 1. 订单统计
+            $orderStats = $this->getOrderStatistics($todayStart, $todayEnd, $monthStart, $monthEnd);
+
+            // 2. 营业额统计
+            $revenueStats = $this->getRevenueStatistics($todayStart, $todayEnd, $monthStart, $monthEnd);
+
+            // 3. 退款统计
+            $refundStats = $this->getRefundStatistics($todayStart, $todayEnd, $monthStart, $monthEnd);
+
+            // 4. 结算统计
+            $settlementStats = $this->getSettlementStatistics();
+
+            // 5. 会员统计
+            $memberStats = $this->getMemberStatistics($todayStart, $todayEnd, $monthStart, $monthEnd);
+
+            return [
+                'code' => 0,
+                'msg' => '获取成功',
+                'data' => [
+                    'order' => $orderStats,
+                    'revenue' => $revenueStats,
+                    'refund' => $refundStats,
+                    'settlement' => $settlementStats,
+                    'member' => $memberStats
+                ]
+            ];
+        } catch (\Exception $e) {
+            return [
+                'code' => 1,
+                'msg' => '获取失败:' . $e->getMessage()
+            ];
+        }
+    }
+
+    /**
+     * 订单统计
+     */
+    private function getOrderStatistics($todayStart, $todayEnd, $monthStart, $monthEnd)
+    {
+        $orderModel = new OrderModel();
+
+        // 总订单数
+        $total = $orderModel->where('mark', 1)->count();
+
+        // 月订单数
+        $month = $orderModel->where('mark', 1)
+            ->whereBetween('create_time', [$monthStart, $monthEnd])
+            ->count();
+
+        // 当日订单数
+        $today = $orderModel->where('mark', 1)
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->count();
+
+        return [
+            'total' => $total,
+            'month' => $month,
+            'today' => $today
+        ];
+    }
+
+    /**
+     * 营业额统计(使用账户明细表统计商城消费)
+     */
+    private function getRevenueStatistics($todayStart, $todayEnd, $monthStart, $monthEnd)
+    {
+        // 使用账户明细表统计商城消费(type=1)和充值缴费(type=2)
+        $accountLogModel = new AccountLogModel();
+
+        // 总营业额(商城消费 + 充值缴费)
+        $total = $accountLogModel->where('mark', 1)
+            ->where('status', 1) // 已完成
+            ->whereIn('type', [1, 2]) // 1-商城消费,2-充值缴费
+            ->sum('money');
+
+        // 月营业额
+        $month = $accountLogModel->where('mark', 1)
+            ->where('status', 1)
+            ->whereIn('type', [1, 2])
+            ->whereBetween('create_time', [$monthStart, $monthEnd])
+            ->sum('money');
+
+        // 当日营业额
+        $today = $accountLogModel->where('mark', 1)
+            ->where('status', 1)
+            ->whereIn('type', [1, 2])
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->sum('money');
+
+        return [
+            'total' => number_format($total, 2, '.', ''),
+            'month' => number_format($month, 2, '.', ''),
+            'today' => number_format($today, 2, '.', '')
+        ];
+    }
+
+    /**
+     * 退款统计(使用账户明细表统计商城退款)
+     */
+    private function getRefundStatistics($todayStart, $todayEnd, $monthStart, $monthEnd)
+    {
+        // 使用账户明细表统计商城退款(type=3)
+        $accountLogModel = new AccountLogModel();
+
+        // 总退款订单数和金额
+        $totalRefund = $accountLogModel->where('mark', 1)
+            ->where('type', 3) // 3-商城退款
+            ->where('status', 1) // 已完成
+            ->selectRaw('COUNT(*) as count, SUM(money) as amount')
+            ->first();
+
+        // 月退款订单数和金额
+        $monthRefund = $accountLogModel->where('mark', 1)
+            ->where('type', 3)
+            ->where('status', 1)
+            ->whereBetween('create_time', [$monthStart, $monthEnd])
+            ->selectRaw('COUNT(*) as count, SUM(money) as amount')
+            ->first();
+
+        // 当日退款订单数和金额
+        $todayRefund = $accountLogModel->where('mark', 1)
+            ->where('type', 3)
+            ->where('status', 1)
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->selectRaw('COUNT(*) as count, SUM(money) as amount')
+            ->first();
+
+        return [
+            'total_count' => $totalRefund->count ?? 0,
+            'total_amount' => number_format($totalRefund->amount ?? 0, 2, '.', ''),
+            'month_count' => $monthRefund->count ?? 0,
+            'month_amount' => number_format($monthRefund->amount ?? 0, 2, '.', ''),
+            'today_count' => $todayRefund->count ?? 0,
+            'today_amount' => number_format($todayRefund->amount ?? 0, 2, '.', '')
+        ];
+    }
+
+    /**
+     * 结算统计(使用账户明细表统计佣金提现)
+     */
+    private function getSettlementStatistics()
+    {
+        // 使用账户明细表统计佣金提现(type=4)
+        $accountLogModel = new AccountLogModel();
+
+        // 已结算金额总数(已完成的佣金提现)
+        $total = $accountLogModel->where('mark', 1)
+            ->where('type', 4) // 4-佣金提现
+            ->where('status', 1) // 已完成
+            ->sum('money');
+
+        return [
+            'total' => number_format($total, 2, '.', '')
+        ];
+    }
+
+    /**
+     * 会员统计
+     */
+    private function getMemberStatistics($todayStart, $todayEnd, $monthStart, $monthEnd)
+    {
+        $memberModel = new MemberModel();
+
+        // 总会员数
+        $total = $memberModel->where('mark', 1)->count();
+
+        // 月新增会员
+        $month = $memberModel->where('mark', 1)
+            ->whereBetween('create_time', [$monthStart, $monthEnd])
+            ->count();
+
+        // 当日新增会员
+        $today = $memberModel->where('mark', 1)
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->count();
+
+        return [
+            'total' => $total,
+            'month' => $month,
+            'today' => $today
+        ];
+    }
+
+    /**
+     * 获取统计列表(按年月日分组)
+     */
+    public function getStatisticsList($params)
+    {
+        $type = $params['type'] ?? 'order';
+        $groupBy = $params['group_by'] ?? 'day';
+        $startDate = $params['start_date'] ?? date('Y-m-d', strtotime('-30 days'));
+        $endDate = $params['end_date'] ?? date('Y-m-d');
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 20;
+
+        $startTime = strtotime($startDate . ' 00:00:00');
+        $endTime = strtotime($endDate . ' 23:59:59');
+
+        try {
+            switch ($type) {
+                case 'order':
+                    return $this->getOrderList($groupBy, $startTime, $endTime, $page, $limit);
+                case 'revenue':
+                    return $this->getRevenueList($groupBy, $startTime, $endTime, $page, $limit);
+                case 'refund':
+                    return $this->getRefundList($groupBy, $startTime, $endTime, $page, $limit);
+                case 'settlement':
+                    return $this->getSettlementList($groupBy, $startTime, $endTime, $page, $limit);
+                case 'member':
+                    return $this->getMemberList($groupBy, $startTime, $endTime, $page, $limit);
+                default:
+                    return ['code' => 1, 'msg' => '未知的统计类型'];
+            }
+        } catch (\Exception $e) {
+            return ['code' => 1, 'msg' => '查询失败:' . $e->getMessage()];
+        }
+    }
+
+    /**
+     * 订单统计列表
+     */
+    private function getOrderList($groupBy, $startTime, $endTime, $page, $limit)
+    {
+        $dateFormat = $this->getDateFormat($groupBy);
+        
+        $query = OrderModel::where('mark', 1)
+            ->whereBetween('create_time', [$startTime, $endTime])
+            ->selectRaw("FROM_UNIXTIME(create_time, '{$dateFormat}') as date, COUNT(*) as count")
+            ->groupBy('date')
+            ->orderBy('date', 'desc');
+
+        $total = $query->get()->count();
+        $data = $query->offset(($page - 1) * $limit)->limit($limit)->get()->toArray();
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $data,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 营业额统计列表
+     */
+    private function getRevenueList($groupBy, $startTime, $endTime, $page, $limit)
+    {
+        $dateFormat = $this->getDateFormat($groupBy);
+        
+        $query = AccountLogModel::where('mark', 1)
+            ->where('status', 1)
+            ->whereIn('type', [1, 2])
+            ->whereBetween('create_time', [$startTime, $endTime])
+            ->selectRaw("FROM_UNIXTIME(create_time, '{$dateFormat}') as date, SUM(money) as amount")
+            ->groupBy('date')
+            ->orderBy('date', 'desc');
+
+        $allResults = $query->get();
+        $total = $allResults->count();
+        $list = $allResults->slice(($page - 1) * $limit, $limit)->values()->toArray();
+        
+        foreach ($list as &$item) {
+            $item['amount'] = number_format($item['amount'], 2, '.', '');
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 退款统计列表
+     */
+    private function getRefundList($groupBy, $startTime, $endTime, $page, $limit)
+    {
+        $dateFormat = $this->getDateFormat($groupBy);
+        
+        $query = AccountLogModel::where('mark', 1)
+            ->where('type', 3)
+            ->where('status', 1)
+            ->whereBetween('create_time', [$startTime, $endTime])
+            ->selectRaw("FROM_UNIXTIME(create_time, '{$dateFormat}') as date, COUNT(*) as count, SUM(money) as amount")
+            ->groupBy('date')
+            ->orderBy('date', 'desc');
+
+        $allResults = $query->get();
+        $total = $allResults->count();
+        $list = $allResults->slice(($page - 1) * $limit, $limit)->values()->toArray();
+        
+        foreach ($list as &$item) {
+            $item['amount'] = number_format($item['amount'], 2, '.', '');
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 结算统计列表
+     */
+    private function getSettlementList($groupBy, $startTime, $endTime, $page, $limit)
+    {
+        $dateFormat = $this->getDateFormat($groupBy);
+        
+        $query = AccountLogModel::where('mark', 1)
+            ->where('type', 4)
+            ->where('status', 1)
+            ->whereBetween('create_time', [$startTime, $endTime])
+            ->selectRaw("FROM_UNIXTIME(create_time, '{$dateFormat}') as date, SUM(money) as amount")
+            ->groupBy('date')
+            ->orderBy('date', 'desc');
+
+        $allResults = $query->get();
+        $total = $allResults->count();
+        $list = $allResults->slice(($page - 1) * $limit, $limit)->values()->toArray();
+        
+        foreach ($list as &$item) {
+            $item['amount'] = number_format($item['amount'], 2, '.', '');
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 会员统计列表
+     */
+    private function getMemberList($groupBy, $startTime, $endTime, $page, $limit)
+    {
+        $dateFormat = $this->getDateFormat($groupBy);
+        
+        $query = MemberModel::where('mark', 1)
+            ->whereBetween('create_time', [$startTime, $endTime])
+            ->selectRaw("FROM_UNIXTIME(create_time, '{$dateFormat}') as date, COUNT(*) as count")
+            ->groupBy('date')
+            ->orderBy('date', 'desc');
+
+        $allResults = $query->get();
+        $total = $allResults->count();
+        $data = $allResults->slice(($page - 1) * $limit, $limit)->values()->toArray();
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $data,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 获取日期格式
+     */
+    private function getDateFormat($groupBy)
+    {
+        switch ($groupBy) {
+            case 'year':
+                return '%Y';
+            case 'month':
+                return '%Y-%m';
+            case 'day':
+            default:
+                return '%Y-%m-%d';
+        }
+    }
+}

+ 256 - 18
app/Services/Common/MemberService.php

@@ -50,7 +50,79 @@ class MemberService extends BaseService
     }
 
     /**
-     * 列表
+     * 获取列表
+     */
+    public function getList()
+    {
+        $params = request()->all();
+        
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 20;
+        $status = $params['status'] ?? '';
+        $keyword = $params['keyword'] ?? '';
+        $mobile = $params['mobile'] ?? '';
+        $userType = $params['user_type'] ?? '';
+        $memberLevel = $params['member_level'] ?? '';
+
+        $query = MemberModel::where('mark', 1);
+
+        // 状态筛选
+        if ($status !== '' && $status != 0) {
+            $query->where('status', $status);
+        }
+
+        // 用户类型筛选
+        if ($userType !== '') {
+            $query->where('user_type', $userType);
+        }
+
+        // 会员等级筛选
+        if ($memberLevel !== '') {
+            $query->where('member_level', $memberLevel);
+        }
+
+        // 手机号搜索
+        if (!empty($mobile)) {
+            $query->where('mobile', 'like', "%{$mobile}%");
+        }
+
+        // 关键词搜索(昵称/姓名)
+        if (!empty($keyword)) {
+            $query->where(function($q) use ($keyword) {
+                $q->where('nickname', 'like', "%{$keyword}%")
+                  ->orWhere('realname', 'like', "%{$keyword}%");
+            });
+        }
+
+        $total = $query->count();
+        $list = $query->orderBy('create_time', 'desc')
+            ->orderBy('id', 'desc')
+            ->offset(($page - 1) * $limit)
+            ->limit($limit)
+            ->get()
+            ->toArray();
+
+        // 格式化数据
+        foreach ($list as &$item) {
+            $item['avatar'] = $item['avatar'] ? get_image_url($item['avatar']) : '';
+            $item['balance'] = number_format($item['balance'], 2, '.', '');
+            $item['create_time_text'] = date('Y-m-d H:i:s', (int)$item['create_time']);
+            $item['login_time_text'] = $item['login_time'] ? date('Y-m-d H:i:s', (int)$item['login_time']) : '-';
+            $item['gender_text'] = ['', '男', '女', '未知'][$item['gender']] ?? '未知';
+            $item['status_text'] = $item['status'] == 1 ? '正常' : '冻结';
+            $item['user_type_text'] = $item['user_type'] == 1 ? '用户' : '其他';
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 列表(兼容旧方法)
      * @param $params
      * @param int $pageSize
      * @return array
@@ -197,10 +269,17 @@ class MemberService extends BaseService
     {
         // 请求参数
         $data = request()->all();
+        $id = isset($data['id']) ? $data['id'] : 0;
+        
+        // 查找会员
+        $member = MemberModel::where('id', $id)->where('mark', 1)->first();
+        if (!$member && $id) {
+            return message('会员不存在', false);
+        }
+
         // 头像处理
-        $avatar = trim($data['avatar']);
-        if ($avatar) {
-            $data['avatar'] = get_image_path($avatar);
+        if (isset($data['avatar']) && $data['avatar']) {
+            $data['avatar'] = get_image_path(trim($data['avatar']));
         }
 
         if (isset($data['driving_license'])) {
@@ -211,25 +290,47 @@ class MemberService extends BaseService
             $data['drivers_license'] = get_image_path($data['drivers_license']);
         }
 
-        // 手机号唯一
-        $id = isset($data['id']) ? $data['id'] : 0;
+        // 手机号唯一性验证
         $mobile = isset($data['mobile']) ? trim($data['mobile']) : '';
-        $checkId = $this->model->where(['mobile' => $mobile, 'mark' => 1])->value('id');
-        if ($checkId && ($id != $checkId)) {
-            return message('手机号已存在', false);
+        if ($mobile) {
+            $checkId = $this->model->where(['mobile' => $mobile, 'mark' => 1])->value('id');
+            if ($checkId && ($id != $checkId)) {
+                return message('手机号已存在', false);
+            }
         }
 
+        // 密码处理
         if (isset($data['password']) && $data['password']) {
             $data['password'] = get_password(trim($data['password']));
+        } else {
+            // 编辑时如果密码为空则不更新密码
+            unset($data['password']);
+        }
+
+        // 处理数值类型字段
+        if (isset($data['gender'])) {
+            $data['gender'] = (int)$data['gender'];
+        }
+        if (isset($data['user_type'])) {
+            $data['user_type'] = (int)$data['user_type'];
+        }
+        if (isset($data['member_level'])) {
+            $data['member_level'] = (int)$data['member_level'];
+        }
+        if (isset($data['balance'])) {
+            $data['balance'] = (float)$data['balance'];
+        }
+        if (isset($data['status'])) {
+            $data['status'] = (int)$data['status'];
         }
 
         // 设置日志
-        ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => '修改司机信息', 'content' => json_encode($data, 256), 'module' => 'admin']);
+        ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => '修改会员信息', 'content' => json_encode($data, 256), 'module' => 'admin']);
         ActionLogModel::record();
 
         RedisService::keyDel("caches:members:count*");
         RedisService::clear("caches:members:info_{$id}");
-        return parent::edit($data); // TODO: Change the autogenerated stub
+        return parent::edit($data);
     }
 
     /**
@@ -265,17 +366,154 @@ class MemberService extends BaseService
     }
 
     /**
+     * 获取详情
+     */
+    public function getInfo($id = null)
+    {
+        if ($id === null) {
+            $id = request()->input('id');
+        }
+        
+        $info = MemberModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$info) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $info = $info->toArray();
+        $info['avatar'] = $info['avatar'] ? get_image_url($info['avatar']) : '';
+        $info['balance'] = number_format($info['balance'], 2, '.', '');
+        $info['create_time_text'] = date('Y-m-d H:i:s', (int)$info['create_time']);
+        $info['login_time_text'] = $info['login_time'] ? date('Y-m-d H:i:s', (int)$info['login_time']) : '-';
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $info
+        ];
+    }
+
+    /**
+     * 添加会员
+     */
+    public function add()
+    {
+        $params = request()->all();
+
+        // 检查手机号是否已存在
+        $mobile = $params['mobile'] ?? '';
+        $exists = MemberModel::where('mobile', $mobile)
+            ->where('mark', 1)
+            ->exists();
+        
+        if ($exists) {
+            return ['code' => 1, 'msg' => '手机号已存在'];
+        }
+
+        // 处理头像
+        $avatar = $params['avatar'] ?? '';
+        if ($avatar) {
+            $params['avatar'] = get_image_path($avatar);
+        }
+
+        // 处理密码
+        if (isset($params['password']) && $params['password']) {
+            $params['password'] = get_password($params['password']);
+        }
+
+        $data = [
+            'openid' => $params['openid'] ?? '',
+            'mobile' => $mobile,
+            'user_type' => (int)($params['user_type'] ?? 1),
+            'password' => $params['password'] ?? '',
+            'member_level' => (int)($params['member_level'] ?? 0),
+            'realname' => $params['realname'] ?? '',
+            'nickname' => $params['nickname'] ?? '',
+            'gender' => (int)($params['gender'] ?? 3),
+            'avatar' => $params['avatar'] ?? '',
+            'balance' => (float)($params['balance'] ?? 0),
+            'parent_id' => (int)($params['parent_id'] ?? 0),
+            'status' => (int)($params['status'] ?? 1),
+            'source' => (int)($params['source'] ?? 2),
+            'create_time' => time(),
+            'update_time' => time(),
+            'mark' => 1
+        ];
+
+        $result = MemberModel::insert($data);
+
+        if ($result) {
+            RedisService::keyDel("caches:members:count*");
+            return ['code' => 0, 'msg' => '添加成功'];
+        }
+
+        return ['code' => 1, 'msg' => '添加失败'];
+    }
+
+    /**
+     * 设置状态
+     */
+    public function status()
+    {
+        $params = request()->all();
+        $id = $params['id'] ?? 0;
+        $status = $params['status'] ?? 1;
+
+        $member = MemberModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$member) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $member->status = $status;
+        $member->update_time = time();
+        $member->save();
+
+        RedisService::clear("caches:members:info_{$id}");
+        return ['code' => 0, 'msg' => '设置成功'];
+    }
+
+    /**
      * 删除
      * @return array
      */
     public function delete()
     {
-        // 设置日志标题
-        ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "删除司机信息", 'content' => json_encode(request()->post(), 256), 'module' => 'admin']);
-        ActionLogModel::record();
-        $this->model->where('mark', 0)->where('update_time', '<=', time() - 7 * 86400)->delete();
-        RedisService::keyDel("caches:members:count*");
-        RedisService::keyDel("caches:members:info*");
-        return parent::delete(); // TODO: Change the autogenerated stub
+        $id = request()->input('id');
+        
+        if (is_array($id)) {
+            // 批量删除
+            $count = MemberModel::whereIn('id', $id)
+                ->where('mark', 1)
+                ->update(['mark' => 0, 'update_time' => time()]);
+            
+            foreach ($id as $memberId) {
+                RedisService::clear("caches:members:info_{$memberId}");
+            }
+            
+            RedisService::keyDel("caches:members:count*");
+            return ['code' => 0, 'msg' => "成功删除{$count}条记录"];
+        } else {
+            // 单个删除
+            $member = MemberModel::where('id', $id)
+                ->where('mark', 1)
+                ->first();
+
+            if (!$member) {
+                return ['code' => 1, 'msg' => '记录不存在'];
+            }
+
+            $member->mark = 0;
+            $member->update_time = time();
+            $member->save();
+
+            RedisService::clear("caches:members:info_{$id}");
+            RedisService::keyDel("caches:members:count*");
+            return ['code' => 0, 'msg' => '删除成功'];
+        }
     }
 }

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 636 - 160
app/Services/Common/OrderService.php


+ 233 - 0
app/Services/Common/PayMealsService.php

@@ -0,0 +1,233 @@
+<?php
+
+namespace App\Services\Common;
+
+use App\Models\PayMealsModel;
+use App\Services\BaseService;
+
+/**
+ * 缴费充值套餐服务
+ */
+class PayMealsService extends BaseService
+{
+    /**
+     * 获取列表
+     */
+    public function getList()
+    {
+        $params = request()->all();
+        
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 20;
+        $type = $params['type'] ?? '';
+        $status = $params['status'] ?? '';
+        $keyword = $params['keyword'] ?? '';
+
+        $query = PayMealsModel::where('mark', 1);
+
+        // 类型筛选
+        if ($type !== '') {
+            $query->where('type', $type);
+        }
+
+        // 状态筛选
+        if ($status !== '') {
+            $query->where('status', $status);
+        }
+
+        // 关键词搜索
+        if (!empty($keyword)) {
+            $query->where(function($q) use ($keyword) {
+                $q->where('money', 'like', "%{$keyword}%")
+                  ->orWhere('remark', 'like', "%{$keyword}%")
+                  ->orWhere('product_id', 'like', "%{$keyword}%");
+            });
+        }
+
+        $total = $query->count();
+        $list = $query->orderBy('sort', 'desc')
+            ->orderBy('id', 'desc')
+            ->offset(($page - 1) * $limit)
+            ->limit($limit)
+            ->get();
+
+        // 格式化数据
+        $result = [];
+        foreach ($list as $item) {
+            $data = $item->toArray();
+            $data['money'] = number_format($data['money'], 2, '.', '');
+            $data['discount'] = number_format($data['discount'], 2, '.', '');
+            // 计算实付金额
+            if ($data['discount'] > 0) {
+                $data['pay_money'] = number_format($data['money'] * $data['discount'] / 100, 2, '.', '');
+            } else {
+                $data['pay_money'] = $data['money'];
+            }
+            $data['create_time_text'] = date('Y-m-d H:i:s', (int)$data['create_time']);
+            $data['update_time_text'] = date('Y-m-d H:i:s', (int)$data['update_time']);
+            $result[] = $data;
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $result,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 获取详情
+     */
+    public function getInfo($id = null)
+    {
+        if ($id === null) {
+            $id = request()->input('id');
+        }
+        
+        $info = PayMealsModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$info) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $info = $info->toArray();
+        $info['money'] = number_format($info['money'], 2, '.', '');
+        $info['discount'] = number_format($info['discount'], 2, '.', '');
+        // 计算实付金额
+        if ($info['discount'] > 0) {
+            $info['pay_money'] = number_format($info['money'] * $info['discount'] / 100, 2, '.', '');
+        } else {
+            $info['pay_money'] = $info['money'];
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $info
+        ];
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        $params = request()->all();
+
+        $data = [
+            'product_id' => (int)($params['product_id'] ?? 0),
+            'money' => (float)($params['money'] ?? 0),
+            'discount' => (float)($params['discount'] ?? 0),
+            'remark' => (string)($params['remark'] ?? ''),
+            'type' => (int)($params['type'] ?? 1),
+            'sort' => (int)($params['sort'] ?? 0),
+            'status' => (int)($params['status'] ?? 1),
+            'create_time' => time(),
+            'update_time' => time(),
+            'mark' => 1
+        ];
+
+        $result = PayMealsModel::insert($data);
+
+        if ($result) {
+            return ['code' => 0, 'msg' => '添加成功'];
+        }
+
+        return ['code' => 1, 'msg' => '添加失败'];
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit()
+    {
+        $params = request()->all();
+        $id = $params['id'] ?? 0;
+
+        $meal = PayMealsModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$meal) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $meal->product_id = $params['product_id'] ?? $meal->product_id;
+        $meal->money = $params['money'] ?? $meal->money;
+        $meal->discount = $params['discount'] ?? $meal->discount;
+        $meal->remark = $params['remark'] ?? $meal->remark;
+        $meal->sort = $params['sort'] ?? $meal->sort;
+        $meal->status = $params['status'] ?? $meal->status;
+        $meal->update_time = time();
+        $meal->save();
+
+        return ['code' => 0, 'msg' => '修改成功'];
+    }
+
+    /**
+     * 删除
+     */
+    public function delete()
+    {
+        $id = request()->input('id');
+        
+        $meal = PayMealsModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$meal) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $meal->mark = 0;
+        $meal->save();
+
+        return ['code' => 0, 'msg' => '删除成功'];
+    }
+
+    /**
+     * 批量删除
+     */
+    public function deleteAll($ids = null)
+    {
+        if ($ids === null) {
+            $ids = request()->input('ids', []);
+        }
+        
+        $count = PayMealsModel::whereIn('id', $ids)
+            ->where('mark', 1)
+            ->update(['mark' => 0]);
+
+        return [
+            'code' => 0,
+            'msg' => "成功删除{$count}条记录"
+        ];
+    }
+
+    /**
+     * 设置状态
+     */
+    public function status()
+    {
+        $params = request()->all();
+        $id = $params['id'] ?? 0;
+        $status = $params['status'] ?? 1;
+
+        $meal = PayMealsModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$meal) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $meal->status = $status;
+        $meal->update_time = time();
+        $meal->save();
+
+        return ['code' => 0, 'msg' => '设置成功'];
+    }
+}

+ 164 - 0
app/Services/Common/PayOrdersService.php

@@ -0,0 +1,164 @@
+<?php
+
+namespace App\Services\Common;
+
+use App\Models\PayOrdersModel;
+use App\Models\MemberModel;
+use App\Services\BaseService;
+
+/**
+ * 充值缴费订单服务
+ */
+class PayOrdersService extends BaseService
+{
+    /**
+     * 获取列表
+     */
+    public function getList()
+    {
+        $params = request()->all();
+        
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 20;
+        $type = $params['type'] ?? '';
+        $status = $params['status'] ?? '';
+        $keyword = $params['keyword'] ?? '';
+        $startTime = $params['start_time'] ?? '';
+        $endTime = $params['end_time'] ?? '';
+
+        $query = PayOrdersModel::where('mark', 1);
+
+        // 类型筛选
+        if ($type !== '') {
+            $query->where('type', $type);
+        }
+
+        // 状态筛选
+        if ($status !== '') {
+            $query->where('status', $status);
+        }
+
+        // 关键词搜索
+        if (!empty($keyword)) {
+            $query->where(function($q) use ($keyword) {
+                $q->where('order_no', 'like', "%{$keyword}%")
+                  ->orWhere('account', 'like', "%{$keyword}%")
+                  ->orWhere('transaction_id', 'like', "%{$keyword}%")
+                  ->orWhereHas('user', function($sq) use ($keyword) {
+                      $sq->where('nickname', 'like', "%{$keyword}%")
+                        ->orWhere('mobile', 'like', "%{$keyword}%");
+                  });
+            });
+        }
+
+        // 时间范围
+        if (!empty($startTime)) {
+            $query->where('create_time', '>=', strtotime($startTime));
+        }
+        if (!empty($endTime)) {
+            $query->where('create_time', '<=', strtotime($endTime . ' 23:59:59'));
+        }
+
+        $total = $query->count();
+        $list = $query->with(['user:id,nickname,mobile'])
+            ->orderBy('create_time', 'desc')
+            ->offset(($page - 1) * $limit)
+            ->limit($limit)
+            ->get()
+            ->toArray();
+
+        // 格式化数据
+        foreach ($list as &$item) {
+            $item['total'] = number_format($item['total'], 2, '.', '');
+            $item['discount'] = number_format($item['discount'], 2, '.', '');
+            $item['pay_total'] = number_format($item['pay_total'], 2, '.', '');
+            $item['create_time_text'] = date('Y-m-d H:i:s', (int)$item['create_time']);
+            $item['update_time_text'] = date('Y-m-d H:i:s', (int)$item['update_time']);
+            
+            // 用户信息
+            if (isset($item['user'])) {
+                $item['user_nickname'] = $item['user']['nickname'] ?? '';
+                $item['user_mobile'] = $item['user']['mobile'] ?? '';
+            }
+        }
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $list,
+            'count' => $total
+        ];
+    }
+
+    /**
+     * 获取详情
+     */
+    public function getInfo($id = null)
+    {
+        if ($id === null) {
+            $id = request()->input('id');
+        }
+        
+        $info = PayOrdersModel::where('id', $id)
+            ->where('mark', 1)
+            ->with(['user:id,nickname,mobile', 'meal'])
+            ->first();
+
+        if (!$info) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $info = $info->toArray();
+        $info['total'] = number_format($info['total'], 2, '.', '');
+        $info['discount'] = number_format($info['discount'], 2, '.', '');
+        $info['pay_total'] = number_format($info['pay_total'], 2, '.', '');
+        $info['create_time_text'] = date('Y-m-d H:i:s', (int)$info['create_time']);
+        $info['update_time_text'] = date('Y-m-d H:i:s', (int)$info['update_time']);
+
+        return [
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $info
+        ];
+    }
+
+    /**
+     * 删除
+     */
+    public function delete()
+    {
+        $id = request()->input('id');
+        
+        $order = PayOrdersModel::where('id', $id)
+            ->where('mark', 1)
+            ->first();
+
+        if (!$order) {
+            return ['code' => 1, 'msg' => '记录不存在'];
+        }
+
+        $order->mark = 0;
+        $order->save();
+
+        return ['code' => 0, 'msg' => '删除成功'];
+    }
+
+    /**
+     * 批量删除
+     */
+    public function deleteAll($ids = null)
+    {
+        if ($ids === null) {
+            $ids = request()->input('ids', []);
+        }
+        
+        $count = PayOrdersModel::whereIn('id', $ids)
+            ->where('mark', 1)
+            ->update(['mark' => 0]);
+
+        return [
+            'code' => 0,
+            'msg' => "成功删除{$count}条记录"
+        ];
+    }
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1004 - 0
database/lev_.sql


+ 146 - 0
database/seeders/AgentTestDataSeeder.php

@@ -0,0 +1,146 @@
+<?php
+
+namespace Database\Seeders;
+
+use Illuminate\Database\Seeder;
+use Illuminate\Support\Facades\DB;
+
+class AgentTestDataSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $agents = [
+            [
+                'user_id' => 1,
+                'real_name' => '张三',
+                'phone' => '13800138001',
+                'balance' => 1500.00,
+                'income' => 5000.00,
+                'withdraw_total' => 3500.00,
+                'order_count' => 25,
+                'idcard' => '440101199001011234',
+                'create_time' => time() - 86400 * 30,
+                'update_time' => time(),
+                'confirm_remark' => '',
+                'status' => 1, // 已审核
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 2,
+                'real_name' => '李四',
+                'phone' => '13800138002',
+                'balance' => 2800.00,
+                'income' => 8500.00,
+                'withdraw_total' => 5700.00,
+                'order_count' => 42,
+                'idcard' => '440101199002021234',
+                'create_time' => time() - 86400 * 25,
+                'update_time' => time(),
+                'confirm_remark' => '',
+                'status' => 1, // 已审核
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 3,
+                'real_name' => '王五',
+                'phone' => '13800138003',
+                'balance' => 0.00,
+                'income' => 0.00,
+                'withdraw_total' => 0.00,
+                'order_count' => 0,
+                'idcard' => '440101199003031234',
+                'create_time' => time() - 86400 * 2,
+                'update_time' => time(),
+                'confirm_remark' => '',
+                'status' => 2, // 待审核
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 4,
+                'real_name' => '赵六',
+                'phone' => '13800138004',
+                'balance' => 0.00,
+                'income' => 0.00,
+                'withdraw_total' => 0.00,
+                'order_count' => 0,
+                'idcard' => '440101199004041234',
+                'create_time' => time() - 86400 * 3,
+                'update_time' => time(),
+                'confirm_remark' => '资料不完整,请补充相关证明材料',
+                'status' => 3, // 已驳回
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 5,
+                'real_name' => '孙七',
+                'phone' => '13800138005',
+                'balance' => 500.00,
+                'income' => 3200.00,
+                'withdraw_total' => 2700.00,
+                'order_count' => 18,
+                'idcard' => '440101199005051234',
+                'create_time' => time() - 86400 * 20,
+                'update_time' => time(),
+                'confirm_remark' => '违规操作,账号已冻结',
+                'status' => 4, // 已冻结
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 6,
+                'real_name' => '周八',
+                'phone' => '13800138006',
+                'balance' => 3500.00,
+                'income' => 12000.00,
+                'withdraw_total' => 8500.00,
+                'order_count' => 65,
+                'idcard' => '440101199006061234',
+                'create_time' => time() - 86400 * 45,
+                'update_time' => time(),
+                'confirm_remark' => '',
+                'status' => 1, // 已审核
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 7,
+                'real_name' => '吴九',
+                'phone' => '13800138007',
+                'balance' => 0.00,
+                'income' => 0.00,
+                'withdraw_total' => 0.00,
+                'order_count' => 0,
+                'idcard' => '440101199007071234',
+                'create_time' => time() - 86400 * 1,
+                'update_time' => time(),
+                'confirm_remark' => '',
+                'status' => 2, // 待审核
+                'mark' => 1,
+            ],
+            [
+                'user_id' => 8,
+                'real_name' => '郑十',
+                'phone' => '13800138008',
+                'balance' => 1200.00,
+                'income' => 4500.00,
+                'withdraw_total' => 3300.00,
+                'order_count' => 28,
+                'idcard' => '440101199008081234',
+                'create_time' => time() - 86400 * 35,
+                'update_time' => time(),
+                'confirm_remark' => '',
+                'status' => 1, // 已审核
+                'mark' => 1,
+            ],
+        ];
+
+        foreach ($agents as $agent) {
+            DB::table('agents')->insert($agent);
+        }
+
+        echo "代理测试数据创建成功!\n";
+    }
+}

+ 7 - 1
database/seeders/DatabaseSeeder.php

@@ -16,6 +16,12 @@ class DatabaseSeeder extends Seeder
         // \App\Models\User::factory(10)->create();
 
         // 生成商家三表关联测试数据
-        $this->call(StoreTestDataSeeder::class);
+        // $this->call(StoreTestDataSeeder::class);
+
+        // 生成缴费充值套餐测试数据
+        $this->call(PayMealsSeeder::class);
+
+        // 生成充值缴费订单测试数据
+        $this->call(PayOrdersSeeder::class);
     }
 }

+ 159 - 0
database/seeders/OrderTestDataSeeder.php

@@ -0,0 +1,159 @@
+<?php
+
+namespace Database\Seeders;
+
+use Illuminate\Database\Seeder;
+use Illuminate\Support\Facades\DB;
+
+class OrderTestDataSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        // 获取现有的用户、店铺和商品数据
+        $users = DB::table('member')->where('mark', 1)->pluck('id')->toArray();
+        $stores = DB::table('stores')->where('mark', 1)->pluck('id')->toArray();
+        $goods = DB::table('goods')->where('mark', 1)->get()->toArray();
+
+        if (empty($users) || empty($stores) || empty($goods)) {
+            echo "请先创建用户、店铺和商品数据\n";
+            return;
+        }
+
+        $statuses = [1, 2, 3, 4]; // 1-待付款,2-已付款,3-已发货,4-已完成
+        $refundStatuses = [0, 1, 2, 3, 4]; // 0-无,1-已退款,2-已审核,3-待审核,4-审核驳回
+        $afterTypes = [0, 1, 2]; // 0-无,1-售后,2-退款
+
+        $provinces = ['广东省', '广西壮族自治区', '北京市', '上海市', '浙江省', '江苏省', '四川省'];
+        $cities = ['广州市', '南宁市', '朝阳区', '浦东新区', '杭州市', '南京市', '成都市'];
+        $districts = ['天河区', '青秀区', '三里屯', '陆家嘴', '西湖区', '玄武区', '武侯区'];
+        $streets = ['中山大道', '民族大道', '建国路', '世纪大道', '延安路', '中山路', '人民南路'];
+
+        $deliveryCompanies = [
+            ['name' => '顺丰速运', 'code' => 'SF'],
+            ['name' => '圆通速递', 'code' => 'YTO'],
+            ['name' => '中通快递', 'code' => 'ZTO'],
+            ['name' => '韵达快递', 'code' => 'YD'],
+            ['name' => '申通快递', 'code' => 'STO'],
+            ['name' => '百世快递', 'code' => 'HTKY'],
+            ['name' => '京东物流', 'code' => 'JD'],
+        ];
+
+        $names = ['张三', '李四', '王五', '赵六', '刘七', '陈八', '杨九', '周十'];
+
+        $time = time();
+
+        // 生成15个订单
+        for ($i = 1; $i <= 15; $i++) {
+            $userId = $users[array_rand($users)];
+            $storeId = $stores[array_rand($stores)];
+            $status = $statuses[array_rand($statuses)];
+            $refundStatus = $i <= 3 ? $refundStatuses[array_rand($refundStatuses)] : 0; // 前3个订单可能有退款
+            $afterType = $refundStatus > 0 ? $afterTypes[array_rand([1, 2])] : 0;
+
+            $orderNo = 'ORD' . date('Ymd') . str_pad($i, 6, '0', STR_PAD_LEFT);
+            $createTime = $time - (15 - $i) * 86400; // 倒序创建时间
+
+            // 随机选择1-3个商品
+            $orderGoodsCount = rand(1, 3);
+            $selectedGoods = array_rand(array_flip(array_keys($goods)), min($orderGoodsCount, count($goods)));
+            if (!is_array($selectedGoods)) {
+                $selectedGoods = [$selectedGoods];
+            }
+
+            $total = 0;
+            $orderGoodsData = [];
+
+            foreach ($selectedGoods as $goodsIndex) {
+                $goodsItem = $goods[$goodsIndex];
+                $quantity = rand(1, 3);
+                $price = $goodsItem->price;
+                $subtotal = $price * $quantity;
+                $total += $subtotal;
+
+                $orderGoodsData[] = [
+                    'goods_name' => $goodsItem->goods_name,
+                    'category_id' => $goodsItem->category_id,
+                    'store_id' => $goodsItem->store_id,
+                    'price' => $price,
+                    'stock' => $quantity,
+                    'unit' => $goodsItem->unit ?: '件',
+                    'weight' => $goodsItem->weight,
+                    'thumb' => $goodsItem->thumb,
+                    'sku_type' => $goodsItem->sku_type,
+                    'sku_id' => 0,
+                    'create_time' => $createTime,
+                    'update_time' => $createTime,
+                    'status' => 1,
+                    'mark' => 1,
+                ];
+            }
+
+            $payTotal = $total - rand(0, 50); // 实付可能有优惠
+            if ($payTotal < 0) $payTotal = $total;
+
+            $receiverName = $names[array_rand($names)];
+            $province = $provinces[array_rand($provinces)];
+            $city = $cities[array_rand($cities)];
+            $district = $districts[array_rand($districts)];
+            $street = $streets[array_rand($streets)];
+            $receiverArea = $province . ' ' . $city . ' ' . $district;
+            $receiverAddress = $street . rand(1, 999) . '号' . rand(1, 30) . '栋' . rand(101, 2999) . '室';
+
+            $delivery = $deliveryCompanies[array_rand($deliveryCompanies)];
+            $deliveryNo = $status >= 3 ? $delivery['code'] . rand(1000000000, 9999999999) : '';
+            $deliveryCompany = $status >= 3 ? $delivery['name'] : '';
+            $deliveryCode = $status >= 3 ? $delivery['code'] : '';
+
+            $transactionId = $status >= 2 ? '4200' . rand(1000000000, 9999999999) . rand(1000000000, 9999999999) : '';
+
+            $bonus = $status == 4 ? round($payTotal * 0.05, 2) : 0; // 完成订单才有佣金
+
+            $afterRealname = $afterType > 0 ? $receiverName : '';
+            $afterPhone = $afterType > 0 ? '1' . rand(3, 9) . rand(100000000, 999999999) : '';
+            $afterRemark = $afterType == 1 ? '商品质量有问题,申请售后' : ($afterType == 2 ? '不想要了,申请退款' : '');
+            $refundRemark = $refundStatus == 2 ? '已审核通过,退款中' : ($refundStatus == 4 ? '不符合退款条件,驳回' : '');
+
+            // 插入订单
+            $orderId = DB::table('orders')->insertGetId([
+                'order_no' => $orderNo,
+                'user_id' => $userId,
+                'store_id' => $storeId,
+                'total' => $total,
+                'pay_total' => $payTotal,
+                'transaction_id' => $transactionId,
+                'receiver_name' => $receiverName,
+                'receiver_area' => $receiverArea,
+                'receiver_address' => $receiverAddress,
+                'delivery_no' => $deliveryNo,
+                'delivery_company' => $deliveryCompany,
+                'delivery_code' => $deliveryCode,
+                'bonus' => $bonus,
+                'after_type' => $afterType,
+                'after_realname' => $afterRealname,
+                'after_phone' => $afterPhone,
+                'after_remark' => $afterRemark,
+                'refund_remark' => $refundRemark,
+                'refund_status' => $refundStatus,
+                'create_time' => $createTime,
+                'update_time' => $createTime,
+                'status' => $status,
+                'mark' => 1,
+            ]);
+
+            // 插入订单商品
+            foreach ($orderGoodsData as &$orderGoodsItem) {
+                $orderGoodsItem['order_id'] = $orderId;
+            }
+            DB::table('orders_goods')->insert($orderGoodsData);
+
+            echo "已创建订单 {$i}/15: {$orderNo}\n";
+        }
+
+        echo "订单测试数据创建完成!\n";
+    }
+}

+ 68 - 0
database/seeders/PayMealsSeeder.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace Database\Seeders;
+
+use Illuminate\Database\Seeder;
+use Illuminate\Support\Facades\DB;
+
+class PayMealsSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $time = time();
+
+        // 话费充值套餐
+        $phoneMeals = [
+            ['product_id' => 1101, 'money' => 10.00, 'discount' => 98, 'remark' => '10元话费', 'type' => 1, 'sort' => 100],
+            ['product_id' => 1102, 'money' => 20.00, 'discount' => 98, 'remark' => '20元话费', 'type' => 1, 'sort' => 90],
+            ['product_id' => 1103, 'money' => 30.00, 'discount' => 97, 'remark' => '30元话费', 'type' => 1, 'sort' => 80],
+            ['product_id' => 1104, 'money' => 50.00, 'discount' => 97, 'remark' => '50元话费', 'type' => 1, 'sort' => 70],
+            ['product_id' => 1105, 'money' => 100.00, 'discount' => 96, 'remark' => '100元话费', 'type' => 1, 'sort' => 60],
+            ['product_id' => 1106, 'money' => 200.00, 'discount' => 95, 'remark' => '200元话费', 'type' => 1, 'sort' => 50],
+            ['product_id' => 1107, 'money' => 300.00, 'discount' => 95, 'remark' => '300元话费', 'type' => 1, 'sort' => 40],
+            ['product_id' => 1108, 'money' => 500.00, 'discount' => 94, 'remark' => '500元话费', 'type' => 1, 'sort' => 30],
+        ];
+
+        // 电费充值套餐
+        $electricityMeals = [
+            ['product_id' => 1040, 'money' => 100.00, 'discount' => 99, 'remark' => '100元电费', 'type' => 2, 'sort' => 100],
+            ['product_id' => 1041, 'money' => 200.00, 'discount' => 98, 'remark' => '200元电费', 'type' => 2, 'sort' => 90],
+            ['product_id' => 1042, 'money' => 300.00, 'discount' => 98, 'remark' => '300元电费', 'type' => 2, 'sort' => 80],
+            ['product_id' => 1043, 'money' => 500.00, 'discount' => 97, 'remark' => '500元电费', 'type' => 2, 'sort' => 70],
+            ['product_id' => 1044, 'money' => 1000.00, 'discount' => 96, 'remark' => '1000元电费', 'type' => 2, 'sort' => 60],
+        ];
+
+        // 燃气充值套餐
+        $gasMeals = [
+            ['product_id' => 1458, 'money' => 100.00, 'discount' => 99, 'remark' => '100元燃气', 'type' => 3, 'sort' => 100],
+            ['product_id' => 1459, 'money' => 200.00, 'discount' => 98, 'remark' => '200元燃气', 'type' => 3, 'sort' => 90],
+            ['product_id' => 1460, 'money' => 300.00, 'discount' => 98, 'remark' => '300元燃气', 'type' => 3, 'sort' => 80],
+            ['product_id' => 1461, 'money' => 500.00, 'discount' => 97, 'remark' => '500元燃气', 'type' => 3, 'sort' => 70],
+            ['product_id' => 1462, 'money' => 1000.00, 'discount' => 96, 'remark' => '1000元燃气', 'type' => 3, 'sort' => 60],
+        ];
+
+        // 合并所有套餐
+        $allMeals = array_merge($phoneMeals, $electricityMeals, $gasMeals);
+
+        // 添加通用字段
+        foreach ($allMeals as &$meal) {
+            $meal['create_time'] = $time;
+            $meal['update_time'] = $time;
+            $meal['status'] = 1;
+            $meal['mark'] = 1;
+        }
+
+        // 插入数据
+        DB::table('pay_meals')->insert($allMeals);
+
+        $this->command->info('缴费充值套餐测试数据添加成功!');
+        $this->command->info('- 话费充值套餐:' . count($phoneMeals) . ' 条');
+        $this->command->info('- 电费充值套餐:' . count($electricityMeals) . ' 条');
+        $this->command->info('- 燃气充值套餐:' . count($gasMeals) . ' 条');
+    }
+}

+ 115 - 0
database/seeders/PayOrdersSeeder.php

@@ -0,0 +1,115 @@
+<?php
+
+namespace Database\Seeders;
+
+use Illuminate\Database\Seeder;
+use Illuminate\Support\Facades\DB;
+
+class PayOrdersSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $time = time();
+        $orders = [];
+
+        // 获取用户ID(假设有一些测试用户)
+        $userIds = DB::table('member')->where('mark', 1)->limit(10)->pluck('id')->toArray();
+        
+        if (empty($userIds)) {
+            $this->command->warn('没有找到用户数据,请先添加用户!');
+            return;
+        }
+
+        // 状态数组
+        $statuses = [1, 2, 3, 4, 5, 6]; // 1-待付款,2-已付款,3-充值中,4-充值成功,5-充值失败,6-已退款
+
+        // 生成话费充值订单(type=1)
+        for ($i = 1; $i <= 20; $i++) {
+            $money = [10, 20, 30, 50, 100, 200][array_rand([10, 20, 30, 50, 100, 200])];
+            $discount = rand(94, 99);
+            $payTotal = round($money * $discount / 100, 2);
+            
+            $orders[] = [
+                'order_no' => 'PHB' . date('Ymd') . str_pad($i, 4, '0', STR_PAD_LEFT),
+                'total' => $money,
+                'type' => 1,
+                'discount' => $discount,
+                'pay_total' => $payTotal,
+                'account' => '1' . rand(3, 9) . str_pad(rand(0, 999999999), 9, '0', STR_PAD_LEFT),
+                'transaction_id' => 'WX' . time() . rand(1000, 9999),
+                'meal_id' => rand(1, 8),
+                'product_id' => 1100 + rand(1, 8),
+                'out_trade_num' => 'OUT' . time() . rand(1000, 9999),
+                'remark' => '话费充值',
+                'create_time' => $time - rand(0, 86400 * 30),
+                'update_time' => $time - rand(0, 86400 * 30),
+                'status' => $statuses[array_rand($statuses)],
+                'mark' => 1
+            ];
+        }
+
+        // 生成电费充值订单(type=2)
+        for ($i = 1; $i <= 15; $i++) {
+            $money = [100, 200, 300, 500, 1000][array_rand([100, 200, 300, 500, 1000])];
+            $discount = rand(96, 99);
+            $payTotal = round($money * $discount / 100, 2);
+            
+            $orders[] = [
+                'order_no' => 'ELB' . date('Ymd') . str_pad($i, 4, '0', STR_PAD_LEFT),
+                'total' => $money,
+                'type' => 2,
+                'discount' => $discount,
+                'pay_total' => $payTotal,
+                'account' => rand(100000000000, 999999999999),
+                'transaction_id' => 'WX' . time() . rand(1000, 9999),
+                'meal_id' => rand(9, 13),
+                'product_id' => 1040 + rand(0, 4),
+                'out_trade_num' => 'OUT' . time() . rand(1000, 9999),
+                'remark' => '电费充值',
+                'create_time' => $time - rand(0, 86400 * 30),
+                'update_time' => $time - rand(0, 86400 * 30),
+                'status' => $statuses[array_rand($statuses)],
+                'mark' => 1
+            ];
+        }
+
+        // 生成燃气充值订单(type=3)
+        for ($i = 1; $i <= 15; $i++) {
+            $money = [100, 200, 300, 500, 1000][array_rand([100, 200, 300, 500, 1000])];
+            $discount = rand(96, 99);
+            $payTotal = round($money * $discount / 100, 2);
+            
+            $orders[] = [
+                'order_no' => 'GAS' . date('Ymd') . str_pad($i, 4, '0', STR_PAD_LEFT),
+                'total' => $money,
+                'type' => 3,
+                'discount' => $discount,
+                'pay_total' => $payTotal,
+                'account' => rand(100000000000, 999999999999),
+                'transaction_id' => 'WX' . time() . rand(1000, 9999),
+                'meal_id' => rand(14, 18),
+                'product_id' => 1458 + rand(0, 4),
+                'out_trade_num' => 'OUT' . time() . rand(1000, 9999),
+                'remark' => '燃气充值',
+                'create_time' => $time - rand(0, 86400 * 30),
+                'update_time' => $time - rand(0, 86400 * 30),
+                'status' => $statuses[array_rand($statuses)],
+                'mark' => 1
+            ];
+        }
+
+        // 插入数据
+        DB::table('pay_orders')->insert($orders);
+
+        $this->command->info('充值缴费订单测试数据添加成功!');
+        $this->command->info('- 话费充值订单:20 条');
+        $this->command->info('- 电费充值订单:15 条');
+        $this->command->info('- 燃气充值订单:15 条');
+        $this->command->info('- 总计:' . count($orders) . ' 条');
+    }
+}

+ 105 - 0
database/seeders/README_PAY.md

@@ -0,0 +1,105 @@
+# 充值管理测试数据说明
+
+## 使用方法
+
+### 1. 运行所有 Seeders
+```bash
+php artisan db:seed
+```
+
+### 2. 只运行充值套餐 Seeder
+```bash
+php artisan db:seed --class=PayMealsSeeder
+```
+
+### 3. 只运行充值订单 Seeder
+```bash
+php artisan db:seed --class=PayOrdersSeeder
+```
+
+## 测试数据说明
+
+### PayMealsSeeder(缴费充值套餐)
+
+生成 **18 条**套餐数据:
+
+#### 话费充值套餐(8条)
+- 10元话费 - 98折
+- 20元话费 - 98折
+- 30元话费 - 97折
+- 50元话费 - 97折
+- 100元话费 - 96折
+- 200元话费 - 95折
+- 300元话费 - 95折
+- 500元话费 - 94折
+
+#### 电费充值套餐(5条)
+- 100元电费 - 99折
+- 200元电费 - 98折
+- 300元电费 - 98折
+- 500元电费 - 97折
+- 1000元电费 - 96折
+
+#### 燃气充值套餐(5条)
+- 100元燃气 - 99折
+- 200元燃气 - 98折
+- 300元燃气 - 98折
+- 500元燃气 - 97折
+- 1000元燃气 - 96折
+
+### PayOrdersSeeder(充值缴费订单)
+
+生成 **50 条**订单数据:
+
+- **话费充值订单**:20 条
+  - 订单号格式:PHB20251212XXXX
+  - 充值金额:10/20/30/50/100/200元随机
+  - 充值号码:随机手机号
+  
+- **电费充值订单**:15 条
+  - 订单号格式:ELB20251212XXXX
+  - 充值金额:100/200/300/500/1000元随机
+  - 充值账号:随机户号
+  
+- **燃气充值订单**:15 条
+  - 订单号格式:GAS20251212XXXX
+  - 充值金额:100/200/300/500/1000元随机
+  - 充值账号:随机户号
+
+#### 订单状态分布
+- 1 - 待付款
+- 2 - 已付款
+- 3 - 充值中
+- 4 - 充值成功
+- 5 - 充值失败
+- 6 - 已退款
+
+## 注意事项
+
+1. **运行订单 Seeder 前**,请确保 `lev_member` 表中有用户数据
+2. 如果没有用户数据,订单 Seeder 会提示警告并跳过
+3. 订单的创建时间是随机的(最近30天内)
+4. 所有套餐默认状态为"有效"(status=1)
+5. 所有数据的 mark 字段都为 1(未删除)
+
+## 清空测试数据
+
+如果需要清空测试数据,可以执行:
+
+```sql
+-- 清空套餐数据
+TRUNCATE TABLE lev_pay_meals;
+
+-- 清空订单数据
+TRUNCATE TABLE lev_pay_orders;
+```
+
+或者使用软删除:
+
+```sql
+-- 软删除套餐数据
+UPDATE lev_pay_meals SET mark = 0;
+
+-- 软删除订单数据
+UPDATE lev_pay_orders SET mark = 0;
+```

+ 71 - 2
routes/web.php

@@ -129,6 +129,54 @@ Route::post('/jobs/edit', [\App\Http\Controllers\Admin\JobsController::class, 'e
 Route::post('/jobs/delete', [\App\Http\Controllers\Admin\JobsController::class, 'delete']);
 Route::post('/jobs/status', [\App\Http\Controllers\Admin\JobsController::class, 'status']);
 
+// 订单管理
+Route::get('/order/index', [\App\Http\Controllers\Admin\OrderController::class, 'index']);
+Route::get('/order/info', [\App\Http\Controllers\Admin\OrderController::class, 'info']);
+Route::get('/order/statistics', [\App\Http\Controllers\Admin\OrderController::class, 'statistics']);
+Route::post('/order/delete', [\App\Http\Controllers\Admin\OrderController::class, 'delete']);
+Route::post('/order/status', [\App\Http\Controllers\Admin\OrderController::class, 'status']);
+Route::post('/order/completePay', [\App\Http\Controllers\Admin\OrderController::class, 'completePay']);
+Route::post('/order/deliver', [\App\Http\Controllers\Admin\OrderController::class, 'deliver']);
+Route::post('/order/complete', [\App\Http\Controllers\Admin\OrderController::class, 'complete']);
+Route::post('/order/cancel', [\App\Http\Controllers\Admin\OrderController::class, 'cancel']);
+Route::post('/order/applyRefund', [\App\Http\Controllers\Admin\OrderController::class, 'applyRefund']);
+Route::post('/order/agreeRefund', [\App\Http\Controllers\Admin\OrderController::class, 'agreeRefund']);
+Route::post('/order/confirmRefund', [\App\Http\Controllers\Admin\OrderController::class, 'confirmRefund']);
+Route::post('/order/rejectRefund', [\App\Http\Controllers\Admin\OrderController::class, 'rejectRefund']);
+
+// 代理管理
+Route::get('/agent/index', [\App\Http\Controllers\Admin\AgentController::class, 'index']);
+Route::get('/agent/info', [\App\Http\Controllers\Admin\AgentController::class, 'info']);
+Route::post('/agent/delete', [\App\Http\Controllers\Admin\AgentController::class, 'delete']);
+Route::post('/agent/status', [\App\Http\Controllers\Admin\AgentController::class, 'status']);
+Route::post('/agent/audit', [\App\Http\Controllers\Admin\AgentController::class, 'audit']);
+Route::post('/agent/freeze', [\App\Http\Controllers\Admin\AgentController::class, 'freeze']);
+
+// 财务管理
+Route::get('/financial/statistics', [\App\Http\Controllers\Admin\FinancialController::class, 'statistics']);
+Route::get('/financial/list', [\App\Http\Controllers\Admin\FinancialController::class, 'getList']);
+
+// 商家提现管理
+Route::get('/financial/storesWithdraw/index', [\App\Http\Controllers\Admin\StoresWithdrawController::class, 'index']);
+Route::get('/financial/storesWithdraw/info', [\App\Http\Controllers\Admin\StoresWithdrawController::class, 'info']);
+Route::post('/financial/storesWithdraw/audit', [\App\Http\Controllers\Admin\StoresWithdrawController::class, 'audit']);
+Route::post('/financial/storesWithdraw/delete', [\App\Http\Controllers\Admin\StoresWithdrawController::class, 'delete']);
+Route::post('/financial/storesWithdraw/deleteAll', [\App\Http\Controllers\Admin\StoresWithdrawController::class, 'deleteAll']);
+
+// 代理提现管理
+Route::get('/financial/agentWithdraw/index', [\App\Http\Controllers\Admin\AgentWithdrawController::class, 'index']);
+Route::get('/financial/agentWithdraw/info', [\App\Http\Controllers\Admin\AgentWithdrawController::class, 'info']);
+Route::post('/financial/agentWithdraw/audit', [\App\Http\Controllers\Admin\AgentWithdrawController::class, 'audit']);
+Route::post('/financial/agentWithdraw/delete', [\App\Http\Controllers\Admin\AgentWithdrawController::class, 'delete']);
+Route::post('/financial/agentWithdraw/deleteAll', [\App\Http\Controllers\Admin\AgentWithdrawController::class, 'deleteAll']);
+
+// 统一余额日志管理(充值/提现)
+Route::get('/financial/balanceLogs/index', [\App\Http\Controllers\Admin\BalanceLogsController::class, 'index']);
+Route::get('/financial/balanceLogs/info', [\App\Http\Controllers\Admin\BalanceLogsController::class, 'info']);
+Route::post('/financial/balanceLogs/audit', [\App\Http\Controllers\Admin\BalanceLogsController::class, 'audit']);
+Route::post('/financial/balanceLogs/delete', [\App\Http\Controllers\Admin\BalanceLogsController::class, 'delete']);
+Route::post('/financial/balanceLogs/deleteAll', [\App\Http\Controllers\Admin\BalanceLogsController::class, 'deleteAll']);
+
 // 广告管理
 Route::get('/ad/index', [AdController::class, 'index']);
 Route::get('/ad/info', [AdController::class, 'info']);
@@ -138,6 +186,8 @@ Route::post('/ad/delete', [AdController::class, 'delete']);
 // 会员管理
 Route::get('/member/index', [MemberController::class, 'index']);
 Route::get('/member/info', [MemberController::class, 'info']);
+Route::get('/member/read', [MemberController::class, 'read']);
+Route::post('/member/add', [MemberController::class, 'add']);
 Route::post('/member/edit', [MemberController::class, 'edit']);
 Route::post('/member/confirm', [MemberController::class, 'confirm']);
 Route::post('/member/delete', [MemberController::class, 'delete']);
@@ -199,10 +249,14 @@ Route::post('/withdraw/payment', [\App\Http\Controllers\Admin\WithdrawController
 Route::post('/withdraw/status', [\App\Http\Controllers\Admin\WithdrawController::class, 'status']);
 Route::post('/withdraw/delete', [\App\Http\Controllers\Admin\WithdrawController::class, 'delete']);
 
-// 交易明细
+// 财务明细(账户明细)
 Route::get('/account/index', [\App\Http\Controllers\Admin\AccountController::class, 'index']);
-Route::post('/account/count', [\App\Http\Controllers\Admin\AccountController::class, 'count']);
+Route::get('/account/read', [\App\Http\Controllers\Admin\AccountController::class, 'read']);
+Route::post('/account/add', [\App\Http\Controllers\Admin\AccountController::class, 'add']);
+Route::post('/account/edit', [\App\Http\Controllers\Admin\AccountController::class, 'edit']);
+Route::post('/account/status', [\App\Http\Controllers\Admin\AccountController::class, 'status']);
 Route::post('/account/delete', [\App\Http\Controllers\Admin\AccountController::class, 'delete']);
+Route::post('/account/count', [\App\Http\Controllers\Admin\AccountController::class, 'count']);
 
 // 登录日志
 Route::get('/loginlog/index', [LoginLogController::class, 'index']);
@@ -236,3 +290,18 @@ Route::post('/store/category/status', [\App\Http\Controllers\Admin\StoreCategory
 Route::post('/store/category/delete', [\App\Http\Controllers\Admin\StoreCategoryController::class, 'delete']);
 Route::post('/store/category/dall', [\App\Http\Controllers\Admin\StoreCategoryController::class, 'deleteAll']);
 Route::get('/store/category/options', [\App\Http\Controllers\Admin\StoreCategoryController::class, 'options']);
+
+// 缴费充值套餐管理
+Route::get('/pay/meals/index', [\App\Http\Controllers\Admin\PayMealsController::class, 'index']);
+Route::get('/pay/meals/read', [\App\Http\Controllers\Admin\PayMealsController::class, 'read']);
+Route::post('/pay/meals/add', [\App\Http\Controllers\Admin\PayMealsController::class, 'add']);
+Route::post('/pay/meals/edit', [\App\Http\Controllers\Admin\PayMealsController::class, 'edit']);
+Route::post('/pay/meals/delete', [\App\Http\Controllers\Admin\PayMealsController::class, 'delete']);
+Route::post('/pay/meals/dall', [\App\Http\Controllers\Admin\PayMealsController::class, 'dall']);
+Route::post('/pay/meals/status', [\App\Http\Controllers\Admin\PayMealsController::class, 'status']);
+
+// 缴费充值订单管理
+Route::get('/pay/orders/index', [\App\Http\Controllers\Admin\PayOrdersController::class, 'index']);
+Route::get('/pay/orders/read', [\App\Http\Controllers\Admin\PayOrdersController::class, 'read']);
+Route::post('/pay/orders/delete', [\App\Http\Controllers\Admin\PayOrdersController::class, 'delete']);
+Route::post('/pay/orders/dall', [\App\Http\Controllers\Admin\PayOrdersController::class, 'dall']);