This commit is contained in:
gpu 2026-02-02 16:06:24 +08:00
parent 8a14724cdb
commit b46950feeb
7 changed files with 116 additions and 22 deletions

View File

@ -23,7 +23,7 @@ public class CouponController : BusinessControllerBase
/// <summary>
/// 获取优惠券模板列表(简化版,用于下拉选择)
/// </summary>
/// <param name="status">状态筛选:1-启用</param>
/// <param name="status">状态筛选:0-启用(数据库中 status=0 表示启用)</param>
/// <returns>优惠券模板列表</returns>
[HttpGet("templates")]
[BusinessPermission("coupon:list")]
@ -34,13 +34,13 @@ public class CouponController : BusinessControllerBase
var request = new CouponListRequest
{
Page = 1,
PageSize = 100 // 获取所有启用的优惠券
PageSize = 100 // 获取所有优惠券
};
var result = await _couponService.GetCouponsAsync(request);
// 如果指定了 status过滤结果
// 数据库中 status=0 表示启用
var list = status.HasValue
? result.List.Where(c => c.Status == status.Value).ToList()
: result.List;
: result.List.Where(c => c.Status == 0).ToList(); // 默认返回启用的
return Ok(list);
}
catch (BusinessException ex)
@ -155,6 +155,27 @@ public class CouponController : BusinessControllerBase
}
}
/// <summary>
/// 修改优惠券状态
/// </summary>
/// <param name="id">优惠券ID</param>
/// <param name="status">状态0-启用 其他-禁用</param>
/// <returns>操作结果</returns>
[HttpPut("{id}/status")]
[BusinessPermission("coupon:edit")]
public async Task<IActionResult> UpdateCouponStatus(int id, [FromQuery] int status)
{
try
{
var result = await _couponService.UpdateCouponStatusAsync(id, status);
return result ? Ok("状态更新成功") : Error(BusinessErrorCodes.InternalError, "状态更新失败");
}
catch (BusinessException ex)
{
return Error(ex.Code, ex.Message);
}
}
/// <summary>
/// 获取优惠券领取记录列表
/// </summary>

View File

@ -138,6 +138,23 @@ public class CouponService : ICouponService
return result;
}
/// <inheritdoc />
public async Task<bool> UpdateCouponStatusAsync(int id, int status)
{
var coupon = await _dbContext.Coupons.FirstOrDefaultAsync(c => c.Id == id);
if (coupon == null)
{
throw new BusinessException(BusinessErrorCodes.NotFound, "优惠券不存在");
}
coupon.Status = (byte)status;
var result = await _dbContext.SaveChangesAsync() > 0;
_logger.LogInformation("更新优惠券状态成功: Id={Id}, Status={Status}", id, status);
return result;
}
/// <inheritdoc />
public async Task<PagedResult<CouponReceiveResponse>> GetCouponReceivesAsync(CouponReceiveListRequest request)
{

View File

@ -44,6 +44,14 @@ public interface ICouponService
/// <returns>是否成功</returns>
Task<bool> DeleteCouponAsync(int id);
/// <summary>
/// 修改优惠券状态
/// </summary>
/// <param name="id">优惠券ID</param>
/// <param name="status">状态0-启用 其他-禁用</param>
/// <returns>是否成功</returns>
Task<bool> UpdateCouponStatusAsync(int id, int status);
/// <summary>
/// 获取优惠券领取记录列表
/// </summary>

View File

@ -52,6 +52,18 @@ export const CouponReceiveStatusLabels: Record<number, string> = {
[CouponReceiveStatus.Expired]: '已过期',
}
/** 优惠券状态枚举(模板状态) */
export enum CouponStatus {
Enabled = 0, // 启用
Disabled = 1 // 禁用
}
/** 优惠券状态标签映射 */
export const CouponStatusLabels: Record<number, string> = {
[CouponStatus.Enabled]: '启用',
[CouponStatus.Disabled]: '禁用',
}
// ==================== 优惠券相关类型定义 ====================
/** 优惠券列表查询参数 */
@ -186,6 +198,20 @@ export function deleteCoupon(id: number): Promise<ApiResponse<string>> {
})
}
/**
*
* @param id ID
* @param status 0- -
* @returns
*/
export function updateCouponStatus(id: number, status: number): Promise<ApiResponse<string>> {
return request({
url: `${COUPON_BASE_URL}/${id}/status`,
method: 'put',
params: { status }
})
}
// ==================== 优惠券领取记录 API ====================
/**

View File

@ -36,6 +36,20 @@
<span>{{ row.useLimitName || getUseLimitName(row.useLimit) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="100" align="center">
<template #default="{ row }">
<el-switch
v-model="row.status"
:active-value="0"
:inactive-value="1"
active-text="启用"
inactive-text="禁用"
inline-prompt
@change="(val: number) => handleStatusChange(row, val)"
/>
</template>
</el-table-column>
<el-table-column label="创建时间" width="160" align="center">
<template #default="{ row }">
@ -71,10 +85,12 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import {
CouponType,
CouponTypeLabels,
CouponUseLimitLabels,
updateCouponStatus,
type CouponResponse
} from '@/api/business/coupon'
@ -145,6 +161,18 @@ const handleEdit = (row: CouponResponse) => {
const handleDelete = (row: CouponResponse) => {
emit('delete', row)
}
//
const handleStatusChange = async (row: CouponResponse, status: number) => {
try {
await updateCouponStatus(row.id, status)
ElMessage.success(status === 0 ? '已启用' : '已禁用')
} catch (error: any) {
//
row.status = status === 0 ? 1 : 0
ElMessage.error(error.message || '状态更新失败')
}
}
</script>
<style scoped>

View File

@ -36,9 +36,7 @@
<div class="coupon-option">
<span class="coupon-title">{{ coupon.title }}</span>
<span class="coupon-value">
<template v-if="coupon.type === 1">{{ coupon.minMoney }}{{ coupon.money }}</template>
<template v-else-if="coupon.type === 2">{{ coupon.discount }}</template>
<template v-else>{{ coupon.money }}</template>
{{ coupon.minPrice }}{{ coupon.discountPrice }}
</span>
</div>
</el-option>
@ -51,11 +49,9 @@
<el-descriptions-item label="名称">{{ selectedCoupon.title }}</el-descriptions-item>
<el-descriptions-item label="类型">{{ couponTypeText }}</el-descriptions-item>
<el-descriptions-item label="面值">
<template v-if="selectedCoupon.type === 1">{{ selectedCoupon.minMoney }}{{ selectedCoupon.money }}</template>
<template v-else-if="selectedCoupon.type === 2">{{ selectedCoupon.discount }}</template>
<template v-else>{{ selectedCoupon.money }}</template>
{{ selectedCoupon.minPrice }}{{ selectedCoupon.discountPrice }}
</el-descriptions-item>
<el-descriptions-item label="剩余数量">{{ selectedCoupon.stock ?? '不限' }}</el-descriptions-item>
<el-descriptions-item label="有效期">{{ selectedCoupon.validDays }}</el-descriptions-item>
</el-descriptions>
</el-form-item>
@ -91,11 +87,11 @@ import { request, type ApiResponse } from '@/utils/request'
interface CouponTemplate {
id: number
title: string
type: number // 1- 2- 3-
money: number //
minMoney: number //
discount: number //
stock: number | null //
type: number // 1- 2- 3-
discountPrice: number //
minPrice: number //
validDays: number //
stock: number | null //
status: number
}
@ -143,15 +139,12 @@ const selectedCoupon = computed(() => {
//
const couponTypeText = computed(() => {
if (!selectedCoupon.value) return ''
const types: Record<number, string> = { 1: '满减券', 2: '折扣券', 3: '无门槛券' }
const types: Record<number, string> = { 1: '新人优惠券', 2: '权益优惠券', 3: '满减优惠券' }
return types[selectedCoupon.value.type] || '未知'
})
//
const maxQuantity = computed(() => {
if (selectedCoupon.value?.stock) {
return selectedCoupon.value.stock
}
return 999
})
@ -160,10 +153,11 @@ const loadCouponList = async () => {
couponLoading.value = true
try {
// API
// status=0
const res: ApiResponse<CouponTemplate[]> = await request({
url: '/admin/business/coupons/templates',
method: 'get',
params: { status: 1 } //
params: { status: 0 } // status=0
})
couponList.value = res.data || []
} catch (error) {

View File

@ -44,7 +44,7 @@ public partial class Coupon
public int? EffectiveDay { get; set; }
/// <summary>
/// 状态: 0禁用 1启
/// 状态: 0启用 其他值禁
/// </summary>
public byte Status { get; set; }