This commit is contained in:
gpu 2026-01-19 00:09:38 +08:00
parent 650fc630b1
commit 9e203f8ea1
225 changed files with 3572 additions and 107 deletions

View File

@ -0,0 +1,309 @@
# Design Document: 仪表盘数据看板
## Overview
本设计文档描述仪表盘数据看板模块的技术实现方案。该模块是后台管理系统的核心运营分析页面包含4个主要卡片区域今日订单、今日货币信息、今日收入汇总、用户数据统计。
需要验证后端API是否已完成如未完成需要新增对应的接口。
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Stand Page (数据看板) │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ Today Order Card │ │ Currency Info Card │ │
│ │ (今日订单卡片) │ │ (今日货币信息卡片) │ │
│ │ - 发起订单数 │ │ - 今日/昨日发放钻石 │ │
│ │ - 支付订单数 │ │ - 今日/昨日消费钻石 │ │
│ │ - 消费人数 │ │ - 今日/昨日发放UU币 │ │
│ │ - 订单总金额 │ │ - 今日/昨日消费UU币 │ │
│ │ - 出货总金额 │ │ - 今日/昨日发放达达券 │ │
│ │ - 各支付方式金额 │ │ - 今日/昨日消费达达券 │ │
│ └─────────────────────────────┘ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ Income Summary Card │ │ User Stats Card │ │
│ │ (今日收入汇总卡片) │ │ (用户数据统计卡片) │ │
│ │ - 订单收入 │ │ - 绑定手机号人数 │ │
│ │ - RMB收入 │ │ - 抽奖人数 │ │
│ │ - 钻石商城收入 │ │ - 用户剩余货币 │ │
│ │ - 其他收入 │ │ - 微信支付金额 │ │
│ │ - 支出/发货金额 │ │ - 订单支付数量 │ │
│ │ - 利润 │ │ - 出货/发货金额 │ │
│ └─────────────────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ API Layer │
│ src/api/business/statistics.ts │
│ - getTodayOrderStats(): Promise<TodayOrderStats>
│ - getCurrencyInfoStats(): Promise<CurrencyInfoStats>
│ - getIncomeSummaryStats(): Promise<IncomeSummaryStats>
│ - getUserStats(): Promise<UserStats>
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ Backend API │
│ GET /api/admin/business/statistics/today-order │
│ GET /api/admin/business/statistics/currency-info │
│ GET /api/admin/business/statistics/income-summary │
│ GET /api/admin/business/statistics/user-stats │
└─────────────────────────────────────────────────────────────────────────────┘
```
## Components and Interfaces
### 1. 后端API模型
#### 1.1 今日订单数据模型
```csharp
public class TodayOrderStatsResponse
{
public int InitiateOrderCount { get; set; } // 发起订单数
public int PaidOrderCount { get; set; } // 支付订单数
public int UserCount { get; set; } // 消费人数
public decimal OrderZheTotal { get; set; } // 订单总金额(折后)
public decimal GoodsTotalAmount { get; set; } // 出货总金额
public decimal UseCoupon { get; set; } // 优惠券抵扣
public decimal Price { get; set; } // RMB支付
public decimal UseMoney { get; set; } // 钻石支付
public decimal UseIntegral { get; set; } // UU币支付
public decimal UseMoney2 { get; set; } // 达达券支付
}
```
#### 1.2 货币信息数据模型
```csharp
public class CurrencyInfoStatsResponse
{
public decimal TodayAddMoney { get; set; } // 今日发放钻石
public decimal TodayUseMoney { get; set; } // 今日消费钻石
public decimal YesterdayAddMoney { get; set; } // 昨日发放钻石
public decimal YesterdayUseMoney { get; set; } // 昨日消费钻石
public decimal TodayAddIntegral { get; set; } // 今日发放UU币
public decimal TodayUseIntegral { get; set; } // 今日消费UU币
public decimal YesterdayAddIntegral { get; set; }// 昨日发放UU币
public decimal YesterdayUseIntegral { get; set; }// 昨日消费UU币
public decimal TodayAddMoney2 { get; set; } // 今日发放达达券
public decimal TodayUseMoney2 { get; set; } // 今日消费达达券
public decimal YesterdayAddMoney2 { get; set; } // 昨日发放达达券
public decimal YesterdayUseMoney2 { get; set; } // 昨日消费达达券
}
```
#### 1.3 收入汇总数据模型
```csharp
public class IncomeSummaryStatsResponse
{
public decimal TodayIncome { get; set; } // 订单收入RMB+钻石)
public decimal RmbIncome { get; set; } // RMB收入
public decimal DiamondIncome { get; set; } // 钻石商城收入
public decimal OtherIncome { get; set; } // 其他收入
public decimal ShippedToday { get; set; } // 订单出货
public decimal Expenses { get; set; } // 支出
public decimal TodayShipped { get; set; } // 当天发货金额
public decimal RemainingCoupon { get; set; } // 当天用户剩余达达券
public decimal BoxRemaining { get; set; } // 盒柜剩余价值
public decimal Profit { get; set; } // 利润
public string Formula { get; set; } // 利润计算公式
}
```
#### 1.4 用户统计数据模型
```csharp
public class UserStatsResponse
{
public int UserRegisterCount { get; set; } // 绑定手机号人数
public int ConsumingUserCount { get; set; } // 抽奖人数
public decimal UserMoney { get; set; } // 用户剩余钻石
public decimal UserIntegral { get; set; } // 用户剩余UU币
public decimal UserMoney2 { get; set; } // 用户剩余达达券
public decimal OrderPriceTotal { get; set; } // 微信支付金额
public int OrderTotalCount { get; set; } // 订单支付数量
public decimal TotalGoodsAmount { get; set; } // 用户出货总金额
public decimal BoxRemainingValue { get; set; } // 用户盒柜剩余价值
public decimal ExchangedCoupon { get; set; } // 用户已兑换的达达券
public decimal ShippedAmount { get; set; } // 用户已发货金额
}
```
### 2. 前端API模块
**文件**: `src/api/business/statistics.ts`
```typescript
// 今日订单统计响应接口
export interface TodayOrderStats {
initiateOrderCount: number; // 发起订单数
paidOrderCount: number; // 支付订单数
userCount: number; // 消费人数
orderZheTotal: number; // 订单总金额
goodsTotalAmount: number; // 出货总金额
useCoupon: number; // 优惠券抵扣
price: number; // RMB支付
useMoney: number; // 钻石支付
useIntegral: number; // UU币支付
useMoney2: number; // 达达券支付
}
// 货币信息统计响应接口
export interface CurrencyInfoStats {
todayAddMoney: number; // 今日发放钻石
todayUseMoney: number; // 今日消费钻石
yesterdayAddMoney: number; // 昨日发放钻石
yesterdayUseMoney: number; // 昨日消费钻石
todayAddIntegral: number; // 今日发放UU币
todayUseIntegral: number; // 今日消费UU币
yesterdayAddIntegral: number; // 昨日发放UU币
yesterdayUseIntegral: number; // 昨日消费UU币
todayAddMoney2: number; // 今日发放达达券
todayUseMoney2: number; // 今日消费达达券
yesterdayAddMoney2: number; // 昨日发放达达券
yesterdayUseMoney2: number; // 昨日消费达达券
}
// 收入汇总统计响应接口
export interface IncomeSummaryStats {
todayIncome: number; // 订单收入
rmbIncome: number; // RMB收入
diamondIncome: number; // 钻石商城收入
otherIncome: number; // 其他收入
shippedToday: number; // 订单出货
expenses: number; // 支出
todayShipped: number; // 当天发货金额
remainingCoupon: number; // 当天用户剩余达达券
boxRemaining: number; // 盒柜剩余价值
profit: number; // 利润
formula: string; // 利润计算公式
}
// 用户统计响应接口
export interface UserStats {
userRegisterCount: number; // 绑定手机号人数
consumingUserCount: number; // 抽奖人数
userMoney: number; // 用户剩余钻石
userIntegral: number; // 用户剩余UU币
userMoney2: number; // 用户剩余达达券
orderPriceTotal: number; // 微信支付金额
orderTotalCount: number; // 订单支付数量
totalGoodsAmount: number; // 用户出货总金额
boxRemainingValue: number; // 用户盒柜剩余价值
exchangedCoupon: number; // 用户已兑换的达达券
shippedAmount: number; // 用户已发货金额
}
// API函数
export function getTodayOrderStats(): Promise<TodayOrderStats>;
export function getCurrencyInfoStats(): Promise<CurrencyInfoStats>;
export function getIncomeSummaryStats(): Promise<IncomeSummaryStats>;
export function getUserStats(): Promise<UserStats>;
```
### 3. 前端组件结构
```
views/business/statistics/
├── data-stand.vue # 数据看板主页面
├── components/
│ ├── TodayOrderCard.vue # 今日订单卡片
│ ├── CurrencyInfoCard.vue # 货币信息卡片
│ ├── IncomeSummaryCard.vue # 收入汇总卡片
│ └── UserStatsCard.vue # 用户统计卡片
```
## Data Models
### 数据库表依赖
| 表名 | 用途 |
|------|------|
| orders | 订单表,存储订单信息 |
| order_list | 订单商品表,存储中奖记录 |
| users | 用户表,存储用户信息 |
| profit_money | 钻石流水表 |
| profit_integral | UU币流水表 |
| profit_money2 | 达达券流水表 |
| diamond_orders | 钻石商城订单表 |
| profit_revenue | 其他收入表 |
| profit_expenses | 支出表 |
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: 今日订单数据一致性
*For any* 今日订单统计数据,支付订单数 SHALL 小于等于发起订单数,消费人数 SHALL 小于等于支付订单数。
**Validates: Requirements 1.2, 1.3, 1.4**
### Property 2: 货币信息数据非负性
*For any* 货币信息统计数据,所有发放和消费数值 SHALL 大于等于0。
**Validates: Requirements 2.2-2.13**
### Property 3: 利润计算正确性
*For any* 收入汇总统计数据,利润 SHALL 等于 订单收入 - 当天发货金额 - 当天用户剩余达达券 - 盒柜剩余价值。
**Validates: Requirements 3.11**
### Property 4: 用户统计数据非负性
*For any* 用户统计数据,所有数值 SHALL 大于等于0。
**Validates: Requirements 4.2-4.12**
### Property 5: API响应格式一致性
*For any* 有效的API响应所有统计字段 SHALL 被正确映射到对应的卡片并展示。
**Validates: Requirements 5.5**
## Error Handling
### API请求错误
1. **网络错误**: 显示"网络连接失败,请检查网络"提示
2. **服务器错误(5xx)**: 显示"服务器繁忙,请稍后重试"提示
3. **权限错误(403)**: 显示"无权限访问此页面"提示
4. **其他错误**: 显示通用错误提示
### 数据展示降级
当API请求失败时所有统计数值显示为默认值0或"-",确保页面正常渲染。
## Testing Strategy
### 单元测试
1. **API模块测试**
- 测试API端点配置正确性
- 测试响应数据类型转换
2. **格式化函数测试**
- 测试金额格式化函数
- 测试边界值0、负数、大数值
### 属性测试
使用 xUnit + FsCheck 进行属性测试:
1. **Property 1**: 验证今日订单数据一致性
2. **Property 2**: 验证货币信息数据非负性
3. **Property 3**: 验证利润计算正确性
4. **Property 4**: 验证用户统计数据非负性
5. **Property 5**: 验证API响应格式一致性
### 集成测试
1. 测试页面加载时API调用
2. 测试错误处理和降级展示
3. 测试刷新按钮功能

View File

@ -0,0 +1,126 @@
# Requirements Document
## Introduction
本文档定义了仪表盘数据看板模块的迁移需求。该模块将从老项目PHP ThinkPHP + Layui迁移到新项目ASP.NET Core + Vue 3 + Element Plus。数据看板是后台管理系统的核心运营分析页面提供全面的业务数据统计概览包含4个主要卡片区域今日订单、今日货币信息、今日收入汇总、用户数据统计。
## Glossary
- **Dashboard**: 仪表盘,后台管理系统的首页
- **Data_Stand**: 数据看板,展示关键业务数据的核心页面
- **Today_Order_Card**: 今日订单卡片,展示当日订单相关统计数据
- **Currency_Info_Card**: 今日货币信息卡片展示钻石、UU币、达达券的发放和消费数据
- **Income_Summary_Card**: 今日收入汇总卡片,展示收入、支出和利润数据
- **User_Stats_Card**: 用户数据统计卡片,展示用户相关的汇总统计数据
- **Statistics_Service**: 统计服务,后端提供统计数据的服务层
- **Admin_Web**: 新项目前端,基于 Vue 3 + Element Plus 的后台管理前端
## Requirements
### Requirement 1: 今日订单卡片
**User Story:** As a 运营人员, I want to 查看今日订单的详细统计数据, so that I can 了解当日订单和支付情况。
#### Acceptance Criteria
1. WHEN 用户访问数据看板页面 THEN THE Today_Order_Card SHALL 显示今日订单统计数据
2. THE Today_Order_Card SHALL 展示发起订单数(今日创建的订单总数)
3. THE Today_Order_Card SHALL 展示支付订单数(今日支付成功的订单数)
4. THE Today_Order_Card SHALL 展示消费人数(今日有消费的用户数)
5. THE Today_Order_Card SHALL 展示订单总金额(今日订单折后总金额)
6. THE Today_Order_Card SHALL 展示出货总金额(今日出货奖品总价值)
7. THE Today_Order_Card SHALL 展示优惠券抵扣(今日优惠券抵扣总额)
8. THE Today_Order_Card SHALL 展示RMB支付今日微信支付总额
9. THE Today_Order_Card SHALL 展示钻石支付(今日钻石支付总额)
10. THE Today_Order_Card SHALL 展示UU币支付今日UU币支付总额
11. THE Today_Order_Card SHALL 展示达达券支付(今日达达券支付总额)
12. WHEN 用户点击刷新按钮 THEN THE Today_Order_Card SHALL 重新加载数据
### Requirement 2: 今日货币信息卡片
**User Story:** As a 运营人员, I want to 查看货币发放和消费情况, so that I can 监控虚拟货币的流通状况。
#### Acceptance Criteria
1. WHEN 用户访问数据看板页面 THEN THE Currency_Info_Card SHALL 显示货币信息统计数据
2. THE Currency_Info_Card SHALL 展示今日发放钻石
3. THE Currency_Info_Card SHALL 展示今日消费钻石
4. THE Currency_Info_Card SHALL 展示昨日发放钻石
5. THE Currency_Info_Card SHALL 展示昨日消费钻石
6. THE Currency_Info_Card SHALL 展示今日发放UU币
7. THE Currency_Info_Card SHALL 展示今日消费UU币
8. THE Currency_Info_Card SHALL 展示昨日发放UU币
9. THE Currency_Info_Card SHALL 展示昨日消费UU币
10. THE Currency_Info_Card SHALL 展示今日发放达达券
11. THE Currency_Info_Card SHALL 展示今日消费达达券
12. THE Currency_Info_Card SHALL 展示昨日发放达达券
13. THE Currency_Info_Card SHALL 展示昨日消费达达券
14. WHEN 用户点击刷新按钮 THEN THE Currency_Info_Card SHALL 重新加载数据
### Requirement 3: 今日收入汇总卡片
**User Story:** As a 运营人员, I want to 查看今日收入和利润情况, so that I can 了解当日的盈利状况。
#### Acceptance Criteria
1. WHEN 用户访问数据看板页面 THEN THE Income_Summary_Card SHALL 显示收入汇总数据
2. THE Income_Summary_Card SHALL 展示订单收入RMB+钻石)
3. THE Income_Summary_Card SHALL 展示RMB收入
4. THE Income_Summary_Card SHALL 展示钻石商城收入
5. THE Income_Summary_Card SHALL 展示其他收入
6. THE Income_Summary_Card SHALL 展示订单出货(今日出货奖品总价值)
7. THE Income_Summary_Card SHALL 展示支出
8. THE Income_Summary_Card SHALL 展示当天发货金额
9. THE Income_Summary_Card SHALL 展示当天用户剩余达达券
10. THE Income_Summary_Card SHALL 展示盒柜剩余价值
11. THE Income_Summary_Card SHALL 展示利润(收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余)
12. THE Income_Summary_Card SHALL 展示利润计算公式
13. WHEN 利润为负值 THEN THE Income_Summary_Card SHALL 以红色显示利润数值
14. WHEN 用户点击刷新按钮 THEN THE Income_Summary_Card SHALL 重新加载数据
### Requirement 4: 用户数据统计卡片
**User Story:** As a 运营人员, I want to 查看用户相关的汇总统计数据, so that I can 了解用户整体情况。
#### Acceptance Criteria
1. WHEN 用户访问数据看板页面 THEN THE User_Stats_Card SHALL 显示用户统计数据
2. THE User_Stats_Card SHALL 展示绑定手机号人数
3. THE User_Stats_Card SHALL 展示抽奖人数(有抽奖记录的用户总数)
4. THE User_Stats_Card SHALL 展示用户剩余钻石
5. THE User_Stats_Card SHALL 展示用户剩余UU币
6. THE User_Stats_Card SHALL 展示用户剩余达达券
7. THE User_Stats_Card SHALL 展示微信支付金额(历史微信支付总额)
8. THE User_Stats_Card SHALL 展示订单支付数量(历史支付成功订单总数)
9. THE User_Stats_Card SHALL 展示用户出货总金额
10. THE User_Stats_Card SHALL 展示用户盒柜剩余价值
11. THE User_Stats_Card SHALL 展示用户已兑换的达达券
12. THE User_Stats_Card SHALL 展示用户已发货金额
13. WHEN 用户点击刷新按钮 THEN THE User_Stats_Card SHALL 重新加载数据
### Requirement 5: 后端API集成
**User Story:** As a 开发人员, I want to 前端正确调用后端统计API, so that I can 获取准确的统计数据。
#### Acceptance Criteria
1. THE Statistics_Service SHALL 提供 `GET /api/admin/business/statistics/today-order` 获取今日订单数据
2. THE Statistics_Service SHALL 提供 `GET /api/admin/business/statistics/currency-info` 获取货币信息数据
3. THE Statistics_Service SHALL 提供 `GET /api/admin/business/statistics/income-summary` 获取收入汇总数据
4. THE Statistics_Service SHALL 提供 `GET /api/admin/business/statistics/user-stats` 获取用户统计数据
5. WHEN API返回成功 THEN THE Admin_Web SHALL 正确解析并展示所有统计字段
6. WHEN API请求失败 THEN THE Admin_Web SHALL 显示错误提示并展示默认值
7. THE Admin_Web SHALL 在API模块中定义完整的TypeScript接口类型
### Requirement 6: 页面布局和交互
**User Story:** As a 运营人员, I want to 数据看板有清晰的布局和良好的交互体验, so that I can 高效地查看数据。
#### Acceptance Criteria
1. THE Data_Stand SHALL 使用两列布局,左侧显示今日订单和今日收入汇总,右侧显示今日货币信息和用户数据统计
2. THE Data_Stand SHALL 每个卡片区域独立异步加载,避免页面阻塞
3. THE Data_Stand SHALL 每个卡片显示加载动画,提升用户体验
4. THE Data_Stand SHALL 每个卡片有独立的刷新按钮
5. WHEN 页面加载时 THEN THE Data_Stand SHALL 自动加载所有卡片数据
6. THE Data_Stand SHALL 使用响应式布局,在不同屏幕尺寸下自适应

View File

@ -0,0 +1,163 @@
# Implementation Plan: 仪表盘数据看板
## Overview
本实现计划将仪表盘数据看板模块从老项目PHP ThinkPHP + Layui迁移到新项目ASP.NET Core + Vue 3 + Element Plus。实现分为后端API开发和前端页面开发两个主要部分。
## Tasks
- [x] 1. 验证和补充后端API - 今日订单统计
- [x] 1.1 检查后端是否已有今日订单统计API
- 检查 `StatisticsController` 是否存在
- 检查是否有 `GetTodayOrderStats` 方法
- 如果不存在,需要创建
- _Requirements: 5.1_
- [x] 1.2 创建今日订单统计API如需要
- 在 `Models/Statistics/` 下创建 `TodayOrderStatsResponse.cs`
- 在 `Services/` 下创建 `IStatisticsService.cs` 接口
- 在 `Services/` 下创建 `StatisticsService.cs` 实现
- 在 `Controllers/` 下创建 `StatisticsController.cs`
- 实现 `GET /api/admin/business/statistics/today-order` 端点
- _Requirements: 1.2-1.11, 5.1_
- [x] 2. 验证和补充后端API - 货币信息统计
- [x] 2.1 创建货币信息统计API
- 在 `Models/Statistics/` 下创建 `CurrencyInfoStatsResponse.cs`
- 在 `IStatisticsService.cs` 添加接口方法
- 在 `StatisticsService.cs` 实现查询逻辑
- 在 `StatisticsController.cs` 添加 `GetCurrencyInfoStats` 方法
- 实现 `GET /api/admin/business/statistics/currency-info` 端点
- _Requirements: 2.2-2.13, 5.2_
- [x] 3. 验证和补充后端API - 收入汇总统计
- [x] 3.1 创建收入汇总统计API
- 在 `Models/Statistics/` 下创建 `IncomeSummaryStatsResponse.cs`
- 在 `IStatisticsService.cs` 添加接口方法
- 在 `StatisticsService.cs` 实现查询逻辑(包含利润计算)
- 在 `StatisticsController.cs` 添加 `GetIncomeSummaryStats` 方法
- 实现 `GET /api/admin/business/statistics/income-summary` 端点
- _Requirements: 3.2-3.12, 5.3_
- [x] 4. 验证和补充后端API - 用户统计
- [x] 4.1 创建用户统计API
- 在 `Models/Statistics/` 下创建 `UserStatsResponse.cs`
- 在 `IStatisticsService.cs` 添加接口方法
- 在 `StatisticsService.cs` 实现查询逻辑
- 在 `StatisticsController.cs` 添加 `GetUserStats` 方法
- 实现 `GET /api/admin/business/statistics/user-stats` 端点
- _Requirements: 4.2-4.12, 5.4_
- [x] 5. Checkpoint - 后端API验证
- 启动后端服务
- 使用Swagger测试所有4个统计API
- 验证返回数据结构符合预期
- 确保权限验证正常工作
- 如有问题,询问用户
- [x] 6. 前端API层开发
- [x] 6.1 创建统计API模块
- 创建 `src/api/business/statistics.ts`
- 定义 `TodayOrderStats` TypeScript接口
- 定义 `CurrencyInfoStats` TypeScript接口
- 定义 `IncomeSummaryStats` TypeScript接口
- 定义 `UserStats` TypeScript接口
- 实现 `getTodayOrderStats` API调用函数
- 实现 `getCurrencyInfoStats` API调用函数
- 实现 `getIncomeSummaryStats` API调用函数
- 实现 `getUserStats` API调用函数
- _Requirements: 5.5, 5.7_
- [x] 7. 前端组件开发 - 今日订单卡片
- [x] 7.1 创建今日订单卡片组件
- 创建 `src/views/business/statistics/components/TodayOrderCard.vue`
- 实现卡片布局3行4列网格
- 实现数据展示10个数据项
- 实现加载状态和刷新按钮
- 实现错误处理和降级展示
- _Requirements: 1.1-1.12, 6.2, 6.3, 6.4_
- [x] 8. 前端组件开发 - 货币信息卡片
- [x] 8.1 创建货币信息卡片组件
- 创建 `src/views/business/statistics/components/CurrencyInfoCard.vue`
- 实现卡片布局3行4列网格
- 实现数据展示12个数据项钻石、UU币、达达券的今日/昨日发放/消费)
- 实现加载状态和刷新按钮
- 实现错误处理和降级展示
- _Requirements: 2.1-2.14, 6.2, 6.3, 6.4_
- [x] 9. 前端组件开发 - 收入汇总卡片
- [x] 9.1 创建收入汇总卡片组件
- 创建 `src/views/business/statistics/components/IncomeSummaryCard.vue`
- 实现表格布局11行数据
- 实现数据展示(包含利润计算公式)
- 实现利润负值红色高亮
- 实现加载状态和刷新按钮
- 实现错误处理和降级展示
- _Requirements: 3.1-3.14, 6.2, 6.3, 6.4_
- [x] 10. 前端组件开发 - 用户统计卡片
- [x] 10.1 创建用户统计卡片组件
- 创建 `src/views/business/statistics/components/UserStatsCard.vue`
- 实现表格布局6行2列
- 实现数据展示11个数据项
- 实现加载状态和刷新按钮
- 实现错误处理和降级展示
- _Requirements: 4.1-4.13, 6.2, 6.3, 6.4_
- [x] 11. 前端页面开发 - 数据看板主页面
- [x] 11.1 创建数据看板主页面
- 创建 `src/views/business/statistics/data-stand.vue`
- 实现两列布局
- 集成4个卡片组件
- 实现页面加载时自动加载所有卡片数据
- 实现响应式布局
- _Requirements: 6.1, 6.5, 6.6_
- [x] 12. 前端路由配置
- [x] 12.1 配置统计模块路由
- 在 `router/modules/business.ts` 添加数据看板路由
- 配置路由权限
- _Requirements: 6.1_
- [x] 13. Checkpoint - 功能验证
- 启动前后端服务
- 登录后台管理系统
- 访问数据看板页面
- 验证4个卡片正常显示数据
- 测试刷新按钮功能
- 测试错误处理
- 如有问题,询问用户
- [ ] 14. 属性测试
- [ ] 14.1 编写今日订单数据一致性属性测试
- **Property 1: 今日订单数据一致性**
- **Validates: Requirements 1.2, 1.3, 1.4**
- [ ] 14.2 编写货币信息数据非负性属性测试
- **Property 2: 货币信息数据非负性**
- **Validates: Requirements 2.2-2.13**
- [ ] 14.3 编写利润计算正确性属性测试
- **Property 3: 利润计算正确性**
- **Validates: Requirements 3.11**
- [ ] 14.4 编写用户统计数据非负性属性测试
- **Property 4: 用户统计数据非负性**
- **Validates: Requirements 4.2-4.12**
- [ ] 14.5 编写API响应格式一致性属性测试
- **Property 5: API响应格式一致性**
- **Validates: Requirements 5.5**
- [ ] 15. Final Checkpoint - 最终验证
- 确保所有功能正常工作
- 确保所有测试通过
- 如有问题,询问用户
## Notes
- 需要先验证后端API是否已完成如未完成需要新增对应的接口
- 每个Checkpoint确保增量验证
- 属性测试验证通用正确性属性
- 后端API需要排除测试用户数据istest > 0

View File

@ -1,7 +1,7 @@
docs\后台管理系统迁移批次规划.md
docs\后台管理系统-功能分析清单.md
你看一下文档,我们要开始创建迁移任务了,迁移 #### 1.1 仪表盘模块
你看一下文档,我们要开始创建迁移任务了
我们只创建任务,不去执行。
我们这次只需要 数据概览卡片,其他的功能不需要
有个问题,我不知道后端接口是否真的完成了,所以需要你在做的过程中去验证,如果完成了,是最好的,没有完成需要新增对应的接口

View File

@ -0,0 +1,607 @@
# HoneyBox 后台管理系统 - Statistics 统计报表模块分析
## 模块概述
Statistics 统计报表模块是后台管理系统的核心运营分析模块,提供全面的业务数据统计、利润分析、用户行为分析等功能。该模块共包含 **10个功能页面**,是运营决策的重要数据支撑。
## 源文件位置
```
server/php/app/admin/view/Statistics/
├── dataStand.html # 数据看板(核心仪表盘)
├── profit.html # 盒子利润统计
├── productsOverview.html # 出货概览
├── lotteryUsers.html # 抽奖用户列表
├── userLotteryDetail.html # 用户抽奖详情
├── userstatistics.html # 用户统计图表
├── orderList.html # 支付订单列表
├── goodsList.html # 出货列表
├── exchangeList.html # 兑换列表
└── shipmentList.html # 发货列表
```
---
## 页面功能详细分析
### 1. dataStand.html - 数据看板(核心仪表盘)⭐⭐⭐⭐⭐
**功能描述:** 综合数据概览页面,是运营人员每日查看的核心页面,包含多个数据卡片区域,支持异步加载和手动刷新。
#### 1.1 今日订单卡片
| 数据项 | 说明 | 数据来源 |
|--------|------|----------|
| 发起订单数 | 今日创建的订单总数 | orders 表 |
| 支付订单数 | 今日支付成功的订单数 | orders 表 status=1 |
| 消费人数 | 今日有消费的用户数 | orders 表去重 user_id |
| 订单总金额 | 今日订单总金额 | orders.order_total |
| 出货总金额 | 今日出货奖品总价值 | order_goods.goodslist_price |
| 优惠券抵扣 | 今日优惠券抵扣总额 | orders.use_coupon |
| RMB支付 | 今日微信支付总额 | orders.price |
| 钻石支付 | 今日钻石支付总额 | orders.use_money |
| UU币支付 | 今日UU币支付总额 | orders.use_integral |
| 达达券支付 | 今日达达券支付总额 | orders.use_money2 |
#### 1.2 今日货币信息卡片
| 数据项 | 说明 |
|--------|------|
| 今日发放钻石 | 今日系统发放的钻石总量 |
| 今日消费钻石 | 今日用户消费的钻石总量 |
| 昨日发放钻石 | 昨日系统发放的钻石总量 |
| 昨日消费钻石 | 昨日用户消费的钻石总量 |
| 今日发放UU币 | 今日系统发放的UU币总量 |
| 今日消费UU币 | 今日用户消费的UU币总量 |
| 昨日发放UU币 | 昨日系统发放的UU币总量 |
| 昨日消费UU币 | 昨日用户消费的UU币总量 |
| 今日发放达达券 | 今日系统发放的达达券总量 |
| 今日消费达达券 | 今日用户消费的达达券总量 |
| 昨日发放达达券 | 昨日系统发放的达达券总量 |
| 昨日消费达达券 | 昨日用户消费的达达券总量 |
#### 1.3 今日收入汇总卡片
| 数据项 | 计算公式/说明 |
|--------|---------------|
| 订单收入RMB+钻石) | orders.price + orders.use_money |
| RMB收入 | orders.price 总和 |
| 钻石商城收入 | 钻石商城订单收入 |
| 其他收入 | 其他渠道收入 |
| 订单出货 | 今日出货奖品总价值 |
| 支出 | 今日系统支出总额 |
| 当天发货金额 | 今日申请发货的奖品总价值 |
| 当天用户剩余达达券 | 今日用户达达券余额总和 |
| 盒柜剩余价值 | 今日用户盒柜中奖品总价值 |
| 利润 | 收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余 |
#### 1.4 用户数据统计卡片
| 数据项 | 说明 |
|--------|------|
| 绑定手机号人数 | 已绑定手机号的用户总数 |
| 抽奖人数 | 有抽奖记录的用户总数 |
| 用户剩余钻石 | 所有用户钻石余额总和 |
| 用户剩余UU币 | 所有用户UU币余额总和 |
| 用户剩余达达券 | 所有用户达达券余额总和 |
| 微信支付金额 | 历史微信支付总额 |
| 订单支付数量 | 历史支付成功订单总数 |
| 用户出货总金额 | 历史出货奖品总价值 |
| 用户盒柜剩余价值 | 所有用户盒柜中奖品总价值 |
| 用户已兑换的达达券 | 历史兑换达达券总额 |
| 用户已发货金额 | 历史已发货奖品总价值 |
#### 1.5 技术实现要点
- **异步加载**:每个卡片区域独立异步加载,避免页面阻塞
- **手动刷新**:每个卡片都有独立的刷新按钮
- **加载状态**:显示 loading 动画,提升用户体验
- **数据缓存**:部分数据可考虑缓存优化
---
### 2. profit.html - 盒子利润统计 ⭐⭐⭐⭐⭐
**功能描述:** 按盒子维度统计利润数据是运营分析的核心功能支持多条件筛选、异步加载详情、导出Excel。
#### 2.1 搜索条件
| 字段 | 类型 | 说明 |
|------|------|------|
| 盒子ID | 文本输入 | 精确匹配盒子ID |
| 盒子名称 | 文本输入 | 模糊匹配盒子名称 |
| 盒子状态 | 下拉选择 | 上架/下架/售罄 |
| 盒子类型 | 下拉选择 | 动态加载盒子类型列表 |
| 时间范围 | 日期时间范围 | 筛选订单时间范围 |
#### 2.2 统计摘要卡片
| 卡片 | 数据项 | 计算公式 |
|------|--------|----------|
| 总收入 | totalIncome | 微信支付 + 钻石支付 |
| 总出货价值 | totalCost | 奖品的采购价格总和 |
| 总利润 | totalProfit | 收入 - (出货价值 - 兑换成本) |
| 总兑换/发货价值 | totalReMoney / totalFhMoney | 已兑换达达券 / 已申请发货金额 |
#### 2.3 列表字段
| 字段 | 说明 | 异步加载 |
|------|------|----------|
| 盒子ID | 盒子唯一标识 | 否 |
| 盒子名称 | 盒子标题 | 否 |
| 盒子类型/状态 | 类型名称 + 上架状态 | 否 |
| 盒子单价 | 单次抽奖价格 | 否 |
| 抽奖次数 | 该盒子被抽奖的总次数 | **是** |
| 收入 | 微信支付 + 钻石支付 | **是** |
| 出货价值 | 奖品采购价格总和 | **是** |
| 已兑换达达券 | 用户兑换的达达券总额 | **是** |
| 已申请发货 | 申请发货的奖品总价值 | **是** |
| 单盒子利润 | 盒子单价 × 抽数 - 出货总额 | **是** |
| 单盒子利润比 | (单价×抽数-出货) / (单价×抽数) × 100% | **是** |
| 利润 | 收入 - (出货价值 - 兑换成本) | **是** |
| 利润率 | 利润 / 收入 × 100% | **是** |
#### 2.4 操作按钮
| 操作 | 功能说明 | 弹窗/跳转 |
|------|----------|-----------|
| 出货概览 | 查看该盒子的奖品出货统计 | 弹窗 productsOverview.html |
| 抽奖用户 | 查看该盒子的抽奖用户列表 | 弹窗 lotteryUsers.html |
| 导出Excel | 导出当前筛选条件下的所有数据 | 文件下载 |
#### 2.5 技术实现要点
- **异步加载队列**表格渲染后将每行数据加入加载队列控制并发请求数最大3个
- **汇总数据独立加载**统计摘要卡片通过独立API获取不依赖表格数据
- **利润负值高亮**:利润为负的行显示红色背景
- **利润详情提示**:鼠标悬停显示计算公式详情
---
### 3. productsOverview.html - 出货概览 ⭐⭐⭐⭐
**功能描述:** 查看单个盒子的奖品出货统计,分析各奖品的出货情况和概率偏差。
#### 3.1 统计摘要
| 数据项 | 说明 |
|--------|------|
| 总出货数量 | 该盒子所有奖品的出货总次数 |
| 总出货价值 | 该盒子所有奖品的出货总价值(兑换价格) |
| 平均每次出货价值 | 总出货价值 / 总出货数量 |
| 盒子单价 | 该盒子的单次抽奖价格 |
| 平均出货价值倍率 | 平均出货价值 / 盒子单价 |
| 出货金额最多的奖品 | 出货总价值最高的奖品名称和金额 |
| 占总出货金额百分比 | 最高奖品出货金额 / 总出货价值 × 100% |
#### 3.2 列表字段
| 字段 | 说明 |
|------|------|
| 奖品ID | 奖品唯一标识 |
| 奖品类型 | 奖品等级A/B/C/D/E等 |
| 奖品名称 | 奖品标题 |
| 奖品图片 | 奖品缩略图 |
| 出货数量 | 该奖品的出货次数 |
| 奖品单价 | 奖品售价 |
| 兑换金额 | 奖品回收价格 |
| 理论概率 | 配置的中奖概率 |
| 实际概率 | 实际出货次数 / 总出货次数 × 100% |
| 概率偏差 | 实际概率 - 理论概率(正值绿色,负值红色) |
| 总价值 | 出货数量 × 兑换金额 |
#### 3.3 技术实现要点
- **概率偏差分析**:帮助运营人员发现概率配置问题
- **数据分析卡片**:自动分析出货金额最多的奖品
- **PHP服务端计算**:统计数据在服务端计算完成后返回
---
### 4. lotteryUsers.html - 抽奖用户列表 ⭐⭐⭐
**功能描述:** 查看某个盒子的所有抽奖用户,分析用户抽奖行为。
#### 4.1 页面信息
- 显示当前盒子名称(通过 boxInfo 返回)
#### 4.2 列表字段
| 字段 | 说明 | 排序 |
|------|------|------|
| 用户ID | 用户唯一标识 | 否 |
| 用户昵称 | 用户昵称 | 否 |
| 抽奖次数 | 该用户在此盒子的抽奖次数 | 是 |
| 出货价值 | 该用户获得奖品的总价值 | 是 |
| 微信支付 | 该用户微信支付总额 | 是 |
| 钻石支付 | 该用户钻石支付总额 | 是 |
| 总支付金额 | 微信支付 + 钻石支付 | 是 |
#### 4.3 操作按钮
| 操作 | 功能说明 |
|------|----------|
| 查看详情 | 查看该用户在此盒子的抽奖明细 |
#### 4.4 技术实现要点
- **分页加载**默认每页20条
- **排序支持**:支持按抽奖次数、出货价值、支付金额排序
- **弹窗打开**:从 profit.html 以弹窗形式打开
---
### 5. userLotteryDetail.html - 用户抽奖详情 ⭐⭐⭐
**功能描述:** 查看单个用户在某盒子的抽奖明细记录。
#### 5.1 页面信息
- 显示用户昵称(通过 userInfo 返回)
- 显示盒子名称(通过 boxInfo 返回)
#### 5.2 统计摘要
| 数据项 | 说明 |
|--------|------|
| 抽奖次数 | 该用户在此盒子的抽奖总次数 |
| 出货价值 | 该用户获得奖品的总价值 |
| 总支付金额 | 该用户的总支付金额 |
| 微信支付 | 微信支付金额 |
| 钻石支付 | 钻石支付金额 |
#### 5.3 列表字段
| 字段 | 说明 |
|------|------|
| ID | 记录ID |
| 抽奖时间 | 抽奖时间(时间戳转换) |
| 奖品名称 | 中奖奖品名称 |
| 奖品价值 | 奖品兑换价格 |
| 订单ID | 关联订单ID |
| 支付方式 | 微信支付/钻石支付 |
| 支付金额 | 本次支付金额 |
| 是否发货 | 已发货/未发货 |
---
### 6. userstatistics.html - 用户统计图表 ⭐⭐⭐⭐
**功能描述:** 用户数据和订单数据的图表展示,使用 ECharts 实现可视化。
#### 6.1 图表区域
| 图表 | 数据系列 | 图表类型 |
|------|----------|----------|
| 用户数据 | 登录人数、注册人数 | 折线图 |
| 订单支付数据 | RMB支付、钻石支付 | 折线图 |
| 其他数据(预留) | 出货价值、发货价值、回收价值 | 折线图 |
#### 6.2 图表功能
- **时间轴**X轴为时间轴支持日期格式化
- **数据缩放**:支持滑动条缩放和鼠标滚轮缩放
- **默认显示**默认显示最近50%的数据
- **保存图片**:支持将图表保存为图片
#### 6.3 数据表格
| 字段分组 | 字段列表 |
|----------|----------|
| 日期 | 统计日期 |
| 用户信息 | 注册人数、登录人数 |
| 订单信息 | 订单数量、用户数量、RMB支付、钻石支付、UU币支付、达达券支付 |
| 钻石商城 | 支付总额 |
#### 6.4 技术实现要点
- **ECharts 5.x**:使用 ECharts 实现图表
- **异步数据加载**:通过 AJAX 获取统计数据
- **表格分页**支持分页显示默认50条/页
- **默认倒序**:按日期倒序排列,最新数据在前
---
### 7. orderList.html - 支付订单列表 ⭐⭐
**功能描述:** 查看所有支付订单的明细列表。
#### 7.1 列表字段
| 字段 | 说明 |
|------|------|
| 序号 | 行号 |
| 订单ID | 订单唯一标识 |
| 订单号 | 订单编号 |
| 用户ID | 用户唯一标识 |
| 用户昵称 | 用户昵称 |
| 盒子ID | 盒子唯一标识 |
| 盒子名称 | 盒子标题 |
| 订单总金额 | 订单原始金额 |
| 实际支付 | 折后实际支付金额 |
| 微信 | 微信支付金额 |
| 钻石 | 钻石支付金额 |
| UU币 | UU币支付金额 |
| 达达券 | 达达券支付金额 |
| 优惠券抵扣 | 优惠券抵扣金额 |
| 订单状态 | 已支付/未支付 |
| 下单时间 | 订单创建时间 |
| 支付时间 | 订单支付时间 |
#### 7.2 技术实现要点
- **宽表格**表格宽度1800px支持横向滚动
- **分页显示**:支持分页
- **状态标签**:已支付显示绿色,未支付显示灰色
---
### 8. goodsList.html - 出货列表 ⭐⭐
**功能描述:** 查看所有出货记录(用户中奖记录)。
#### 8.1 列表字段
| 字段 | 说明 |
|------|------|
| ID | 记录ID |
| 订单ID | 关联订单ID |
| 用户ID | 用户唯一标识 |
| 盒子ID | 盒子唯一标识 |
| 盒子排序 | 盒子内序号 |
| 奖品ID | 奖品唯一标识 |
| 奖品名称 | 奖品标题 |
| 奖品图片 | 奖品缩略图 |
| 奖品价值 | 奖品售价 |
| 兑换价值 | 奖品回收价格 |
| 奖品类型 | 现货/预售/货币/宝箱 |
| 状态 | 待选择/回收/选择发货/发布集市 |
| 添加时间 | 中奖时间 |
#### 8.2 状态说明
| 状态值 | 显示 | 说明 |
|--------|------|------|
| 0 | 待选择 | 用户尚未选择处理方式 |
| 1 | 回收 | 用户选择回收兑换达达券 |
| 2 | 选择发货 | 用户选择申请发货 |
| 3 | 发布集市 | 用户选择发布到集市交易 |
---
### 9. exchangeList.html - 兑换列表 ⭐⭐
**功能描述:** 查看所有兑换(回收)记录,即用户将奖品兑换为达达券的记录。
#### 9.1 列表字段
| 字段 | 说明 |
|------|------|
| 序号 | 行号 |
| ID | 记录ID |
| 订单ID | 关联订单ID |
| 用户ID | 用户唯一标识 |
| 兑换单号 | 兑换记录编号 |
| 盒子ID | 盒子唯一标识 |
| 奖品ID | 奖品唯一标识 |
| 奖品名称 | 奖品标题 |
| 奖品图片 | 奖品缩略图 |
| 奖品价值 | 奖品售价 |
| 兑换价值 | 兑换获得的达达券金额 |
| 奖品类型 | 现货/预售/货币/宝箱 |
| 添加时间 | 中奖时间 |
| 选择时间 | 兑换操作时间 |
---
### 10. shipmentList.html - 发货列表 ⭐⭐
**功能描述:** 查看所有发货记录,即用户申请发货的奖品记录。
#### 10.1 列表字段
| 字段 | 说明 |
|------|------|
| ID | 记录ID |
| 订单ID | 关联订单ID |
| 用户ID | 用户唯一标识 |
| 发货单号 | 发货记录编号 |
| 盒子ID | 盒子唯一标识 |
| 奖品ID | 奖品唯一标识 |
| 奖品名称 | 奖品标题 |
| 奖品图片 | 奖品缩略图 |
| 奖品价值 | 奖品售价 |
| 兑换价值 | 奖品回收价格 |
| 奖品类型 | 现货/预售/货币/宝箱 |
| 保险状态 | 是/否(是否购买保险) |
| 添加时间 | 中奖时间 |
| 选择时间 | 申请发货时间 |
---
## 模块复杂度评估
| 页面 | 主要功能 | 复杂度 | 迁移优先级 |
|------|----------|--------|------------|
| dataStand.html | 数据看板、多卡片、异步加载 | ⭐⭐⭐⭐⭐ | P0 |
| profit.html | 盒子利润统计、异步加载、导出 | ⭐⭐⭐⭐⭐ | P0 |
| userstatistics.html | ECharts图表、数据表格 | ⭐⭐⭐⭐ | P0 |
| productsOverview.html | 出货概览、概率分析 | ⭐⭐⭐⭐ | P1 |
| lotteryUsers.html | 抽奖用户列表 | ⭐⭐⭐ | P1 |
| userLotteryDetail.html | 用户抽奖详情 | ⭐⭐⭐ | P1 |
| orderList.html | 订单列表 | ⭐⭐ | P2 |
| goodsList.html | 出货列表 | ⭐⭐ | P2 |
| exchangeList.html | 兑换列表 | ⭐⭐ | P2 |
| shipmentList.html | 发货列表 | ⭐⭐ | P2 |
---
## 后端 API 设计建议
### 数据看板 API
```
GET /api/admin/statistics/today-order # 今日订单数据
GET /api/admin/statistics/currency-info # 今日货币信息
GET /api/admin/statistics/income-summary # 今日收入汇总
GET /api/admin/statistics/user-stats # 用户数据统计
```
### 盒子利润统计 API
```
GET /api/admin/statistics/profit # 盒子利润列表(分页)
GET /api/admin/statistics/profit/summary # 利润汇总数据
GET /api/admin/statistics/profit/{goodsId} # 单个盒子详细统计
GET /api/admin/statistics/profit/export # 导出Excel
```
### 出货概览 API
```
GET /api/admin/statistics/products-overview/{goodsId} # 盒子出货概览
```
### 抽奖用户 API
```
GET /api/admin/statistics/lottery-users/{goodsId} # 抽奖用户列表
GET /api/admin/statistics/lottery-users/{goodsId}/{userId} # 用户抽奖详情
GET /api/admin/statistics/lottery-users/{goodsId}/{userId}/summary # 用户抽奖汇总
```
### 用户统计图表 API
```
GET /api/admin/statistics/daily-statistics # 每日统计数据
```
### 列表查询 API
```
GET /api/admin/statistics/orders # 支付订单列表
GET /api/admin/statistics/goods # 出货列表
GET /api/admin/statistics/exchanges # 兑换列表
GET /api/admin/statistics/shipments # 发货列表
```
---
## 数据库表依赖
### 主要数据表
| 表名 | 用途 |
|------|------|
| orders | 订单表,存储订单信息 |
| order_goods | 订单商品表,存储中奖记录 |
| goods | 盒子表,存储盒子信息 |
| goodslist | 奖品表,存储奖品信息 |
| users | 用户表,存储用户信息 |
| user_money_log | 用户余额流水表 |
| user_integral_log | 用户积分流水表 |
| user_score_log | 用户钻石流水表 |
| send_order | 发货订单表 |
| send_order_goods | 发货订单商品表 |
### 关键字段映射
| PHP字段 | 说明 | .NET建议字段 |
|---------|------|--------------|
| order_total | 订单总金额 | OrderTotal |
| order_zhe_total | 折后金额 | DiscountedTotal |
| price | 微信支付金额 | WechatPayment |
| use_money | 钻石支付金额 | DiamondPayment |
| use_integral | UU币支付金额 | UuCoinPayment |
| use_money2 | 达达券支付金额 | DadaCouponPayment |
| use_coupon | 优惠券抵扣 | CouponDiscount |
| goodslist_price | 奖品售价 | PrizePrice |
| goodslist_money | 奖品兑换价格 | PrizeExchangePrice |
| real_pro | 理论概率 | TheoreticalProbability |
---
## 前端技术要点
### Vue 3 + Element Plus 实现建议
#### 数据看板组件结构
```
views/business/statistics/
├── dashboard.vue # 数据看板主页面
├── profit.vue # 盒子利润统计
├── user-statistics.vue # 用户统计图表
├── components/
│ ├── TodayOrderCard.vue # 今日订单卡片
│ ├── CurrencyInfoCard.vue # 货币信息卡片
│ ├── IncomeSummaryCard.vue # 收入汇总卡片
│ ├── UserStatsCard.vue # 用户统计卡片
│ ├── ProfitTable.vue # 利润统计表格
│ ├── ProfitSummary.vue # 利润汇总卡片
│ ├── ProductsOverviewDialog.vue # 出货概览弹窗
│ ├── LotteryUsersDialog.vue # 抽奖用户弹窗
│ ├── UserLotteryDetailDialog.vue # 用户抽奖详情弹窗
│ └── StatisticsChart.vue # 统计图表组件
```
#### 图表库选择
- **ECharts 5.x**:功能强大,与 PHP 版本保持一致
- **vue-echarts**Vue 3 封装版本,使用更方便
#### 异步加载实现
```typescript
// 利润表格异步加载示例
const loadingQueue = ref<GoodsItem[]>([])
const maxConcurrentRequests = 3
const processLoadingQueue = async () => {
const batch = loadingQueue.value.splice(0, maxConcurrentRequests)
await Promise.all(batch.map(item => loadBoxStatistics(item)))
if (loadingQueue.value.length > 0) {
processLoadingQueue()
}
}
```
---
## 迁移计划建议
### 阶段1核心功能2周
1. **数据看板** (dataStand.html)
- 后端4个统计API
- 前端4个卡片组件 + 主页面
2. **盒子利润统计** (profit.html)
- 后端利润列表API、汇总API、详情API、导出API
- 前端:表格组件、汇总卡片、异步加载逻辑
3. **用户统计图表** (userstatistics.html)
- 后端每日统计API
- 前端ECharts图表组件、数据表格
### 阶段2详情功能1周
4. **出货概览** (productsOverview.html)
5. **抽奖用户列表** (lotteryUsers.html)
6. **用户抽奖详情** (userLotteryDetail.html)
### 阶段3列表功能1周
7. **支付订单列表** (orderList.html)
8. **出货列表** (goodsList.html)
9. **兑换列表** (exchangeList.html)
10. **发货列表** (shipmentList.html)
---
## 更新记录
| 日期 | 版本 | 更新内容 |
|------|------|----------|
| 2026-01-18 | v1.0 | 初始版本完成10个页面功能分析 |

View File

@ -0,0 +1,143 @@
-- =============================================
-- 统计报表模块菜单初始化脚本
-- 用于在后台管理系统中添加统计报表相关菜单
-- 包含:数据看板
--
-- 注意:此脚本需要在 Admin 数据库中执行
-- 表名使用小写menus, roles, permissions, role_menus, role_permissions
-- =============================================
-- 注意:执行此脚本前请确保:
-- 1. 已存在超级管理员角色 (Code = 'super_admin')
-- 2. 数据库中已有基础菜单数据
-- 声明变量
DECLARE @StatisticsMenuId BIGINT;
DECLARE @SuperAdminRoleId BIGINT;
-- 获取超级管理员角色ID
SELECT @SuperAdminRoleId = Id FROM roles WHERE Code = 'super_admin';
-- =============================================
-- 1. 创建统计报表目录(顶级菜单)
-- =============================================
IF NOT EXISTS (SELECT 1 FROM menus WHERE Path = '/business/statistics')
BEGIN
INSERT INTO menus (ParentId, Name, Path, Component, Icon, MenuType, Permission, SortOrder, Status, IsExternal, IsCache, CreatedAt)
VALUES (0, N'统计报表', '/business/statistics', 'Layout', 'DataAnalysis', 1, NULL, 5, 1, 0, 0, GETDATE());
SET @StatisticsMenuId = SCOPE_IDENTITY();
PRINT N'创建统计报表目录ID: ' + CAST(@StatisticsMenuId AS VARCHAR);
END
ELSE
BEGIN
SELECT @StatisticsMenuId = Id FROM menus WHERE Path = '/business/statistics';
UPDATE menus SET ParentId = 0, Component = 'Layout' WHERE Id = @StatisticsMenuId AND ParentId <> 0;
PRINT N'统计报表目录已存在ID: ' + CAST(@StatisticsMenuId AS VARCHAR);
END
-- =============================================
-- 2. 创建数据看板子菜单
-- =============================================
IF NOT EXISTS (SELECT 1 FROM menus WHERE Path = '/business/statistics/data-stand')
BEGIN
INSERT INTO menus (ParentId, Name, Path, Component, Icon, MenuType, Permission, SortOrder, Status, IsExternal, IsCache, CreatedAt)
VALUES (@StatisticsMenuId, N'数据看板', '/business/statistics/data-stand', 'business/statistics/data-stand', 'DataBoard', 2, 'statistics:data-stand', 1, 1, 0, 1, GETDATE());
PRINT N'创建数据看板菜单';
END
-- =============================================
-- 3. 添加统计报表相关权限
-- =============================================
IF NOT EXISTS (SELECT 1 FROM permissions WHERE Code = 'statistics:data-stand')
INSERT INTO permissions (Name, Code, Module, CreatedAt) VALUES (N'数据看板', 'statistics:data-stand', N'统计报表', GETDATE());
-- =============================================
-- 4. 为超级管理员角色分配新菜单
-- =============================================
IF @SuperAdminRoleId IS NOT NULL
BEGIN
-- 分配统计报表目录
IF NOT EXISTS (SELECT 1 FROM role_menus WHERE RoleId = @SuperAdminRoleId AND MenuId = @StatisticsMenuId)
BEGIN
INSERT INTO role_menus (RoleId, MenuId) VALUES (@SuperAdminRoleId, @StatisticsMenuId);
PRINT N'为超级管理员分配统计报表目录';
END
-- 分配所有新创建的子菜单
INSERT INTO role_menus (RoleId, MenuId)
SELECT @SuperAdminRoleId, m.Id
FROM menus m
WHERE m.ParentId = @StatisticsMenuId
AND NOT EXISTS (SELECT 1 FROM role_menus rm WHERE rm.RoleId = @SuperAdminRoleId AND rm.MenuId = m.Id);
PRINT N'为超级管理员分配统计报表子菜单';
-- 分配新增的权限
INSERT INTO role_permissions (RoleId, PermissionId)
SELECT @SuperAdminRoleId, p.Id
FROM permissions p
WHERE p.Code IN ('statistics:data-stand')
AND NOT EXISTS (
SELECT 1 FROM role_permissions rp
WHERE rp.RoleId = @SuperAdminRoleId AND rp.PermissionId = p.Id
);
PRINT N'为超级管理员分配统计报表权限';
END
-- =============================================
-- 5. 验证结果
-- =============================================
PRINT N'';
PRINT N'========== 菜单创建结果 ==========';
SELECT
m.Id,
m.ParentId,
m.Name,
m.Path,
m.Component,
m.MenuType,
m.Permission,
m.SortOrder
FROM menus m
WHERE m.Path LIKE '/business/statistics%'
ORDER BY m.ParentId, m.SortOrder;
PRINT N'';
PRINT N'========== 权限创建结果 ==========';
SELECT
p.Id,
p.Name,
p.Code,
p.Module
FROM permissions p
WHERE p.Code LIKE 'statistics:%'
ORDER BY p.Code;
PRINT N'';
PRINT N'========== 角色菜单分配结果 ==========';
SELECT
r.Name AS RoleName,
m.Name AS MenuName,
m.Path
FROM role_menus rm
INNER JOIN roles r ON rm.RoleId = r.Id
INNER JOIN menus m ON rm.MenuId = m.Id
WHERE m.Path LIKE '/business/statistics%'
ORDER BY r.Name, m.Path;
PRINT N'';
PRINT N'========== 角色权限分配结果 ==========';
SELECT
r.Name AS RoleName,
p.Name AS PermissionName,
p.Code
FROM role_permissions rp
INNER JOIN roles r ON rp.RoleId = r.Id
INNER JOIN permissions p ON rp.PermissionId = p.Id
WHERE p.Code LIKE 'statistics:%'
ORDER BY r.Name, p.Code;
PRINT N'';
PRINT N'统计报表模块菜单初始化完成';

View File

@ -0,0 +1,67 @@
using HoneyBox.Admin.Business.Attributes;
using HoneyBox.Admin.Business.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace HoneyBox.Admin.Business.Controllers;
/// <summary>
/// 统计报表控制器
/// </summary>
[Route("api/admin/business/statistics")]
public class StatisticsController : BusinessControllerBase
{
private readonly IStatisticsService _statisticsService;
public StatisticsController(IStatisticsService statisticsService)
{
_statisticsService = statisticsService;
}
/// <summary>
/// 获取今日订单统计数据
/// </summary>
/// <returns>今日订单统计</returns>
[HttpGet("today-order")]
[BusinessPermission("statistics:view")]
public async Task<IActionResult> GetTodayOrderStats()
{
var result = await _statisticsService.GetTodayOrderStatsAsync();
return Ok(result);
}
/// <summary>
/// 获取货币信息统计数据
/// </summary>
/// <returns>货币信息统计</returns>
[HttpGet("currency-info")]
[BusinessPermission("statistics:view")]
public async Task<IActionResult> GetCurrencyInfoStats()
{
var result = await _statisticsService.GetCurrencyInfoStatsAsync();
return Ok(result);
}
/// <summary>
/// 获取收入汇总统计数据
/// </summary>
/// <returns>收入汇总统计</returns>
[HttpGet("income-summary")]
[BusinessPermission("statistics:view")]
public async Task<IActionResult> GetIncomeSummaryStats()
{
var result = await _statisticsService.GetIncomeSummaryStatsAsync();
return Ok(result);
}
/// <summary>
/// 获取用户统计数据
/// </summary>
/// <returns>用户统计</returns>
[HttpGet("user-stats")]
[BusinessPermission("statistics:view")]
public async Task<IActionResult> GetUserStats()
{
var result = await _statisticsService.GetUserStatsAsync();
return Ok(result);
}
}

View File

@ -0,0 +1,67 @@
namespace HoneyBox.Admin.Business.Models.Statistics;
/// <summary>
/// 货币信息统计响应
/// </summary>
public class CurrencyInfoStatsResponse
{
/// <summary>
/// 今日发放钻石
/// </summary>
public decimal TodayAddMoney { get; set; }
/// <summary>
/// 今日消费钻石
/// </summary>
public decimal TodayUseMoney { get; set; }
/// <summary>
/// 昨日发放钻石
/// </summary>
public decimal YesterdayAddMoney { get; set; }
/// <summary>
/// 昨日消费钻石
/// </summary>
public decimal YesterdayUseMoney { get; set; }
/// <summary>
/// 今日发放UU币
/// </summary>
public decimal TodayAddIntegral { get; set; }
/// <summary>
/// 今日消费UU币
/// </summary>
public decimal TodayUseIntegral { get; set; }
/// <summary>
/// 昨日发放UU币
/// </summary>
public decimal YesterdayAddIntegral { get; set; }
/// <summary>
/// 昨日消费UU币
/// </summary>
public decimal YesterdayUseIntegral { get; set; }
/// <summary>
/// 今日发放达达券
/// </summary>
public decimal TodayAddMoney2 { get; set; }
/// <summary>
/// 今日消费达达券
/// </summary>
public decimal TodayUseMoney2 { get; set; }
/// <summary>
/// 昨日发放达达券
/// </summary>
public decimal YesterdayAddMoney2 { get; set; }
/// <summary>
/// 昨日消费达达券
/// </summary>
public decimal YesterdayUseMoney2 { get; set; }
}

View File

@ -0,0 +1,62 @@
namespace HoneyBox.Admin.Business.Models.Statistics;
/// <summary>
/// 收入汇总统计响应
/// </summary>
public class IncomeSummaryStatsResponse
{
/// <summary>
/// 订单收入RMB+钻石)
/// </summary>
public decimal TodayIncome { get; set; }
/// <summary>
/// RMB收入
/// </summary>
public decimal RmbIncome { get; set; }
/// <summary>
/// 钻石商城收入
/// </summary>
public decimal DiamondIncome { get; set; }
/// <summary>
/// 其他收入
/// </summary>
public decimal OtherIncome { get; set; }
/// <summary>
/// 订单出货(今日出货奖品总价值)
/// </summary>
public decimal ShippedToday { get; set; }
/// <summary>
/// 支出
/// </summary>
public decimal Expenses { get; set; }
/// <summary>
/// 当天发货金额
/// </summary>
public decimal TodayShipped { get; set; }
/// <summary>
/// 当天用户剩余达达券
/// </summary>
public decimal RemainingCoupon { get; set; }
/// <summary>
/// 盒柜剩余价值
/// </summary>
public decimal BoxRemaining { get; set; }
/// <summary>
/// 利润
/// </summary>
public decimal Profit { get; set; }
/// <summary>
/// 利润计算公式
/// </summary>
public string Formula { get; set; } = string.Empty;
}

View File

@ -0,0 +1,57 @@
namespace HoneyBox.Admin.Business.Models.Statistics;
/// <summary>
/// 今日订单统计响应
/// </summary>
public class TodayOrderStatsResponse
{
/// <summary>
/// 发起订单数(今日创建的订单总数)
/// </summary>
public int InitiateOrderCount { get; set; }
/// <summary>
/// 支付订单数(今日支付成功的订单数)
/// </summary>
public int PaidOrderCount { get; set; }
/// <summary>
/// 消费人数(今日有消费的用户数)
/// </summary>
public int UserCount { get; set; }
/// <summary>
/// 订单总金额(今日订单折后总金额)
/// </summary>
public decimal OrderZheTotal { get; set; }
/// <summary>
/// 出货总金额(今日出货奖品总价值)
/// </summary>
public decimal GoodsTotalAmount { get; set; }
/// <summary>
/// 优惠券抵扣(今日优惠券抵扣总额)
/// </summary>
public decimal UseCoupon { get; set; }
/// <summary>
/// RMB支付今日微信支付总额
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// 钻石支付(今日钻石支付总额)
/// </summary>
public decimal UseMoney { get; set; }
/// <summary>
/// UU币支付今日UU币支付总额
/// </summary>
public decimal UseIntegral { get; set; }
/// <summary>
/// 达达券支付(今日达达券支付总额)
/// </summary>
public decimal UseMoney2 { get; set; }
}

View File

@ -0,0 +1,62 @@
namespace HoneyBox.Admin.Business.Models.Statistics;
/// <summary>
/// 用户统计响应
/// </summary>
public class UserStatsResponse
{
/// <summary>
/// 绑定手机号人数
/// </summary>
public int UserRegisterCount { get; set; }
/// <summary>
/// 抽奖人数(有抽奖记录的用户总数)
/// </summary>
public int ConsumingUserCount { get; set; }
/// <summary>
/// 用户剩余钻石
/// </summary>
public decimal UserMoney { get; set; }
/// <summary>
/// 用户剩余UU币
/// </summary>
public decimal UserIntegral { get; set; }
/// <summary>
/// 用户剩余达达券
/// </summary>
public decimal UserMoney2 { get; set; }
/// <summary>
/// 微信支付金额(历史微信支付总额)
/// </summary>
public decimal OrderPriceTotal { get; set; }
/// <summary>
/// 订单支付数量(历史支付成功订单总数)
/// </summary>
public int OrderTotalCount { get; set; }
/// <summary>
/// 用户出货总金额
/// </summary>
public decimal TotalGoodsAmount { get; set; }
/// <summary>
/// 用户盒柜剩余价值
/// </summary>
public decimal BoxRemainingValue { get; set; }
/// <summary>
/// 用户已兑换的达达券
/// </summary>
public decimal ExchangedCoupon { get; set; }
/// <summary>
/// 用户已发货金额
/// </summary>
public decimal ShippedAmount { get; set; }
}

View File

@ -0,0 +1,33 @@
using HoneyBox.Admin.Business.Models.Statistics;
namespace HoneyBox.Admin.Business.Services.Interfaces;
/// <summary>
/// 统计服务接口
/// </summary>
public interface IStatisticsService
{
/// <summary>
/// 获取今日订单统计数据
/// </summary>
/// <returns>今日订单统计</returns>
Task<TodayOrderStatsResponse> GetTodayOrderStatsAsync();
/// <summary>
/// 获取货币信息统计数据
/// </summary>
/// <returns>货币信息统计</returns>
Task<CurrencyInfoStatsResponse> GetCurrencyInfoStatsAsync();
/// <summary>
/// 获取收入汇总统计数据
/// </summary>
/// <returns>收入汇总统计</returns>
Task<IncomeSummaryStatsResponse> GetIncomeSummaryStatsAsync();
/// <summary>
/// 获取用户统计数据
/// </summary>
/// <returns>用户统计</returns>
Task<UserStatsResponse> GetUserStatsAsync();
}

View File

@ -0,0 +1,389 @@
using HoneyBox.Admin.Business.Models.Statistics;
using HoneyBox.Admin.Business.Services.Interfaces;
using HoneyBox.Model.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HoneyBox.Admin.Business.Services;
/// <summary>
/// 统计服务实现
/// </summary>
public class StatisticsService : IStatisticsService
{
private readonly HoneyBoxDbContext _dbContext;
private readonly ILogger<StatisticsService> _logger;
public StatisticsService(HoneyBoxDbContext dbContext, ILogger<StatisticsService> logger)
{
_dbContext = dbContext;
_logger = logger;
}
/// <summary>
/// 获取今日订单统计数据
/// </summary>
public async Task<TodayOrderStatsResponse> GetTodayOrderStatsAsync()
{
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
// 排除测试用户的订单
var todayOrdersQuery = _dbContext.Orders
.Where(o => o.CreatedAt >= today && o.CreatedAt < tomorrow)
.Join(_dbContext.Users.Where(u => u.IsTest == 0),
o => o.UserId,
u => u.Id,
(o, u) => o);
// 今日已支付订单查询
var todayPaidOrdersQuery = todayOrdersQuery.Where(o => o.Status == 1);
// 发起订单数(今日创建的订单总数)
var initiateOrderCount = await todayOrdersQuery.CountAsync();
// 支付订单数(今日支付成功的订单数)
var paidOrderCount = await todayPaidOrdersQuery.CountAsync();
// 消费人数(今日有消费的用户数,去重)
var userCount = await todayPaidOrdersQuery
.Select(o => o.UserId)
.Distinct()
.CountAsync();
// 订单总金额(今日订单折后总金额)
var orderZheTotal = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.OrderZheTotal) ?? 0;
// 出货总金额(今日出货奖品总价值)- 从订单详情表获取
var goodsTotalAmount = await _dbContext.OrderItems
.Where(oi => oi.CreatedAt >= today && oi.CreatedAt < tomorrow)
.Join(_dbContext.Users.Where(u => u.IsTest == 0),
oi => oi.UserId,
u => u.Id,
(oi, u) => oi)
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
// 优惠券抵扣(今日优惠券抵扣总额)
var useCoupon = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.UseCoupon) ?? 0;
// RMB支付今日微信支付总额
var price = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.Price) ?? 0;
// 钻石支付(今日钻石支付总额)
var useMoney = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.UseMoney) ?? 0;
// UU币支付今日UU币支付总额
var useIntegral = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.UseIntegral) ?? 0;
// 达达券支付(今日达达券支付总额)
var useMoney2 = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.UseMoney2) ?? 0;
return new TodayOrderStatsResponse
{
InitiateOrderCount = initiateOrderCount,
PaidOrderCount = paidOrderCount,
UserCount = userCount,
OrderZheTotal = orderZheTotal,
GoodsTotalAmount = goodsTotalAmount,
UseCoupon = useCoupon,
Price = price,
UseMoney = useMoney,
UseIntegral = useIntegral,
UseMoney2 = useMoney2
};
}
/// <summary>
/// 获取货币信息统计数据
/// </summary>
public async Task<CurrencyInfoStatsResponse> GetCurrencyInfoStatsAsync()
{
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
var yesterday = today.AddDays(-1);
// 排除测试用户
var nonTestUserIds = _dbContext.Users
.Where(u => u.IsTest == 0)
.Select(u => u.Id);
// 钻石流水查询ProfitMoney表
var todayMoneyQuery = _dbContext.ProfitMoneys
.Where(p => p.CreatedAt >= today && p.CreatedAt < tomorrow)
.Where(p => nonTestUserIds.Contains(p.UserId));
var yesterdayMoneyQuery = _dbContext.ProfitMoneys
.Where(p => p.CreatedAt >= yesterday && p.CreatedAt < today)
.Where(p => nonTestUserIds.Contains(p.UserId));
// 今日发放钻石ChangeMoney > 0
var todayAddMoney = await todayMoneyQuery
.Where(p => p.ChangeMoney > 0)
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
// 今日消费钻石ChangeMoney < 0取绝对值
var todayUseMoney = await todayMoneyQuery
.Where(p => p.ChangeMoney < 0)
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
// 昨日发放钻石
var yesterdayAddMoney = await yesterdayMoneyQuery
.Where(p => p.ChangeMoney > 0)
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
// 昨日消费钻石
var yesterdayUseMoney = await yesterdayMoneyQuery
.Where(p => p.ChangeMoney < 0)
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
// UU币流水查询ProfitIntegral表
var todayIntegralQuery = _dbContext.ProfitIntegrals
.Where(p => p.CreatedAt >= today && p.CreatedAt < tomorrow)
.Where(p => nonTestUserIds.Contains(p.UserId));
var yesterdayIntegralQuery = _dbContext.ProfitIntegrals
.Where(p => p.CreatedAt >= yesterday && p.CreatedAt < today)
.Where(p => nonTestUserIds.Contains(p.UserId));
// 今日发放UU币
var todayAddIntegral = await todayIntegralQuery
.Where(p => p.ChangeMoney > 0)
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
// 今日消费UU币
var todayUseIntegral = await todayIntegralQuery
.Where(p => p.ChangeMoney < 0)
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
// 昨日发放UU币
var yesterdayAddIntegral = await yesterdayIntegralQuery
.Where(p => p.ChangeMoney > 0)
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
// 昨日消费UU币
var yesterdayUseIntegral = await yesterdayIntegralQuery
.Where(p => p.ChangeMoney < 0)
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
// 达达券流水查询ProfitMoney2表
var todayMoney2Query = _dbContext.ProfitMoney2s
.Where(p => p.CreatedAt >= today && p.CreatedAt < tomorrow)
.Where(p => nonTestUserIds.Contains(p.UserId));
var yesterdayMoney2Query = _dbContext.ProfitMoney2s
.Where(p => p.CreatedAt >= yesterday && p.CreatedAt < today)
.Where(p => nonTestUserIds.Contains(p.UserId));
// 今日发放达达券
var todayAddMoney2 = await todayMoney2Query
.Where(p => p.ChangeMoney > 0)
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
// 今日消费达达券
var todayUseMoney2 = await todayMoney2Query
.Where(p => p.ChangeMoney < 0)
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
// 昨日发放达达券
var yesterdayAddMoney2 = await yesterdayMoney2Query
.Where(p => p.ChangeMoney > 0)
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
// 昨日消费达达券
var yesterdayUseMoney2 = await yesterdayMoney2Query
.Where(p => p.ChangeMoney < 0)
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
return new CurrencyInfoStatsResponse
{
TodayAddMoney = todayAddMoney,
TodayUseMoney = todayUseMoney,
YesterdayAddMoney = yesterdayAddMoney,
YesterdayUseMoney = yesterdayUseMoney,
TodayAddIntegral = todayAddIntegral,
TodayUseIntegral = todayUseIntegral,
YesterdayAddIntegral = yesterdayAddIntegral,
YesterdayUseIntegral = yesterdayUseIntegral,
TodayAddMoney2 = todayAddMoney2,
TodayUseMoney2 = todayUseMoney2,
YesterdayAddMoney2 = yesterdayAddMoney2,
YesterdayUseMoney2 = yesterdayUseMoney2
};
}
/// <summary>
/// 获取收入汇总统计数据
/// </summary>
public async Task<IncomeSummaryStatsResponse> GetIncomeSummaryStatsAsync()
{
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
// 排除测试用户
var nonTestUserIds = _dbContext.Users
.Where(u => u.IsTest == 0)
.Select(u => u.Id);
// 今日已支付订单查询(排除测试用户)
var todayPaidOrdersQuery = _dbContext.Orders
.Where(o => o.CreatedAt >= today && o.CreatedAt < tomorrow && o.Status == 1)
.Where(o => nonTestUserIds.Contains(o.UserId));
// RMB收入今日微信支付总额
var rmbIncome = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.Price) ?? 0;
// 钻石支付收入
var diamondPayment = await todayPaidOrdersQuery
.SumAsync(o => (decimal?)o.UseMoney) ?? 0;
// 订单收入RMB + 钻石)
var todayIncome = rmbIncome + diamondPayment;
// 钻石商城收入(今日钻石商城已支付订单)
var diamondIncome = await _dbContext.DiamondOrders
.Where(d => d.CreatedAt >= today && d.CreatedAt < tomorrow && d.Status == "paid")
.Where(d => nonTestUserIds.Contains((int)d.UserId))
.SumAsync(d => (decimal?)d.AmountPaid) ?? 0;
// 其他收入暂时设为0可根据实际业务扩展
var otherIncome = 0m;
// 订单出货(今日出货奖品总价值)- 从订单详情表获取
var shippedToday = await _dbContext.OrderItems
.Where(oi => oi.CreatedAt >= today && oi.CreatedAt < tomorrow)
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
// 支出暂时设为0可根据实际业务扩展
var expenses = 0m;
// 当天发货金额今日申请发货的奖品总价值status=2表示已发货
var todayShippedAmount = await _dbContext.OrderItems
.Where(oi => oi.CreatedAt >= today && oi.CreatedAt < tomorrow && oi.Status == 2)
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
// 当天用户剩余达达券(所有非测试用户的达达券余额总和)
var remainingCoupon = await _dbContext.Users
.Where(u => u.IsTest == 0)
.SumAsync(u => (decimal?)u.Money2) ?? 0;
// 盒柜剩余价值今日用户盒柜中奖品总价值status=0表示待处理
var boxRemaining = await _dbContext.OrderItems
.Where(oi => oi.Status == 0)
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
// 利润计算:收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余
var profit = todayIncome - todayShippedAmount - remainingCoupon - boxRemaining;
// 利润计算公式
var formula = $"利润 = 订单收入({todayIncome:F2}) - 发货金额({todayShippedAmount:F2}) - 用户剩余达达券({remainingCoupon:F2}) - 盒柜剩余({boxRemaining:F2})";
return new IncomeSummaryStatsResponse
{
TodayIncome = todayIncome,
RmbIncome = rmbIncome,
DiamondIncome = diamondIncome,
OtherIncome = otherIncome,
ShippedToday = shippedToday,
Expenses = expenses,
TodayShipped = todayShippedAmount,
RemainingCoupon = remainingCoupon,
BoxRemaining = boxRemaining,
Profit = profit,
Formula = formula
};
}
/// <summary>
/// 获取用户统计数据
/// </summary>
public async Task<UserStatsResponse> GetUserStatsAsync()
{
// 排除测试用户
var nonTestUsersQuery = _dbContext.Users.Where(u => u.IsTest == 0);
var nonTestUserIds = nonTestUsersQuery.Select(u => u.Id);
// 绑定手机号人数(手机号不为空且不为空字符串的用户数)
var userRegisterCount = await nonTestUsersQuery
.Where(u => u.Mobile != null && u.Mobile != "")
.CountAsync();
// 抽奖人数(有抽奖记录的用户总数,去重)
var consumingUserCount = await _dbContext.OrderItems
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.Select(oi => oi.UserId)
.Distinct()
.CountAsync();
// 用户剩余钻石(所有非测试用户的钻石余额总和)
var userMoney = await nonTestUsersQuery
.SumAsync(u => (decimal?)u.Money) ?? 0;
// 用户剩余UU币所有非测试用户的UU币余额总和
var userIntegral = await nonTestUsersQuery
.SumAsync(u => (decimal?)u.Integral) ?? 0;
// 用户剩余达达券(所有非测试用户的达达券余额总和)
var userMoney2 = await nonTestUsersQuery
.SumAsync(u => (decimal?)u.Money2) ?? 0;
// 微信支付金额(历史微信支付总额,排除测试用户)
var orderPriceTotal = await _dbContext.Orders
.Where(o => o.Status == 1)
.Where(o => nonTestUserIds.Contains(o.UserId))
.SumAsync(o => (decimal?)o.Price) ?? 0;
// 订单支付数量(历史支付成功订单总数,排除测试用户)
var orderTotalCount = await _dbContext.Orders
.Where(o => o.Status == 1)
.Where(o => nonTestUserIds.Contains(o.UserId))
.CountAsync();
// 用户出货总金额(所有中奖记录的奖品总价值,排除测试用户)
var totalGoodsAmount = await _dbContext.OrderItems
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
// 用户盒柜剩余价值status=0表示待处理的奖品排除测试用户
var boxRemainingValue = await _dbContext.OrderItems
.Where(oi => oi.Status == 0)
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
// 用户已兑换的达达券status=1表示已回收的奖品回收金额总和排除测试用户
var exchangedCoupon = await _dbContext.OrderItems
.Where(oi => oi.Status == 1)
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistMoney) ?? 0;
// 用户已发货金额status=2表示已发货的奖品价值总和排除测试用户
var shippedAmount = await _dbContext.OrderItems
.Where(oi => oi.Status == 2)
.Where(oi => nonTestUserIds.Contains(oi.UserId))
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
return new UserStatsResponse
{
UserRegisterCount = userRegisterCount,
ConsumingUserCount = consumingUserCount,
UserMoney = userMoney,
UserIntegral = userIntegral,
UserMoney2 = userMoney2,
OrderPriceTotal = orderPriceTotal,
OrderTotalCount = orderTotalCount,
TotalGoodsAmount = totalGoodsAmount,
BoxRemainingValue = boxRemainingValue,
ExchangedCoupon = exchangedCoupon,
ShippedAmount = shippedAmount
};
}
}

View File

@ -0,0 +1,165 @@
import { request, type ApiResponse } from '@/utils/request'
// ==================== 统计类型定义 ====================
/**
*
*/
export interface TodayOrderStats {
/** 发起订单数(今日创建的订单总数) */
initiateOrderCount: number
/** 支付订单数(今日支付成功的订单数) */
paidOrderCount: number
/** 消费人数(今日有消费的用户数) */
userCount: number
/** 订单总金额(今日订单折后总金额) */
orderZheTotal: number
/** 出货总金额(今日出货奖品总价值) */
goodsTotalAmount: number
/** 优惠券抵扣(今日优惠券抵扣总额) */
useCoupon: number
/** RMB支付今日微信支付总额 */
price: number
/** 钻石支付(今日钻石支付总额) */
useMoney: number
/** UU币支付今日UU币支付总额 */
useIntegral: number
/** 达达券支付(今日达达券支付总额) */
useMoney2: number
}
/**
*
*/
export interface CurrencyInfoStats {
/** 今日发放钻石 */
todayAddMoney: number
/** 今日消费钻石 */
todayUseMoney: number
/** 昨日发放钻石 */
yesterdayAddMoney: number
/** 昨日消费钻石 */
yesterdayUseMoney: number
/** 今日发放UU币 */
todayAddIntegral: number
/** 今日消费UU币 */
todayUseIntegral: number
/** 昨日发放UU币 */
yesterdayAddIntegral: number
/** 昨日消费UU币 */
yesterdayUseIntegral: number
/** 今日发放达达券 */
todayAddMoney2: number
/** 今日消费达达券 */
todayUseMoney2: number
/** 昨日发放达达券 */
yesterdayAddMoney2: number
/** 昨日消费达达券 */
yesterdayUseMoney2: number
}
/**
*
*/
export interface IncomeSummaryStats {
/** 订单收入RMB+钻石) */
todayIncome: number
/** RMB收入 */
rmbIncome: number
/** 钻石商城收入 */
diamondIncome: number
/** 其他收入 */
otherIncome: number
/** 订单出货(今日出货奖品总价值) */
shippedToday: number
/** 支出 */
expenses: number
/** 当天发货金额 */
todayShipped: number
/** 当天用户剩余达达券 */
remainingCoupon: number
/** 盒柜剩余价值 */
boxRemaining: number
/** 利润 */
profit: number
/** 利润计算公式 */
formula: string
}
// ==================== API 基础路径 ====================
const STATISTICS_BASE_URL = '/admin/business/statistics'
// ==================== 统计 API ====================
/**
*
* @returns
*/
export function getTodayOrderStats(): Promise<ApiResponse<TodayOrderStats>> {
return request({
url: `${STATISTICS_BASE_URL}/today-order`,
method: 'get'
})
}
/**
*
* @returns
*/
export function getCurrencyInfoStats(): Promise<ApiResponse<CurrencyInfoStats>> {
return request({
url: `${STATISTICS_BASE_URL}/currency-info`,
method: 'get'
})
}
/**
*
* @returns
*/
export function getIncomeSummaryStats(): Promise<ApiResponse<IncomeSummaryStats>> {
return request({
url: `${STATISTICS_BASE_URL}/income-summary`,
method: 'get'
})
}
/**
*
*/
export interface UserStats {
/** 绑定手机号人数 */
userRegisterCount: number
/** 抽奖人数(有抽奖记录的用户总数) */
consumingUserCount: number
/** 用户剩余钻石 */
userMoney: number
/** 用户剩余UU币 */
userIntegral: number
/** 用户剩余达达券 */
userMoney2: number
/** 微信支付金额(历史微信支付总额) */
orderPriceTotal: number
/** 订单支付数量(历史支付成功订单总数) */
orderTotalCount: number
/** 用户出货总金额 */
totalGoodsAmount: number
/** 用户盒柜剩余价值 */
boxRemainingValue: number
/** 用户已兑换的达达券 */
exchangedCoupon: number
/** 用户已发货金额 */
shippedAmount: number
}
/**
*
* @returns
*/
export function getUserStats(): Promise<ApiResponse<UserStats>> {
return request({
url: `${STATISTICS_BASE_URL}/user-stats`,
method: 'get'
})
}

View File

@ -550,6 +550,27 @@ export const businessRoutes: RouteRecordRaw[] = [
}
}
]
},
// 统计报表
{
path: 'statistics',
redirect: '/business/statistics/data-stand',
meta: {
title: '统计报表',
icon: 'DataAnalysis'
},
children: [
{
path: 'data-stand',
name: 'DataStand',
component: () => import('@/views/business/statistics/data-stand.vue'),
meta: {
title: '数据看板',
permission: 'statistics:data-stand',
keepAlive: true
}
}
]
}
]
}
@ -1116,4 +1137,34 @@ export const welfareTaskPermissions = {
qyLevelPrizeDelete: 'qylevel:prize-delete'
}
/**
*
*
*
*
* 1.
* - name: 统计报表
* - path: /business/statistics
* - menuType: 1 ()
* - icon: DataAnalysis
* - sortOrder: 5
*
* 2.
* - name: 数据看板
* - path: /business/statistics/data-stand
* - component: business/statistics/data-stand
* - menuType: 2 ()
* - permission: statistics:data-stand
* - sortOrder: 1
*/
/**
*
*
*/
export const statisticsPermissions = {
// 数据看板
dataStand: 'statistics:data-stand'
}
export default businessRoutes

View File

@ -0,0 +1,258 @@
<template>
<el-card class="currency-info-card" v-loading="loading">
<template #header>
<div class="card-header">
<span class="card-title">今日货币信息</span>
<el-button
type="primary"
link
:icon="Refresh"
@click="handleRefresh"
:loading="loading"
>
刷新
</el-button>
</div>
</template>
<div class="stats-grid">
<!-- 第一行钻石 -->
<div class="stat-item">
<div class="stat-label">今日发放钻石</div>
<div class="stat-value add">{{ formatNumber(data.todayAddMoney) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">今日消费钻石</div>
<div class="stat-value use">{{ formatNumber(data.todayUseMoney) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">昨日发放钻石</div>
<div class="stat-value add">{{ formatNumber(data.yesterdayAddMoney) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">昨日消费钻石</div>
<div class="stat-value use">{{ formatNumber(data.yesterdayUseMoney) }}</div>
</div>
<!-- 第二行UU币 -->
<div class="stat-item">
<div class="stat-label">今日发放UU币</div>
<div class="stat-value add">{{ formatNumber(data.todayAddIntegral) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">今日消费UU币</div>
<div class="stat-value use">{{ formatNumber(data.todayUseIntegral) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">昨日发放UU币</div>
<div class="stat-value add">{{ formatNumber(data.yesterdayAddIntegral) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">昨日消费UU币</div>
<div class="stat-value use">{{ formatNumber(data.yesterdayUseIntegral) }}</div>
</div>
<!-- 第三行达达券 -->
<div class="stat-item">
<div class="stat-label">今日发放达达券</div>
<div class="stat-value add">{{ formatNumber(data.todayAddMoney2) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">今日消费达达券</div>
<div class="stat-value use">{{ formatNumber(data.todayUseMoney2) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">昨日发放达达券</div>
<div class="stat-value add">{{ formatNumber(data.yesterdayAddMoney2) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">昨日消费达达券</div>
<div class="stat-value use">{{ formatNumber(data.yesterdayUseMoney2) }}</div>
</div>
</div>
<!-- 错误提示 -->
<div v-if="error" class="error-message">
<el-icon><WarningFilled /></el-icon>
<span>{{ error }}</span>
</div>
</el-card>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { Refresh, WarningFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getCurrencyInfoStats, type CurrencyInfoStats } from '@/api/business/statistics'
import { formatNumber } from '@/utils/format'
// ==================== ====================
const loading = ref(false)
const error = ref<string | null>(null)
//
const defaultData: CurrencyInfoStats = {
todayAddMoney: 0,
todayUseMoney: 0,
yesterdayAddMoney: 0,
yesterdayUseMoney: 0,
todayAddIntegral: 0,
todayUseIntegral: 0,
yesterdayAddIntegral: 0,
yesterdayUseIntegral: 0,
todayAddMoney2: 0,
todayUseMoney2: 0,
yesterdayAddMoney2: 0,
yesterdayUseMoney2: 0
}
const data = reactive<CurrencyInfoStats>({ ...defaultData })
// ==================== ====================
/**
* 加载货币信息统计数据
*/
async function loadData() {
loading.value = true
error.value = null
try {
const response = await getCurrencyInfoStats()
if (response.code === 0 && response.data) {
Object.assign(data, response.data)
} else {
error.value = response.message || '获取数据失败'
Object.assign(data, defaultData)
}
} catch (err: unknown) {
console.error('加载货币信息数据失败:', err)
//
if (err instanceof Error) {
if (err.message.includes('403') || err.message.includes('权限')) {
error.value = '无权限访问此页面'
} else if (err.message.includes('network') || err.message.includes('Network')) {
error.value = '网络连接失败,请检查网络'
} else {
error.value = '服务器繁忙,请稍后重试'
}
} else {
error.value = '获取数据失败'
}
//
Object.assign(data, defaultData)
} finally {
loading.value = false
}
}
/**
* 刷新数据
*/
function handleRefresh() {
loadData()
ElMessage.info('正在刷新数据...')
}
// ==================== ====================
onMounted(() => {
loadData()
})
// ==================== ====================
defineExpose({
refresh: loadData
})
</script>
<style scoped>
.currency-info-card {
height: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.stat-item {
padding: 12px;
background: var(--el-fill-color-light);
border-radius: 8px;
text-align: center;
transition: all 0.3s ease;
}
.stat-item:hover {
background: var(--el-fill-color);
transform: translateY(-2px);
}
.stat-label {
font-size: 12px;
color: var(--el-text-color-secondary);
margin-bottom: 8px;
}
.stat-value {
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.stat-value.add {
color: var(--el-color-success);
}
.stat-value.use {
color: var(--el-color-warning);
}
.error-message {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-top: 16px;
padding: 12px;
background: var(--el-color-danger-light-9);
border-radius: 4px;
color: var(--el-color-danger);
font-size: 14px;
}
/* 响应式布局 */
@media (max-width: 768px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.stat-value {
font-size: 16px;
}
}
@media (max-width: 480px) {
.stats-grid {
grid-template-columns: 1fr;
}
}
</style>

View File

@ -0,0 +1,225 @@
<template>
<el-card class="income-summary-card" v-loading="loading">
<template #header>
<div class="card-header">
<span class="card-title">今日收入汇总</span>
<el-button
type="primary"
link
:icon="Refresh"
@click="handleRefresh"
:loading="loading"
>
刷新
</el-button>
</div>
</template>
<el-table :data="tableData" border stripe class="income-table">
<el-table-column prop="category" label="类别" width="120" />
<el-table-column prop="item" label="项目" min-width="150" />
<el-table-column prop="value" label="金额" min-width="120" align="right">
<template #default="{ row }">
<span :class="{ 'negative-value': row.isNegative }">
{{ row.value }}
</span>
</template>
</el-table-column>
</el-table>
<!-- 利润计算公式 -->
<div class="formula-section">
<div class="formula-label">利润计算公式</div>
<div class="formula-content">{{ data.formula || '收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余' }}</div>
</div>
<!-- 错误提示 -->
<div v-if="error" class="error-message">
<el-icon><WarningFilled /></el-icon>
<span>{{ error }}</span>
</div>
</el-card>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { Refresh, WarningFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getIncomeSummaryStats, type IncomeSummaryStats } from '@/api/business/statistics'
import { formatCurrency } from '@/utils/format'
// ==================== ====================
const loading = ref(false)
const error = ref<string | null>(null)
//
const defaultData: IncomeSummaryStats = {
todayIncome: 0,
rmbIncome: 0,
diamondIncome: 0,
otherIncome: 0,
shippedToday: 0,
expenses: 0,
todayShipped: 0,
remainingCoupon: 0,
boxRemaining: 0,
profit: 0,
formula: '收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余'
}
const data = reactive<IncomeSummaryStats>({ ...defaultData })
// ==================== ====================
/**
* 表格数据
*/
const tableData = computed(() => [
{ category: '收入', item: '订单收入RMB+钻石)', value: formatCurrency(data.todayIncome), isNegative: false },
{ category: '收入', item: 'RMB收入', value: formatCurrency(data.rmbIncome), isNegative: false },
{ category: '收入', item: '钻石商城收入', value: formatCurrency(data.diamondIncome), isNegative: false },
{ category: '收入', item: '其他收入', value: formatCurrency(data.otherIncome), isNegative: false },
{ category: '出货', item: '订单出货', value: formatCurrency(data.shippedToday), isNegative: false },
{ category: '支出', item: '支出', value: formatCurrency(data.expenses), isNegative: false },
{ category: '支出', item: '当天发货金额', value: formatCurrency(data.todayShipped), isNegative: false },
{ category: '支出', item: '当天用户剩余达达券', value: formatCurrency(data.remainingCoupon), isNegative: false },
{ category: '支出', item: '盒柜剩余价值', value: formatCurrency(data.boxRemaining), isNegative: false },
{ category: '利润', item: '利润', value: formatCurrency(data.profit), isNegative: data.profit < 0 }
])
// ==================== ====================
/**
* 加载收入汇总统计数据
*/
async function loadData() {
loading.value = true
error.value = null
try {
const response = await getIncomeSummaryStats()
if (response.code === 0 && response.data) {
Object.assign(data, response.data)
} else {
error.value = response.message || '获取数据失败'
Object.assign(data, defaultData)
}
} catch (err: unknown) {
console.error('加载收入汇总数据失败:', err)
//
if (err instanceof Error) {
if (err.message.includes('403') || err.message.includes('权限')) {
error.value = '无权限访问此页面'
} else if (err.message.includes('network') || err.message.includes('Network')) {
error.value = '网络连接失败,请检查网络'
} else {
error.value = '服务器繁忙,请稍后重试'
}
} else {
error.value = '获取数据失败'
}
//
Object.assign(data, defaultData)
} finally {
loading.value = false
}
}
/**
* 刷新数据
*/
function handleRefresh() {
loadData()
ElMessage.info('正在刷新数据...')
}
// ==================== ====================
onMounted(() => {
loadData()
})
// ==================== ====================
defineExpose({
refresh: loadData
})
</script>
<style scoped>
.income-summary-card {
height: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.income-table {
width: 100%;
}
.income-table :deep(.el-table__row) {
transition: background-color 0.3s ease;
}
.income-table :deep(.el-table__row:hover) {
background-color: var(--el-fill-color-light);
}
.negative-value {
color: var(--el-color-danger);
font-weight: 600;
}
.formula-section {
margin-top: 16px;
padding: 12px;
background: var(--el-fill-color-light);
border-radius: 8px;
}
.formula-label {
font-size: 12px;
color: var(--el-text-color-secondary);
margin-bottom: 4px;
}
.formula-content {
font-size: 14px;
color: var(--el-text-color-primary);
font-family: 'Courier New', monospace;
}
.error-message {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-top: 16px;
padding: 12px;
background: var(--el-color-danger-light-9);
border-radius: 4px;
color: var(--el-color-danger);
font-size: 14px;
}
/* 响应式布局 */
@media (max-width: 768px) {
.income-table :deep(.el-table__cell) {
padding: 8px 4px;
font-size: 12px;
}
}
</style>

View File

@ -0,0 +1,244 @@
<template>
<el-card class="today-order-card" v-loading="loading">
<template #header>
<div class="card-header">
<span class="card-title">今日订单</span>
<el-button
type="primary"
link
:icon="Refresh"
@click="handleRefresh"
:loading="loading"
>
刷新
</el-button>
</div>
</template>
<div class="stats-grid">
<!-- 第一行 -->
<div class="stat-item">
<div class="stat-label">发起订单数</div>
<div class="stat-value">{{ formatNumber(data.initiateOrderCount) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">支付订单数</div>
<div class="stat-value">{{ formatNumber(data.paidOrderCount) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">消费人数</div>
<div class="stat-value">{{ formatNumber(data.userCount) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">订单总金额</div>
<div class="stat-value currency">{{ formatCurrency(data.orderZheTotal) }}</div>
</div>
<!-- 第二行 -->
<div class="stat-item">
<div class="stat-label">出货总金额</div>
<div class="stat-value currency">{{ formatCurrency(data.goodsTotalAmount) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">优惠券抵扣</div>
<div class="stat-value currency">{{ formatCurrency(data.useCoupon) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">RMB支付</div>
<div class="stat-value currency">{{ formatCurrency(data.price) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">钻石支付</div>
<div class="stat-value">{{ formatNumber(data.useMoney) }}</div>
</div>
<!-- 第三行 -->
<div class="stat-item">
<div class="stat-label">UU币支付</div>
<div class="stat-value">{{ formatNumber(data.useIntegral) }}</div>
</div>
<div class="stat-item">
<div class="stat-label">达达券支付</div>
<div class="stat-value">{{ formatNumber(data.useMoney2) }}</div>
</div>
</div>
<!-- 错误提示 -->
<div v-if="error" class="error-message">
<el-icon><WarningFilled /></el-icon>
<span>{{ error }}</span>
</div>
</el-card>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { Refresh, WarningFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getTodayOrderStats, type TodayOrderStats } from '@/api/business/statistics'
import { formatCurrency, formatNumber } from '@/utils/format'
// ==================== ====================
const loading = ref(false)
const error = ref<string | null>(null)
//
const defaultData: TodayOrderStats = {
initiateOrderCount: 0,
paidOrderCount: 0,
userCount: 0,
orderZheTotal: 0,
goodsTotalAmount: 0,
useCoupon: 0,
price: 0,
useMoney: 0,
useIntegral: 0,
useMoney2: 0
}
const data = reactive<TodayOrderStats>({ ...defaultData })
// ==================== ====================
/**
* 加载今日订单统计数据
*/
async function loadData() {
loading.value = true
error.value = null
try {
const response = await getTodayOrderStats()
if (response.code === 0 && response.data) {
Object.assign(data, response.data)
} else {
error.value = response.message || '获取数据失败'
Object.assign(data, defaultData)
}
} catch (err: unknown) {
console.error('加载今日订单数据失败:', err)
//
if (err instanceof Error) {
if (err.message.includes('403') || err.message.includes('权限')) {
error.value = '无权限访问此页面'
} else if (err.message.includes('network') || err.message.includes('Network')) {
error.value = '网络连接失败,请检查网络'
} else {
error.value = '服务器繁忙,请稍后重试'
}
} else {
error.value = '获取数据失败'
}
//
Object.assign(data, defaultData)
} finally {
loading.value = false
}
}
/**
* 刷新数据
*/
function handleRefresh() {
loadData()
ElMessage.info('正在刷新数据...')
}
// ==================== ====================
onMounted(() => {
loadData()
})
// ==================== ====================
defineExpose({
refresh: loadData
})
</script>
<style scoped>
.today-order-card {
height: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.stat-item {
padding: 12px;
background: var(--el-fill-color-light);
border-radius: 8px;
text-align: center;
transition: all 0.3s ease;
}
.stat-item:hover {
background: var(--el-fill-color);
transform: translateY(-2px);
}
.stat-label {
font-size: 12px;
color: var(--el-text-color-secondary);
margin-bottom: 8px;
}
.stat-value {
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.stat-value.currency {
color: var(--el-color-success);
}
.error-message {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-top: 16px;
padding: 12px;
background: var(--el-color-danger-light-9);
border-radius: 4px;
color: var(--el-color-danger);
font-size: 14px;
}
/* 响应式布局 */
@media (max-width: 768px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.stat-value {
font-size: 16px;
}
}
@media (max-width: 480px) {
.stats-grid {
grid-template-columns: 1fr;
}
}
</style>

View File

@ -0,0 +1,195 @@
<template>
<el-card class="user-stats-card" v-loading="loading">
<template #header>
<div class="card-header">
<span class="card-title">用户数据统计</span>
<el-button
type="primary"
link
:icon="Refresh"
@click="handleRefresh"
:loading="loading"
>
刷新
</el-button>
</div>
</template>
<el-table :data="tableData" border stripe class="user-stats-table">
<el-table-column prop="category" label="类别" width="120" />
<el-table-column prop="item" label="项目" min-width="150" />
<el-table-column prop="value" label="数值" min-width="120" align="right" />
</el-table>
<!-- 错误提示 -->
<div v-if="error" class="error-message">
<el-icon><WarningFilled /></el-icon>
<span>{{ error }}</span>
</div>
</el-card>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { Refresh, WarningFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getUserStats, type UserStats } from '@/api/business/statistics'
import { formatCurrency, formatNumber } from '@/utils/format'
// ==================== ====================
const loading = ref(false)
const error = ref<string | null>(null)
//
const defaultData: UserStats = {
userRegisterCount: 0,
consumingUserCount: 0,
userMoney: 0,
userIntegral: 0,
userMoney2: 0,
orderPriceTotal: 0,
orderTotalCount: 0,
totalGoodsAmount: 0,
boxRemainingValue: 0,
exchangedCoupon: 0,
shippedAmount: 0
}
const data = reactive<UserStats>({ ...defaultData })
// ==================== ====================
/**
* 表格数据 - 6行2列布局展示11个数据项
*/
const tableData = computed(() => [
//
{ category: '用户基础', item: '绑定手机号人数', value: formatNumber(data.userRegisterCount) },
{ category: '用户基础', item: '抽奖人数', value: formatNumber(data.consumingUserCount) },
//
{ category: '剩余货币', item: '用户剩余钻石', value: formatNumber(data.userMoney) },
{ category: '剩余货币', item: '用户剩余UU币', value: formatNumber(data.userIntegral) },
{ category: '剩余货币', item: '用户剩余达达券', value: formatNumber(data.userMoney2) },
//
{ category: '支付数据', item: '微信支付金额', value: formatCurrency(data.orderPriceTotal) },
{ category: '支付数据', item: '订单支付数量', value: formatNumber(data.orderTotalCount) },
//
{ category: '出货数据', item: '用户出货总金额', value: formatCurrency(data.totalGoodsAmount) },
{ category: '出货数据', item: '用户盒柜剩余价值', value: formatCurrency(data.boxRemainingValue) },
//
{ category: '兑换发货', item: '用户已兑换的达达券', value: formatNumber(data.exchangedCoupon) },
{ category: '兑换发货', item: '用户已发货金额', value: formatCurrency(data.shippedAmount) }
])
// ==================== ====================
/**
* 加载用户统计数据
*/
async function loadData() {
loading.value = true
error.value = null
try {
const response = await getUserStats()
if (response.code === 0 && response.data) {
Object.assign(data, response.data)
} else {
error.value = response.message || '获取数据失败'
Object.assign(data, defaultData)
}
} catch (err: unknown) {
console.error('加载用户统计数据失败:', err)
//
if (err instanceof Error) {
if (err.message.includes('403') || err.message.includes('权限')) {
error.value = '无权限访问此页面'
} else if (err.message.includes('network') || err.message.includes('Network')) {
error.value = '网络连接失败,请检查网络'
} else {
error.value = '服务器繁忙,请稍后重试'
}
} else {
error.value = '获取数据失败'
}
//
Object.assign(data, defaultData)
} finally {
loading.value = false
}
}
/**
* 刷新数据
*/
function handleRefresh() {
loadData()
ElMessage.info('正在刷新数据...')
}
// ==================== ====================
onMounted(() => {
loadData()
})
// ==================== ====================
defineExpose({
refresh: loadData
})
</script>
<style scoped>
.user-stats-card {
height: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.user-stats-table {
width: 100%;
}
.user-stats-table :deep(.el-table__row) {
transition: background-color 0.3s ease;
}
.user-stats-table :deep(.el-table__row:hover) {
background-color: var(--el-fill-color-light);
}
.error-message {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-top: 16px;
padding: 12px;
background: var(--el-color-danger-light-9);
border-radius: 4px;
color: var(--el-color-danger);
font-size: 14px;
}
/* 响应式布局 */
@media (max-width: 768px) {
.user-stats-table :deep(.el-table__cell) {
padding: 8px 4px;
font-size: 12px;
}
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<div class="data-stand-container">
<!-- 页面标题 -->
<div class="page-header">
<h2 class="page-title">数据看板</h2>
<el-button type="primary" :icon="Refresh" @click="refreshAll" :loading="isRefreshing">
刷新全部
</el-button>
</div>
<!-- 两列布局 -->
<el-row :gutter="20" class="stats-row">
<!-- 左侧列 -->
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="card-wrapper">
<TodayOrderCard ref="todayOrderCardRef" />
</div>
<div class="card-wrapper">
<IncomeSummaryCard ref="incomeSummaryCardRef" />
</div>
</el-col>
<!-- 右侧列 -->
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="card-wrapper">
<CurrencyInfoCard ref="currencyInfoCardRef" />
</div>
<div class="card-wrapper">
<UserStatsCard ref="userStatsCardRef" />
</div>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import TodayOrderCard from './components/TodayOrderCard.vue'
import CurrencyInfoCard from './components/CurrencyInfoCard.vue'
import IncomeSummaryCard from './components/IncomeSummaryCard.vue'
import UserStatsCard from './components/UserStatsCard.vue'
// ==================== ====================
const todayOrderCardRef = ref<InstanceType<typeof TodayOrderCard> | null>(null)
const currencyInfoCardRef = ref<InstanceType<typeof CurrencyInfoCard> | null>(null)
const incomeSummaryCardRef = ref<InstanceType<typeof IncomeSummaryCard> | null>(null)
const userStatsCardRef = ref<InstanceType<typeof UserStatsCard> | null>(null)
// ==================== ====================
const isRefreshing = ref(false)
// ==================== ====================
/**
* 刷新所有卡片数据
*/
async function refreshAll() {
isRefreshing.value = true
ElMessage.info('正在刷新所有数据...')
try {
//
await Promise.all([
todayOrderCardRef.value?.refresh(),
currencyInfoCardRef.value?.refresh(),
incomeSummaryCardRef.value?.refresh(),
userStatsCardRef.value?.refresh()
])
ElMessage.success('数据刷新完成')
} catch (error) {
console.error('刷新数据失败:', error)
ElMessage.error('部分数据刷新失败')
} finally {
isRefreshing.value = false
}
}
</script>
<style scoped>
.data-stand-container {
padding: 20px;
background: var(--el-bg-color-page);
min-height: calc(100vh - 84px);
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.page-title {
font-size: 20px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 0;
}
.stats-row {
margin: 0 !important;
}
.card-wrapper {
margin-bottom: 20px;
}
/* 响应式布局调整 */
@media (max-width: 991px) {
.data-stand-container {
padding: 16px;
}
.page-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.page-title {
font-size: 18px;
}
}
@media (max-width: 767px) {
.data-stand-container {
padding: 12px;
}
.card-wrapper {
margin-bottom: 16px;
}
}
</style>

View File

@ -201,7 +201,7 @@ async function loadOverviewData() {
overviewLoading.value = true
try {
const response = await getDashboardOverview()
if (response.success && response.data) {
if (response.code === 0 && response.data) {
overviewData.value = response.data
} else {
ElMessage.warning(response.message || '获取概览数据失败')

View File

@ -1 +1 @@
import{d as r,c as a,b as t,e as p,w as _,g as l,t as d,i as c,k as u,_ as i}from"./index-DlmlUUdG.js";const m={class:"error-page"},f={class:"error-content"},x=r({__name:"404",setup(k){const o=c(),s=()=>{o.push("/")};return(v,e)=>{const n=l("el-button");return u(),a("div",m,[t("div",f,[e[1]||(e[1]=t("h1",null,"404",-1)),e[2]||(e[2]=t("p",null,"抱歉,您访问的页面不存在",-1)),p(n,{type:"primary",onClick:s},{default:_(()=>[...e[0]||(e[0]=[d("返回首页",-1)])]),_:1})])])}}}),b=i(x,[["__scopeId","data-v-7e9f7d47"]]);export{b as default};
import{d as r,c as a,b as t,e as p,w as _,g as l,t as d,i as c,k as u,_ as i}from"./index-C-IfdMnF.js";const m={class:"error-page"},f={class:"error-content"},x=r({__name:"404",setup(k){const o=c(),s=()=>{o.push("/")};return(v,e)=>{const n=l("el-button");return u(),a("div",m,[t("div",f,[e[1]||(e[1]=t("h1",null,"404",-1)),e[2]||(e[2]=t("p",null,"抱歉,您访问的页面不存在",-1)),p(n,{type:"primary",onClick:s},{default:_(()=>[...e[0]||(e[0]=[d("返回首页",-1)])]),_:1})])])}}}),b=i(x,[["__scopeId","data-v-7e9f7d47"]]);export{b as default};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.image-upload-container[data-v-ca2445f7]{display:flex;gap:12px;align-items:flex-start}.preview-image[data-v-ca2445f7]{width:80px;height:60px;border-radius:4px;flex-shrink:0}.image-error[data-v-ca2445f7]{display:flex;justify-content:center;align-items:center;width:80px;height:60px;background:#f5f7fa;color:#909399;font-size:20px}.form-tip[data-v-ca2445f7]{font-size:12px;color:#909399;margin-top:4px}

View File

@ -0,0 +1 @@
import{d as w,r as f,G as b,g as o,J as L,c as p,k as l,K as V,e as a,z as k,w as n,t as _,x as d,b as z,l as c,I as E,_ as $}from"./index-C-IfdMnF.js";import{A as r,b as F}from"./advert-CHXWibni.js";const G={class:"advert-table"},K={class:"image-error"},W={key:1,class:"no-image"},X={key:0},Y={key:1},q={key:2},H={key:3,class:"url-text"},M={key:4},O=w({__name:"AdvertTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","delete"],setup(g,{emit:C}){const u=g,m=C,h=f(u.page),v=f(u.pageSize);b(()=>u.page,t=>{h.value=t}),b(()=>u.pageSize,t=>{v.value=t});const T=t=>F[t]||"未知",S=t=>{m("page-change",t)},j=t=>{m("size-change",t)},x=t=>{m("edit",t)},D=t=>{m("delete",t)};return(t,s)=>{const i=o("el-table-column"),I=o("el-tag"),N=o("el-icon"),A=o("el-image"),y=o("el-button"),U=o("el-table"),B=o("el-pagination"),J=L("loading");return l(),p("div",G,[V((l(),k(U,{data:g.data,border:"",stripe:""},{default:n(()=>[a(i,{prop:"id",label:"ID",width:"80",align:"center"}),a(i,{label:"广告类型",width:"120",align:"center"},{default:n(({row:e})=>[a(I,{size:"small"},{default:n(()=>[_(d(e.typeName),1)]),_:2},1024)]),_:1}),a(i,{label:"广告图片",width:"150",align:"center"},{default:n(({row:e})=>[e.imageUrl?(l(),k(A,{key:0,src:e.imageUrl,"preview-src-list":[e.imageUrl],fit:"cover",class:"advert-image","preview-teleported":""},{error:n(()=>[z("div",K,[a(N,null,{default:n(()=>[a(c(E))]),_:1})])]),_:1},8,["src","preview-src-list"])):(l(),p("span",W,"暂无图片"))]),_:1}),a(i,{label:"跳转类型",width:"120",align:"center"},{default:n(({row:e})=>[z("span",null,d(e.jumpTypeName||T(e.jumpType)),1)]),_:1}),a(i,{label:"跳转目标","min-width":"150"},{default:n(({row:e})=>[e.jumpType===c(r).None?(l(),p("span",X,"-")):e.jumpType===c(r).Coupon?(l(),p("span",Y,"优惠券ID: "+d(e.couponId),1)):e.jumpType===c(r).YiFanShang||e.jumpType===c(r).WuXianShang||e.jumpType===c(r).LianJiShang?(l(),p("span",q," 盒子ID: "+d(e.goodsId),1)):e.jumpType===c(r).CustomUrl?(l(),p("span",H,d(e.urlLink),1)):(l(),p("span",M,"-"))]),_:1}),a(i,{prop:"sort",label:"排序值",width:"100",align:"center"}),a(i,{label:"创建时间",width:"160",align:"center"},{default:n(({row:e})=>[_(d(e.createdAt||"-"),1)]),_:1}),a(i,{label:"操作",width:"150",align:"center",fixed:"right"},{default:n(({row:e})=>[a(y,{type:"primary",link:"",size:"small",onClick:P=>x(e)},{default:n(()=>[...s[2]||(s[2]=[_(" 编辑 ",-1)])]),_:1},8,["onClick"]),a(y,{type:"danger",link:"",size:"small",onClick:P=>D(e)},{default:n(()=>[...s[3]||(s[3]=[_(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[J,g.loading]]),a(B,{"current-page":h.value,"onUpdate:currentPage":s[0]||(s[0]=e=>h.value=e),"page-size":v.value,"onUpdate:pageSize":s[1]||(s[1]=e=>v.value=e),"page-sizes":[10,20,50,100],total:g.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:j,onCurrentChange:S,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),Z=$(O,[["__scopeId","data-v-0e1cc97d"]]);export{Z as default};

View File

@ -0,0 +1 @@
.advert-table[data-v-0e1cc97d]{width:100%}.advert-image[data-v-0e1cc97d]{width:80px;height:60px;border-radius:4px}.image-error[data-v-0e1cc97d]{display:flex;justify-content:center;align-items:center;width:80px;height:60px;background:#f5f7fa;color:#909399;font-size:20px}.no-image[data-v-0e1cc97d]{color:#909399;font-size:12px}.url-text[data-v-0e1cc97d]{color:#409eff;word-break:break-all}.pagination[data-v-0e1cc97d]{margin-top:16px;justify-content:flex-end}

View File

@ -0,0 +1 @@
import{d as P,v as Q,r as _,a as E,G as W,g as r,J as X,z as b,k as i,w as l,b as F,K as Y,c as y,H as Z,e as n,t as d,l as B,C as ee,f as te,F as h,x as z,L as ae,E as u,D as le,_ as ne}from"./index-C-IfdMnF.js";import{_ as se}from"./AdvertTypeForm.vue_vue_type_script_setup_true_lang-BQ3SKluS.js";import{g as oe,e as ie,f as de,h as re}from"./advert-CHXWibni.js";const ue={class:"type-dialog-content"},me={class:"action-bar"},ce={key:0,class:"add-form"},pe=P({__name:"AdvertTypeDialog",props:{modelValue:{type:Boolean}},emits:["update:modelValue","refresh"],setup($,{emit:K}){const A=$,g=K,x=Q({get:()=>A.modelValue,set:t=>g("update:modelValue",t)}),w=_(!1),k=_([]),f=_(!1),N=_();let s=E({name:"",sort:0});const m=_(null),o=E({name:"",sort:0}),C=async()=>{w.value=!0;try{const t=await oe();k.value=t.data}finally{w.value=!1}};W(()=>A.modelValue,t=>{t&&C()});const S=()=>{f.value=!0,s.name="",s.sort=0},U=async()=>{if(!s.name.trim()){u.warning("请输入类型名称");return}if(k.value.some(e=>e.name===s.name.trim())){u.warning("类型名称已存在");return}try{await ie({name:s.name.trim(),sort:s.sort}),u.success("添加成功"),f.value=!1,C(),g("refresh")}catch{}},I=()=>{f.value=!1},R=t=>{m.value=t.id,o.name=t.name,o.sort=t.sort},D=async t=>{if(!o.name.trim()){u.warning("请输入类型名称");return}if(k.value.some(V=>V.name===o.name.trim()&&V.id!==t.id)){u.warning("类型名称已存在");return}try{await de(t.id,{name:o.name.trim(),sort:o.sort}),u.success("更新成功"),m.value=null,C(),g("refresh")}catch{}},L=()=>{m.value=null},M=async t=>{if(t.advertCount>0){u.warning(`该类型下有 ${t.advertCount} 个广告,无法删除`);return}try{await le.confirm(`确定要删除类型 "${t.name}" 吗?`,"删除确认",{type:"warning"}),await re(t.id),u.success("删除成功"),C(),g("refresh")}catch{}},T=()=>{x.value=!1,f.value=!1,m.value=null};return(t,e)=>{const V=r("el-icon"),p=r("el-button"),v=r("el-table-column"),G=r("el-input"),H=r("el-input-number"),J=r("el-tag"),j=r("el-table"),q=r("el-dialog"),O=X("loading");return i(),b(q,{modelValue:x.value,"onUpdate:modelValue":e[3]||(e[3]=a=>x.value=a),title:"广告类型管理",width:"650px","close-on-click-modal":!1,onClose:T},{footer:l(()=>[n(p,{onClick:T},{default:l(()=>[...e[9]||(e[9]=[d("关闭",-1)])]),_:1})]),default:l(()=>[F("div",ue,[F("div",me,[n(p,{type:"primary",size:"small",onClick:S},{default:l(()=>[n(V,null,{default:l(()=>[n(B(ee))]),_:1}),e[4]||(e[4]=d("添加类型 ",-1))]),_:1})]),Y((i(),b(j,{data:k.value,border:"",stripe:"",size:"small"},{default:l(()=>[n(v,{prop:"id",label:"ID",width:"80",align:"center"}),n(v,{prop:"name",label:"类型名称","min-width":"150"},{default:l(({row:a})=>[m.value===a.id?(i(),b(G,{key:0,modelValue:o.name,"onUpdate:modelValue":e[0]||(e[0]=c=>o.name=c),size:"small",placeholder:"请输入类型名称",onKeyup:te(c=>D(a),["enter"])},null,8,["modelValue","onKeyup"])):(i(),y(h,{key:1},[d(z(a.name),1)],64))]),_:1}),n(v,{prop:"sort",label:"排序",width:"120",align:"center"},{default:l(({row:a})=>[m.value===a.id?(i(),b(H,{key:0,modelValue:o.sort,"onUpdate:modelValue":e[1]||(e[1]=c=>o.sort=c),size:"small",min:0,max:9999,"controls-position":"right"},null,8,["modelValue"])):(i(),y(h,{key:1},[d(z(a.sort),1)],64))]),_:1}),n(v,{prop:"advertCount",label:"广告数量",width:"100",align:"center"},{default:l(({row:a})=>[n(J,{size:"small",type:a.advertCount>0?"success":"info"},{default:l(()=>[d(z(a.advertCount),1)]),_:2},1032,["type"])]),_:1}),n(v,{label:"操作",width:"150",align:"center",fixed:"right"},{default:l(({row:a})=>[m.value===a.id?(i(),y(h,{key:0},[n(p,{type:"success",link:"",size:"small",onClick:c=>D(a)},{default:l(()=>[...e[5]||(e[5]=[d(" 保存 ",-1)])]),_:1},8,["onClick"]),n(p,{type:"info",link:"",size:"small",onClick:L},{default:l(()=>[...e[6]||(e[6]=[d(" 取消 ",-1)])]),_:1})],64)):(i(),y(h,{key:1},[n(p,{type:"primary",link:"",size:"small",onClick:c=>R(a)},{default:l(()=>[...e[7]||(e[7]=[d(" 编辑 ",-1)])]),_:1},8,["onClick"]),n(p,{type:"danger",link:"",size:"small",onClick:c=>M(a)},{default:l(()=>[...e[8]||(e[8]=[d(" 删除 ",-1)])]),_:1},8,["onClick"])],64))]),_:1})]),_:1},8,["data"])),[[O,w.value]]),f.value?(i(),y("div",ce,[n(se,{ref_key:"addFormRef",ref:N,modelValue:B(s),"onUpdate:modelValue":e[2]||(e[2]=a=>ae(s)?s.value=a:s=a),onSubmit:U,onCancel:I},null,8,["modelValue"])])):Z("",!0)])]),_:1},8,["modelValue"])}}}),ye=ne(pe,[["__scopeId","data-v-f8b0e1a3"]]);export{ye as default};

View File

@ -0,0 +1 @@
.type-dialog-content[data-v-f8b0e1a3]{min-height:200px}.action-bar[data-v-f8b0e1a3]{margin-bottom:16px}.add-form[data-v-f8b0e1a3]{margin-top:16px;padding:16px;background:#f5f7fa;border-radius:4px}

View File

@ -0,0 +1 @@
import{_ as m}from"./AdvertTypeForm.vue_vue_type_script_setup_true_lang-BQ3SKluS.js";import"./index-C-IfdMnF.js";export{m as default};

View File

@ -0,0 +1 @@
import{d as C,r as p,G as c,g as r,z as h,k as z,w as a,e as o,t as f}from"./index-C-IfdMnF.js";const R=C({__name:"AdvertTypeForm",props:{modelValue:{}},emits:["update:modelValue","submit","cancel"],setup(_,{expose:v,emit:V}){const m=_,s=V,n=p(),t=p({name:m.modelValue.name,sort:m.modelValue.sort});c(()=>m.modelValue,e=>{t.value={...e}},{deep:!0}),c(t,e=>{s("update:modelValue",e)},{deep:!0});const b={name:[{required:!0,message:"请输入类型名称",trigger:"blur"},{min:1,max:20,message:"名称长度在1-20个字符",trigger:"blur"}],sort:[{required:!0,message:"请输入排序值",trigger:"blur"}]},g=async()=>{if(n.value)try{await n.value.validate(),s("submit")}catch{}},x=()=>{s("cancel")};return v({validate:()=>{var e;return(e=n.value)==null?void 0:e.validate()},resetFields:()=>{var e;return(e=n.value)==null?void 0:e.resetFields()}}),(e,l)=>{const w=r("el-input"),u=r("el-form-item"),y=r("el-input-number"),i=r("el-button"),k=r("el-form");return z(),h(k,{ref_key:"formRef",ref:n,model:t.value,rules:b,"label-width":"80px",inline:""},{default:a(()=>[o(u,{label:"类型名称",prop:"name"},{default:a(()=>[o(w,{modelValue:t.value.name,"onUpdate:modelValue":l[0]||(l[0]=d=>t.value.name=d),placeholder:"请输入类型名称",maxlength:"20","show-word-limit":"",style:{width:"200px"}},null,8,["modelValue"])]),_:1}),o(u,{label:"排序值",prop:"sort"},{default:a(()=>[o(y,{modelValue:t.value.sort,"onUpdate:modelValue":l[1]||(l[1]=d=>t.value.sort=d),min:0,max:9999,"controls-position":"right",style:{width:"120px"}},null,8,["modelValue"])]),_:1}),o(u,null,{default:a(()=>[o(i,{type:"primary",size:"small",onClick:g},{default:a(()=>[...l[2]||(l[2]=[f(" 确定 ",-1)])]),_:1}),o(i,{size:"small",onClick:x},{default:a(()=>[...l[3]||(l[3]=[f(" 取消 ",-1)])]),_:1})]),_:1})]),_:1},8,["model"])}}});export{R as _};

View File

@ -1 +1 @@
import{d as q,r as A,v as B,g as n,z as R,k as N,w as l,e,b as m,t as f,x as b,l as z,J as F,_ as M}from"./index-DlmlUUdG.js";const S={class:"merchant-header"},J={class:"merchant-title"},T=q({__name:"AlipayMerchantForm",props:{modelValue:{},index:{},canDelete:{type:Boolean}},emits:["update:modelValue","delete","change"],setup(c,{expose:V,emit:x}){const g=c,i=x,_=A(),t=B({get:()=>g.modelValue,set:v=>i("update:modelValue",v)}),y={name:[{required:!0,message:"请输入商户名称",trigger:"blur"},{max:50,message:"商户名称不能超过50个字符",trigger:"blur"}],appId:[{required:!0,message:"请输入应用ID",trigger:"blur"},{max:32,message:"应用ID不能超过32个字符",trigger:"blur"}],privateKey:[{required:!0,message:"请输入应用私钥",trigger:"blur"}],publicKey:[{required:!0,message:"请输入支付宝公钥",trigger:"blur"}],weight:[{required:!0,message:"请输入权重",trigger:"blur"},{type:"number",min:1,max:100,message:"权重必须在1-100之间",trigger:"blur"}]},u=()=>{i("change")},h=()=>{i("delete",g.index)};return V({validate:async()=>{if(!_.value)return!1;try{return await _.value.validate(),!0}catch{return!1}}}),(v,a)=>{const w=n("el-tag"),I=n("el-icon"),k=n("el-button"),s=n("el-input"),r=n("el-form-item"),d=n("el-col"),p=n("el-row"),D=n("el-input-number"),K=n("el-switch"),C=n("el-form"),U=n("el-card");return N(),R(U,{class:"merchant-card",shadow:"hover"},{header:l(()=>[m("div",S,[m("span",J,[e(w,{type:t.value.is_enabled===1?"success":"info",size:"small"},{default:l(()=>[f(b(t.value.is_enabled===1?"已启用":"已禁用"),1)]),_:1},8,["type"]),f(" "+b(t.value.name||"新商户"),1)]),e(k,{type:"danger",link:"",disabled:!c.canDelete,onClick:h},{default:l(()=>[e(I,null,{default:l(()=>[e(z(F))]),_:1}),a[7]||(a[7]=f("删除 ",-1))]),_:1},8,["disabled"])])]),default:l(()=>[e(C,{ref_key:"formRef",ref:_,model:t.value,rules:y,"label-width":"100px",class:"merchant-form"},{default:l(()=>[e(p,{gutter:20},{default:l(()=>[e(d,{span:12},{default:l(()=>[e(r,{label:"商户名称",prop:"name"},{default:l(()=>[e(s,{modelValue:t.value.name,"onUpdate:modelValue":a[0]||(a[0]=o=>t.value.name=o),placeholder:"请输入商户名称",maxlength:"50",onInput:u},null,8,["modelValue"])]),_:1})]),_:1}),e(d,{span:12},{default:l(()=>[e(r,{label:"应用ID",prop:"appId"},{default:l(()=>[e(s,{modelValue:t.value.appId,"onUpdate:modelValue":a[1]||(a[1]=o=>t.value.appId=o),placeholder:"请输入支付宝应用ID(AppId)",maxlength:"32",onInput:u},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:12},{default:l(()=>[e(r,{label:"权重",prop:"weight"},{default:l(()=>[e(D,{modelValue:t.value.weight,"onUpdate:modelValue":a[2]||(a[2]=o=>t.value.weight=o),min:1,max:100,placeholder:"请输入权重",onChange:u},null,8,["modelValue"]),a[8]||(a[8]=m("div",{class:"form-tip"},"权重越高,支付时被选中的概率越大",-1))]),_:1})]),_:1}),e(d,{span:12},{default:l(()=>[e(r,{label:"启用状态",prop:"is_enabled"},{default:l(()=>[e(K,{modelValue:t.value.is_enabled,"onUpdate:modelValue":a[3]||(a[3]=o=>t.value.is_enabled=o),"active-value":1,"inactive-value":0,"active-text":"启用","inactive-text":"禁用",onChange:u},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:24},{default:l(()=>[e(r,{label:"应用私钥",prop:"privateKey"},{default:l(()=>[e(s,{modelValue:t.value.privateKey,"onUpdate:modelValue":a[4]||(a[4]=o=>t.value.privateKey=o),type:"textarea",rows:4,placeholder:"请输入应用私钥RSA2私钥",onInput:u},null,8,["modelValue"]),a[9]||(a[9]=m("div",{class:"form-tip"},"用于签名请求,请妥善保管",-1))]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:24},{default:l(()=>[e(r,{label:"支付宝公钥",prop:"publicKey"},{default:l(()=>[e(s,{modelValue:t.value.publicKey,"onUpdate:modelValue":a[5]||(a[5]=o=>t.value.publicKey=o),type:"textarea",rows:4,placeholder:"请输入支付宝公钥",onInput:u},null,8,["modelValue"]),a[10]||(a[10]=m("div",{class:"form-tip"},"用于验证支付宝返回的签名",-1))]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:24},{default:l(()=>[e(r,{label:"备注",prop:"remark"},{default:l(()=>[e(s,{modelValue:t.value.remark,"onUpdate:modelValue":a[6]||(a[6]=o=>t.value.remark=o),type:"textarea",rows:2,placeholder:"请输入备注信息(可选)",maxlength:"200","show-word-limit":"",onInput:u},null,8,["modelValue"])]),_:1})]),_:1})]),_:1})]),_:1},8,["model"])]),_:1})}}}),G=M(T,[["__scopeId","data-v-e5bdfc39"]]);export{G as default};
import{d as q,r as A,v as B,g as n,z as R,k as N,w as l,e,b as m,t as f,x as b,l as z,O as F,_ as M}from"./index-C-IfdMnF.js";const S={class:"merchant-header"},O={class:"merchant-title"},T=q({__name:"AlipayMerchantForm",props:{modelValue:{},index:{},canDelete:{type:Boolean}},emits:["update:modelValue","delete","change"],setup(c,{expose:V,emit:x}){const g=c,i=x,_=A(),t=B({get:()=>g.modelValue,set:v=>i("update:modelValue",v)}),y={name:[{required:!0,message:"请输入商户名称",trigger:"blur"},{max:50,message:"商户名称不能超过50个字符",trigger:"blur"}],appId:[{required:!0,message:"请输入应用ID",trigger:"blur"},{max:32,message:"应用ID不能超过32个字符",trigger:"blur"}],privateKey:[{required:!0,message:"请输入应用私钥",trigger:"blur"}],publicKey:[{required:!0,message:"请输入支付宝公钥",trigger:"blur"}],weight:[{required:!0,message:"请输入权重",trigger:"blur"},{type:"number",min:1,max:100,message:"权重必须在1-100之间",trigger:"blur"}]},u=()=>{i("change")},h=()=>{i("delete",g.index)};return V({validate:async()=>{if(!_.value)return!1;try{return await _.value.validate(),!0}catch{return!1}}}),(v,a)=>{const w=n("el-tag"),I=n("el-icon"),k=n("el-button"),s=n("el-input"),r=n("el-form-item"),d=n("el-col"),p=n("el-row"),D=n("el-input-number"),K=n("el-switch"),C=n("el-form"),U=n("el-card");return N(),R(U,{class:"merchant-card",shadow:"hover"},{header:l(()=>[m("div",S,[m("span",O,[e(w,{type:t.value.is_enabled===1?"success":"info",size:"small"},{default:l(()=>[f(b(t.value.is_enabled===1?"已启用":"已禁用"),1)]),_:1},8,["type"]),f(" "+b(t.value.name||"新商户"),1)]),e(k,{type:"danger",link:"",disabled:!c.canDelete,onClick:h},{default:l(()=>[e(I,null,{default:l(()=>[e(z(F))]),_:1}),a[7]||(a[7]=f("删除 ",-1))]),_:1},8,["disabled"])])]),default:l(()=>[e(C,{ref_key:"formRef",ref:_,model:t.value,rules:y,"label-width":"100px",class:"merchant-form"},{default:l(()=>[e(p,{gutter:20},{default:l(()=>[e(d,{span:12},{default:l(()=>[e(r,{label:"商户名称",prop:"name"},{default:l(()=>[e(s,{modelValue:t.value.name,"onUpdate:modelValue":a[0]||(a[0]=o=>t.value.name=o),placeholder:"请输入商户名称",maxlength:"50",onInput:u},null,8,["modelValue"])]),_:1})]),_:1}),e(d,{span:12},{default:l(()=>[e(r,{label:"应用ID",prop:"appId"},{default:l(()=>[e(s,{modelValue:t.value.appId,"onUpdate:modelValue":a[1]||(a[1]=o=>t.value.appId=o),placeholder:"请输入支付宝应用ID(AppId)",maxlength:"32",onInput:u},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:12},{default:l(()=>[e(r,{label:"权重",prop:"weight"},{default:l(()=>[e(D,{modelValue:t.value.weight,"onUpdate:modelValue":a[2]||(a[2]=o=>t.value.weight=o),min:1,max:100,placeholder:"请输入权重",onChange:u},null,8,["modelValue"]),a[8]||(a[8]=m("div",{class:"form-tip"},"权重越高,支付时被选中的概率越大",-1))]),_:1})]),_:1}),e(d,{span:12},{default:l(()=>[e(r,{label:"启用状态",prop:"is_enabled"},{default:l(()=>[e(K,{modelValue:t.value.is_enabled,"onUpdate:modelValue":a[3]||(a[3]=o=>t.value.is_enabled=o),"active-value":1,"inactive-value":0,"active-text":"启用","inactive-text":"禁用",onChange:u},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:24},{default:l(()=>[e(r,{label:"应用私钥",prop:"privateKey"},{default:l(()=>[e(s,{modelValue:t.value.privateKey,"onUpdate:modelValue":a[4]||(a[4]=o=>t.value.privateKey=o),type:"textarea",rows:4,placeholder:"请输入应用私钥RSA2私钥",onInput:u},null,8,["modelValue"]),a[9]||(a[9]=m("div",{class:"form-tip"},"用于签名请求,请妥善保管",-1))]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:24},{default:l(()=>[e(r,{label:"支付宝公钥",prop:"publicKey"},{default:l(()=>[e(s,{modelValue:t.value.publicKey,"onUpdate:modelValue":a[5]||(a[5]=o=>t.value.publicKey=o),type:"textarea",rows:4,placeholder:"请输入支付宝公钥",onInput:u},null,8,["modelValue"]),a[10]||(a[10]=m("div",{class:"form-tip"},"用于验证支付宝返回的签名",-1))]),_:1})]),_:1})]),_:1}),e(p,{gutter:20},{default:l(()=>[e(d,{span:24},{default:l(()=>[e(r,{label:"备注",prop:"remark"},{default:l(()=>[e(s,{modelValue:t.value.remark,"onUpdate:modelValue":a[6]||(a[6]=o=>t.value.remark=o),type:"textarea",rows:2,placeholder:"请输入备注信息(可选)",maxlength:"200","show-word-limit":"",onInput:u},null,8,["modelValue"])]),_:1})]),_:1})]),_:1})]),_:1},8,["model"])]),_:1})}}}),G=M(T,[["__scopeId","data-v-e5bdfc39"]]);export{G as default};

View File

@ -1 +0,0 @@
import{d as j,r as z,P,g as u,B as A,c as d,k as l,C as E,e as s,z as x,w as n,b as t,D as c,x as a,l as R,R as $,t as g,_ as q}from"./index-DlmlUUdG.js";import{O as k}from"./order-JIUblY8O.js";const G={class:"order-table"},H={class:"user-info"},J={class:"nickname"},K={class:"uid"},L={key:0,class:"mobile"},Q={class:"order-num"},W={class:"goods-info"},X={class:"image-error"},Y={class:"goods-detail"},Z={class:"goods-title"},w={class:"goods-meta"},ee={class:"money-info"},te={class:"money"},ae={key:0},se={class:"discount"},ne={class:"money"},ie={class:"pay-info"},oe={key:0},le={key:1},de={key:2},ce={key:3},re={key:4},ue={class:"time-info"},_e={key:0},me=j({__name:"BuyOrderTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","view-detail"],setup(v,{emit:C}){const h=v,y=C,f=z(h.page),b=z(h.pageSize);P(()=>h.page,i=>{f.value=i}),P(()=>h.pageSize,i=>{b.value=i});const S=i=>{switch(i){case k.Paid:return"success";case k.Unpaid:return"warning";case k.Cancelled:return"info";default:return"info"}},N=i=>{y("page-change",i)},T=i=>{y("size-change",i)},B=i=>{y("view-detail",i)};return(i,o)=>{const r=u("el-table-column"),U=u("el-icon"),D=u("el-image"),F=u("el-tag"),I=u("el-button"),V=u("el-table"),O=u("el-pagination"),M=A("loading");return l(),d("div",G,[E((l(),x(V,{data:v.data,border:"",stripe:""},{default:n(()=>[s(r,{label:"用户信息","min-width":"160",fixed:"left"},{default:n(({row:e})=>[t("div",H,[t("div",J,a(e.userNickname||"-"),1),t("div",K,"UID: "+a(e.userId),1),e.userMobile?(l(),d("div",L,a(e.userMobile),1)):c("",!0)])]),_:1}),s(r,{prop:"orderNum",label:"订单号","min-width":"180"},{default:n(({row:e})=>[t("span",Q,a(e.orderNum),1)]),_:1}),s(r,{label:"盒子信息","min-width":"200"},{default:n(({row:e})=>[t("div",W,[e.goodsImgUrl?(l(),x(D,{key:0,src:e.goodsImgUrl,"preview-src-list":[e.goodsImgUrl],fit:"cover",class:"goods-img",lazy:""},{error:n(()=>[t("div",X,[s(U,null,{default:n(()=>[s(R($))]),_:1})])]),_:1},8,["src","preview-src-list"])):c("",!0),t("div",Y,[t("div",Z,a(e.goodsTitle||"-"),1),t("div",w,[t("span",null,"抽奖次数: "+a(e.num),1),t("span",null,"中奖数: "+a(e.prizeNum),1)])])])]),_:1}),s(r,{label:"金额详情","min-width":"180"},{default:n(({row:e})=>{var _,m,p;return[t("div",ee,[t("div",null,[o[2]||(o[2]=g("订单金额: ",-1)),t("span",te,"¥"+a(((_=e.orderTotal)==null?void 0:_.toFixed(2))||"0.00"),1)]),e.discount>0?(l(),d("div",ae,[o[3]||(o[3]=g("折扣: ",-1)),t("span",se,"-¥"+a((m=e.discount)==null?void 0:m.toFixed(2)),1)])):c("",!0),t("div",null,[o[4]||(o[4]=g("实付金额: ",-1)),t("span",ne,"¥"+a(((p=e.discountTotal)==null?void 0:p.toFixed(2))||"0.00"),1)])])]}),_:1}),s(r,{label:"支付方式","min-width":"140"},{default:n(({row:e})=>{var _,m,p;return[t("div",ie,[e.weChatPayment>0?(l(),d("div",oe,"微信: ¥"+a((_=e.weChatPayment)==null?void 0:_.toFixed(2)),1)):c("",!0),e.balancePayment>0?(l(),d("div",le,"余额: ¥"+a((m=e.balancePayment)==null?void 0:m.toFixed(2)),1)):c("",!0),e.integralPayment>0?(l(),d("div",de,"积分: "+a(e.integralPayment),1)):c("",!0),e.scorePayment>0?(l(),d("div",ce,"评分: "+a(e.scorePayment),1)):c("",!0),e.couponPayment&&e.couponPayment>0?(l(),d("div",re,"优惠券: ¥"+a((p=e.couponPayment)==null?void 0:p.toFixed(2)),1)):c("",!0)])]}),_:1}),s(r,{label:"状态",width:"100",align:"center"},{default:n(({row:e})=>[s(F,{type:S(e.status),size:"small"},{default:n(()=>[g(a(e.statusName),1)]),_:2},1032,["type"])]),_:1}),s(r,{label:"时间","min-width":"160"},{default:n(({row:e})=>[t("div",ue,[t("div",null,"下单: "+a(e.createdAt),1),e.payTime?(l(),d("div",_e,"支付: "+a(e.payTime),1)):c("",!0)])]),_:1}),s(r,{label:"操作",width:"120",fixed:"right",align:"center"},{default:n(({row:e})=>[s(I,{type:"primary",link:"",onClick:_=>B(e)},{default:n(()=>[...o[5]||(o[5]=[g(" 查看详情 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[M,v.loading]]),s(O,{"current-page":f.value,"onUpdate:currentPage":o[0]||(o[0]=e=>f.value=e),"page-size":b.value,"onUpdate:pageSize":o[1]||(o[1]=e=>b.value=e),"page-sizes":[10,20,50,100],total:v.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:T,onCurrentChange:N,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),ve=q(me,[["__scopeId","data-v-3010f6cf"]]);export{ve as default};

View File

@ -0,0 +1 @@
import{d as j,r as z,G as P,g as u,J as A,c as d,k as l,K as E,e as s,z as x,w as n,b as t,H as c,x as a,l as G,I as H,t as g,_ as J}from"./index-C-IfdMnF.js";import{O as k}from"./order-DGQ-DcLZ.js";const K={class:"order-table"},$={class:"user-info"},q={class:"nickname"},L={class:"uid"},Q={key:0,class:"mobile"},R={class:"order-num"},W={class:"goods-info"},X={class:"image-error"},Y={class:"goods-detail"},Z={class:"goods-title"},w={class:"goods-meta"},ee={class:"money-info"},te={class:"money"},ae={key:0},se={class:"discount"},ne={class:"money"},ie={class:"pay-info"},oe={key:0},le={key:1},de={key:2},ce={key:3},re={key:4},ue={class:"time-info"},_e={key:0},me=j({__name:"BuyOrderTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","view-detail"],setup(v,{emit:C}){const h=v,y=C,f=z(h.page),b=z(h.pageSize);P(()=>h.page,i=>{f.value=i}),P(()=>h.pageSize,i=>{b.value=i});const S=i=>{switch(i){case k.Paid:return"success";case k.Unpaid:return"warning";case k.Cancelled:return"info";default:return"info"}},N=i=>{y("page-change",i)},T=i=>{y("size-change",i)},B=i=>{y("view-detail",i)};return(i,o)=>{const r=u("el-table-column"),I=u("el-icon"),U=u("el-image"),F=u("el-tag"),D=u("el-button"),V=u("el-table"),O=u("el-pagination"),M=A("loading");return l(),d("div",K,[E((l(),x(V,{data:v.data,border:"",stripe:""},{default:n(()=>[s(r,{label:"用户信息","min-width":"160",fixed:"left"},{default:n(({row:e})=>[t("div",$,[t("div",q,a(e.userNickname||"-"),1),t("div",L,"UID: "+a(e.userId),1),e.userMobile?(l(),d("div",Q,a(e.userMobile),1)):c("",!0)])]),_:1}),s(r,{prop:"orderNum",label:"订单号","min-width":"180"},{default:n(({row:e})=>[t("span",R,a(e.orderNum),1)]),_:1}),s(r,{label:"盒子信息","min-width":"200"},{default:n(({row:e})=>[t("div",W,[e.goodsImgUrl?(l(),x(U,{key:0,src:e.goodsImgUrl,"preview-src-list":[e.goodsImgUrl],fit:"cover",class:"goods-img",lazy:""},{error:n(()=>[t("div",X,[s(I,null,{default:n(()=>[s(G(H))]),_:1})])]),_:1},8,["src","preview-src-list"])):c("",!0),t("div",Y,[t("div",Z,a(e.goodsTitle||"-"),1),t("div",w,[t("span",null,"抽奖次数: "+a(e.num),1),t("span",null,"中奖数: "+a(e.prizeNum),1)])])])]),_:1}),s(r,{label:"金额详情","min-width":"180"},{default:n(({row:e})=>{var _,m,p;return[t("div",ee,[t("div",null,[o[2]||(o[2]=g("订单金额: ",-1)),t("span",te,"¥"+a(((_=e.orderTotal)==null?void 0:_.toFixed(2))||"0.00"),1)]),e.discount>0?(l(),d("div",ae,[o[3]||(o[3]=g("折扣: ",-1)),t("span",se,"-¥"+a((m=e.discount)==null?void 0:m.toFixed(2)),1)])):c("",!0),t("div",null,[o[4]||(o[4]=g("实付金额: ",-1)),t("span",ne,"¥"+a(((p=e.discountTotal)==null?void 0:p.toFixed(2))||"0.00"),1)])])]}),_:1}),s(r,{label:"支付方式","min-width":"140"},{default:n(({row:e})=>{var _,m,p;return[t("div",ie,[e.weChatPayment>0?(l(),d("div",oe,"微信: ¥"+a((_=e.weChatPayment)==null?void 0:_.toFixed(2)),1)):c("",!0),e.balancePayment>0?(l(),d("div",le,"余额: ¥"+a((m=e.balancePayment)==null?void 0:m.toFixed(2)),1)):c("",!0),e.integralPayment>0?(l(),d("div",de,"积分: "+a(e.integralPayment),1)):c("",!0),e.scorePayment>0?(l(),d("div",ce,"评分: "+a(e.scorePayment),1)):c("",!0),e.couponPayment&&e.couponPayment>0?(l(),d("div",re,"优惠券: ¥"+a((p=e.couponPayment)==null?void 0:p.toFixed(2)),1)):c("",!0)])]}),_:1}),s(r,{label:"状态",width:"100",align:"center"},{default:n(({row:e})=>[s(F,{type:S(e.status),size:"small"},{default:n(()=>[g(a(e.statusName),1)]),_:2},1032,["type"])]),_:1}),s(r,{label:"时间","min-width":"160"},{default:n(({row:e})=>[t("div",ue,[t("div",null,"下单: "+a(e.createdAt),1),e.payTime?(l(),d("div",_e,"支付: "+a(e.payTime),1)):c("",!0)])]),_:1}),s(r,{label:"操作",width:"120",fixed:"right",align:"center"},{default:n(({row:e})=>[s(D,{type:"primary",link:"",onClick:_=>B(e)},{default:n(()=>[...o[5]||(o[5]=[g(" 查看详情 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[M,v.loading]]),s(O,{"current-page":f.value,"onUpdate:currentPage":o[0]||(o[0]=e=>f.value=e),"page-size":b.value,"onUpdate:pageSize":o[1]||(o[1]=e=>b.value=e),"page-sizes":[10,20,50,100],total:v.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:T,onCurrentChange:N,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),ve=J(me,[["__scopeId","data-v-3010f6cf"]]);export{ve as default};

View File

@ -0,0 +1 @@
import{_ as o}from"./CouponFormDialog.vue_vue_type_script_setup_true_lang-Rxwnl7jf.js";import"./coupon--n92Yf2J.js";import"./index-C-IfdMnF.js";export{o as default};

View File

@ -0,0 +1 @@
import{C as x,a as C,b as z,c as G,u as M,e as S}from"./coupon--n92Yf2J.js";import{d as A,v as H,r as D,a as I,G as J,g as u,z as b,k as m,w as o,e as i,c as k,F as U,y as E,l as F,t as d,E as q}from"./index-C-IfdMnF.js";const W=A({__name:"CouponFormDialog",props:{modelValue:{type:Boolean},coupon:{},isEdit:{type:Boolean}},emits:["update:modelValue","success"],setup(V,{emit:N}){const a=V,v=N,c=H({get:()=>a.modelValue,set:s=>v("update:modelValue",s)}),p=D(),f=D(!1),t=I({title:"",minPrice:0,discountPrice:0,validDays:7,type:C.FullReduction,useLimit:x.NoLimit}),B={title:[{required:!0,message:"请输入优惠券名称",trigger:"blur"},{min:1,max:50,message:"名称长度在1-50个字符",trigger:"blur"}],type:[{required:!0,message:"请选择优惠券类型",trigger:"change"}],useLimit:[{required:!0,message:"请选择使用限制",trigger:"change"}],minPrice:[{required:!0,message:"请输入满减门槛",trigger:"blur"},{type:"number",min:0,message:"满减门槛不能为负数",trigger:"blur"}],discountPrice:[{required:!0,message:"请输入优惠金额",trigger:"blur"},{type:"number",min:.01,message:"优惠金额必须大于0",trigger:"blur"}],validDays:[{required:!0,message:"请输入有效期",trigger:"blur"},{type:"number",min:1,max:365,message:"有效期在1-365天之间",trigger:"blur"}]};J(()=>a.modelValue,s=>{s&&(a.isEdit&&a.coupon?Object.assign(t,{title:a.coupon.title,minPrice:a.coupon.minPrice,discountPrice:a.coupon.discountPrice,validDays:a.coupon.validDays,type:a.coupon.type,useLimit:a.coupon.useLimit}):_())});const _=()=>{var s;Object.assign(t,{title:"",minPrice:0,discountPrice:0,validDays:7,type:C.FullReduction,useLimit:x.NoLimit}),(s=p.value)==null||s.resetFields()},g=()=>{c.value=!1,_()},R=async()=>{if(p.value){try{await p.value.validate()}catch{return}f.value=!0;try{const s={title:t.title,minPrice:t.minPrice,discountPrice:t.discountPrice,validDays:t.validDays,type:t.type,useLimit:t.useLimit};a.isEdit&&a.coupon?(await M(a.coupon.id,s),q.success("更新成功")):(await S(s),q.success("创建成功")),v("success"),g()}finally{f.value=!1}}};return(s,e)=>{const P=u("el-option"),L=u("el-select"),n=u("el-form-item"),T=u("el-input"),y=u("el-input-number"),j=u("el-form"),w=u("el-button"),O=u("el-dialog");return m(),b(O,{modelValue:c.value,"onUpdate:modelValue":e[6]||(e[6]=l=>c.value=l),title:V.isEdit?"编辑优惠券":"新增优惠券",width:"550px","close-on-click-modal":!1,onClose:g},{footer:o(()=>[i(w,{onClick:g},{default:o(()=>[...e[10]||(e[10]=[d("取消",-1)])]),_:1}),i(w,{type:"primary",loading:f.value,onClick:R},{default:o(()=>[...e[11]||(e[11]=[d(" 确定 ",-1)])]),_:1},8,["loading"])]),default:o(()=>[i(j,{ref_key:"formRef",ref:p,model:t,rules:B,"label-width":"100px"},{default:o(()=>[i(n,{label:"优惠券类型",prop:"type"},{default:o(()=>[i(L,{modelValue:t.type,"onUpdate:modelValue":e[0]||(e[0]=l=>t.type=l),placeholder:"请选择类型",style:{width:"100%"}},{default:o(()=>[(m(!0),k(U,null,E(F(z),(l,r)=>(m(),b(P,{key:r,label:l,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),i(n,{label:"使用限制",prop:"useLimit"},{default:o(()=>[i(L,{modelValue:t.useLimit,"onUpdate:modelValue":e[1]||(e[1]=l=>t.useLimit=l),placeholder:"请选择使用限制",style:{width:"100%"}},{default:o(()=>[(m(!0),k(U,null,E(F(G),(l,r)=>(m(),b(P,{key:r,label:l,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),i(n,{label:"优惠券名称",prop:"title"},{default:o(()=>[i(T,{modelValue:t.title,"onUpdate:modelValue":e[2]||(e[2]=l=>t.title=l),placeholder:"请输入优惠券名称",maxlength:"50","show-word-limit":""},null,8,["modelValue"])]),_:1}),i(n,{label:"满减门槛",prop:"minPrice"},{default:o(()=>[i(y,{modelValue:t.minPrice,"onUpdate:modelValue":e[3]||(e[3]=l=>t.minPrice=l),min:0,max:999999,precision:2,placeholder:"请输入满减门槛",style:{width:"100%"}},{suffix:o(()=>[...e[7]||(e[7]=[d("元",-1)])]),_:1},8,["modelValue"])]),_:1}),i(n,{label:"优惠金额",prop:"discountPrice"},{default:o(()=>[i(y,{modelValue:t.discountPrice,"onUpdate:modelValue":e[4]||(e[4]=l=>t.discountPrice=l),min:.01,max:999999,precision:2,placeholder:"请输入优惠金额",style:{width:"100%"}},{suffix:o(()=>[...e[8]||(e[8]=[d("元",-1)])]),_:1},8,["modelValue"])]),_:1}),i(n,{label:"有效期",prop:"validDays"},{default:o(()=>[i(y,{modelValue:t.validDays,"onUpdate:modelValue":e[5]||(e[5]=l=>t.validDays=l),min:1,max:365,placeholder:"请输入有效期天数",style:{width:"100%"}},{suffix:o(()=>[...e[9]||(e[9]=[d("天",-1)])]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue","title"])}}});export{W as _};

View File

@ -0,0 +1 @@
.search-form[data-v-a394cb85]{margin-bottom:16px}

View File

@ -0,0 +1 @@
import{d as v,a as x,g as n,z as f,k as d,w as t,e as o,f as F,c as B,F as N,y as S,l as p,t as y,T,s as g,_ as K}from"./index-C-IfdMnF.js";import{b as L}from"./coupon--n92Yf2J.js";const U=v({__name:"CouponSearchForm",emits:["search","reset"],setup(z,{emit:k}){const m=k,e=x({keyword:"",type:void 0}),u=()=>{const r={};e.keyword&&(r.keyword=e.keyword),e.type!==void 0&&(r.type=e.type),m("search",r)},w=()=>{e.keyword="",e.type=void 0,m("reset")};return(r,l)=>{const b=n("el-input"),s=n("el-form-item"),h=n("el-option"),C=n("el-select"),c=n("el-icon"),_=n("el-button"),V=n("el-form");return d(),f(V,{inline:!0,model:e,class:"search-form"},{default:t(()=>[o(s,{label:"标题关键词"},{default:t(()=>[o(b,{modelValue:e.keyword,"onUpdate:modelValue":l[0]||(l[0]=a=>e.keyword=a),placeholder:"请输入优惠券标题",clearable:"",onKeyup:F(u,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),o(s,{label:"优惠券类型"},{default:t(()=>[o(C,{modelValue:e.type,"onUpdate:modelValue":l[1]||(l[1]=a=>e.type=a),placeholder:"全部类型",clearable:"",style:{width:"140px"}},{default:t(()=>[(d(!0),B(N,null,S(p(L),(a,i)=>(d(),f(h,{key:i,label:a,value:Number(i)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),o(s,null,{default:t(()=>[o(_,{type:"primary",onClick:u},{default:t(()=>[o(c,null,{default:t(()=>[o(p(T))]),_:1}),l[2]||(l[2]=y("查询 ",-1))]),_:1}),o(_,{onClick:w},{default:t(()=>[o(c,null,{default:t(()=>[o(p(g))]),_:1}),l[3]||(l[3]=y("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),R=K(U,[["__scopeId","data-v-a394cb85"]]);export{R as default};

View File

@ -0,0 +1 @@
import{b as U,a as _,c as E}from"./coupon--n92Yf2J.js";import{d as F,r as f,G as y,g as c,J as V,c as I,k as C,K as $,e as a,z as j,w as n,b,x as s,t as r,_ as q}from"./index-C-IfdMnF.js";const A={class:"coupon-table"},G={class:"money"},J={class:"discount"},K=F({__name:"CouponTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","delete"],setup(d,{emit:v}){const p=d,u=v,g=f(p.page),m=f(p.pageSize);y(()=>p.page,t=>{g.value=t}),y(()=>p.pageSize,t=>{m.value=t});const z=t=>U[t]||"未知类型",w=t=>{switch(t){case _.NewUser:return"success";case _.Equity:return"warning";case _.FullReduction:return"";default:return"info"}},k=t=>E[t]||"不限制",x=t=>{u("page-change",t)},T=t=>{u("size-change",t)},N=t=>{u("edit",t)},S=t=>{u("delete",t)};return(t,o)=>{const l=c("el-table-column"),D=c("el-tag"),h=c("el-button"),L=c("el-table"),P=c("el-pagination"),B=V("loading");return C(),I("div",A,[$((C(),j(L,{data:d.data,border:"",stripe:""},{default:n(()=>[a(l,{prop:"id",label:"ID",width:"80",align:"center"}),a(l,{prop:"title",label:"优惠券名称","min-width":"150"}),a(l,{label:"满减门槛",width:"100",align:"right"},{default:n(({row:e})=>{var i;return[b("span",G,"¥"+s(((i=e.minPrice)==null?void 0:i.toFixed(2))||"0.00"),1)]}),_:1}),a(l,{label:"优惠金额",width:"100",align:"right"},{default:n(({row:e})=>{var i;return[b("span",J,"¥"+s(((i=e.discountPrice)==null?void 0:i.toFixed(2))||"0.00"),1)]}),_:1}),a(l,{label:"有效期",width:"100",align:"center"},{default:n(({row:e})=>[r(s(e.validDays)+"天 ",1)]),_:1}),a(l,{label:"类型",width:"120",align:"center"},{default:n(({row:e})=>[a(D,{type:w(e.type),size:"small"},{default:n(()=>[r(s(e.typeName||z(e.type)),1)]),_:2},1032,["type"])]),_:1}),a(l,{label:"使用限制",width:"100",align:"center"},{default:n(({row:e})=>[b("span",null,s(e.useLimitName||k(e.useLimit)),1)]),_:1}),a(l,{label:"创建时间",width:"160",align:"center"},{default:n(({row:e})=>[r(s(e.createdAt||"-"),1)]),_:1}),a(l,{label:"操作",width:"150",align:"center",fixed:"right"},{default:n(({row:e})=>[a(h,{type:"primary",link:"",size:"small",onClick:i=>N(e)},{default:n(()=>[...o[2]||(o[2]=[r(" 编辑 ",-1)])]),_:1},8,["onClick"]),a(h,{type:"danger",link:"",size:"small",onClick:i=>S(e)},{default:n(()=>[...o[3]||(o[3]=[r(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[B,d.loading]]),a(P,{"current-page":g.value,"onUpdate:currentPage":o[0]||(o[0]=e=>g.value=e),"page-size":m.value,"onUpdate:pageSize":o[1]||(o[1]=e=>m.value=e),"page-sizes":[10,20,50,100],total:d.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:T,onCurrentChange:x,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),M=q(K,[["__scopeId","data-v-d396bd83"]]);export{M as default};

View File

@ -0,0 +1 @@
.coupon-table[data-v-d396bd83]{width:100%}.money[data-v-d396bd83]{color:#909399}.discount[data-v-d396bd83]{color:#e6a23c;font-weight:500}.pagination[data-v-d396bd83]{margin-top:16px;justify-content:flex-end}

View File

@ -0,0 +1 @@
.currency-info-card[data-v-56649aa2]{height:100%}.card-header[data-v-56649aa2]{display:flex;justify-content:space-between;align-items:center}.card-title[data-v-56649aa2]{font-size:16px;font-weight:600;color:var(--el-text-color-primary)}.stats-grid[data-v-56649aa2]{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}.stat-item[data-v-56649aa2]{padding:12px;background:var(--el-fill-color-light);border-radius:8px;text-align:center;transition:all .3s ease}.stat-item[data-v-56649aa2]:hover{background:var(--el-fill-color);transform:translateY(-2px)}.stat-label[data-v-56649aa2]{font-size:12px;color:var(--el-text-color-secondary);margin-bottom:8px}.stat-value[data-v-56649aa2]{font-size:18px;font-weight:600;color:var(--el-text-color-primary)}.stat-value.add[data-v-56649aa2]{color:var(--el-color-success)}.stat-value.use[data-v-56649aa2]{color:var(--el-color-warning)}.error-message[data-v-56649aa2]{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:16px;padding:12px;background:var(--el-color-danger-light-9);border-radius:4px;color:var(--el-color-danger);font-size:14px}@media(max-width:768px){.stats-grid[data-v-56649aa2]{grid-template-columns:repeat(2,1fr)}.stat-value[data-v-56649aa2]{font-size:16px}}@media(max-width:480px){.stats-grid[data-v-56649aa2]{grid-template-columns:1fr}}

View File

@ -0,0 +1 @@
import{d as A,r as _,a as I,o as C,g as y,J as h,K as k,z as w,k as m,w as r,b as s,c as x,H as N,x as d,l as a,e as u,a2 as D,s as B,t as E,E as V,_ as j}from"./index-C-IfdMnF.js";import{g as O}from"./statistics-m3Qi5dJo.js";import{f as l}from"./format-Dmin6C3l.js";const S={class:"card-header"},z={class:"stats-grid"},H={class:"stat-item"},J={class:"stat-value add"},K={class:"stat-item"},R={class:"stat-value use"},T={class:"stat-item"},q={class:"stat-value add"},F={class:"stat-item"},G={class:"stat-value use"},L={class:"stat-item"},P={class:"stat-value add"},Q={class:"stat-item"},W={class:"stat-value use"},X={class:"stat-item"},Y={class:"stat-value add"},Z={class:"stat-item"},$={class:"stat-value use"},ss={class:"stat-item"},ts={class:"stat-value add"},es={class:"stat-item"},as={class:"stat-value use"},ds={class:"stat-item"},os={class:"stat-value add"},ls={class:"stat-item"},ns={class:"stat-value use"},is={key:0,class:"error-message"},rs=A({__name:"CurrencyInfoCard",setup(cs,{expose:f}){const i=_(!1),n=_(null),c={todayAddMoney:0,todayUseMoney:0,yesterdayAddMoney:0,yesterdayUseMoney:0,todayAddIntegral:0,todayUseIntegral:0,yesterdayAddIntegral:0,yesterdayUseIntegral:0,todayAddMoney2:0,todayUseMoney2:0,yesterdayAddMoney2:0,yesterdayUseMoney2:0},e=I({...c});async function v(){i.value=!0,n.value=null;try{const o=await O();o.code===0&&o.data?Object.assign(e,o.data):(n.value=o.message||"获取数据失败",Object.assign(e,c))}catch(o){console.error("加载货币信息数据失败:",o),o instanceof Error?o.message.includes("403")||o.message.includes("权限")?n.value="无权限访问此页面":o.message.includes("network")||o.message.includes("Network")?n.value="网络连接失败,请检查网络":n.value="服务器繁忙,请稍后重试":n.value="获取数据失败",Object.assign(e,c)}finally{i.value=!1}}function g(){v(),V.info("正在刷新数据...")}return C(()=>{v()}),f({refresh:v}),(o,t)=>{const p=y("el-button"),U=y("el-icon"),b=y("el-card"),M=h("loading");return k((m(),w(b,{class:"currency-info-card"},{header:r(()=>[s("div",S,[t[1]||(t[1]=s("span",{class:"card-title"},"今日货币信息",-1)),u(p,{type:"primary",link:"",icon:a(B),onClick:g,loading:i.value},{default:r(()=>[...t[0]||(t[0]=[E(" 刷新 ",-1)])]),_:1},8,["icon","loading"])])]),default:r(()=>[s("div",z,[s("div",H,[t[2]||(t[2]=s("div",{class:"stat-label"},"今日发放钻石",-1)),s("div",J,d(a(l)(e.todayAddMoney)),1)]),s("div",K,[t[3]||(t[3]=s("div",{class:"stat-label"},"今日消费钻石",-1)),s("div",R,d(a(l)(e.todayUseMoney)),1)]),s("div",T,[t[4]||(t[4]=s("div",{class:"stat-label"},"昨日发放钻石",-1)),s("div",q,d(a(l)(e.yesterdayAddMoney)),1)]),s("div",F,[t[5]||(t[5]=s("div",{class:"stat-label"},"昨日消费钻石",-1)),s("div",G,d(a(l)(e.yesterdayUseMoney)),1)]),s("div",L,[t[6]||(t[6]=s("div",{class:"stat-label"},"今日发放UU币",-1)),s("div",P,d(a(l)(e.todayAddIntegral)),1)]),s("div",Q,[t[7]||(t[7]=s("div",{class:"stat-label"},"今日消费UU币",-1)),s("div",W,d(a(l)(e.todayUseIntegral)),1)]),s("div",X,[t[8]||(t[8]=s("div",{class:"stat-label"},"昨日发放UU币",-1)),s("div",Y,d(a(l)(e.yesterdayAddIntegral)),1)]),s("div",Z,[t[9]||(t[9]=s("div",{class:"stat-label"},"昨日消费UU币",-1)),s("div",$,d(a(l)(e.yesterdayUseIntegral)),1)]),s("div",ss,[t[10]||(t[10]=s("div",{class:"stat-label"},"今日发放达达券",-1)),s("div",ts,d(a(l)(e.todayAddMoney2)),1)]),s("div",es,[t[11]||(t[11]=s("div",{class:"stat-label"},"今日消费达达券",-1)),s("div",as,d(a(l)(e.todayUseMoney2)),1)]),s("div",ds,[t[12]||(t[12]=s("div",{class:"stat-label"},"昨日发放达达券",-1)),s("div",os,d(a(l)(e.yesterdayAddMoney2)),1)]),s("div",ls,[t[13]||(t[13]=s("div",{class:"stat-label"},"昨日消费达达券",-1)),s("div",ns,d(a(l)(e.yesterdayUseMoney2)),1)])]),n.value?(m(),x("div",is,[u(U,null,{default:r(()=>[u(a(D))]),_:1}),s("span",null,d(n.value),1)])):N("",!0)]),_:1})),[[M,i.value]])}}}),_s=j(rs,[["__scopeId","data-v-56649aa2"]]);export{_s as default};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.editor-container[data-v-a99f3b28]{width:100%;border:1px solid #dcdfe6;border-radius:4px;overflow:hidden}.editor-toolbar[data-v-a99f3b28]{padding:8px;background:#f5f7fa;border-bottom:1px solid #dcdfe6;display:flex;flex-wrap:wrap;gap:4px}.editor-textarea[data-v-a99f3b28] .el-textarea__inner{border:none;border-radius:0;min-height:300px!important;font-family:monospace}.editor-preview[data-v-a99f3b28]{min-height:300px;padding:12px;background:#fff;overflow:auto}.editor-preview[data-v-a99f3b28] img{max-width:100%;height:auto}.form-tip[data-v-a99f3b28]{font-size:12px;color:#909399;margin-top:4px}

View File

@ -0,0 +1 @@
import{d as w,g as o,J as x,c as k,k as r,K as y,z as C,w as a,e as t,b as z,x as _,t as p,_ as D}from"./index-C-IfdMnF.js";const B={class:"danye-table"},T=w({__name:"DanyeTable",props:{data:{},loading:{type:Boolean}},emits:["edit","toggle-optimizer"],setup(s,{emit:m}){const c=m,g=n=>{c("edit",n)},u=(n,i)=>{c("toggle-optimizer",n,i)};return(n,i)=>{const l=o("el-table-column"),b=o("el-switch"),h=o("el-button"),f=o("el-table"),v=x("loading");return r(),k("div",B,[y((r(),C(f,{data:s.data,border:"",stripe:""},{default:a(()=>[t(l,{prop:"id",label:"ID",width:"80",align:"center"}),t(l,{prop:"title",label:"标题","min-width":"200"},{default:a(({row:e})=>[z("span",null,_(e.title),1)]),_:1}),t(l,{label:"图片优化",width:"120",align:"center"},{default:a(({row:e})=>[t(b,{"model-value":e.isImageOptimizer,onChange:d=>u(e,d),"active-text":"开","inactive-text":"关","inline-prompt":""},null,8,["model-value","onChange"])]),_:1}),t(l,{label:"更新时间",width:"180",align:"center"},{default:a(({row:e})=>[p(_(e.updateTime||"-"),1)]),_:1}),t(l,{label:"操作",width:"100",align:"center",fixed:"right"},{default:a(({row:e})=>[t(h,{type:"primary",link:"",size:"small",onClick:d=>g(e)},{default:a(()=>[...i[0]||(i[0]=[p(" 编辑 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[v,s.loading]])])}}}),N=D(T,[["__scopeId","data-v-a0cfe3e4"]]);export{N as default};

View File

@ -0,0 +1 @@
.danye-table[data-v-a0cfe3e4]{width:100%}

View File

@ -1 +1 @@
import{d as x,a as y,g as a,z as k,k as w,w as l,e,f as C,t as i,l as p,Q as F,s as S,_ as B}from"./index-DlmlUUdG.js";const D=x({__name:"DiamondSearchForm",emits:["search","reset"],setup(K,{emit:f}){const r=f,t=y({name:"",status:void 0}),u=()=>{const n={};t.name&&(n.name=t.name),t.status!==void 0&&(n.status=t.status),r("search",n)},h=()=>{t.name="",t.status=void 0,r("reset")};return(n,o)=>{const b=a("el-input"),s=a("el-form-item"),d=a("el-option"),v=a("el-select"),_=a("el-icon"),c=a("el-button"),V=a("el-form");return w(),k(V,{inline:!0,model:t,class:"search-form"},{default:l(()=>[e(s,{label:"商品名称"},{default:l(()=>[e(b,{modelValue:t.name,"onUpdate:modelValue":o[0]||(o[0]=m=>t.name=m),placeholder:"请输入商品名称",clearable:"",onKeyup:C(u,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),e(s,{label:"状态"},{default:l(()=>[e(v,{modelValue:t.status,"onUpdate:modelValue":o[1]||(o[1]=m=>t.status=m),placeholder:"全部状态",clearable:"",style:{width:"120px"}},{default:l(()=>[e(d,{label:"启用",value:1}),e(d,{label:"禁用",value:0})]),_:1},8,["modelValue"])]),_:1}),e(s,null,{default:l(()=>[e(c,{type:"primary",onClick:u},{default:l(()=>[e(_,null,{default:l(()=>[e(p(F))]),_:1}),o[2]||(o[2]=i("查询 ",-1))]),_:1}),e(c,{onClick:h},{default:l(()=>[e(_,null,{default:l(()=>[e(p(S))]),_:1}),o[3]||(o[3]=i("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),U=B(D,[["__scopeId","data-v-328e75c4"]]);export{U as default};
import{d as x,a as y,g as a,z as k,k as w,w as l,e,f as C,t as i,l as p,T as F,s as S,_ as B}from"./index-C-IfdMnF.js";const D=x({__name:"DiamondSearchForm",emits:["search","reset"],setup(K,{emit:f}){const r=f,t=y({name:"",status:void 0}),u=()=>{const n={};t.name&&(n.name=t.name),t.status!==void 0&&(n.status=t.status),r("search",n)},h=()=>{t.name="",t.status=void 0,r("reset")};return(n,o)=>{const b=a("el-input"),s=a("el-form-item"),d=a("el-option"),v=a("el-select"),_=a("el-icon"),c=a("el-button"),V=a("el-form");return w(),k(V,{inline:!0,model:t,class:"search-form"},{default:l(()=>[e(s,{label:"商品名称"},{default:l(()=>[e(b,{modelValue:t.name,"onUpdate:modelValue":o[0]||(o[0]=m=>t.name=m),placeholder:"请输入商品名称",clearable:"",onKeyup:C(u,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),e(s,{label:"状态"},{default:l(()=>[e(v,{modelValue:t.status,"onUpdate:modelValue":o[1]||(o[1]=m=>t.status=m),placeholder:"全部状态",clearable:"",style:{width:"120px"}},{default:l(()=>[e(d,{label:"启用",value:1}),e(d,{label:"禁用",value:0})]),_:1},8,["modelValue"])]),_:1}),e(s,null,{default:l(()=>[e(c,{type:"primary",onClick:u},{default:l(()=>[e(_,null,{default:l(()=>[e(p(F))]),_:1}),o[2]||(o[2]=i("查询 ",-1))]),_:1}),e(c,{onClick:h},{default:l(()=>[e(_,null,{default:l(()=>[e(p(S))]),_:1}),o[3]||(o[3]=i("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),T=B(D,[["__scopeId","data-v-328e75c4"]]);export{T as default};

View File

@ -1 +0,0 @@
import{d as A,r as v,P as b,g as o,B as E,c as C,k as g,C as $,e as a,z,w as n,b as x,x as u,t as c,l as j,R as O,_ as R}from"./index-DlmlUUdG.js";const q={class:"diamond-table"},G={class:"money"},H={class:"image-error"},J={key:1,class:"text-muted"},K=A({__name:"DiamondTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","delete","status-change"],setup(d,{emit:y}){const p=d,r=y,_=v(p.page),m=v(p.pageSize);b(()=>p.page,t=>{_.value=t}),b(()=>p.pageSize,t=>{m.value=t});const h=t=>t.isFirst===1&&t.firstChargeImage?t.firstChargeImage:t.normalImage||"",k=t=>{r("page-change",t)},w=t=>{r("size-change",t)},S=t=>{r("edit",t)},D=t=>{r("delete",t)},I=(t,i)=>{r("status-change",t,i)};return(t,i)=>{const l=o("el-table-column"),V=o("el-tag"),B=o("el-icon"),P=o("el-image"),F=o("el-switch"),f=o("el-button"),U=o("el-table"),N=o("el-pagination"),T=E("loading");return g(),C("div",q,[$((g(),z(U,{data:d.data,border:"",stripe:""},{default:n(()=>[a(l,{prop:"id",label:"ID",width:"80",align:"center"}),a(l,{prop:"name",label:"商品名称","min-width":"120"}),a(l,{prop:"productsId",label:"商品编号",width:"120",align:"center"}),a(l,{prop:"price",label:"价格",width:"100",align:"right"},{default:n(({row:e})=>{var s;return[x("span",G,"¥"+u(((s=e.price)==null?void 0:s.toFixed(2))||"0.00"),1)]}),_:1}),a(l,{label:"是否首充",width:"90",align:"center"},{default:n(({row:e})=>[a(V,{type:e.isFirst===1?"success":"info",size:"small"},{default:n(()=>[c(u(e.isFirst===1?"是":"否"),1)]),_:2},1032,["type"])]),_:1}),a(l,{label:"展示图",width:"100",align:"center"},{default:n(({row:e})=>[h(e)?(g(),z(P,{key:0,src:h(e),"preview-src-list":[h(e)],fit:"cover",style:{width:"50px",height:"50px","border-radius":"4px"},"preview-teleported":""},{error:n(()=>[x("div",H,[a(B,null,{default:n(()=>[a(j(O))]),_:1})])]),_:1},8,["src","preview-src-list"])):(g(),C("span",J,"-"))]),_:1}),a(l,{prop:"sortOrder",label:"排序",width:"80",align:"center"}),a(l,{label:"状态",width:"90",align:"center"},{default:n(({row:e})=>[a(F,{modelValue:e.status,"onUpdate:modelValue":s=>e.status=s,"active-value":1,"inactive-value":0,onChange:s=>I(e,s)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),a(l,{label:"创建时间",width:"160",align:"center"},{default:n(({row:e})=>[c(u(e.createdAt||"-"),1)]),_:1}),a(l,{label:"更新时间",width:"160",align:"center"},{default:n(({row:e})=>[c(u(e.updatedAt||"-"),1)]),_:1}),a(l,{label:"操作",width:"150",align:"center",fixed:"right"},{default:n(({row:e})=>[a(f,{type:"primary",link:"",size:"small",onClick:s=>S(e)},{default:n(()=>[...i[2]||(i[2]=[c(" 编辑 ",-1)])]),_:1},8,["onClick"]),a(f,{type:"danger",link:"",size:"small",onClick:s=>D(e)},{default:n(()=>[...i[3]||(i[3]=[c(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[T,d.loading]]),a(N,{"current-page":_.value,"onUpdate:currentPage":i[0]||(i[0]=e=>_.value=e),"page-size":m.value,"onUpdate:pageSize":i[1]||(i[1]=e=>m.value=e),"page-sizes":[10,20,50,100],total:d.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:w,onCurrentChange:k,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),M=R(K,[["__scopeId","data-v-8e189c08"]]);export{M as default};

View File

@ -0,0 +1 @@
import{d as A,r as v,G as b,g as o,J as E,c as z,k as g,K as $,e as a,z as C,w as n,b as x,x as u,t as c,l as j,I as G,_ as J}from"./index-C-IfdMnF.js";const K={class:"diamond-table"},O={class:"money"},q={class:"image-error"},H={key:1,class:"text-muted"},L=A({__name:"DiamondTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","delete","status-change"],setup(d,{emit:y}){const p=d,r=y,_=v(p.page),m=v(p.pageSize);b(()=>p.page,t=>{_.value=t}),b(()=>p.pageSize,t=>{m.value=t});const h=t=>t.isFirst===1&&t.firstChargeImage?t.firstChargeImage:t.normalImage||"",k=t=>{r("page-change",t)},w=t=>{r("size-change",t)},S=t=>{r("edit",t)},D=t=>{r("delete",t)},I=(t,i)=>{r("status-change",t,i)};return(t,i)=>{const l=o("el-table-column"),V=o("el-tag"),B=o("el-icon"),F=o("el-image"),P=o("el-switch"),f=o("el-button"),U=o("el-table"),N=o("el-pagination"),T=E("loading");return g(),z("div",K,[$((g(),C(U,{data:d.data,border:"",stripe:""},{default:n(()=>[a(l,{prop:"id",label:"ID",width:"80",align:"center"}),a(l,{prop:"name",label:"商品名称","min-width":"120"}),a(l,{prop:"productsId",label:"商品编号",width:"120",align:"center"}),a(l,{prop:"price",label:"价格",width:"100",align:"right"},{default:n(({row:e})=>{var s;return[x("span",O,"¥"+u(((s=e.price)==null?void 0:s.toFixed(2))||"0.00"),1)]}),_:1}),a(l,{label:"是否首充",width:"90",align:"center"},{default:n(({row:e})=>[a(V,{type:e.isFirst===1?"success":"info",size:"small"},{default:n(()=>[c(u(e.isFirst===1?"是":"否"),1)]),_:2},1032,["type"])]),_:1}),a(l,{label:"展示图",width:"100",align:"center"},{default:n(({row:e})=>[h(e)?(g(),C(F,{key:0,src:h(e),"preview-src-list":[h(e)],fit:"cover",style:{width:"50px",height:"50px","border-radius":"4px"},"preview-teleported":""},{error:n(()=>[x("div",q,[a(B,null,{default:n(()=>[a(j(G))]),_:1})])]),_:1},8,["src","preview-src-list"])):(g(),z("span",H,"-"))]),_:1}),a(l,{prop:"sortOrder",label:"排序",width:"80",align:"center"}),a(l,{label:"状态",width:"90",align:"center"},{default:n(({row:e})=>[a(P,{modelValue:e.status,"onUpdate:modelValue":s=>e.status=s,"active-value":1,"inactive-value":0,onChange:s=>I(e,s)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),a(l,{label:"创建时间",width:"160",align:"center"},{default:n(({row:e})=>[c(u(e.createdAt||"-"),1)]),_:1}),a(l,{label:"更新时间",width:"160",align:"center"},{default:n(({row:e})=>[c(u(e.updatedAt||"-"),1)]),_:1}),a(l,{label:"操作",width:"150",align:"center",fixed:"right"},{default:n(({row:e})=>[a(f,{type:"primary",link:"",size:"small",onClick:s=>S(e)},{default:n(()=>[...i[2]||(i[2]=[c(" 编辑 ",-1)])]),_:1},8,["onClick"]),a(f,{type:"danger",link:"",size:"small",onClick:s=>D(e)},{default:n(()=>[...i[3]||(i[3]=[c(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[T,d.loading]]),a(N,{"current-page":_.value,"onUpdate:currentPage":i[0]||(i[0]=e=>_.value=e),"page-size":m.value,"onUpdate:pageSize":i[1]||(i[1]=e=>m.value=e),"page-sizes":[10,20,50,100],total:d.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:w,onCurrentChange:k,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),Q=J(L,[["__scopeId","data-v-8e189c08"]]);export{Q as default};

View File

@ -0,0 +1 @@
.image-upload-container[data-v-c308e8cc]{display:flex;gap:12px;align-items:flex-start}.preview-image[data-v-c308e8cc]{width:60px;height:60px;border-radius:4px;flex-shrink:0}.image-error[data-v-c308e8cc]{display:flex;justify-content:center;align-items:center;width:60px;height:60px;background:#f5f7fa;color:#909399;font-size:18px}[data-v-c308e8cc] .el-divider__text{font-size:13px;color:#606266}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.floatball-table[data-v-003b6c43]{width:100%}.table-image[data-v-003b6c43]{width:60px;height:60px;border-radius:4px}.image-error[data-v-003b6c43]{display:flex;justify-content:center;align-items:center;width:60px;height:60px;background:#f5f7fa;color:#909399;font-size:18px}.no-image[data-v-003b6c43]{color:#909399;font-size:12px}.url-text[data-v-003b6c43]{color:#409eff;word-break:break-all;font-size:12px}.pagination[data-v-003b6c43]{margin-top:16px;justify-content:flex-end}

View File

@ -0,0 +1 @@
import{d as J,r as B,G as x,g as c,J as L,c as d,k as s,K as $,e as t,z as f,w as a,t as p,x as o,b as _,l as r,I as k,_ as A}from"./index-C-IfdMnF.js";import{a as S,d as G,F as K,b as X}from"./floatball-PNgSvdp6.js";const Y={class:"floatball-table"},q={class:"image-error"},H={key:1,class:"no-image"},M={class:"image-error"},O={key:1,class:"no-image"},Q={class:"image-error"},R={key:1,class:"no-image"},W={key:0,class:"url-text"},Z={key:1,class:"no-image"},ee=J({__name:"FloatBallTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","delete","status-change"],setup(u,{emit:D}){const m=u,g=D,h=B(m.page),v=B(m.pageSize);x(()=>m.page,l=>{h.value=l}),x(()=>m.pageSize,l=>{v.value=l});const F=l=>{g("page-change",l)},P=l=>{g("size-change",l)},T=l=>{g("edit",l)},j=l=>{g("delete",l)},E=(l,i)=>{g("status-change",l,i)};return(l,i)=>{const n=c("el-table-column"),b=c("el-icon"),y=c("el-image"),w=c("el-tag"),I=c("el-switch"),C=c("el-button"),U=c("el-table"),N=c("el-pagination"),V=L("loading");return s(),d("div",Y,[$((s(),f(U,{data:u.data,border:"",stripe:""},{default:a(()=>[t(n,{prop:"id",label:"ID",width:"70",align:"center"}),t(n,{prop:"title",label:"标题",width:"120",align:"center"},{default:a(({row:e})=>[p(o(e.title||"-"),1)]),_:1}),t(n,{label:"悬浮球图片",width:"100",align:"center"},{default:a(({row:e})=>[e.image?(s(),f(y,{key:0,src:e.image,"preview-src-list":[e.image],fit:"cover",class:"table-image","preview-teleported":"",lazy:""},{error:a(()=>[_("div",q,[t(b,null,{default:a(()=>[t(r(k))]),_:1})])]),_:1},8,["src","preview-src-list"])):(s(),d("span",H,"-"))]),_:1}),t(n,{label:"背景图",width:"100",align:"center"},{default:a(({row:e})=>[e.imageBj?(s(),f(y,{key:0,src:e.imageBj,"preview-src-list":[e.imageBj],fit:"cover",class:"table-image","preview-teleported":"",lazy:""},{error:a(()=>[_("div",M,[t(b,null,{default:a(()=>[t(r(k))]),_:1})])]),_:1},8,["src","preview-src-list"])):(s(),d("span",O,"-"))]),_:1}),t(n,{label:"详情图",width:"100",align:"center"},{default:a(({row:e})=>[e.imageDetails?(s(),f(y,{key:0,src:e.imageDetails,"preview-src-list":[e.imageDetails],fit:"cover",class:"table-image","preview-teleported":"",lazy:""},{error:a(()=>[_("div",Q,[t(b,null,{default:a(()=>[t(r(k))]),_:1})])]),_:1},8,["src","preview-src-list"])):(s(),d("span",R,"-"))]),_:1}),t(n,{label:"类型",width:"100",align:"center"},{default:a(({row:e})=>[t(w,{type:e.type===r(S).ShowImage?"info":"primary",size:"small"},{default:a(()=>[p(o(r(G)[e.type]||"未知"),1)]),_:2},1032,["type"])]),_:1}),t(n,{label:"跳转链接","min-width":"150"},{default:a(({row:e})=>[e.type===r(S).JumpPage&&e.linkUrl?(s(),d("span",W,o(e.linkUrl),1)):(s(),d("span",Z,"-"))]),_:1}),t(n,{label:"位置",width:"100",align:"center"},{default:a(({row:e})=>[_("span",null,o(e.positionX)+", "+o(e.positionY),1)]),_:1}),t(n,{label:"尺寸",width:"100",align:"center"},{default:a(({row:e})=>[_("span",null,o(e.width)+" × "+o(e.height),1)]),_:1}),t(n,{label:"特效",width:"100",align:"center"},{default:a(({row:e})=>[t(w,{type:e.effect===r(K).Scale?"success":"info",size:"small"},{default:a(()=>[p(o(r(X)[e.effect]||"无特效"),1)]),_:2},1032,["type"])]),_:1}),t(n,{label:"状态",width:"90",align:"center"},{default:a(({row:e})=>[t(I,{"model-value":e.status===1,onChange:z=>E(e,z?1:0),"inline-prompt":"","active-text":"开","inactive-text":"关"},null,8,["model-value","onChange"])]),_:1}),t(n,{label:"创建时间",width:"160",align:"center"},{default:a(({row:e})=>[p(o(e.createdAt||"-"),1)]),_:1}),t(n,{label:"操作",width:"130",align:"center",fixed:"right"},{default:a(({row:e})=>[t(C,{type:"primary",link:"",size:"small",onClick:z=>T(e)},{default:a(()=>[...i[2]||(i[2]=[p(" 编辑 ",-1)])]),_:1},8,["onClick"]),t(C,{type:"danger",link:"",size:"small",onClick:z=>j(e)},{default:a(()=>[...i[3]||(i[3]=[p(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[V,u.loading]]),t(N,{"current-page":h.value,"onUpdate:currentPage":i[0]||(i[0]=e=>h.value=e),"page-size":v.value,"onUpdate:pageSize":i[1]||(i[1]=e=>v.value=e),"page-sizes":[10,20,50,100],total:u.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:P,onCurrentChange:F,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),le=A(ee,[["__scopeId","data-v-003b6c43"]]);export{le as default};

View File

@ -1 +0,0 @@
import{d as J,v as y,r as g,a as K,P as W,g as r,z as I,k as u,w as t,c,D,e as o,b as p,l as X,m as Y,x as s,F as m,y as Z,t as d,E as B,O as $,_ as ee}from"./index-DlmlUUdG.js";import{a as te}from"./user-C-g-VGDy.js";const ae={key:0,class:"user-info"},le={class:"user-detail"},oe={class:"nickname"},se={class:"uid"},ne={class:"coupon-option"},ue={class:"coupon-title"},ie={class:"coupon-value"},re={key:0,class:"quantity-tip"},de=J({__name:"GiftCouponDialog",props:{modelValue:{type:Boolean},user:{}},emits:["update:modelValue","success"],setup(_,{emit:U}){const k=_,L=U,b=y({get:()=>k.modelValue,set:a=>L("update:modelValue",a)}),V=g(),h=g(!1),x=g(!1),f=g([]),i=K({couponId:0,quantity:1}),z={couponId:[{required:!0,message:"请选择优惠券",trigger:"change"}],quantity:[{required:!0,message:"请输入赠送数量",trigger:"blur"},{type:"number",min:1,message:"数量必须大于0",trigger:"blur"}]},l=y(()=>f.value.find(a=>a.id===i.couponId)),E=y(()=>l.value?{1:"满减券",2:"折扣券",3:"无门槛券"}[l.value.type]||"未知":""),F=y(()=>{var a;return(a=l.value)!=null&&a.stock?l.value.stock:999}),M=async()=>{x.value=!0;try{const a=await $({url:"/admin/business/coupons/templates",method:"get",params:{status:1}});f.value=a.data||[]}catch(a){console.error("加载优惠券列表失败",a),f.value=[]}finally{x.value=!1}},O=()=>{var a;i.couponId=0,i.quantity=1,(a=V.value)==null||a.resetFields(),M()},C=()=>{b.value=!1},R=async()=>{var n;if(!k.user){B.warning("用户信息不存在");return}if(await((n=V.value)==null?void 0:n.validate())){h.value=!0;try{await te(k.user.id,i),B.success("赠送成功"),L("success"),C()}catch(q){B.error(q.message||"赠送失败")}finally{h.value=!1}}};return W(()=>i.couponId,()=>{i.quantity=1}),(a,n)=>{const q=r("el-icon"),T=r("el-avatar"),G=r("el-option"),S=r("el-select"),w=r("el-form-item"),v=r("el-descriptions-item"),P=r("el-descriptions"),Q=r("el-input-number"),j=r("el-form"),N=r("el-button"),A=r("el-dialog");return u(),I(A,{modelValue:b.value,"onUpdate:modelValue":n[2]||(n[2]=e=>b.value=e),title:"赠送优惠券",width:"600px","close-on-click-modal":!1,onClose:C,onOpen:O},{footer:t(()=>[o(N,{onClick:C},{default:t(()=>[...n[3]||(n[3]=[d("取消",-1)])]),_:1}),o(N,{type:"primary",onClick:R,loading:h.value},{default:t(()=>[...n[4]||(n[4]=[d("确定赠送",-1)])]),_:1},8,["loading"])]),default:t(()=>[_.user?(u(),c("div",ae,[o(T,{src:_.user.avatar,size:40},{default:t(()=>[o(q,null,{default:t(()=>[o(X(Y))]),_:1})]),_:1},8,["src"]),p("div",le,[p("div",oe,s(_.user.nickname||"-"),1),p("div",se,"UID: "+s(_.user.id),1)])])):D("",!0),o(j,{ref_key:"formRef",ref:V,model:i,rules:z,"label-width":"100px"},{default:t(()=>[o(w,{label:"选择优惠券",prop:"couponId"},{default:t(()=>[o(S,{modelValue:i.couponId,"onUpdate:modelValue":n[0]||(n[0]=e=>i.couponId=e),placeholder:"请选择优惠券",style:{width:"100%"},filterable:"",loading:x.value},{default:t(()=>[(u(!0),c(m,null,Z(f.value,e=>(u(),I(G,{key:e.id,label:e.title,value:e.id},{default:t(()=>[p("div",ne,[p("span",ue,s(e.title),1),p("span",ie,[e.type===1?(u(),c(m,{key:0},[d("满"+s(e.minMoney)+"减"+s(e.money),1)],64)):e.type===2?(u(),c(m,{key:1},[d(s(e.discount)+"折",1)],64)):(u(),c(m,{key:2},[d(s(e.money)+"元",1)],64))])])]),_:2},1032,["label","value"]))),128))]),_:1},8,["modelValue","loading"])]),_:1}),l.value?(u(),I(w,{key:0,label:"优惠券详情"},{default:t(()=>[o(P,{column:2,border:"",size:"small"},{default:t(()=>[o(v,{label:"名称"},{default:t(()=>[d(s(l.value.title),1)]),_:1}),o(v,{label:"类型"},{default:t(()=>[d(s(E.value),1)]),_:1}),o(v,{label:"面值"},{default:t(()=>[l.value.type===1?(u(),c(m,{key:0},[d("满"+s(l.value.minMoney)+"减"+s(l.value.money),1)],64)):l.value.type===2?(u(),c(m,{key:1},[d(s(l.value.discount)+"折",1)],64)):(u(),c(m,{key:2},[d(s(l.value.money)+"元",1)],64))]),_:1}),o(v,{label:"剩余数量"},{default:t(()=>[d(s(l.value.stock??"不限"),1)]),_:1})]),_:1})]),_:1})):D("",!0),o(w,{label:"赠送数量",prop:"quantity"},{default:t(()=>{var e;return[o(Q,{modelValue:i.quantity,"onUpdate:modelValue":n[1]||(n[1]=H=>i.quantity=H),min:1,max:F.value,style:{width:"200px"}},null,8,["modelValue","max"]),(e=l.value)!=null&&e.stock?(u(),c("span",re," (最多可赠送 "+s(l.value.stock)+" 张) ",1)):D("",!0)]}),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])}}}),pe=ee(de,[["__scopeId","data-v-5333f49e"]]);export{pe as default};

View File

@ -0,0 +1 @@
import{d as K,v as y,r as g,a as P,G as W,g as r,z as I,k as u,w as t,c,H as B,e as o,b as p,l as X,m as Y,x as s,F as m,y as Z,t as d,E as D,M as $,_ as ee}from"./index-C-IfdMnF.js";import{a as te}from"./user-fHRNfewZ.js";const ae={key:0,class:"user-info"},le={class:"user-detail"},oe={class:"nickname"},se={class:"uid"},ne={class:"coupon-option"},ue={class:"coupon-title"},ie={class:"coupon-value"},re={key:0,class:"quantity-tip"},de=K({__name:"GiftCouponDialog",props:{modelValue:{type:Boolean},user:{}},emits:["update:modelValue","success"],setup(_,{emit:N}){const k=_,L=N,b=y({get:()=>k.modelValue,set:a=>L("update:modelValue",a)}),V=g(),h=g(!1),x=g(!1),f=g([]),i=P({couponId:0,quantity:1}),U={couponId:[{required:!0,message:"请选择优惠券",trigger:"change"}],quantity:[{required:!0,message:"请输入赠送数量",trigger:"blur"},{type:"number",min:1,message:"数量必须大于0",trigger:"blur"}]},l=y(()=>f.value.find(a=>a.id===i.couponId)),z=y(()=>l.value?{1:"满减券",2:"折扣券",3:"无门槛券"}[l.value.type]||"未知":""),E=y(()=>{var a;return(a=l.value)!=null&&a.stock?l.value.stock:999}),F=async()=>{x.value=!0;try{const a=await $({url:"/admin/business/coupons/templates",method:"get",params:{status:1}});f.value=a.data||[]}catch(a){console.error("加载优惠券列表失败",a),f.value=[]}finally{x.value=!1}},G=()=>{var a;i.couponId=0,i.quantity=1,(a=V.value)==null||a.resetFields(),F()},C=()=>{b.value=!1},R=async()=>{var n;if(!k.user){D.warning("用户信息不存在");return}if(await((n=V.value)==null?void 0:n.validate())){h.value=!0;try{await te(k.user.id,i),D.success("赠送成功"),L("success"),C()}catch(q){D.error(q.message||"赠送失败")}finally{h.value=!1}}};return W(()=>i.couponId,()=>{i.quantity=1}),(a,n)=>{const q=r("el-icon"),T=r("el-avatar"),O=r("el-option"),S=r("el-select"),w=r("el-form-item"),v=r("el-descriptions-item"),H=r("el-descriptions"),Q=r("el-input-number"),j=r("el-form"),M=r("el-button"),A=r("el-dialog");return u(),I(A,{modelValue:b.value,"onUpdate:modelValue":n[2]||(n[2]=e=>b.value=e),title:"赠送优惠券",width:"600px","close-on-click-modal":!1,onClose:C,onOpen:G},{footer:t(()=>[o(M,{onClick:C},{default:t(()=>[...n[3]||(n[3]=[d("取消",-1)])]),_:1}),o(M,{type:"primary",onClick:R,loading:h.value},{default:t(()=>[...n[4]||(n[4]=[d("确定赠送",-1)])]),_:1},8,["loading"])]),default:t(()=>[_.user?(u(),c("div",ae,[o(T,{src:_.user.avatar,size:40},{default:t(()=>[o(q,null,{default:t(()=>[o(X(Y))]),_:1})]),_:1},8,["src"]),p("div",le,[p("div",oe,s(_.user.nickname||"-"),1),p("div",se,"UID: "+s(_.user.id),1)])])):B("",!0),o(j,{ref_key:"formRef",ref:V,model:i,rules:U,"label-width":"100px"},{default:t(()=>[o(w,{label:"选择优惠券",prop:"couponId"},{default:t(()=>[o(S,{modelValue:i.couponId,"onUpdate:modelValue":n[0]||(n[0]=e=>i.couponId=e),placeholder:"请选择优惠券",style:{width:"100%"},filterable:"",loading:x.value},{default:t(()=>[(u(!0),c(m,null,Z(f.value,e=>(u(),I(O,{key:e.id,label:e.title,value:e.id},{default:t(()=>[p("div",ne,[p("span",ue,s(e.title),1),p("span",ie,[e.type===1?(u(),c(m,{key:0},[d("满"+s(e.minMoney)+"减"+s(e.money),1)],64)):e.type===2?(u(),c(m,{key:1},[d(s(e.discount)+"折",1)],64)):(u(),c(m,{key:2},[d(s(e.money)+"元",1)],64))])])]),_:2},1032,["label","value"]))),128))]),_:1},8,["modelValue","loading"])]),_:1}),l.value?(u(),I(w,{key:0,label:"优惠券详情"},{default:t(()=>[o(H,{column:2,border:"",size:"small"},{default:t(()=>[o(v,{label:"名称"},{default:t(()=>[d(s(l.value.title),1)]),_:1}),o(v,{label:"类型"},{default:t(()=>[d(s(z.value),1)]),_:1}),o(v,{label:"面值"},{default:t(()=>[l.value.type===1?(u(),c(m,{key:0},[d("满"+s(l.value.minMoney)+"减"+s(l.value.money),1)],64)):l.value.type===2?(u(),c(m,{key:1},[d(s(l.value.discount)+"折",1)],64)):(u(),c(m,{key:2},[d(s(l.value.money)+"元",1)],64))]),_:1}),o(v,{label:"剩余数量"},{default:t(()=>[d(s(l.value.stock??"不限"),1)]),_:1})]),_:1})]),_:1})):B("",!0),o(w,{label:"赠送数量",prop:"quantity"},{default:t(()=>{var e;return[o(Q,{modelValue:i.quantity,"onUpdate:modelValue":n[1]||(n[1]=J=>i.quantity=J),min:1,max:E.value,style:{width:"200px"}},null,8,["modelValue","max"]),(e=l.value)!=null&&e.stock?(u(),c("span",re," (最多可赠送 "+s(l.value.stock)+" 张) ",1)):B("",!0)]}),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])}}}),pe=ee(de,[["__scopeId","data-v-5333f49e"]]);export{pe as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as w,a as C,g as s,z as f,k as r,w as l,e as t,f as F,c as g,F as B,y as S,t as y,l as v,Q as T,s as U,_ as G}from"./index-DlmlUUdG.js";const K=w({__name:"GoodsSearchForm",props:{goodsTypes:{}},emits:["search","reset"],setup(b,{emit:V}){const p=V,e=C({title:"",status:void 0,type:void 0}),i=()=>{const n={};e.title&&(n.title=e.title),e.status!==void 0&&(n.status=e.status),e.type!==void 0&&(n.type=e.type),p("search",n)},h=()=>{e.title="",e.status=void 0,e.type=void 0,p("reset")};return(n,o)=>{const x=s("el-input"),u=s("el-form-item"),d=s("el-option"),m=s("el-select"),c=s("el-icon"),_=s("el-button"),k=s("el-form");return r(),f(k,{inline:!0,model:e,class:"search-form"},{default:l(()=>[t(u,{label:"盒子标题"},{default:l(()=>[t(x,{modelValue:e.title,"onUpdate:modelValue":o[0]||(o[0]=a=>e.title=a),placeholder:"请输入盒子标题",clearable:"",onKeyup:F(i,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),t(u,{label:"状态"},{default:l(()=>[t(m,{modelValue:e.status,"onUpdate:modelValue":o[1]||(o[1]=a=>e.status=a),placeholder:"全部状态",clearable:"",style:{width:"120px"}},{default:l(()=>[t(d,{label:"上架",value:1}),t(d,{label:"下架",value:0}),t(d,{label:"售罄",value:2})]),_:1},8,["modelValue"])]),_:1}),t(u,{label:"盒子类型"},{default:l(()=>[t(m,{modelValue:e.type,"onUpdate:modelValue":o[2]||(o[2]=a=>e.type=a),placeholder:"全部类型",clearable:"",style:{width:"140px"}},{default:l(()=>[(r(!0),g(B,null,S(b.goodsTypes,a=>(r(),f(d,{key:a.value,label:a.name,value:a.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),t(u,null,{default:l(()=>[t(_,{type:"primary",onClick:i},{default:l(()=>[t(c,null,{default:l(()=>[t(v(T))]),_:1}),o[3]||(o[3]=y("查询 ",-1))]),_:1}),t(_,{onClick:h},{default:l(()=>[t(c,null,{default:l(()=>[t(v(U))]),_:1}),o[4]||(o[4]=y("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),z=G(K,[["__scopeId","data-v-af89f674"]]);export{z as default};
import{d as w,a as C,g as s,z as f,k as r,w as l,e as t,f as F,c as g,F as T,y as B,t as y,l as v,T as S,s as U,_ as G}from"./index-C-IfdMnF.js";const K=w({__name:"GoodsSearchForm",props:{goodsTypes:{}},emits:["search","reset"],setup(b,{emit:V}){const p=V,e=C({title:"",status:void 0,type:void 0}),i=()=>{const n={};e.title&&(n.title=e.title),e.status!==void 0&&(n.status=e.status),e.type!==void 0&&(n.type=e.type),p("search",n)},h=()=>{e.title="",e.status=void 0,e.type=void 0,p("reset")};return(n,o)=>{const x=s("el-input"),u=s("el-form-item"),d=s("el-option"),m=s("el-select"),c=s("el-icon"),_=s("el-button"),k=s("el-form");return r(),f(k,{inline:!0,model:e,class:"search-form"},{default:l(()=>[t(u,{label:"盒子标题"},{default:l(()=>[t(x,{modelValue:e.title,"onUpdate:modelValue":o[0]||(o[0]=a=>e.title=a),placeholder:"请输入盒子标题",clearable:"",onKeyup:F(i,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),t(u,{label:"状态"},{default:l(()=>[t(m,{modelValue:e.status,"onUpdate:modelValue":o[1]||(o[1]=a=>e.status=a),placeholder:"全部状态",clearable:"",style:{width:"120px"}},{default:l(()=>[t(d,{label:"上架",value:1}),t(d,{label:"下架",value:0}),t(d,{label:"售罄",value:2})]),_:1},8,["modelValue"])]),_:1}),t(u,{label:"盒子类型"},{default:l(()=>[t(m,{modelValue:e.type,"onUpdate:modelValue":o[2]||(o[2]=a=>e.type=a),placeholder:"全部类型",clearable:"",style:{width:"140px"}},{default:l(()=>[(r(!0),g(T,null,B(b.goodsTypes,a=>(r(),f(d,{key:a.value,label:a.name,value:a.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),t(u,null,{default:l(()=>[t(_,{type:"primary",onClick:i},{default:l(()=>[t(c,null,{default:l(()=>[t(v(S))]),_:1}),o[3]||(o[3]=y("查询 ",-1))]),_:1}),t(_,{onClick:h},{default:l(()=>[t(c,null,{default:l(()=>[t(v(U))]),_:1}),o[4]||(o[4]=y("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),z=G(K,[["__scopeId","data-v-af89f674"]]);export{z as default};

View File

@ -0,0 +1 @@
import{d as w,r as g,a as S,v as B,o as D,g as r,J as R,K as E,z as M,k as p,w as i,e as o,b as l,c as V,H as j,x as v,P as O,l as _,a2 as T,s as z,t as H,E as J,_ as K}from"./index-C-IfdMnF.js";import{a as P}from"./statistics-m3Qi5dJo.js";import{a as t}from"./format-Dmin6C3l.js";const q={class:"card-header"},A={class:"formula-section"},F={class:"formula-content"},G={key:0,class:"error-message"},L=w({__name:"IncomeSummaryCard",setup(Q,{expose:y}){const c=g(!1),s=g(null),m={todayIncome:0,rmbIncome:0,diamondIncome:0,otherIncome:0,shippedToday:0,expenses:0,todayShipped:0,remainingCoupon:0,boxRemaining:0,profit:0,formula:"收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余"},e=S({...m}),b=B(()=>[{category:"收入",item:"订单收入RMB+钻石)",value:t(e.todayIncome),isNegative:!1},{category:"收入",item:"RMB收入",value:t(e.rmbIncome),isNegative:!1},{category:"收入",item:"钻石商城收入",value:t(e.diamondIncome),isNegative:!1},{category:"收入",item:"其他收入",value:t(e.otherIncome),isNegative:!1},{category:"出货",item:"订单出货",value:t(e.shippedToday),isNegative:!1},{category:"支出",item:"支出",value:t(e.expenses),isNegative:!1},{category:"支出",item:"当天发货金额",value:t(e.todayShipped),isNegative:!1},{category:"支出",item:"当天用户剩余达达券",value:t(e.remainingCoupon),isNegative:!1},{category:"支出",item:"盒柜剩余价值",value:t(e.boxRemaining),isNegative:!1},{category:"利润",item:"利润",value:t(e.profit),isNegative:e.profit<0}]);async function d(){c.value=!0,s.value=null;try{const a=await P();a.code===0&&a.data?Object.assign(e,a.data):(s.value=a.message||"获取数据失败",Object.assign(e,m))}catch(a){console.error("加载收入汇总数据失败:",a),a instanceof Error?a.message.includes("403")||a.message.includes("权限")?s.value="无权限访问此页面":a.message.includes("network")||a.message.includes("Network")?s.value="网络连接失败,请检查网络":s.value="服务器繁忙,请稍后重试":s.value="获取数据失败",Object.assign(e,m)}finally{c.value=!1}}function h(){d(),J.info("正在刷新数据...")}return D(()=>{d()}),y({refresh:d}),(a,n)=>{const N=r("el-button"),u=r("el-table-column"),I=r("el-table"),x=r("el-icon"),C=r("el-card"),k=R("loading");return E((p(),M(C,{class:"income-summary-card"},{header:i(()=>[l("div",q,[n[1]||(n[1]=l("span",{class:"card-title"},"今日收入汇总",-1)),o(N,{type:"primary",link:"",icon:_(z),onClick:h,loading:c.value},{default:i(()=>[...n[0]||(n[0]=[H(" 刷新 ",-1)])]),_:1},8,["icon","loading"])])]),default:i(()=>[o(I,{data:b.value,border:"",stripe:"",class:"income-table"},{default:i(()=>[o(u,{prop:"category",label:"类别",width:"120"}),o(u,{prop:"item",label:"项目","min-width":"150"}),o(u,{prop:"value",label:"金额","min-width":"120",align:"right"},{default:i(({row:f})=>[l("span",{class:O({"negative-value":f.isNegative})},v(f.value),3)]),_:1})]),_:1},8,["data"]),l("div",A,[n[2]||(n[2]=l("div",{class:"formula-label"},"利润计算公式:",-1)),l("div",F,v(e.formula||"收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余"),1)]),s.value?(p(),V("div",G,[o(x,null,{default:i(()=>[o(_(T))]),_:1}),l("span",null,v(s.value),1)])):j("",!0)]),_:1})),[[k,c.value]])}}}),Y=K(L,[["__scopeId","data-v-4296cb29"]]);export{Y as default};

View File

@ -0,0 +1 @@
.income-summary-card[data-v-4296cb29]{height:100%}.card-header[data-v-4296cb29]{display:flex;justify-content:space-between;align-items:center}.card-title[data-v-4296cb29]{font-size:16px;font-weight:600;color:var(--el-text-color-primary)}.income-table[data-v-4296cb29]{width:100%}.income-table[data-v-4296cb29] .el-table__row{transition:background-color .3s ease}.income-table[data-v-4296cb29] .el-table__row:hover{background-color:var(--el-fill-color-light)}.negative-value[data-v-4296cb29]{color:var(--el-color-danger);font-weight:600}.formula-section[data-v-4296cb29]{margin-top:16px;padding:12px;background:var(--el-fill-color-light);border-radius:8px}.formula-label[data-v-4296cb29]{font-size:12px;color:var(--el-text-color-secondary);margin-bottom:4px}.formula-content[data-v-4296cb29]{font-size:14px;color:var(--el-text-color-primary);font-family:Courier New,monospace}.error-message[data-v-4296cb29]{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:16px;padding:12px;background:var(--el-color-danger-light-9);border-radius:4px;color:var(--el-color-danger);font-size:14px}@media(max-width:768px){.income-table[data-v-4296cb29] .el-table__cell{padding:8px 4px;font-size:12px}}

View File

@ -1 +1 @@
import{d as M,v as $,r as m,g as s,B as q,z as k,k as g,w as o,c as A,D as I,C as F,e as l,b as d,l as G,m as H,x as u,t as v,E as z,_ as J}from"./index-DlmlUUdG.js";import{b as K}from"./user-C-g-VGDy.js";const Q={key:0,class:"user-info"},R={class:"user-detail"},W={class:"nickname"},X={class:"uid"},Y={class:"login-stats"},Z={class:"ip-info"},ee={class:"ip-address"},te=M({__name:"IpLogDialog",props:{modelValue:{type:Boolean},user:{}},emits:["update:modelValue"],setup(r,{emit:V}){const f=r,D=V,h=$({get:()=>f.modelValue,set:a=>D("update:modelValue",a)}),b=m(!1),C=m([]),_=m(0),n=m(1),p=m(20),y=async()=>{var a,e;if(f.user){b.value=!0;try{const i=await K(f.user.id,n.value,p.value);C.value=((a=i.data)==null?void 0:a.list)||[],_.value=((e=i.data)==null?void 0:e.total)||0}catch(i){console.error("获取IP登录历史失败",i),C.value=[],_.value=0}finally{b.value=!1}}},P=a=>{n.value=a,y()},B=a=>{p.value=a,n.value=1,y()},L=async a=>{try{await navigator.clipboard.writeText(a),z.success("IP地址已复制")}catch{const e=document.createElement("textarea");e.value=a,document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e),z.success("IP地址已复制")}},S=()=>{n.value=1,p.value=20,y()},x=()=>{h.value=!1};return(a,e)=>{const i=s("el-icon"),U=s("el-avatar"),E=s("el-statistic"),c=s("el-table-column"),w=s("el-button"),N=s("el-table"),T=s("el-pagination"),O=s("el-dialog"),j=q("loading");return g(),k(O,{modelValue:h.value,"onUpdate:modelValue":e[2]||(e[2]=t=>h.value=t),title:"IP登录历史",width:"800px","close-on-click-modal":!1,onClose:x,onOpen:S},{footer:o(()=>[l(w,{onClick:x},{default:o(()=>[...e[4]||(e[4]=[v("关闭",-1)])]),_:1})]),default:o(()=>[r.user?(g(),A("div",Q,[l(U,{src:r.user.avatar,size:40},{default:o(()=>[l(i,null,{default:o(()=>[l(G(H))]),_:1})]),_:1},8,["src"]),d("div",R,[d("div",W,u(r.user.nickname||"-"),1),d("div",X,"UID: "+u(r.user.id),1)]),d("div",Y,[l(E,{title:"登录记录数",value:_.value},null,8,["value"])])])):I("",!0),F((g(),k(N,{data:C.value,border:"",stripe:"","max-height":"400"},{default:o(()=>[l(c,{prop:"id",label:"ID",width:"80"}),l(c,{prop:"loginDate",label:"登录日期",width:"120"}),l(c,{label:"登录时间",width:"170"},{default:o(({row:t})=>[v(u(t.loginTime||t.lastLoginTime||"-"),1)]),_:1}),l(c,{prop:"ip",label:"IP地址","min-width":"150"},{default:o(({row:t})=>[d("div",Z,[d("span",ee,u(t.ip||"-"),1),t.ip?(g(),k(w,{key:0,type:"primary",link:"",size:"small",onClick:ae=>L(t.ip)},{default:o(()=>[...e[3]||(e[3]=[v(" 复制 ",-1)])]),_:1},8,["onClick"])):I("",!0)])]),_:1}),l(c,{prop:"location",label:"归属地","min-width":"150"},{default:o(({row:t})=>[v(u(t.location||"-"),1)]),_:1}),l(c,{prop:"device",label:"设备信息","min-width":"150","show-overflow-tooltip":""},{default:o(({row:t})=>[v(u(t.device||"-"),1)]),_:1})]),_:1},8,["data"])),[[j,b.value]]),l(T,{"current-page":n.value,"onUpdate:currentPage":e[0]||(e[0]=t=>n.value=t),"page-size":p.value,"onUpdate:pageSize":e[1]||(e[1]=t=>p.value=t),"page-sizes":[10,20,50,100],total:_.value,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:B,onCurrentChange:P,class:"pagination"},null,8,["current-page","page-size","total"])]),_:1},8,["modelValue"])}}}),se=J(te,[["__scopeId","data-v-85f89221"]]);export{se as default};
import{d as H,v as J,r as m,g as s,J as K,z as k,k as g,w as o,c as M,H as I,K as $,e as l,b as d,l as q,m as A,x as u,t as v,E as z,_ as F}from"./index-C-IfdMnF.js";import{b as G}from"./user-fHRNfewZ.js";const Q={key:0,class:"user-info"},R={class:"user-detail"},W={class:"nickname"},X={class:"uid"},Y={class:"login-stats"},Z={class:"ip-info"},ee={class:"ip-address"},te=H({__name:"IpLogDialog",props:{modelValue:{type:Boolean},user:{}},emits:["update:modelValue"],setup(r,{emit:V}){const f=r,D=V,h=J({get:()=>f.modelValue,set:a=>D("update:modelValue",a)}),b=m(!1),C=m([]),_=m(0),n=m(1),p=m(20),y=async()=>{var a,e;if(f.user){b.value=!0;try{const i=await G(f.user.id,n.value,p.value);C.value=((a=i.data)==null?void 0:a.list)||[],_.value=((e=i.data)==null?void 0:e.total)||0}catch(i){console.error("获取IP登录历史失败",i),C.value=[],_.value=0}finally{b.value=!1}}},P=a=>{n.value=a,y()},L=a=>{p.value=a,n.value=1,y()},B=async a=>{try{await navigator.clipboard.writeText(a),z.success("IP地址已复制")}catch{const e=document.createElement("textarea");e.value=a,document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e),z.success("IP地址已复制")}},S=()=>{n.value=1,p.value=20,y()},x=()=>{h.value=!1};return(a,e)=>{const i=s("el-icon"),U=s("el-avatar"),E=s("el-statistic"),c=s("el-table-column"),w=s("el-button"),N=s("el-table"),T=s("el-pagination"),O=s("el-dialog"),j=K("loading");return g(),k(O,{modelValue:h.value,"onUpdate:modelValue":e[2]||(e[2]=t=>h.value=t),title:"IP登录历史",width:"800px","close-on-click-modal":!1,onClose:x,onOpen:S},{footer:o(()=>[l(w,{onClick:x},{default:o(()=>[...e[4]||(e[4]=[v("关闭",-1)])]),_:1})]),default:o(()=>[r.user?(g(),M("div",Q,[l(U,{src:r.user.avatar,size:40},{default:o(()=>[l(i,null,{default:o(()=>[l(q(A))]),_:1})]),_:1},8,["src"]),d("div",R,[d("div",W,u(r.user.nickname||"-"),1),d("div",X,"UID: "+u(r.user.id),1)]),d("div",Y,[l(E,{title:"登录记录数",value:_.value},null,8,["value"])])])):I("",!0),$((g(),k(N,{data:C.value,border:"",stripe:"","max-height":"400"},{default:o(()=>[l(c,{prop:"id",label:"ID",width:"80"}),l(c,{prop:"loginDate",label:"登录日期",width:"120"}),l(c,{label:"登录时间",width:"170"},{default:o(({row:t})=>[v(u(t.loginTime||t.lastLoginTime||"-"),1)]),_:1}),l(c,{prop:"ip",label:"IP地址","min-width":"150"},{default:o(({row:t})=>[d("div",Z,[d("span",ee,u(t.ip||"-"),1),t.ip?(g(),k(w,{key:0,type:"primary",link:"",size:"small",onClick:ae=>B(t.ip)},{default:o(()=>[...e[3]||(e[3]=[v(" 复制 ",-1)])]),_:1},8,["onClick"])):I("",!0)])]),_:1}),l(c,{prop:"location",label:"归属地","min-width":"150"},{default:o(({row:t})=>[v(u(t.location||"-"),1)]),_:1}),l(c,{prop:"device",label:"设备信息","min-width":"150","show-overflow-tooltip":""},{default:o(({row:t})=>[v(u(t.device||"-"),1)]),_:1})]),_:1},8,["data"])),[[j,b.value]]),l(T,{"current-page":n.value,"onUpdate:currentPage":e[0]||(e[0]=t=>n.value=t),"page-size":p.value,"onUpdate:pageSize":e[1]||(e[1]=t=>p.value=t),"page-sizes":[10,20,50,100],total:_.value,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:L,onCurrentChange:P,class:"pagination"},null,8,["current-page","page-size","total"])]),_:1},8,["modelValue"])}}}),se=F(te,[["__scopeId","data-v-85f89221"]]);export{se as default};

View File

@ -1 +1 @@
import{d as S,r as N,v as R,g as r,z as C,k as V,w as t,e as l,b as f,t as _,c as z,F as O,y as J,x as I,l as L,J as T,_ as $}from"./index-DlmlUUdG.js";const j={class:"miniprogram-header"},G={class:"miniprogram-title"},H=S({__name:"MiniprogramForm",props:{modelValue:{},index:{},canDelete:{type:Boolean},existingPrefixes:{},weixinMerchants:{}},emits:["update:modelValue","delete","change","defaultChange"],setup(g,{expose:A,emit:P}){const p=g,i=P,c=N(),a=R({get:()=>p.modelValue,set:v=>i("update:modelValue",v)}),U={name:[{required:!0,message:"请输入小程序名称",trigger:"blur"},{max:50,message:"小程序名称不能超过50个字符",trigger:"blur"}],appid:[{required:!0,message:"请输入AppId",trigger:"blur"},{max:50,message:"AppId不能超过50个字符",trigger:"blur"}],appsecret:[{required:!0,message:"请输入AppSecret",trigger:"blur"}],order_prefix:[{required:!0,message:"请输入订单前缀",trigger:"blur"},{validator:(v,e,n)=>{if(!e){n(new Error("请输入订单前缀"));return}if(e.length!==2){n(new Error("订单前缀必须为2位字符"));return}if(p.existingPrefixes.filter((h,d)=>d!==p.index).includes(e)){n(new Error("订单前缀已被其他小程序使用"));return}n()},trigger:"blur"}]},m=()=>{i("change")},k=()=>{a.value.is_default===1&&i("defaultChange",p.index),i("change")},B=()=>{i("delete",p.index)};return A({validate:async()=>{if(!c.value)return!1;try{return await c.value.validate(),!0}catch{return!1}}}),(v,e)=>{const n=r("el-tag"),b=r("el-icon"),h=r("el-button"),d=r("el-input"),s=r("el-form-item"),u=r("el-col"),x=r("el-row"),w=r("el-radio"),D=r("el-radio-group"),q=r("el-option"),E=r("el-select"),F=r("el-form"),M=r("el-card");return V(),C(M,{class:"miniprogram-card",shadow:"hover"},{header:t(()=>[f("div",j,[f("span",G,[l(n,{type:a.value.is_default===1?"success":"info",size:"small"},{default:t(()=>[_(I(a.value.is_default===1?"默认":"非默认"),1)]),_:1},8,["type"]),_(" "+I(a.value.name||"新小程序"),1)]),l(h,{type:"danger",link:"",disabled:!g.canDelete,onClick:B},{default:t(()=>[l(b,null,{default:t(()=>[l(L(T))]),_:1}),e[6]||(e[6]=_("删除 ",-1))]),_:1},8,["disabled"])])]),default:t(()=>[l(F,{ref_key:"formRef",ref:c,model:a.value,rules:U,"label-width":"100px",class:"miniprogram-form"},{default:t(()=>[l(x,{gutter:20},{default:t(()=>[l(u,{span:12},{default:t(()=>[l(s,{label:"小程序名称",prop:"name"},{default:t(()=>[l(d,{modelValue:a.value.name,"onUpdate:modelValue":e[0]||(e[0]=o=>a.value.name=o),placeholder:"请输入小程序名称",maxlength:"50",onInput:m},null,8,["modelValue"])]),_:1})]),_:1}),l(u,{span:12},{default:t(()=>[l(s,{label:"AppId",prop:"appid"},{default:t(()=>[l(d,{modelValue:a.value.appid,"onUpdate:modelValue":e[1]||(e[1]=o=>a.value.appid=o),placeholder:"请输入小程序AppId",maxlength:"50",onInput:m},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),l(x,{gutter:20},{default:t(()=>[l(u,{span:12},{default:t(()=>[l(s,{label:"AppSecret",prop:"appsecret"},{default:t(()=>[l(d,{modelValue:a.value.appsecret,"onUpdate:modelValue":e[2]||(e[2]=o=>a.value.appsecret=o),type:"password",placeholder:"请输入小程序AppSecret","show-password":"",onInput:m},null,8,["modelValue"])]),_:1})]),_:1}),l(u,{span:12},{default:t(()=>[l(s,{label:"订单前缀",prop:"order_prefix"},{default:t(()=>[l(d,{modelValue:a.value.order_prefix,"onUpdate:modelValue":e[3]||(e[3]=o=>a.value.order_prefix=o),placeholder:"请输入2位订单前缀",maxlength:"2",onInput:m},null,8,["modelValue"]),e[7]||(e[7]=f("div",{class:"form-tip"},"必须为2位字符用于区分不同小程序的订单",-1))]),_:1})]),_:1})]),_:1}),l(x,{gutter:20},{default:t(()=>[l(u,{span:12},{default:t(()=>[l(s,{label:"是否默认",prop:"is_default"},{default:t(()=>[l(D,{modelValue:a.value.is_default,"onUpdate:modelValue":e[4]||(e[4]=o=>a.value.is_default=o),onChange:k},{default:t(()=>[l(w,{value:1},{default:t(()=>[...e[8]||(e[8]=[_("是",-1)])]),_:1}),l(w,{value:0},{default:t(()=>[...e[9]||(e[9]=[_("否",-1)])]),_:1})]),_:1},8,["modelValue"]),e[10]||(e[10]=f("div",{class:"form-tip"},"默认小程序用于未匹配域名时的兜底",-1))]),_:1})]),_:1}),l(u,{span:12},{default:t(()=>[l(s,{label:"关联商户",prop:"merchants"},{default:t(()=>[l(E,{modelValue:a.value.merchants,"onUpdate:modelValue":e[5]||(e[5]=o=>a.value.merchants=o),multiple:"",placeholder:"请选择关联的微信支付商户",style:{width:"100%"},onChange:m},{default:t(()=>[(V(!0),z(O,null,J(g.weixinMerchants,(o,y)=>(V(),C(q,{key:y,label:o.name||`商户${y+1}`,value:o.mch_id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e[11]||(e[11]=f("div",{class:"form-tip"},"选择该小程序可使用的微信支付商户",-1))]),_:1})]),_:1})]),_:1})]),_:1},8,["model"])]),_:1})}}}),X=$(H,[["__scopeId","data-v-b2192302"]]);export{X as default};
import{d as S,r as N,v as O,g as r,z as C,k as V,w as t,e as l,b as f,t as _,c as R,F as z,y as L,x as I,l as T,O as $,_ as j}from"./index-C-IfdMnF.js";const G={class:"miniprogram-header"},H={class:"miniprogram-title"},J=S({__name:"MiniprogramForm",props:{modelValue:{},index:{},canDelete:{type:Boolean},existingPrefixes:{},weixinMerchants:{}},emits:["update:modelValue","delete","change","defaultChange"],setup(g,{expose:A,emit:P}){const p=g,i=P,c=N(),a=O({get:()=>p.modelValue,set:v=>i("update:modelValue",v)}),U={name:[{required:!0,message:"请输入小程序名称",trigger:"blur"},{max:50,message:"小程序名称不能超过50个字符",trigger:"blur"}],appid:[{required:!0,message:"请输入AppId",trigger:"blur"},{max:50,message:"AppId不能超过50个字符",trigger:"blur"}],appsecret:[{required:!0,message:"请输入AppSecret",trigger:"blur"}],order_prefix:[{required:!0,message:"请输入订单前缀",trigger:"blur"},{validator:(v,e,n)=>{if(!e){n(new Error("请输入订单前缀"));return}if(e.length!==2){n(new Error("订单前缀必须为2位字符"));return}if(p.existingPrefixes.filter((h,d)=>d!==p.index).includes(e)){n(new Error("订单前缀已被其他小程序使用"));return}n()},trigger:"blur"}]},m=()=>{i("change")},k=()=>{a.value.is_default===1&&i("defaultChange",p.index),i("change")},B=()=>{i("delete",p.index)};return A({validate:async()=>{if(!c.value)return!1;try{return await c.value.validate(),!0}catch{return!1}}}),(v,e)=>{const n=r("el-tag"),b=r("el-icon"),h=r("el-button"),d=r("el-input"),s=r("el-form-item"),u=r("el-col"),x=r("el-row"),w=r("el-radio"),D=r("el-radio-group"),q=r("el-option"),E=r("el-select"),F=r("el-form"),M=r("el-card");return V(),C(M,{class:"miniprogram-card",shadow:"hover"},{header:t(()=>[f("div",G,[f("span",H,[l(n,{type:a.value.is_default===1?"success":"info",size:"small"},{default:t(()=>[_(I(a.value.is_default===1?"默认":"非默认"),1)]),_:1},8,["type"]),_(" "+I(a.value.name||"新小程序"),1)]),l(h,{type:"danger",link:"",disabled:!g.canDelete,onClick:B},{default:t(()=>[l(b,null,{default:t(()=>[l(T($))]),_:1}),e[6]||(e[6]=_("删除 ",-1))]),_:1},8,["disabled"])])]),default:t(()=>[l(F,{ref_key:"formRef",ref:c,model:a.value,rules:U,"label-width":"100px",class:"miniprogram-form"},{default:t(()=>[l(x,{gutter:20},{default:t(()=>[l(u,{span:12},{default:t(()=>[l(s,{label:"小程序名称",prop:"name"},{default:t(()=>[l(d,{modelValue:a.value.name,"onUpdate:modelValue":e[0]||(e[0]=o=>a.value.name=o),placeholder:"请输入小程序名称",maxlength:"50",onInput:m},null,8,["modelValue"])]),_:1})]),_:1}),l(u,{span:12},{default:t(()=>[l(s,{label:"AppId",prop:"appid"},{default:t(()=>[l(d,{modelValue:a.value.appid,"onUpdate:modelValue":e[1]||(e[1]=o=>a.value.appid=o),placeholder:"请输入小程序AppId",maxlength:"50",onInput:m},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),l(x,{gutter:20},{default:t(()=>[l(u,{span:12},{default:t(()=>[l(s,{label:"AppSecret",prop:"appsecret"},{default:t(()=>[l(d,{modelValue:a.value.appsecret,"onUpdate:modelValue":e[2]||(e[2]=o=>a.value.appsecret=o),type:"password",placeholder:"请输入小程序AppSecret","show-password":"",onInput:m},null,8,["modelValue"])]),_:1})]),_:1}),l(u,{span:12},{default:t(()=>[l(s,{label:"订单前缀",prop:"order_prefix"},{default:t(()=>[l(d,{modelValue:a.value.order_prefix,"onUpdate:modelValue":e[3]||(e[3]=o=>a.value.order_prefix=o),placeholder:"请输入2位订单前缀",maxlength:"2",onInput:m},null,8,["modelValue"]),e[7]||(e[7]=f("div",{class:"form-tip"},"必须为2位字符用于区分不同小程序的订单",-1))]),_:1})]),_:1})]),_:1}),l(x,{gutter:20},{default:t(()=>[l(u,{span:12},{default:t(()=>[l(s,{label:"是否默认",prop:"is_default"},{default:t(()=>[l(D,{modelValue:a.value.is_default,"onUpdate:modelValue":e[4]||(e[4]=o=>a.value.is_default=o),onChange:k},{default:t(()=>[l(w,{value:1},{default:t(()=>[...e[8]||(e[8]=[_("是",-1)])]),_:1}),l(w,{value:0},{default:t(()=>[...e[9]||(e[9]=[_("否",-1)])]),_:1})]),_:1},8,["modelValue"]),e[10]||(e[10]=f("div",{class:"form-tip"},"默认小程序用于未匹配域名时的兜底",-1))]),_:1})]),_:1}),l(u,{span:12},{default:t(()=>[l(s,{label:"关联商户",prop:"merchants"},{default:t(()=>[l(E,{modelValue:a.value.merchants,"onUpdate:modelValue":e[5]||(e[5]=o=>a.value.merchants=o),multiple:"",placeholder:"请选择关联的微信支付商户",style:{width:"100%"},onChange:m},{default:t(()=>[(V(!0),R(z,null,L(g.weixinMerchants,(o,y)=>(V(),C(q,{key:y,label:o.name||`商户${y+1}`,value:o.mch_id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e[11]||(e[11]=f("div",{class:"form-tip"},"选择该小程序可使用的微信支付商户",-1))]),_:1})]),_:1})]),_:1})]),_:1},8,["model"])]),_:1})}}}),X=j(J,[["__scopeId","data-v-b2192302"]]);export{X as default};

View File

@ -1 +1 @@
import{c as P}from"./user-C-g-VGDy.js";import{d as j,v as l,r as $,a as A,P as G,g as u,z as H,k as J,w as o,e as n,b as p,x as m,t as v,K as O,E as V,_ as Q}from"./index-DlmlUUdG.js";const W={class:"current-value"},X={class:"preview-info"},Y={class:"operation-symbol"},Z={class:"amount-value"},ee=j({__name:"MoneyChangeDialog",props:{modelValue:{type:Boolean},user:{},type:{},action:{default:"add"}},emits:["update:modelValue","success"],setup(D,{emit:L}){const t=D,w=L,f=l({get:()=>t.modelValue,set:r=>w("update:modelValue",r)}),_=$(),g=$(!1),a=A({type:1,amount:0,operation:1,remark:""}),U=l(()=>({operation:[{required:!0,message:"请选择操作类型",trigger:"change"}],amount:[{required:!0,message:"请输入金额",trigger:"blur"},{type:"number",min:.01,message:"金额必须大于0",trigger:"blur"},{validator:(r,e,s)=>{a.operation===2&&e>d.value?s(new Error(`扣除金额不能超过当前${c.value}`)):s()},trigger:"blur"}]})),c=l(()=>({1:"余额",2:"积分",3:"钻石"})[t.type]||"余额"),h=l(()=>`${t.action==="add"?"充值":"扣除"}${c.value}`),x=l(()=>`当前${c.value}`),B=l(()=>`${c.value}数量`),d=l(()=>t.user&&{1:t.user.balance||0,2:t.user.integral||0,3:t.user.diamond||0}[t.type]||0),k=l(()=>t.type===1?`¥${d.value.toFixed(2)}`:d.value.toString()),S=l(()=>t.type===1?2:0),E=l(()=>(t.type===1,1)),b=l(()=>{const r=a.amount||0;return a.operation===1?d.value+r:Math.max(0,d.value-r)}),F=l(()=>t.type===1?`¥${b.value.toFixed(2)}`:b.value.toString()),N=l(()=>a.operation===1?"positive":b.value<d.value?"negative":"");G(()=>t.modelValue,r=>{var e;r&&(a.type=t.type,a.operation=t.action==="add"?1:2,a.amount=0,a.remark="",(e=_.value)==null||e.resetFields())});const y=()=>{f.value=!1},R=async()=>{var e;if(!t.user){V.warning("用户信息不存在");return}if(await((e=_.value)==null?void 0:e.validate())){g.value=!0;try{await P(t.user.id,a),V.success("操作成功"),w("success"),y()}catch(s){V.error(s.message||"操作失败")}finally{g.value=!1}}};return(r,e)=>{const s=u("el-form-item"),C=u("el-radio"),q=u("el-radio-group"),z=u("el-input-number"),T=u("el-input"),I=u("el-form"),M=u("el-button"),K=u("el-dialog");return J(),H(K,{modelValue:f.value,"onUpdate:modelValue":e[3]||(e[3]=i=>f.value=i),title:h.value,width:"450px","close-on-click-modal":!1,onClose:y},{footer:o(()=>[n(M,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[v("取消",-1)])]),_:1}),n(M,{type:"primary",onClick:R,loading:g.value},{default:o(()=>[...e[8]||(e[8]=[v("确定",-1)])]),_:1},8,["loading"])]),default:o(()=>[n(I,{ref_key:"formRef",ref:_,model:a,rules:U.value,"label-width":"100px"},{default:o(()=>[n(s,{label:x.value},{default:o(()=>[p("span",W,m(k.value),1)]),_:1},8,["label"]),n(s,{label:"操作类型",prop:"operation"},{default:o(()=>[n(q,{modelValue:a.operation,"onUpdate:modelValue":e[0]||(e[0]=i=>a.operation=i)},{default:o(()=>[n(C,{value:1},{default:o(()=>[...e[4]||(e[4]=[v("充值(增加)",-1)])]),_:1}),n(C,{value:2},{default:o(()=>[...e[5]||(e[5]=[v("扣除(减少)",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),n(s,{label:B.value,prop:"amount"},{default:o(()=>[n(z,{modelValue:a.amount,"onUpdate:modelValue":e[1]||(e[1]=i=>a.amount=i),min:.01,max:999999999,precision:S.value,step:E.value,style:{width:"100%"},placeholder:"请输入金额"},null,8,["modelValue","precision","step"])]),_:1},8,["label"]),n(s,{label:"备注",prop:"remark"},{default:o(()=>[n(T,{modelValue:a.remark,"onUpdate:modelValue":e[2]||(e[2]=i=>a.remark=i),type:"textarea",rows:3,placeholder:"请输入操作备注(选填)",maxlength:"200","show-word-limit":""},null,8,["modelValue"])]),_:1}),n(s,{label:"操作预览"},{default:o(()=>[p("div",X,[p("span",null,m(x.value)+""+m(k.value),1),p("span",Y,m(a.operation===1?"+":"-"),1),p("span",Z,m(a.amount||0),1),e[6]||(e[6]=p("span",{class:"result-symbol"},"=",-1)),p("span",{class:O(["result-value",N.value])},m(F.value),3)])]),_:1})]),_:1},8,["model","rules"])]),_:1},8,["modelValue","title"])}}}),le=Q(ee,[["__scopeId","data-v-7219a039"]]);export{le as default};
import{c as P}from"./user-fHRNfewZ.js";import{d as j,v as l,r as $,a as A,G as H,g as u,z as J,k as K,w as o,e as n,b as p,x as m,t as v,P as O,E as V,_ as Q}from"./index-C-IfdMnF.js";const W={class:"current-value"},X={class:"preview-info"},Y={class:"operation-symbol"},Z={class:"amount-value"},ee=j({__name:"MoneyChangeDialog",props:{modelValue:{type:Boolean},user:{},type:{},action:{default:"add"}},emits:["update:modelValue","success"],setup(D,{emit:L}){const t=D,w=L,f=l({get:()=>t.modelValue,set:r=>w("update:modelValue",r)}),_=$(),g=$(!1),a=A({type:1,amount:0,operation:1,remark:""}),U=l(()=>({operation:[{required:!0,message:"请选择操作类型",trigger:"change"}],amount:[{required:!0,message:"请输入金额",trigger:"blur"},{type:"number",min:.01,message:"金额必须大于0",trigger:"blur"},{validator:(r,e,s)=>{a.operation===2&&e>d.value?s(new Error(`扣除金额不能超过当前${c.value}`)):s()},trigger:"blur"}]})),c=l(()=>({1:"余额",2:"积分",3:"钻石"})[t.type]||"余额"),h=l(()=>`${t.action==="add"?"充值":"扣除"}${c.value}`),x=l(()=>`当前${c.value}`),B=l(()=>`${c.value}数量`),d=l(()=>t.user&&{1:t.user.balance||0,2:t.user.integral||0,3:t.user.diamond||0}[t.type]||0),k=l(()=>t.type===1?`¥${d.value.toFixed(2)}`:d.value.toString()),S=l(()=>t.type===1?2:0),E=l(()=>(t.type===1,1)),b=l(()=>{const r=a.amount||0;return a.operation===1?d.value+r:Math.max(0,d.value-r)}),F=l(()=>t.type===1?`¥${b.value.toFixed(2)}`:b.value.toString()),N=l(()=>a.operation===1?"positive":b.value<d.value?"negative":"");H(()=>t.modelValue,r=>{var e;r&&(a.type=t.type,a.operation=t.action==="add"?1:2,a.amount=0,a.remark="",(e=_.value)==null||e.resetFields())});const y=()=>{f.value=!1},R=async()=>{var e;if(!t.user){V.warning("用户信息不存在");return}if(await((e=_.value)==null?void 0:e.validate())){g.value=!0;try{await P(t.user.id,a),V.success("操作成功"),w("success"),y()}catch(s){V.error(s.message||"操作失败")}finally{g.value=!1}}};return(r,e)=>{const s=u("el-form-item"),C=u("el-radio"),q=u("el-radio-group"),z=u("el-input-number"),T=u("el-input"),G=u("el-form"),M=u("el-button"),I=u("el-dialog");return K(),J(I,{modelValue:f.value,"onUpdate:modelValue":e[3]||(e[3]=i=>f.value=i),title:h.value,width:"450px","close-on-click-modal":!1,onClose:y},{footer:o(()=>[n(M,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[v("取消",-1)])]),_:1}),n(M,{type:"primary",onClick:R,loading:g.value},{default:o(()=>[...e[8]||(e[8]=[v("确定",-1)])]),_:1},8,["loading"])]),default:o(()=>[n(G,{ref_key:"formRef",ref:_,model:a,rules:U.value,"label-width":"100px"},{default:o(()=>[n(s,{label:x.value},{default:o(()=>[p("span",W,m(k.value),1)]),_:1},8,["label"]),n(s,{label:"操作类型",prop:"operation"},{default:o(()=>[n(q,{modelValue:a.operation,"onUpdate:modelValue":e[0]||(e[0]=i=>a.operation=i)},{default:o(()=>[n(C,{value:1},{default:o(()=>[...e[4]||(e[4]=[v("充值(增加)",-1)])]),_:1}),n(C,{value:2},{default:o(()=>[...e[5]||(e[5]=[v("扣除(减少)",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),n(s,{label:B.value,prop:"amount"},{default:o(()=>[n(z,{modelValue:a.amount,"onUpdate:modelValue":e[1]||(e[1]=i=>a.amount=i),min:.01,max:999999999,precision:S.value,step:E.value,style:{width:"100%"},placeholder:"请输入金额"},null,8,["modelValue","precision","step"])]),_:1},8,["label"]),n(s,{label:"备注",prop:"remark"},{default:o(()=>[n(T,{modelValue:a.remark,"onUpdate:modelValue":e[2]||(e[2]=i=>a.remark=i),type:"textarea",rows:3,placeholder:"请输入操作备注(选填)",maxlength:"200","show-word-limit":""},null,8,["modelValue"])]),_:1}),n(s,{label:"操作预览"},{default:o(()=>[p("div",X,[p("span",null,m(x.value)+""+m(k.value),1),p("span",Y,m(a.operation===1?"+":"-"),1),p("span",Z,m(a.amount||0),1),e[6]||(e[6]=p("span",{class:"result-symbol"},"=",-1)),p("span",{class:O(["result-value",N.value])},m(F.value),3)])]),_:1})]),_:1},8,["model","rules"])]),_:1},8,["modelValue","title"])}}}),le=Q(ee,[["__scopeId","data-v-7219a039"]]);export{le as default};

View File

@ -1 +1 @@
import{d as q,r as b,P as C,g as u,B as H,z as h,k as d,w as e,C as J,c as _,D as g,F as I,e as t,t as o,x as s,b as n,y as K,l as Q,R as W,_ as X}from"./index-DlmlUUdG.js";import{a as Y,O as z,b as k}from"./order-JIUblY8O.js";const Z={class:"order-detail"},$={class:"money"},ee={class:"money"},te={key:0,class:"prize-section"},le={class:"prize-groups"},se={class:"prize-header"},ae={class:"image-error"},oe={class:"prize-info"},ne={class:"prize-title"},ie={class:"prize-meta"},re={class:"money"},de={class:"recovery-money"},ce={key:0,class:"prize-items"},ue={key:0},_e={key:1},me={key:2,class:"text-muted"},pe=q({__name:"OrderDetailDialog",props:{modelValue:{type:Boolean},orderId:{}},emits:["update:modelValue","close"],setup(O,{emit:T}){const p=O,N=T,f=b(p.modelValue),y=b(!1),l=b(null);C(()=>p.modelValue,i=>{f.value=i,i&&p.orderId&&B()}),C(f,i=>{N("update:modelValue",i)});const B=async()=>{if(p.orderId){y.value=!0;try{const i=await Y(p.orderId);l.value=i.data}catch(i){console.error("获取订单详情失败:",i)}finally{y.value=!1}}},F=i=>{switch(i){case z.Paid:return"success";case z.Unpaid:return"warning";case z.Cancelled:return"info";default:return"info"}},S=i=>{switch(i){case k.Pending:return"warning";case k.Recovered:return"info";case k.Shipped:return"success";default:return"info"}},V=()=>{f.value=!1,l.value=null,N("close")};return(i,c)=>{const r=u("el-descriptions-item"),w=u("el-tag"),U=u("el-descriptions"),G=u("el-icon"),P=u("el-image"),v=u("el-table-column"),A=u("el-table"),M=u("el-empty"),R=u("el-button"),E=u("el-dialog"),L=H("loading");return d(),h(E,{modelValue:f.value,"onUpdate:modelValue":c[0]||(c[0]=a=>f.value=a),title:"订单详情",width:"800px","close-on-click-modal":!1,onClose:V},{footer:e(()=>[t(R,{onClick:V},{default:e(()=>[...c[4]||(c[4]=[o("关闭",-1)])]),_:1})]),default:e(()=>[J((d(),_("div",Z,[l.value?(d(),_(I,{key:0},[t(U,{column:2,border:"",class:"order-info"},{default:e(()=>[t(r,{label:"订单号"},{default:e(()=>[o(s(l.value.orderNum),1)]),_:1}),t(r,{label:"订单状态"},{default:e(()=>[t(w,{type:F(l.value.status),size:"small"},{default:e(()=>[o(s(l.value.statusName),1)]),_:1},8,["type"])]),_:1}),t(r,{label:"用户昵称"},{default:e(()=>[o(s(l.value.userNickname||"-"),1)]),_:1}),t(r,{label:"用户ID"},{default:e(()=>[o(s(l.value.userId),1)]),_:1}),t(r,{label:"手机号"},{default:e(()=>[o(s(l.value.userMobile||"-"),1)]),_:1}),t(r,{label:"盒子名称"},{default:e(()=>[o(s(l.value.goodsTitle||"-"),1)]),_:1}),t(r,{label:"抽奖次数"},{default:e(()=>[o(s(l.value.num),1)]),_:1}),t(r,{label:"中奖数量"},{default:e(()=>[o(s(l.value.prizeNum),1)]),_:1}),t(r,{label:"订单金额"},{default:e(()=>{var a;return[n("span",$,"¥"+s(((a=l.value.orderTotal)==null?void 0:a.toFixed(2))||"0.00"),1)]}),_:1}),t(r,{label:"实付金额"},{default:e(()=>{var a;return[n("span",ee,"¥"+s(((a=l.value.discountTotal)==null?void 0:a.toFixed(2))||"0.00"),1)]}),_:1}),t(r,{label:"下单时间"},{default:e(()=>[o(s(l.value.createdAt),1)]),_:1}),t(r,{label:"支付时间"},{default:e(()=>[o(s(l.value.payTime||"-"),1)]),_:1})]),_:1}),l.value.prizeGroups&&l.value.prizeGroups.length>0?(d(),_("div",te,[c[3]||(c[3]=n("h4",{class:"section-title"},"中奖奖品明细",-1)),n("div",le,[(d(!0),_(I,null,K(l.value.prizeGroups,(a,j)=>{var x,D;return d(),_("div",{key:j,class:"prize-group"},[n("div",se,[a.imgUrl?(d(),h(P,{key:0,src:a.imgUrl,"preview-src-list":[a.imgUrl],fit:"cover",class:"prize-img",lazy:""},{error:e(()=>[n("div",ae,[t(G,null,{default:e(()=>[t(Q(W))]),_:1})])]),_:1},8,["src","preview-src-list"])):g("",!0),n("div",oe,[n("div",ne,s(a.title||"-"),1),n("div",ie,[n("span",null,[c[1]||(c[1]=o("价值: ",-1)),n("span",re,"¥"+s(((x=a.price)==null?void 0:x.toFixed(2))||"0.00"),1)]),n("span",null,[c[2]||(c[2]=o("兑换价值: ",-1)),n("span",de,"¥"+s(((D=a.recoveryMoney)==null?void 0:D.toFixed(2))||"0.00"),1)]),n("span",null,"数量: "+s(a.count),1)])])]),a.items&&a.items.length>0?(d(),_("div",ce,[t(A,{data:a.items,size:"small",border:""},{default:e(()=>[t(v,{prop:"luckNo",label:"幸运号",width:"80",align:"center"}),t(v,{label:"状态",width:"100",align:"center"},{default:e(({row:m})=>[t(w,{type:S(m.status),size:"small"},{default:e(()=>[o(s(m.statusName),1)]),_:2},1032,["type"])]),_:1}),t(v,{label:"关联单号","min-width":"180"},{default:e(({row:m})=>[m.recoveryNum?(d(),_("span",ue,"回收: "+s(m.recoveryNum),1)):m.sendNum?(d(),_("span",_e,"发货: "+s(m.sendNum),1)):(d(),_("span",me,"-"))]),_:1}),t(v,{prop:"createdAt",label:"中奖时间","min-width":"160"})]),_:1},8,["data"])])):g("",!0)])}),128))])])):(d(),h(M,{key:1,description:"暂无中奖记录"}))],64)):g("",!0)])),[[L,y.value]])]),_:1},8,["modelValue"])}}}),ye=X(pe,[["__scopeId","data-v-caf193f4"]]);export{ye as default};
import{d as L,r as b,G as I,g as u,J as R,z as h,k as d,w as e,K as j,c as _,H as g,F as C,e as t,t as o,x as s,b as n,y as q,l as Q,I as W,_ as X}from"./index-C-IfdMnF.js";import{a as Y,O as z,b as k}from"./order-DGQ-DcLZ.js";const Z={class:"order-detail"},$={class:"money"},ee={class:"money"},te={key:0,class:"prize-section"},le={class:"prize-groups"},se={class:"prize-header"},ae={class:"image-error"},oe={class:"prize-info"},ne={class:"prize-title"},ie={class:"prize-meta"},re={class:"money"},de={class:"recovery-money"},ce={key:0,class:"prize-items"},ue={key:0},_e={key:1},me={key:2,class:"text-muted"},pe=L({__name:"OrderDetailDialog",props:{modelValue:{type:Boolean},orderId:{}},emits:["update:modelValue","close"],setup(O,{emit:T}){const p=O,N=T,f=b(p.modelValue),y=b(!1),l=b(null);I(()=>p.modelValue,i=>{f.value=i,i&&p.orderId&&F()}),I(f,i=>{N("update:modelValue",i)});const F=async()=>{if(p.orderId){y.value=!0;try{const i=await Y(p.orderId);l.value=i.data}catch(i){console.error("获取订单详情失败:",i)}finally{y.value=!1}}},S=i=>{switch(i){case z.Paid:return"success";case z.Unpaid:return"warning";case z.Cancelled:return"info";default:return"info"}},B=i=>{switch(i){case k.Pending:return"warning";case k.Recovered:return"info";case k.Shipped:return"success";default:return"info"}},V=()=>{f.value=!1,l.value=null,N("close")};return(i,c)=>{const r=u("el-descriptions-item"),w=u("el-tag"),U=u("el-descriptions"),G=u("el-icon"),A=u("el-image"),v=u("el-table-column"),M=u("el-table"),P=u("el-empty"),E=u("el-button"),H=u("el-dialog"),J=R("loading");return d(),h(H,{modelValue:f.value,"onUpdate:modelValue":c[0]||(c[0]=a=>f.value=a),title:"订单详情",width:"800px","close-on-click-modal":!1,onClose:V},{footer:e(()=>[t(E,{onClick:V},{default:e(()=>[...c[4]||(c[4]=[o("关闭",-1)])]),_:1})]),default:e(()=>[j((d(),_("div",Z,[l.value?(d(),_(C,{key:0},[t(U,{column:2,border:"",class:"order-info"},{default:e(()=>[t(r,{label:"订单号"},{default:e(()=>[o(s(l.value.orderNum),1)]),_:1}),t(r,{label:"订单状态"},{default:e(()=>[t(w,{type:S(l.value.status),size:"small"},{default:e(()=>[o(s(l.value.statusName),1)]),_:1},8,["type"])]),_:1}),t(r,{label:"用户昵称"},{default:e(()=>[o(s(l.value.userNickname||"-"),1)]),_:1}),t(r,{label:"用户ID"},{default:e(()=>[o(s(l.value.userId),1)]),_:1}),t(r,{label:"手机号"},{default:e(()=>[o(s(l.value.userMobile||"-"),1)]),_:1}),t(r,{label:"盒子名称"},{default:e(()=>[o(s(l.value.goodsTitle||"-"),1)]),_:1}),t(r,{label:"抽奖次数"},{default:e(()=>[o(s(l.value.num),1)]),_:1}),t(r,{label:"中奖数量"},{default:e(()=>[o(s(l.value.prizeNum),1)]),_:1}),t(r,{label:"订单金额"},{default:e(()=>{var a;return[n("span",$,"¥"+s(((a=l.value.orderTotal)==null?void 0:a.toFixed(2))||"0.00"),1)]}),_:1}),t(r,{label:"实付金额"},{default:e(()=>{var a;return[n("span",ee,"¥"+s(((a=l.value.discountTotal)==null?void 0:a.toFixed(2))||"0.00"),1)]}),_:1}),t(r,{label:"下单时间"},{default:e(()=>[o(s(l.value.createdAt),1)]),_:1}),t(r,{label:"支付时间"},{default:e(()=>[o(s(l.value.payTime||"-"),1)]),_:1})]),_:1}),l.value.prizeGroups&&l.value.prizeGroups.length>0?(d(),_("div",te,[c[3]||(c[3]=n("h4",{class:"section-title"},"中奖奖品明细",-1)),n("div",le,[(d(!0),_(C,null,q(l.value.prizeGroups,(a,K)=>{var x,D;return d(),_("div",{key:K,class:"prize-group"},[n("div",se,[a.imgUrl?(d(),h(A,{key:0,src:a.imgUrl,"preview-src-list":[a.imgUrl],fit:"cover",class:"prize-img",lazy:""},{error:e(()=>[n("div",ae,[t(G,null,{default:e(()=>[t(Q(W))]),_:1})])]),_:1},8,["src","preview-src-list"])):g("",!0),n("div",oe,[n("div",ne,s(a.title||"-"),1),n("div",ie,[n("span",null,[c[1]||(c[1]=o("价值: ",-1)),n("span",re,"¥"+s(((x=a.price)==null?void 0:x.toFixed(2))||"0.00"),1)]),n("span",null,[c[2]||(c[2]=o("兑换价值: ",-1)),n("span",de,"¥"+s(((D=a.recoveryMoney)==null?void 0:D.toFixed(2))||"0.00"),1)]),n("span",null,"数量: "+s(a.count),1)])])]),a.items&&a.items.length>0?(d(),_("div",ce,[t(M,{data:a.items,size:"small",border:""},{default:e(()=>[t(v,{prop:"luckNo",label:"幸运号",width:"80",align:"center"}),t(v,{label:"状态",width:"100",align:"center"},{default:e(({row:m})=>[t(w,{type:B(m.status),size:"small"},{default:e(()=>[o(s(m.statusName),1)]),_:2},1032,["type"])]),_:1}),t(v,{label:"关联单号","min-width":"180"},{default:e(({row:m})=>[m.recoveryNum?(d(),_("span",ue,"回收: "+s(m.recoveryNum),1)):m.sendNum?(d(),_("span",_e,"发货: "+s(m.sendNum),1)):(d(),_("span",me,"-"))]),_:1}),t(v,{prop:"createdAt",label:"中奖时间","min-width":"160"})]),_:1},8,["data"])])):g("",!0)])}),128))])])):(d(),h(P,{key:1,description:"暂无中奖记录"}))],64)):g("",!0)])),[[J,y.value]])]),_:1},8,["modelValue"])}}}),ye=X(pe,[["__scopeId","data-v-caf193f4"]]);export{ye as default};

View File

@ -1 +1 @@
import{d as g,a as D,r as L,g as d,z as i,k as m,w as o,e as l,f as y,c as v,F as V,y as h,l as c,t as k,Q as C,s as F,_ as K}from"./index-DlmlUUdG.js";import{c as Y,A,d as B}from"./order-JIUblY8O.js";const O=g({__name:"OrderListSearchForm",emits:["search","reset"],setup(M,{emit:I}){const x=I,e=D({userId:"",mobile:"",orderNum:"",status:void 0,accountType:void 0,accountStatus:void 0}),s=L(null),p=()=>{const u={};e.userId&&(u.userId=parseInt(e.userId)),e.mobile&&(u.mobile=e.mobile),e.orderNum&&(u.orderNum=e.orderNum),e.status!==void 0&&(u.status=e.status),e.accountType!==void 0&&(u.accountType=e.accountType),e.accountStatus!==void 0&&(u.accountStatus=e.accountStatus),s.value&&s.value.length===2&&(u.startDate=s.value[0],u.endDate=s.value[1]),x("search",u)},w=()=>{e.userId="",e.mobile="",e.orderNum="",e.status=void 0,e.accountType=void 0,e.accountStatus=void 0,s.value=null,x("reset")};return(u,a)=>{const f=d("el-input"),n=d("el-form-item"),_=d("el-option"),b=d("el-select"),T=d("el-date-picker"),N=d("el-icon"),S=d("el-button"),U=d("el-form");return m(),i(U,{inline:!0,model:e,class:"search-form"},{default:o(()=>[l(n,{label:"用户ID"},{default:o(()=>[l(f,{modelValue:e.userId,"onUpdate:modelValue":a[0]||(a[0]=t=>e.userId=t),placeholder:"用户ID",clearable:"",onKeyup:y(p,["enter"]),style:{width:"120px"}},null,8,["modelValue"])]),_:1}),l(n,{label:"手机号"},{default:o(()=>[l(f,{modelValue:e.mobile,"onUpdate:modelValue":a[1]||(a[1]=t=>e.mobile=t),placeholder:"手机号",clearable:"",onKeyup:y(p,["enter"]),style:{width:"140px"}},null,8,["modelValue"])]),_:1}),l(n,{label:"订单号"},{default:o(()=>[l(f,{modelValue:e.orderNum,"onUpdate:modelValue":a[2]||(a[2]=t=>e.orderNum=t),placeholder:"订单号",clearable:"",onKeyup:y(p,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),l(n,{label:"支付状态"},{default:o(()=>[l(b,{modelValue:e.status,"onUpdate:modelValue":a[3]||(a[3]=t=>e.status=t),placeholder:"全部",clearable:"",style:{width:"120px"}},{default:o(()=>[(m(!0),v(V,null,h(c(Y),(t,r)=>(m(),i(_,{key:r,label:t,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(n,{label:"账号类型"},{default:o(()=>[l(b,{modelValue:e.accountType,"onUpdate:modelValue":a[4]||(a[4]=t=>e.accountType=t),placeholder:"全部",clearable:"",style:{width:"100px"}},{default:o(()=>[(m(!0),v(V,null,h(c(A),(t,r)=>(m(),i(_,{key:r,label:t,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(n,{label:"账号状态"},{default:o(()=>[l(b,{modelValue:e.accountStatus,"onUpdate:modelValue":a[5]||(a[5]=t=>e.accountStatus=t),placeholder:"全部",clearable:"",style:{width:"100px"}},{default:o(()=>[(m(!0),v(V,null,h(c(B),(t,r)=>(m(),i(_,{key:r,label:t,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(n,{label:"下单时间"},{default:o(()=>[l(T,{modelValue:s.value,"onUpdate:modelValue":a[6]||(a[6]=t=>s.value=t),type:"daterange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期","value-format":"YYYY-MM-DD",style:{width:"240px"}},null,8,["modelValue"])]),_:1}),l(n,null,{default:o(()=>[l(S,{type:"primary",onClick:p},{default:o(()=>[l(N,null,{default:o(()=>[l(c(C))]),_:1}),a[7]||(a[7]=k("查询 ",-1))]),_:1}),l(S,{onClick:w},{default:o(()=>[l(N,null,{default:o(()=>[l(c(F))]),_:1}),a[8]||(a[8]=k("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),E=K(O,[["__scopeId","data-v-d503489c"]]);export{E as default};
import{d as g,a as D,r as L,g as d,z as i,k as m,w as o,e as l,f as y,c as v,F as V,y as h,l as c,t as k,T as C,s as F,_ as K}from"./index-C-IfdMnF.js";import{c as Y,A,d as B}from"./order-DGQ-DcLZ.js";const O=g({__name:"OrderListSearchForm",emits:["search","reset"],setup(M,{emit:I}){const x=I,e=D({userId:"",mobile:"",orderNum:"",status:void 0,accountType:void 0,accountStatus:void 0}),s=L(null),p=()=>{const u={};e.userId&&(u.userId=parseInt(e.userId)),e.mobile&&(u.mobile=e.mobile),e.orderNum&&(u.orderNum=e.orderNum),e.status!==void 0&&(u.status=e.status),e.accountType!==void 0&&(u.accountType=e.accountType),e.accountStatus!==void 0&&(u.accountStatus=e.accountStatus),s.value&&s.value.length===2&&(u.startDate=s.value[0],u.endDate=s.value[1]),x("search",u)},w=()=>{e.userId="",e.mobile="",e.orderNum="",e.status=void 0,e.accountType=void 0,e.accountStatus=void 0,s.value=null,x("reset")};return(u,a)=>{const f=d("el-input"),n=d("el-form-item"),_=d("el-option"),b=d("el-select"),T=d("el-date-picker"),N=d("el-icon"),S=d("el-button"),U=d("el-form");return m(),i(U,{inline:!0,model:e,class:"search-form"},{default:o(()=>[l(n,{label:"用户ID"},{default:o(()=>[l(f,{modelValue:e.userId,"onUpdate:modelValue":a[0]||(a[0]=t=>e.userId=t),placeholder:"用户ID",clearable:"",onKeyup:y(p,["enter"]),style:{width:"120px"}},null,8,["modelValue"])]),_:1}),l(n,{label:"手机号"},{default:o(()=>[l(f,{modelValue:e.mobile,"onUpdate:modelValue":a[1]||(a[1]=t=>e.mobile=t),placeholder:"手机号",clearable:"",onKeyup:y(p,["enter"]),style:{width:"140px"}},null,8,["modelValue"])]),_:1}),l(n,{label:"订单号"},{default:o(()=>[l(f,{modelValue:e.orderNum,"onUpdate:modelValue":a[2]||(a[2]=t=>e.orderNum=t),placeholder:"订单号",clearable:"",onKeyup:y(p,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),l(n,{label:"支付状态"},{default:o(()=>[l(b,{modelValue:e.status,"onUpdate:modelValue":a[3]||(a[3]=t=>e.status=t),placeholder:"全部",clearable:"",style:{width:"120px"}},{default:o(()=>[(m(!0),v(V,null,h(c(Y),(t,r)=>(m(),i(_,{key:r,label:t,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(n,{label:"账号类型"},{default:o(()=>[l(b,{modelValue:e.accountType,"onUpdate:modelValue":a[4]||(a[4]=t=>e.accountType=t),placeholder:"全部",clearable:"",style:{width:"100px"}},{default:o(()=>[(m(!0),v(V,null,h(c(A),(t,r)=>(m(),i(_,{key:r,label:t,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(n,{label:"账号状态"},{default:o(()=>[l(b,{modelValue:e.accountStatus,"onUpdate:modelValue":a[5]||(a[5]=t=>e.accountStatus=t),placeholder:"全部",clearable:"",style:{width:"100px"}},{default:o(()=>[(m(!0),v(V,null,h(c(B),(t,r)=>(m(),i(_,{key:r,label:t,value:Number(r)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),l(n,{label:"下单时间"},{default:o(()=>[l(T,{modelValue:s.value,"onUpdate:modelValue":a[6]||(a[6]=t=>s.value=t),type:"daterange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期","value-format":"YYYY-MM-DD",style:{width:"240px"}},null,8,["modelValue"])]),_:1}),l(n,null,{default:o(()=>[l(S,{type:"primary",onClick:p},{default:o(()=>[l(N,null,{default:o(()=>[l(c(C))]),_:1}),a[7]||(a[7]=k("查询 ",-1))]),_:1}),l(S,{onClick:w},{default:o(()=>[l(N,null,{default:o(()=>[l(c(F))]),_:1}),a[8]||(a[8]=k("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),E=K(O,[["__scopeId","data-v-d503489c"]]);export{E as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as y,a as x,r as N,g as d,z as k,k as w,w as t,e as l,f as p,t as f,l as b,Q as D,s as g,_ as C}from"./index-DlmlUUdG.js";const U=y({__name:"OrderSearchForm",emits:["search","reset"],setup(K,{emit:V}){const i=V,e=x({userId:"",mobile:"",orderNum:""}),a=N(null),s=()=>{const r={};e.userId&&(r.userId=parseInt(e.userId)),e.mobile&&(r.mobile=e.mobile),e.orderNum&&(r.orderNum=e.orderNum),a.value&&a.value.length===2&&(r.startDate=a.value[0],r.endDate=a.value[1]),i("search",r)},h=()=>{e.userId="",e.mobile="",e.orderNum="",a.value=null,i("reset")};return(r,o)=>{const m=d("el-input"),u=d("el-form-item"),I=d("el-date-picker"),_=d("el-icon"),c=d("el-button"),v=d("el-form");return w(),k(v,{inline:!0,model:e,class:"search-form"},{default:t(()=>[l(u,{label:"用户ID"},{default:t(()=>[l(m,{modelValue:e.userId,"onUpdate:modelValue":o[0]||(o[0]=n=>e.userId=n),placeholder:"用户ID/UID",clearable:"",onKeyup:p(s,["enter"]),style:{width:"120px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"手机号"},{default:t(()=>[l(m,{modelValue:e.mobile,"onUpdate:modelValue":o[1]||(o[1]=n=>e.mobile=n),placeholder:"手机号",clearable:"",onKeyup:p(s,["enter"]),style:{width:"140px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"订单号"},{default:t(()=>[l(m,{modelValue:e.orderNum,"onUpdate:modelValue":o[2]||(o[2]=n=>e.orderNum=n),placeholder:"订单号",clearable:"",onKeyup:p(s,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"下单时间"},{default:t(()=>[l(I,{modelValue:a.value,"onUpdate:modelValue":o[3]||(o[3]=n=>a.value=n),type:"daterange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期","value-format":"YYYY-MM-DD",style:{width:"240px"}},null,8,["modelValue"])]),_:1}),l(u,null,{default:t(()=>[l(c,{type:"primary",onClick:s},{default:t(()=>[l(_,null,{default:t(()=>[l(b(D))]),_:1}),o[4]||(o[4]=f("查询 ",-1))]),_:1}),l(c,{onClick:h},{default:t(()=>[l(_,null,{default:t(()=>[l(b(g))]),_:1}),o[5]||(o[5]=f("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),F=C(U,[["__scopeId","data-v-9eaa58b8"]]);export{F as default};
import{d as y,a as x,r as N,g as d,z as k,k as w,w as t,e as l,f as p,t as f,l as b,T as D,s as g,_ as C}from"./index-C-IfdMnF.js";const U=y({__name:"OrderSearchForm",emits:["search","reset"],setup(K,{emit:V}){const i=V,e=x({userId:"",mobile:"",orderNum:""}),a=N(null),s=()=>{const r={};e.userId&&(r.userId=parseInt(e.userId)),e.mobile&&(r.mobile=e.mobile),e.orderNum&&(r.orderNum=e.orderNum),a.value&&a.value.length===2&&(r.startDate=a.value[0],r.endDate=a.value[1]),i("search",r)},h=()=>{e.userId="",e.mobile="",e.orderNum="",a.value=null,i("reset")};return(r,o)=>{const m=d("el-input"),u=d("el-form-item"),I=d("el-date-picker"),_=d("el-icon"),c=d("el-button"),v=d("el-form");return w(),k(v,{inline:!0,model:e,class:"search-form"},{default:t(()=>[l(u,{label:"用户ID"},{default:t(()=>[l(m,{modelValue:e.userId,"onUpdate:modelValue":o[0]||(o[0]=n=>e.userId=n),placeholder:"用户ID/UID",clearable:"",onKeyup:p(s,["enter"]),style:{width:"120px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"手机号"},{default:t(()=>[l(m,{modelValue:e.mobile,"onUpdate:modelValue":o[1]||(o[1]=n=>e.mobile=n),placeholder:"手机号",clearable:"",onKeyup:p(s,["enter"]),style:{width:"140px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"订单号"},{default:t(()=>[l(m,{modelValue:e.orderNum,"onUpdate:modelValue":o[2]||(o[2]=n=>e.orderNum=n),placeholder:"订单号",clearable:"",onKeyup:p(s,["enter"]),style:{width:"180px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"下单时间"},{default:t(()=>[l(I,{modelValue:a.value,"onUpdate:modelValue":o[3]||(o[3]=n=>a.value=n),type:"daterange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期","value-format":"YYYY-MM-DD",style:{width:"240px"}},null,8,["modelValue"])]),_:1}),l(u,null,{default:t(()=>[l(c,{type:"primary",onClick:s},{default:t(()=>[l(_,null,{default:t(()=>[l(b(D))]),_:1}),o[4]||(o[4]=f("查询 ",-1))]),_:1}),l(c,{onClick:h},{default:t(()=>[l(_,null,{default:t(()=>[l(b(g))]),_:1}),o[5]||(o[5]=f("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),F=C(U,[["__scopeId","data-v-9eaa58b8"]]);export{F as default};

View File

@ -0,0 +1 @@
import{_ as o}from"./QyLevelFormDialog.vue_vue_type_script_setup_true_lang-DFiAHKJt.js";import"./qylevel-BeI00SSd.js";import"./index-C-IfdMnF.js";export{o as default};

View File

@ -0,0 +1 @@
import{u as E}from"./qylevel-BeI00SSd.js";import{d as U,v as h,r as _,a as k,G as B,g as a,z as D,k as F,w as n,e as r,t as V,E as d}from"./index-C-IfdMnF.js";const Q=U({__name:"QyLevelFormDialog",props:{modelValue:{type:Boolean},level:{}},emits:["update:modelValue","success"],setup(b,{emit:w}){const i=b,c=w,m=h({get:()=>i.modelValue,set:t=>c("update:modelValue",t)}),u=_(),p=_(!1),l=k({level:1,title:"",requiredPoints:0}),q={level:[{required:!0,validator:(t,e,o)=>{e==null||e===""?o(new Error("此字段为必填项")):typeof e!="number"||e<=0?o(new Error("必须为大于0的正整数")):o()},trigger:"blur"}],title:[{required:!0,message:"请输入等级名称",trigger:"blur"},{min:1,max:50,message:"名称长度在1-50个字符之间",trigger:"blur"}],requiredPoints:[{required:!0,validator:(t,e,o)=>{e==null||e===""?o(new Error("此字段为必填项")):typeof e!="number"||e<0?o(new Error("必须为非负整数")):o()},trigger:"blur"}]};B(()=>i.modelValue,t=>{t&&i.level&&Object.assign(l,{level:i.level.level||1,title:i.level.title||"",requiredPoints:i.level.requiredPoints||0})});const y=()=>{var t;Object.assign(l,{level:1,title:"",requiredPoints:0}),(t=u.value)==null||t.resetFields()},f=()=>{m.value=!1,y()},P=async()=>{if(u.value){try{await u.value.validate()}catch{return}if(l.level<=0){d.error("等级必须大于0");return}if(l.requiredPoints<0){d.error("所需欧气值不能为负数");return}if(!i.level){d.error("未选择要编辑的等级");return}p.value=!0;try{const t={level:l.level,title:l.title,requiredPoints:l.requiredPoints};await E(i.level.id,t),d.success("更新成功"),c("success"),f()}finally{p.value=!1}}};return(t,e)=>{const o=a("el-input-number"),v=a("el-form-item"),x=a("el-input"),N=a("el-form"),g=a("el-button"),C=a("el-dialog");return F(),D(C,{modelValue:m.value,"onUpdate:modelValue":e[3]||(e[3]=s=>m.value=s),title:"编辑权益等级",width:"500px","close-on-click-modal":!1,onClose:f},{footer:n(()=>[r(g,{onClick:f},{default:n(()=>[...e[4]||(e[4]=[V("取消",-1)])]),_:1}),r(g,{type:"primary",loading:p.value,onClick:P},{default:n(()=>[...e[5]||(e[5]=[V(" 确定 ",-1)])]),_:1},8,["loading"])]),default:n(()=>[r(N,{ref_key:"formRef",ref:u,model:l,rules:q,"label-width":"100px"},{default:n(()=>[r(v,{label:"等级",prop:"level"},{default:n(()=>[r(o,{modelValue:l.level,"onUpdate:modelValue":e[0]||(e[0]=s=>l.level=s),min:1,precision:0,placeholder:"请输入等级",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),r(v,{label:"等级名称",prop:"title"},{default:n(()=>[r(x,{modelValue:l.title,"onUpdate:modelValue":e[1]||(e[1]=s=>l.title=s),placeholder:"请输入等级名称",maxlength:"50","show-word-limit":""},null,8,["modelValue"])]),_:1}),r(v,{label:"所需欧气值",prop:"requiredPoints"},{default:n(()=>[r(o,{modelValue:l.requiredPoints,"onUpdate:modelValue":e[2]||(e[2]=s=>l.requiredPoints=s),min:0,precision:0,placeholder:"请输入所需欧气值",style:{width:"100%"}},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])}}});export{Q as _};

View File

@ -0,0 +1 @@
import{d as X,v as Y,r as v,a as Z,G as ee,g as s,J as le,z as h,k as i,w as a,b as L,K as te,e as t,c as p,F as _,y as ae,l as g,t as d,C as ne,x as u,D as oe,E as ie,_ as se}from"./index-C-IfdMnF.js";import de from"./QyLevelPrizeFormDialog-WgBxlmE6.js";import{Q as E,a as k,g as re,d as pe}from"./qylevel-BeI00SSd.js";import"./coupon--n92Yf2J.js";const ue={class:"toolbar"},ce={class:"filter-area"},ge={key:1},me={key:0},ve={key:1},ye={class:"probability-value"},_e=X({__name:"QyLevelPrizeDialog",props:{modelValue:{type:Boolean},level:{}},emits:["update:modelValue"],setup(C,{emit:N}){const y=C,U=N,V=Y({get:()=>y.modelValue,set:n=>U("update:modelValue",n)}),x=v(!1),S=v([]),D=v(0),o=Z({page:1,pageSize:10,type:void 0,keyword:void 0}),f=v(!1),w=v(!1),P=v(null),m=async()=>{var n;if((n=y.level)!=null&&n.id){x.value=!0;try{const l=await re(y.level.id,o);S.value=l.data.list,D.value=l.data.total}finally{x.value=!1}}};ee(()=>y.modelValue,n=>{n&&y.level&&(o.page=1,o.type=void 0,o.keyword=void 0,m())});const F=()=>{o.page=1,m()},T=n=>{o.page=n,m()},$=n=>{o.pageSize=n,o.page=1,m()},q=()=>{w.value=!1,P.value=null,f.value=!0},I=n=>{w.value=!0,P.value={...n},f.value=!0},M=async n=>{try{await oe.confirm("确定要删除该奖品吗?删除后不可恢复!","删除确认",{type:"warning"}),await pe(n.id),ie.success("删除成功"),m()}catch{}},Q=()=>{V.value=!1};return(n,l)=>{var B;const A=s("el-option"),G=s("el-select"),J=s("el-icon"),b=s("el-button"),r=s("el-table-column"),K=s("el-tag"),j=s("el-image"),H=s("el-table"),O=s("el-pagination"),R=s("el-dialog"),W=le("loading");return i(),h(R,{modelValue:V.value,"onUpdate:modelValue":l[4]||(l[4]=z=>V.value=z),title:`${((B=C.level)==null?void 0:B.title)||"权益等级"} - 奖品管理`,width:"900px","close-on-click-modal":!1,onClose:Q},{footer:a(()=>[t(b,{onClick:Q},{default:a(()=>[...l[8]||(l[8]=[d("关闭",-1)])]),_:1})]),default:a(()=>{var z;return[L("div",ue,[L("div",ce,[t(G,{modelValue:o.type,"onUpdate:modelValue":l[0]||(l[0]=e=>o.type=e),placeholder:"奖品类型",clearable:"",style:{width:"150px"},onChange:F},{default:a(()=>[(i(!0),p(_,null,ae(g(E),(e,c)=>(i(),h(A,{key:c,label:e,value:Number(c)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),t(b,{type:"primary",onClick:q},{default:a(()=>[t(J,null,{default:a(()=>[t(g(ne))]),_:1}),l[5]||(l[5]=d("新增奖品 ",-1))]),_:1})]),te((i(),h(H,{data:S.value,border:"",stripe:"","max-height":"400"},{default:a(()=>[t(r,{prop:"id",label:"ID",width:"60",align:"center"}),t(r,{label:"奖品类型",width:"100",align:"center"},{default:a(({row:e})=>[t(K,{type:e.type===g(k).Coupon?"warning":"success",size:"small"},{default:a(()=>[d(u(e.typeName||g(E)[e.type]||"未知"),1)]),_:2},1032,["type"])]),_:1}),t(r,{label:"奖品名称","min-width":"150"},{default:a(({row:e})=>{var c;return[e.type===g(k).Coupon?(i(),p(_,{key:0},[d(u(((c=e.coupon)==null?void 0:c.title)||e.title||"-"),1)],64)):(i(),p(_,{key:1},[d(u(e.title||"-"),1)],64))]}),_:1}),t(r,{label:"图片",width:"80",align:"center"},{default:a(({row:e})=>[e.image?(i(),h(j,{key:0,src:e.image,"preview-src-list":[e.image],fit:"cover",style:{width:"40px",height:"40px"}},null,8,["src","preview-src-list"])):(i(),p("span",ge,"-"))]),_:1}),t(r,{label:"数量/价值",width:"100",align:"center"},{default:a(({row:e})=>[e.type===g(k).Coupon?(i(),p(_,{key:0},[d(u(e.quantity??1)+"张 ",1)],64)):(i(),p(_,{key:1},[d(" ¥"+u(e.value??0),1)],64))]),_:1}),t(r,{label:"兑换价",width:"90",align:"center"},{default:a(({row:e})=>[e.type===g(k).Physical?(i(),p("span",me," ¥"+u(e.exchangePrice??0),1)):(i(),p("span",ve,"-"))]),_:1}),t(r,{label:"概率",width:"80",align:"center"},{default:a(({row:e})=>[L("span",ye,u(e.probability??0)+"%",1)]),_:1}),t(r,{label:"排序",width:"70",align:"center"},{default:a(({row:e})=>[d(u(e.sort??0),1)]),_:1}),t(r,{label:"操作",width:"130",align:"center",fixed:"right"},{default:a(({row:e})=>[t(b,{type:"primary",link:"",size:"small",onClick:c=>I(e)},{default:a(()=>[...l[6]||(l[6]=[d(" 编辑 ",-1)])]),_:1},8,["onClick"]),t(b,{type:"danger",link:"",size:"small",onClick:c=>M(e)},{default:a(()=>[...l[7]||(l[7]=[d(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[W,x.value]]),t(O,{"current-page":o.page,"onUpdate:currentPage":l[1]||(l[1]=e=>o.page=e),"page-size":o.pageSize,"onUpdate:pageSize":l[2]||(l[2]=e=>o.pageSize=e),"page-sizes":[10,20,50],total:D.value,layout:"total, sizes, prev, pager, next",onSizeChange:$,onCurrentChange:T,class:"pagination"},null,8,["current-page","page-size","total"]),t(de,{modelValue:f.value,"onUpdate:modelValue":l[3]||(l[3]=e=>f.value=e),"level-id":(z=C.level)==null?void 0:z.id,prize:P.value,"is-edit":w.value,onSuccess:m},null,8,["modelValue","level-id","prize","is-edit"])]}),_:1},8,["modelValue","title"])}}}),ke=se(_e,[["__scopeId","data-v-8df0773e"]]);export{ke as default};

View File

@ -0,0 +1 @@
.toolbar[data-v-8df0773e]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.filter-area[data-v-8df0773e]{display:flex;gap:12px}.probability-value[data-v-8df0773e]{color:#409eff;font-weight:500}.pagination[data-v-8df0773e]{margin-top:16px;justify-content:flex-end}

View File

@ -0,0 +1 @@
.form-tip[data-v-b7ab0280]{font-size:12px;color:#909399;margin-top:4px}.image-preview[data-v-b7ab0280]{margin-top:8px}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.qylevel-table[data-v-6a449688]{width:100%}.points-value[data-v-6a449688]{color:#e6a23c;font-weight:500}.pagination[data-v-6a449688]{margin-top:16px;justify-content:flex-end}

View File

@ -0,0 +1 @@
import{d as B,r as m,G as v,g as s,J as D,c as N,k as z,K as T,e as a,z as V,w as l,t as o,x as r,b as q,_ as A}from"./index-C-IfdMnF.js";const E={class:"qylevel-table"},I={class:"points-value"},L=B({__name:"QyLevelTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","prizes"],setup(c,{emit:b}){const d=c,p=b,g=m(d.page),u=m(d.pageSize);v(()=>d.page,t=>{g.value=t}),v(()=>d.pageSize,t=>{u.value=t});const h=t=>{p("page-change",t)},f=t=>{p("size-change",t)},C=t=>{p("edit",t)},y=t=>{p("prizes",t)};return(t,n)=>{const i=s("el-table-column"),k=s("el-tag"),_=s("el-button"),w=s("el-table"),x=s("el-pagination"),S=D("loading");return z(),N("div",E,[T((z(),V(w,{data:c.data,border:"",stripe:""},{default:l(()=>[a(i,{prop:"id",label:"ID",width:"70",align:"center"}),a(i,{label:"等级",width:"80",align:"center"},{default:l(({row:e})=>[a(k,{type:"primary",size:"small"},{default:l(()=>[o(r(e.level),1)]),_:2},1024)]),_:1}),a(i,{prop:"title",label:"等级名称","min-width":"150"},{default:l(({row:e})=>[o(r(e.title||"-"),1)]),_:1}),a(i,{label:"所需欧气值",width:"120",align:"center"},{default:l(({row:e})=>[q("span",I,r(e.requiredPoints??0),1)]),_:1}),a(i,{label:"创建时间",width:"170",align:"center"},{default:l(({row:e})=>[o(r(e.createdAt||"-"),1)]),_:1}),a(i,{label:"更新时间",width:"170",align:"center"},{default:l(({row:e})=>[o(r(e.updatedAt||"-"),1)]),_:1}),a(i,{label:"操作",width:"150",align:"center",fixed:"right"},{default:l(({row:e})=>[a(_,{type:"primary",link:"",size:"small",onClick:P=>C(e)},{default:l(()=>[...n[2]||(n[2]=[o(" 编辑 ",-1)])]),_:1},8,["onClick"]),a(_,{type:"success",link:"",size:"small",onClick:P=>y(e)},{default:l(()=>[...n[3]||(n[3]=[o(" 奖品 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[S,c.loading]]),a(x,{"current-page":g.value,"onUpdate:currentPage":n[0]||(n[0]=e=>g.value=e),"page-size":u.value,"onUpdate:pageSize":n[1]||(n[1]=e=>u.value=e),"page-sizes":[10,20,50,100],total:c.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:f,onCurrentChange:h,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),U=A(L,[["__scopeId","data-v-6a449688"]]);export{U as default};

View File

@ -0,0 +1 @@
import{g as B,u as D,a as L,c as M,b as N}from"./rank-CH5CETmK.js";import{d as j,v as O,r as f,a as W,G,o as H,g as s,z as v,k as d,w as o,e as i,c as w,F as S,y as A,H as J,t as U,E as P,_ as K}from"./index-C-IfdMnF.js";const Q={key:0,class:"image-preview"},X=j({__name:"RankPrizeFormDialog",props:{modelValue:{type:Boolean},prize:{},isEdit:{type:Boolean},type:{}},emits:["update:modelValue","success"],setup(y,{emit:T}){const r=y,b=T,u=O({get:()=>r.modelValue,set:a=>b("update:modelValue",a)}),p=f(),m=f(!1),_=f([]),e=W({rank:1,title:"",imgUrl:"",price:0,costPrice:0,prizeTypeId:void 0}),x={rank:[{required:!0,message:"请输入排名",trigger:"blur"},{type:"number",min:1,message:"排名必须大于0",trigger:"blur"}],title:[{required:!0,message:"请输入奖品名称",trigger:"blur"},{min:1,max:100,message:"名称长度在1-100个字符",trigger:"blur"}],prizeTypeId:[{required:!0,message:"请选择奖品类型",trigger:"change"}],price:[{required:!0,message:"请输入售价",trigger:"blur"},{type:"number",min:0,message:"售价不能为负数",trigger:"blur"}],costPrice:[{required:!0,message:"请输入采购价",trigger:"blur"},{type:"number",min:0,message:"采购价不能为负数",trigger:"blur"}],imgUrl:[{required:!0,message:"请输入图片URL",trigger:"blur"}]},I=async()=>{try{const a=await B();_.value=a.data}catch{}};G(()=>r.modelValue,a=>{a&&(r.isEdit&&r.prize?Object.assign(e,{rank:r.prize.rank,title:r.prize.title,imgUrl:r.prize.imgUrl,price:r.prize.price,costPrice:r.prize.costPrice,prizeTypeId:r.prize.prizeTypeId||void 0}):z())});const z=()=>{var a;Object.assign(e,{rank:1,title:"",imgUrl:"",price:0,costPrice:0,prizeTypeId:void 0}),(a=p.value)==null||a.resetFields()},c=()=>{u.value=!1,z()},h=async()=>{if(p.value){try{await p.value.validate()}catch{return}m.value=!0;try{const a={rank:e.rank,title:e.title,imgUrl:e.imgUrl,price:e.price,costPrice:e.costPrice,prizeTypeId:e.prizeTypeId||0};r.isEdit&&r.prize?(r.type==="week"?await D(r.prize.id,a):await L(r.prize.id,a),P.success("更新成功")):(r.type==="week"?await M(a):await N(a),P.success("创建成功")),b("success"),c()}finally{m.value=!1}}};return H(()=>{I()}),(a,l)=>{const g=s("el-input-number"),n=s("el-form-item"),V=s("el-input"),C=s("el-option"),E=s("el-select"),R=s("el-image"),q=s("el-form"),k=s("el-button"),F=s("el-dialog");return d(),v(F,{modelValue:u.value,"onUpdate:modelValue":l[6]||(l[6]=t=>u.value=t),title:y.isEdit?"编辑奖品":"新增奖品",width:"550px","close-on-click-modal":!1,onClose:c},{footer:o(()=>[i(k,{onClick:c},{default:o(()=>[...l[7]||(l[7]=[U("取消",-1)])]),_:1}),i(k,{type:"primary",loading:m.value,onClick:h},{default:o(()=>[...l[8]||(l[8]=[U(" 确定 ",-1)])]),_:1},8,["loading"])]),default:o(()=>[i(q,{ref_key:"formRef",ref:p,model:e,rules:x,"label-width":"100px"},{default:o(()=>[i(n,{label:"排名",prop:"rank"},{default:o(()=>[i(g,{modelValue:e.rank,"onUpdate:modelValue":l[0]||(l[0]=t=>e.rank=t),min:1,max:999,placeholder:"请输入排名",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),i(n,{label:"奖品名称",prop:"title"},{default:o(()=>[i(V,{modelValue:e.title,"onUpdate:modelValue":l[1]||(l[1]=t=>e.title=t),placeholder:"请输入奖品名称",maxlength:"100","show-word-limit":""},null,8,["modelValue"])]),_:1}),i(n,{label:"奖品类型",prop:"prizeTypeId"},{default:o(()=>[i(E,{modelValue:e.prizeTypeId,"onUpdate:modelValue":l[2]||(l[2]=t=>e.prizeTypeId=t),placeholder:"请选择奖品类型",style:{width:"100%"}},{default:o(()=>[(d(!0),w(S,null,A(_.value,t=>(d(),v(C,{key:t.id,label:t.title,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),i(n,{label:"售价",prop:"price"},{default:o(()=>[i(g,{modelValue:e.price,"onUpdate:modelValue":l[3]||(l[3]=t=>e.price=t),min:0,max:999999,precision:2,placeholder:"请输入售价",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),i(n,{label:"采购价",prop:"costPrice"},{default:o(()=>[i(g,{modelValue:e.costPrice,"onUpdate:modelValue":l[4]||(l[4]=t=>e.costPrice=t),min:0,max:999999,precision:2,placeholder:"请输入采购价",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),i(n,{label:"奖品图片",prop:"imgUrl"},{default:o(()=>[i(V,{modelValue:e.imgUrl,"onUpdate:modelValue":l[5]||(l[5]=t=>e.imgUrl=t),placeholder:"请输入图片URL"},null,8,["modelValue"]),e.imgUrl?(d(),w("div",Q,[i(R,{src:e.imgUrl,fit:"cover",class:"preview-img"},null,8,["src"])])):J("",!0)]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue","title"])}}}),$=K(X,[["__scopeId","data-v-7b317bde"]]);export{$ as default};

View File

@ -0,0 +1 @@
.image-preview[data-v-7b317bde]{margin-top:8px}.preview-img[data-v-7b317bde]{width:100px;height:100px;border-radius:4px}

View File

@ -1 +1 @@
import{d as M,r as P,v as A,P as V,g as c,z as f,k as u,w as e,b as o,c as b,D as E,F as S,e as t,t as r,x as s,l as h,R as k,_ as T}from"./index-DlmlUUdG.js";const j={class:"recovery-detail"},q={class:"money"},G={key:0,class:"prize-section"},H={class:"image-error"},J={key:1,class:"image-error"},K={class:"prize-code"},L={class:"price"},O={class:"recovery-money"},Q={class:"summary-bar"},W={class:"price"},X={class:"recovery-money"},Y=M({__name:"RecoveryDetailDialog",props:{modelValue:{type:Boolean},recoveryData:{}},emits:["update:modelValue","close"],setup(a,{emit:x}){const p=a,g=x,m=P(p.modelValue),w=A(()=>{var d;return(d=p.recoveryData)!=null&&d.prizes?p.recoveryData.prizes.reduce((l,i)=>l+(i.price||0),0):0});V(()=>p.modelValue,d=>{m.value=d}),V(m,d=>{g("update:modelValue",d)});const D=()=>{m.value=!1,g("close")};return(d,l)=>{const i=c("el-descriptions-item"),C=c("el-tag"),F=c("el-descriptions"),z=c("el-icon"),N=c("el-image"),_=c("el-table-column"),U=c("el-table"),B=c("el-empty"),I=c("el-button"),R=c("el-dialog");return u(),f(R,{modelValue:m.value,"onUpdate:modelValue":l[0]||(l[0]=v=>m.value=v),title:"回收订单详情",width:"800px","close-on-click-modal":!1,onClose:D},{footer:e(()=>[t(I,{onClick:D},{default:e(()=>[...l[6]||(l[6]=[r("关闭",-1)])]),_:1})]),default:e(()=>{var v;return[o("div",j,[a.recoveryData?(u(),b(S,{key:0},[t(F,{column:2,border:"",class:"order-info"},{default:e(()=>[t(i,{label:"回收单号"},{default:e(()=>[r(s(a.recoveryData.recoveryNum),1)]),_:1}),t(i,{label:"回收数量"},{default:e(()=>[t(C,{type:"info",size:"small"},{default:e(()=>[r(s(a.recoveryData.count)+" 件",1)]),_:1})]),_:1}),t(i,{label:"用户昵称"},{default:e(()=>[r(s(a.recoveryData.userNickname||"-"),1)]),_:1}),t(i,{label:"用户ID"},{default:e(()=>[r(s(a.recoveryData.userId),1)]),_:1}),t(i,{label:"手机号"},{default:e(()=>[r(s(a.recoveryData.userMobile||"-"),1)]),_:1}),t(i,{label:"用户UID"},{default:e(()=>[r(s(a.recoveryData.userUid||"-"),1)]),_:1}),t(i,{label:"回收金额"},{default:e(()=>{var n;return[o("span",q,"¥"+s(((n=a.recoveryData.money)==null?void 0:n.toFixed(2))||"0.00"),1)]}),_:1}),t(i,{label:"回收时间"},{default:e(()=>[r(s(a.recoveryData.createdAt),1)]),_:1})]),_:1}),a.recoveryData.prizes&&a.recoveryData.prizes.length>0?(u(),b("div",G,[l[5]||(l[5]=o("h4",{class:"section-title"},"回收奖品明细",-1)),t(U,{data:a.recoveryData.prizes,border:"",size:"small"},{default:e(()=>[t(_,{label:"奖品图片",width:"80",align:"center"},{default:e(({row:n})=>[n.imgUrl?(u(),f(N,{key:0,src:n.imgUrl,"preview-src-list":[n.imgUrl],fit:"cover",class:"prize-img",lazy:""},{error:e(()=>[o("div",H,[t(z,null,{default:e(()=>[t(h(k))]),_:1})])]),_:1},8,["src","preview-src-list"])):(u(),b("div",J,[t(z,null,{default:e(()=>[t(h(k))]),_:1})]))]),_:1}),t(_,{prop:"title",label:"奖品名称","min-width":"180"},{default:e(({row:n})=>[o("span",null,s(n.title||"-"),1)]),_:1}),t(_,{prop:"prizeCode",label:"奖品编码","min-width":"120"},{default:e(({row:n})=>[o("span",K,s(n.prizeCode||"-"),1)]),_:1}),t(_,{label:"奖品价值",width:"120",align:"right"},{default:e(({row:n})=>{var y;return[o("span",L,"¥"+s(((y=n.price)==null?void 0:y.toFixed(2))||"0.00"),1)]}),_:1}),t(_,{label:"回收金额",width:"120",align:"right"},{default:e(({row:n})=>{var y;return[o("span",O,"¥"+s(((y=n.recoveryMoney)==null?void 0:y.toFixed(2))||"0.00"),1)]}),_:1})]),_:1},8,["data"]),o("div",Q,[o("span",null,[l[1]||(l[1]=r("共 ",-1)),o("strong",null,s(a.recoveryData.prizes.length),1),l[2]||(l[2]=r(" 件奖品",-1))]),o("span",null,[l[3]||(l[3]=r("总价值: ",-1)),o("span",W,"¥"+s(w.value.toFixed(2)),1)]),o("span",null,[l[4]||(l[4]=r("回收总额: ",-1)),o("span",X,"¥"+s(((v=a.recoveryData.money)==null?void 0:v.toFixed(2))||"0.00"),1)])])])):(u(),f(B,{key:1,description:"暂无回收奖品记录"}))],64)):E("",!0)])]}),_:1},8,["modelValue"])}}}),$=T(Y,[["__scopeId","data-v-de0cb6ca"]]);export{$ as default};
import{d as R,r as A,v as E,G as V,g as c,z as f,k as u,w as e,b as o,c as b,H as G,F as H,e as t,t as r,x as s,l as h,I as k,_ as P}from"./index-C-IfdMnF.js";const S={class:"recovery-detail"},T={class:"money"},j={key:0,class:"prize-section"},q={class:"image-error"},J={key:1,class:"image-error"},K={class:"prize-code"},L={class:"price"},O={class:"recovery-money"},Q={class:"summary-bar"},W={class:"price"},X={class:"recovery-money"},Y=R({__name:"RecoveryDetailDialog",props:{modelValue:{type:Boolean},recoveryData:{}},emits:["update:modelValue","close"],setup(a,{emit:x}){const p=a,g=x,m=A(p.modelValue),w=E(()=>{var d;return(d=p.recoveryData)!=null&&d.prizes?p.recoveryData.prizes.reduce((l,i)=>l+(i.price||0),0):0});V(()=>p.modelValue,d=>{m.value=d}),V(m,d=>{g("update:modelValue",d)});const D=()=>{m.value=!1,g("close")};return(d,l)=>{const i=c("el-descriptions-item"),C=c("el-tag"),F=c("el-descriptions"),z=c("el-icon"),N=c("el-image"),_=c("el-table-column"),U=c("el-table"),B=c("el-empty"),I=c("el-button"),M=c("el-dialog");return u(),f(M,{modelValue:m.value,"onUpdate:modelValue":l[0]||(l[0]=v=>m.value=v),title:"回收订单详情",width:"800px","close-on-click-modal":!1,onClose:D},{footer:e(()=>[t(I,{onClick:D},{default:e(()=>[...l[6]||(l[6]=[r("关闭",-1)])]),_:1})]),default:e(()=>{var v;return[o("div",S,[a.recoveryData?(u(),b(H,{key:0},[t(F,{column:2,border:"",class:"order-info"},{default:e(()=>[t(i,{label:"回收单号"},{default:e(()=>[r(s(a.recoveryData.recoveryNum),1)]),_:1}),t(i,{label:"回收数量"},{default:e(()=>[t(C,{type:"info",size:"small"},{default:e(()=>[r(s(a.recoveryData.count)+" 件",1)]),_:1})]),_:1}),t(i,{label:"用户昵称"},{default:e(()=>[r(s(a.recoveryData.userNickname||"-"),1)]),_:1}),t(i,{label:"用户ID"},{default:e(()=>[r(s(a.recoveryData.userId),1)]),_:1}),t(i,{label:"手机号"},{default:e(()=>[r(s(a.recoveryData.userMobile||"-"),1)]),_:1}),t(i,{label:"用户UID"},{default:e(()=>[r(s(a.recoveryData.userUid||"-"),1)]),_:1}),t(i,{label:"回收金额"},{default:e(()=>{var n;return[o("span",T,"¥"+s(((n=a.recoveryData.money)==null?void 0:n.toFixed(2))||"0.00"),1)]}),_:1}),t(i,{label:"回收时间"},{default:e(()=>[r(s(a.recoveryData.createdAt),1)]),_:1})]),_:1}),a.recoveryData.prizes&&a.recoveryData.prizes.length>0?(u(),b("div",j,[l[5]||(l[5]=o("h4",{class:"section-title"},"回收奖品明细",-1)),t(U,{data:a.recoveryData.prizes,border:"",size:"small"},{default:e(()=>[t(_,{label:"奖品图片",width:"80",align:"center"},{default:e(({row:n})=>[n.imgUrl?(u(),f(N,{key:0,src:n.imgUrl,"preview-src-list":[n.imgUrl],fit:"cover",class:"prize-img",lazy:""},{error:e(()=>[o("div",q,[t(z,null,{default:e(()=>[t(h(k))]),_:1})])]),_:1},8,["src","preview-src-list"])):(u(),b("div",J,[t(z,null,{default:e(()=>[t(h(k))]),_:1})]))]),_:1}),t(_,{prop:"title",label:"奖品名称","min-width":"180"},{default:e(({row:n})=>[o("span",null,s(n.title||"-"),1)]),_:1}),t(_,{prop:"prizeCode",label:"奖品编码","min-width":"120"},{default:e(({row:n})=>[o("span",K,s(n.prizeCode||"-"),1)]),_:1}),t(_,{label:"奖品价值",width:"120",align:"right"},{default:e(({row:n})=>{var y;return[o("span",L,"¥"+s(((y=n.price)==null?void 0:y.toFixed(2))||"0.00"),1)]}),_:1}),t(_,{label:"回收金额",width:"120",align:"right"},{default:e(({row:n})=>{var y;return[o("span",O,"¥"+s(((y=n.recoveryMoney)==null?void 0:y.toFixed(2))||"0.00"),1)]}),_:1})]),_:1},8,["data"]),o("div",Q,[o("span",null,[l[1]||(l[1]=r("共 ",-1)),o("strong",null,s(a.recoveryData.prizes.length),1),l[2]||(l[2]=r(" 件奖品",-1))]),o("span",null,[l[3]||(l[3]=r("总价值: ",-1)),o("span",W,"¥"+s(w.value.toFixed(2)),1)]),o("span",null,[l[4]||(l[4]=r("回收总额: ",-1)),o("span",X,"¥"+s(((v=a.recoveryData.money)==null?void 0:v.toFixed(2))||"0.00"),1)])])])):(u(),f(B,{key:1,description:"暂无回收奖品记录"}))],64)):G("",!0)])]}),_:1},8,["modelValue"])}}}),$=P(Y,[["__scopeId","data-v-de0cb6ca"]]);export{$ as default};

View File

@ -1 +1 @@
import{d as D,r as h,P as v,g as c,B as P,c as f,k as m,C as V,e as a,z as I,w as n,b as i,D as T,x as o,t as b,_ as U}from"./index-DlmlUUdG.js";const A={class:"order-table"},M={class:"user-info"},O={class:"nickname"},R={class:"uid"},j={key:0,class:"mobile"},E={class:"order-num"},F={class:"money"},$={class:"time-text"},q=D({__name:"RecoveryOrderTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","view-detail"],setup(r,{emit:z}){const d=r,p=z,u=h(d.page),g=h(d.pageSize);v(()=>d.page,t=>{u.value=t}),v(()=>d.pageSize,t=>{g.value=t});const y=t=>{p("page-change",t)},C=t=>{p("size-change",t)},x=t=>{p("view-detail",t)};return(t,l)=>{const s=c("el-table-column"),k=c("el-tag"),w=c("el-button"),S=c("el-table"),N=c("el-pagination"),B=P("loading");return m(),f("div",A,[V((m(),I(S,{data:r.data,border:"",stripe:""},{default:n(()=>[a(s,{label:"用户信息","min-width":"160",fixed:"left"},{default:n(({row:e})=>[i("div",M,[i("div",O,o(e.userNickname||"-"),1),i("div",R,"UID: "+o(e.userId),1),e.userMobile?(m(),f("div",j,o(e.userMobile),1)):T("",!0)])]),_:1}),a(s,{prop:"recoveryNum",label:"回收单号","min-width":"180"},{default:n(({row:e})=>[i("span",E,o(e.recoveryNum),1)]),_:1}),a(s,{label:"兑换金额","min-width":"120",align:"right"},{default:n(({row:e})=>{var _;return[i("span",F,"¥"+o(((_=e.money)==null?void 0:_.toFixed(2))||"0.00"),1)]}),_:1}),a(s,{prop:"count",label:"兑换数量","min-width":"100",align:"center"},{default:n(({row:e})=>[a(k,{type:"info",size:"small"},{default:n(()=>[b(o(e.count)+" 件",1)]),_:2},1024)]),_:1}),a(s,{prop:"createdAt",label:"兑换时间","min-width":"160"},{default:n(({row:e})=>[i("span",$,o(e.createdAt),1)]),_:1}),a(s,{label:"操作",width:"120",fixed:"right",align:"center"},{default:n(({row:e})=>[a(w,{type:"primary",link:"",onClick:_=>x(e)},{default:n(()=>[...l[2]||(l[2]=[b(" 查看详情 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[B,r.loading]]),a(N,{"current-page":u.value,"onUpdate:currentPage":l[0]||(l[0]=e=>u.value=e),"page-size":g.value,"onUpdate:pageSize":l[1]||(l[1]=e=>g.value=e),"page-sizes":[10,20,50,100],total:r.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:C,onCurrentChange:y,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),H=U(q,[["__scopeId","data-v-9c430daf"]]);export{H as default};
import{d as D,r as h,G as v,g as c,J as V,c as f,k as m,K as P,e as a,z as I,w as n,b as i,H as T,x as o,t as b,_ as U}from"./index-C-IfdMnF.js";const A={class:"order-table"},M={class:"user-info"},O={class:"nickname"},R={class:"uid"},j={key:0,class:"mobile"},E={class:"order-num"},F={class:"money"},G={class:"time-text"},H=D({__name:"RecoveryOrderTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","view-detail"],setup(r,{emit:z}){const d=r,p=z,u=h(d.page),g=h(d.pageSize);v(()=>d.page,t=>{u.value=t}),v(()=>d.pageSize,t=>{g.value=t});const y=t=>{p("page-change",t)},x=t=>{p("size-change",t)},C=t=>{p("view-detail",t)};return(t,l)=>{const s=c("el-table-column"),k=c("el-tag"),w=c("el-button"),S=c("el-table"),N=c("el-pagination"),B=V("loading");return m(),f("div",A,[P((m(),I(S,{data:r.data,border:"",stripe:""},{default:n(()=>[a(s,{label:"用户信息","min-width":"160",fixed:"left"},{default:n(({row:e})=>[i("div",M,[i("div",O,o(e.userNickname||"-"),1),i("div",R,"UID: "+o(e.userId),1),e.userMobile?(m(),f("div",j,o(e.userMobile),1)):T("",!0)])]),_:1}),a(s,{prop:"recoveryNum",label:"回收单号","min-width":"180"},{default:n(({row:e})=>[i("span",E,o(e.recoveryNum),1)]),_:1}),a(s,{label:"兑换金额","min-width":"120",align:"right"},{default:n(({row:e})=>{var _;return[i("span",F,"¥"+o(((_=e.money)==null?void 0:_.toFixed(2))||"0.00"),1)]}),_:1}),a(s,{prop:"count",label:"兑换数量","min-width":"100",align:"center"},{default:n(({row:e})=>[a(k,{type:"info",size:"small"},{default:n(()=>[b(o(e.count)+" 件",1)]),_:2},1024)]),_:1}),a(s,{prop:"createdAt",label:"兑换时间","min-width":"160"},{default:n(({row:e})=>[i("span",G,o(e.createdAt),1)]),_:1}),a(s,{label:"操作",width:"120",fixed:"right",align:"center"},{default:n(({row:e})=>[a(w,{type:"primary",link:"",onClick:_=>C(e)},{default:n(()=>[...l[2]||(l[2]=[b(" 查看详情 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[B,r.loading]]),a(N,{"current-page":u.value,"onUpdate:currentPage":l[0]||(l[0]=e=>u.value=e),"page-size":g.value,"onUpdate:pageSize":l[1]||(l[1]=e=>g.value=e),"page-sizes":[10,20,50,100],total:r.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:x,onCurrentChange:y,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),K=U(H,[["__scopeId","data-v-9c430daf"]]);export{K as default};

View File

@ -0,0 +1 @@
.reward-config-container[data-v-fb2bdfe3]{min-height:200px}.config-header[data-v-fb2bdfe3]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #ebeef5}.config-title[data-v-fb2bdfe3]{font-size:14px;color:#606266}.empty-tip[data-v-fb2bdfe3]{text-align:center;color:#909399;padding:40px 0}.reward-item[data-v-fb2bdfe3]{margin-bottom:12px}.reward-card[data-v-fb2bdfe3]{background:#fafafa}.reward-card[data-v-fb2bdfe3] .el-card__body{padding:12px 16px}.reward-row[data-v-fb2bdfe3]{display:flex;align-items:center;gap:12px}.reward-type-item[data-v-fb2bdfe3]{margin-bottom:0}.reward-value-item[data-v-fb2bdfe3]{margin-bottom:0;flex:1;display:flex;align-items:center;gap:8px}.reward-unit[data-v-fb2bdfe3]{color:#909399;font-size:12px;white-space:nowrap}.delete-btn[data-v-fb2bdfe3]{flex-shrink:0}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as R,r as J,P as L,o as O,g as u,c as r,k as d,e as o,F as y,y as v,w as c,l as g,J as z,t as A,G as B,_ as F}from"./index-DlmlUUdG.js";const S={class:"reward-config-input"},E=R({__name:"RewardConfigInput",props:{modelValue:{}},emits:["update:modelValue"],setup(h,{emit:V}){const m=h,b=V,C=[{label:"钻石",value:"diamond"},{label:"积分",value:"integral"},{label:"UU币",value:"score"},{label:"余额",value:"money"}],a=J([{type:"diamond",amount:0}]),p=e=>{if(!e)return[{type:"diamond",amount:0}];try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length>0)return t.map(n=>({type:n.type||"diamond",amount:n.amount||0}))}catch{}return[{type:"diamond",amount:0}]},w=e=>{const t=e.filter(n=>n.type&&n.amount>0);return t.length===0?"":JSON.stringify(t)};L(()=>m.modelValue,e=>{a.value=p(e)},{immediate:!0});const i=()=>{const e=w(a.value);b("update:modelValue",e)},x=()=>{a.value.push({type:"diamond",amount:0})},k=e=>{a.value.length>1&&(a.value.splice(e,1),i())};return O(()=>{a.value=p(m.modelValue)}),(e,t)=>{const n=u("el-option"),U=u("el-select"),I=u("el-input-number"),_=u("el-button"),N=u("el-icon");return d(),r("div",S,[(d(!0),r(y,null,v(a.value,(s,f)=>(d(),r("div",{key:f,class:"reward-item"},[o(U,{modelValue:s.type,"onUpdate:modelValue":l=>s.type=l,placeholder:"货币类型",style:{width:"120px"},onChange:i},{default:c(()=>[(d(),r(y,null,v(C,l=>o(n,{key:l.value,label:l.label,value:l.value},null,8,["label","value"])),64))]),_:1},8,["modelValue","onUpdate:modelValue"]),o(I,{modelValue:s.amount,"onUpdate:modelValue":l=>s.amount=l,min:0,max:999999999,placeholder:"数量",style:{width:"150px","margin-left":"8px"},onChange:i},null,8,["modelValue","onUpdate:modelValue"]),o(_,{type:"danger",icon:g(z),circle:"",size:"small",style:{"margin-left":"8px"},onClick:l=>k(f),disabled:a.value.length<=1},null,8,["icon","onClick","disabled"])]))),128)),o(_,{type:"primary",link:"",onClick:x,style:{"margin-top":"8px"}},{default:c(()=>[o(N,null,{default:c(()=>[o(g(B))]),_:1}),t[0]||(t[0]=A("添加货币 ",-1))]),_:1})])}}}),M=F(E,[["__scopeId","data-v-f0c83e30"]]);export{M as default};
import{d as O,r as R,G as L,o as z,g as u,c as r,k as d,e as o,F as y,y as v,w as c,l as g,O as A,t as B,C as F,_ as J}from"./index-C-IfdMnF.js";const S={class:"reward-config-input"},E=O({__name:"RewardConfigInput",props:{modelValue:{}},emits:["update:modelValue"],setup(h,{emit:V}){const m=h,C=V,b=[{label:"钻石",value:"diamond"},{label:"积分",value:"integral"},{label:"UU币",value:"score"},{label:"余额",value:"money"}],a=R([{type:"diamond",amount:0}]),p=e=>{if(!e)return[{type:"diamond",amount:0}];try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length>0)return t.map(n=>({type:n.type||"diamond",amount:n.amount||0}))}catch{}return[{type:"diamond",amount:0}]},w=e=>{const t=e.filter(n=>n.type&&n.amount>0);return t.length===0?"":JSON.stringify(t)};L(()=>m.modelValue,e=>{a.value=p(e)},{immediate:!0});const i=()=>{const e=w(a.value);C("update:modelValue",e)},x=()=>{a.value.push({type:"diamond",amount:0})},k=e=>{a.value.length>1&&(a.value.splice(e,1),i())};return z(()=>{a.value=p(m.modelValue)}),(e,t)=>{const n=u("el-option"),U=u("el-select"),I=u("el-input-number"),_=u("el-button"),N=u("el-icon");return d(),r("div",S,[(d(!0),r(y,null,v(a.value,(s,f)=>(d(),r("div",{key:f,class:"reward-item"},[o(U,{modelValue:s.type,"onUpdate:modelValue":l=>s.type=l,placeholder:"货币类型",style:{width:"120px"},onChange:i},{default:c(()=>[(d(),r(y,null,v(b,l=>o(n,{key:l.value,label:l.label,value:l.value},null,8,["label","value"])),64))]),_:1},8,["modelValue","onUpdate:modelValue"]),o(I,{modelValue:s.amount,"onUpdate:modelValue":l=>s.amount=l,min:0,max:999999999,placeholder:"数量",style:{width:"150px","margin-left":"8px"},onChange:i},null,8,["modelValue","onUpdate:modelValue"]),o(_,{type:"danger",icon:g(A),circle:"",size:"small",style:{"margin-left":"8px"},onClick:l=>k(f),disabled:a.value.length<=1},null,8,["icon","onClick","disabled"])]))),128)),o(_,{type:"primary",link:"",onClick:x,style:{"margin-top":"8px"}},{default:c(()=>[o(N,null,{default:c(()=>[o(g(F))]),_:1}),t[0]||(t[0]=B("添加货币 ",-1))]),_:1})])}}}),M=J(E,[["__scopeId","data-v-f0c83e30"]]);export{M as default};

View File

@ -0,0 +1 @@
import{_ as o}from"./RewardFormDialog.vue_vue_type_script_setup_true_lang-DDKD3g32.js";import"./reward-Bp8GzQej.js";import"./index-C-IfdMnF.js";import"./coupon--n92Yf2J.js";export{o as default};

View File

@ -0,0 +1 @@
import{R as d,a as H,u as M,c as A}from"./reward-Bp8GzQej.js";import{g as I}from"./coupon--n92Yf2J.js";import{d as J,v as h,r as w,a as K,G as B,g as s,z as u,k as i,w as o,e as n,H as F,c as L,F as U,y as N,l as _,t as q,E as c}from"./index-C-IfdMnF.js";const Y=J({__name:"RewardFormDialog",props:{modelValue:{type:Boolean},reward:{},isEdit:{type:Boolean}},emits:["update:modelValue","success"],setup(f,{emit:D}){const t=f,T=D,y=h({get:()=>t.modelValue,set:l=>T("update:modelValue",l)}),p=w(),V=w(!1),g=w([]),v=w(!1),e=K({rewardType:void 0,rewardExtend:void 0,rewardValue:1,description:""}),$=h(()=>({rewardType:[{required:!0,message:"请选择奖励类型",trigger:"change"}],rewardExtend:e.rewardType===d.Coupon?[{required:!0,message:"请选择优惠券",trigger:"change"}]:[],rewardValue:e.rewardType&&e.rewardType!==d.Coupon?[{required:!0,message:"请输入奖励数值",trigger:"blur"},{type:"number",min:1,message:"奖励数值必须大于0",trigger:"blur"}]:[]})),j=async()=>{v.value=!0;try{const l=await I({page:1,pageSize:1e3});g.value=l.data.list}catch{g.value=[]}finally{v.value=!1}};B(()=>t.modelValue,l=>{l&&(j(),t.isEdit&&t.reward?Object.assign(e,{rewardType:t.reward.rewardType,rewardExtend:t.reward.rewardExtend,rewardValue:t.reward.rewardValue||1,description:t.reward.description||""}):x())}),B(()=>e.rewardType,(l,r)=>{r!==void 0&&l!==r&&(l===d.Coupon?e.rewardValue=1:e.rewardExtend=void 0)});const x=()=>{var l;Object.assign(e,{rewardType:void 0,rewardExtend:void 0,rewardValue:1,description:""}),(l=p.value)==null||l.resetFields()},b=()=>{y.value=!1,x()},z=async()=>{if(p.value){try{await p.value.validate()}catch{return}if(e.rewardType===d.Coupon&&!e.rewardExtend){c.error("请选择优惠券");return}if(e.rewardType!==d.Coupon&&e.rewardValue<=0){c.error("奖励数值必须大于0");return}V.value=!0;try{const l={rewardType:e.rewardType,rewardExtend:e.rewardType===d.Coupon?e.rewardExtend:void 0,rewardValue:e.rewardType===d.Coupon?1:e.rewardValue,description:e.description||void 0};t.isEdit&&t.reward?(await M(t.reward.id,l),c.success("更新成功")):(await A(l),c.success("创建成功")),T("success"),b()}finally{V.value=!1}}};return(l,r)=>{const E=s("el-option"),C=s("el-select"),m=s("el-form-item"),O=s("el-input-number"),P=s("el-input"),S=s("el-form"),k=s("el-button"),G=s("el-dialog");return i(),u(G,{modelValue:y.value,"onUpdate:modelValue":r[4]||(r[4]=a=>y.value=a),title:f.isEdit?"编辑奖励":"新增奖励",width:"550px","close-on-click-modal":!1,onClose:b},{footer:o(()=>[n(k,{onClick:b},{default:o(()=>[...r[5]||(r[5]=[q("取消",-1)])]),_:1}),n(k,{type:"primary",loading:V.value,onClick:z},{default:o(()=>[...r[6]||(r[6]=[q(" 确定 ",-1)])]),_:1},8,["loading"])]),default:o(()=>[n(S,{ref_key:"formRef",ref:p,model:e,rules:$.value,"label-width":"100px"},{default:o(()=>[n(m,{label:"奖励类型",prop:"rewardType"},{default:o(()=>[n(C,{modelValue:e.rewardType,"onUpdate:modelValue":r[0]||(r[0]=a=>e.rewardType=a),placeholder:"请选择奖励类型",style:{width:"100%"},disabled:f.isEdit},{default:o(()=>[(i(!0),L(U,null,N(_(H),(a,R)=>(i(),u(E,{key:R,label:a,value:Number(R)},null,8,["label","value"]))),128))]),_:1},8,["modelValue","disabled"])]),_:1}),e.rewardType===_(d).Coupon?(i(),u(m,{key:0,label:"选择优惠券",prop:"rewardExtend"},{default:o(()=>[n(C,{modelValue:e.rewardExtend,"onUpdate:modelValue":r[1]||(r[1]=a=>e.rewardExtend=a),placeholder:"请选择优惠券",style:{width:"100%"},filterable:"",loading:v.value},{default:o(()=>[(i(!0),L(U,null,N(g.value,a=>(i(),u(E,{key:a.id,label:`${a.title} (满${a.minPrice}${a.discountPrice})`,value:a.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue","loading"])]),_:1})):F("",!0),e.rewardType&&e.rewardType!==_(d).Coupon?(i(),u(m,{key:1,label:"奖励数值",prop:"rewardValue"},{default:o(()=>[n(O,{modelValue:e.rewardValue,"onUpdate:modelValue":r[2]||(r[2]=a=>e.rewardValue=a),min:1,precision:0,placeholder:"请输入奖励数值",style:{width:"100%"}},null,8,["modelValue"])]),_:1})):F("",!0),n(m,{label:"描述",prop:"description"},{default:o(()=>[n(P,{modelValue:e.description,"onUpdate:modelValue":r[3]||(r[3]=a=>e.description=a),type:"textarea",rows:3,placeholder:"请输入描述(可选)",maxlength:"200","show-word-limit":""},null,8,["modelValue"])]),_:1})]),_:1},8,["model","rules"])]),_:1},8,["modelValue","title"])}}});export{Y as _};

View File

@ -0,0 +1 @@
.search-form[data-v-9e083f89]{margin-bottom:16px}

View File

@ -0,0 +1 @@
import{d as x,a as T,g as a,z as i,k as s,w as l,e,c as v,F as C,y as F,l as d,f as R,t as f,T as B,s as N,_ as S}from"./index-C-IfdMnF.js";import{a as g}from"./reward-Bp8GzQej.js";const K=x({__name:"RewardSearchForm",emits:["search","reset"],setup(L,{emit:y}){const t=T({rewardType:void 0,keyword:""}),m=y,c=()=>{m("search",{...t})},w=()=>{t.rewardType=void 0,t.keyword="",m("reset")};return(U,o)=>{const k=a("el-option"),h=a("el-select"),n=a("el-form-item"),b=a("el-input"),_=a("el-icon"),u=a("el-button"),V=a("el-form");return s(),i(V,{model:t,inline:"",class:"search-form"},{default:l(()=>[e(n,{label:"奖励类型"},{default:l(()=>[e(h,{modelValue:t.rewardType,"onUpdate:modelValue":o[0]||(o[0]=r=>t.rewardType=r),placeholder:"全部类型",clearable:"",style:{width:"140px"}},{default:l(()=>[(s(!0),v(C,null,F(d(g),(r,p)=>(s(),i(k,{key:p,label:r,value:Number(p)},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(n,{label:"关键词"},{default:l(()=>[e(b,{modelValue:t.keyword,"onUpdate:modelValue":o[1]||(o[1]=r=>t.keyword=r),placeholder:"请输入描述关键词",clearable:"",style:{width:"200px"},onKeyup:R(c,["enter"])},null,8,["modelValue"])]),_:1}),e(n,null,{default:l(()=>[e(u,{type:"primary",onClick:c},{default:l(()=>[e(_,null,{default:l(()=>[e(d(B))]),_:1}),o[2]||(o[2]=f("搜索 ",-1))]),_:1}),e(u,{onClick:w},{default:l(()=>[e(_,null,{default:l(()=>[e(d(N))]),_:1}),o[3]||(o[3]=f("重置 ",-1))]),_:1})]),_:1})]),_:1},8,["model"])}}}),I=S(K,[["__scopeId","data-v-9e083f89"]]);export{I as default};

View File

@ -0,0 +1 @@
import{a as P,R as d}from"./reward-Bp8GzQej.js";import{d as U,r as h,G as y,g as c,J as N,c as p,k as s,K as V,e as t,z as F,w as n,t as i,x as r,l as b,F as z,_ as $}from"./index-C-IfdMnF.js";const j={class:"reward-table"},A={key:0,class:"coupon-info"},G={key:1,class:"no-data"},J=U({__name:"RewardTable",props:{data:{},loading:{type:Boolean},total:{},page:{},pageSize:{}},emits:["page-change","size-change","edit","delete"],setup(g,{emit:v}){const u=g,_=v,m=h(u.page),f=h(u.pageSize);y(()=>u.page,a=>{m.value=a}),y(()=>u.pageSize,a=>{f.value=a});const C=a=>{switch(a){case d.Diamond:return"primary";case d.UUCoin:return"success";case d.DaDaCoin:return"warning";case d.Coupon:return"danger";default:return"info"}},k=a=>{_("page-change",a)},T=a=>{_("size-change",a)},D=a=>{_("edit",a)},x=a=>{_("delete",a)};return(a,l)=>{const o=c("el-table-column"),S=c("el-tag"),w=c("el-button"),I=c("el-table"),R=c("el-pagination"),B=N("loading");return s(),p("div",j,[V((s(),F(I,{data:g.data,border:"",stripe:""},{default:n(()=>[t(o,{prop:"id",label:"ID",width:"70",align:"center"}),t(o,{prop:"rewardId",label:"奖励ID",width:"150",align:"center"},{default:n(({row:e})=>[i(r(e.rewardId||"-"),1)]),_:1}),t(o,{label:"奖励类型",width:"100",align:"center"},{default:n(({row:e})=>[t(S,{type:C(e.rewardType),size:"small"},{default:n(()=>[i(r(e.rewardTypeName||b(P)[e.rewardType]||"未知"),1)]),_:2},1032,["type"])]),_:1}),t(o,{label:"奖励值",width:"120",align:"center"},{default:n(({row:e})=>[e.rewardType===b(d).Coupon?(s(),p(z,{key:0},[e.coupon?(s(),p("span",A,r(e.coupon.title),1)):(s(),p("span",G,"优惠券ID: "+r(e.rewardExtend),1))],64)):(s(),p(z,{key:1},[i(r(e.rewardValue),1)],64))]),_:1}),t(o,{label:"关联ID",width:"100",align:"center"},{default:n(({row:e})=>[i(r(e.rewardExtend||"-"),1)]),_:1}),t(o,{prop:"description",label:"描述","min-width":"150"},{default:n(({row:e})=>[i(r(e.description||"-"),1)]),_:1}),t(o,{label:"创建时间",width:"160",align:"center"},{default:n(({row:e})=>[i(r(e.createdAt||"-"),1)]),_:1}),t(o,{label:"操作",width:"130",align:"center",fixed:"right"},{default:n(({row:e})=>[t(w,{type:"primary",link:"",size:"small",onClick:E=>D(e)},{default:n(()=>[...l[2]||(l[2]=[i(" 编辑 ",-1)])]),_:1},8,["onClick"]),t(w,{type:"danger",link:"",size:"small",onClick:E=>x(e)},{default:n(()=>[...l[3]||(l[3]=[i(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[B,g.loading]]),t(R,{"current-page":m.value,"onUpdate:currentPage":l[0]||(l[0]=e=>m.value=e),"page-size":f.value,"onUpdate:pageSize":l[1]||(l[1]=e=>f.value=e),"page-sizes":[10,20,50,100],total:g.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:T,onCurrentChange:k,class:"pagination"},null,8,["current-page","page-size","total"])])}}}),q=$(J,[["__scopeId","data-v-2ac71bae"]]);export{q as default};

View File

@ -0,0 +1 @@
.reward-table[data-v-2ac71bae]{width:100%}.coupon-info[data-v-2ac71bae]{color:#e6a23c;font-size:12px}.no-data[data-v-2ac71bae]{color:#909399;font-size:12px}.pagination[data-v-2ac71bae]{margin-top:16px;justify-content:flex-end}

Some files were not shown because too many files have changed in this diff Show More