feat(coupon): 支持立减优惠券并统一营销管理页面

This commit is contained in:
pikachu1995@126.com
2026-11-04 14:50:33 +08:00
parent cbaf89c835
commit d521587ad8
18 changed files with 1739 additions and 991 deletions

View File

@@ -2,29 +2,12 @@
<div class="search member-benefit">
<el-card shadow="never" class="table-card">
<el-card>
<template #header>
<div class="card-header-bar">
<div class="header-title">
<span>客户权益列表</span>
</div>
<div class="header-actions">
<el-button size="small" @click="getData">刷新</el-button>
<el-button type="primary" size="small" @click="openAdd">添加权益设置</el-button>
</div>
</div>
</template>
<div class="operation padding-row benefit-actions">
<el-button type="primary" @click="openAdd">添加权益设置</el-button>
<el-button @click="getData">刷新</el-button>
</div>
@@ -33,16 +16,14 @@
<el-table
v-loading="loading"
stripe
border
:data="data"
empty-text="暂无数据"
class="custom-benefit-table"
class="custom-benefit-table mt_10"
row-key="id"
style="width: 100%"
@@ -50,13 +31,13 @@
<!-- 权益ID -->
<el-table-column prop="id" label="权益ID" min-width="190" show-overflow-tooltip />
<el-table-column prop="id" label="权益ID" min-width="150" show-overflow-tooltip />
<!-- 权益LOGO -->
<el-table-column label="权益LOGO" width="86" align="center">
<el-table-column label="权益LOGO" width="100" align="center">
<template #default="{ row }">
@@ -96,7 +77,7 @@
<!-- 权益名称 -->
<el-table-column prop="benefitName" label="权益名称" min-width="180" show-overflow-tooltip />
<el-table-column prop="benefitName" label="权益名称" min-width="150" show-overflow-tooltip />
@@ -108,7 +89,7 @@
<!-- 权益类型 -->
<el-table-column label="权益类型" width="140" align="center">
<el-table-column label="权益类型" width="120" align="center">
<template #default="{ row }">
@@ -122,13 +103,13 @@
<!-- 排序 -->
<el-table-column prop="benefitSort" label="排序" width="80" align="center" />
<el-table-column prop="benefitSort" label="排序" width="70" align="center" />
<!-- 状态 -->
<el-table-column label="状态" width="110" align="center">
<el-table-column label="状态" width="100" align="center">
<template #default="{ row }">
@@ -158,7 +139,7 @@
<!-- 操作 -->
<el-table-column label="操作" width="140" align="center" fixed="right">
<el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row }">
@@ -484,13 +465,15 @@
</el-form>
<div class="benefit-drawer-footer-btns">
<template #footer>
<div class="benefit-drawer-footer-btns">
<el-button @click="addFlag = false">取消</el-button>
<el-button type="primary" :loading="submitAddLoading" @click="submitAdd">提交</el-button>
</div>
</div>
</template>
</el-drawer>
@@ -724,13 +707,15 @@
</el-form>
<div class="benefit-drawer-footer-btns">
<template #footer>
<div class="benefit-drawer-footer-btns">
<el-button @click="editFlag = false">取消</el-button>
<el-button type="primary" :loading="submitEditLoading" @click="submitEdit">提交</el-button>
</div>
</div>
</template>
</el-drawer>
@@ -1770,47 +1755,15 @@ onMounted(() => {
<style lang="scss" scoped>
.card-header-bar {
.benefit-actions {
display: flex;
justify-content: space-between;
align-items: center;
.header-title {
display: flex;
align-items: center;
gap: 10px;
font-size: 15px;
font-weight: 600;
color: #303133;
}
.header-actions {
display: flex;
align-items: center;
gap: 8px;
}
flex-wrap: wrap;
gap: 10px;
}
.benefit-actions .el-button + .el-button {
margin-left: 0;
}
.font-mono {
@@ -1913,21 +1866,13 @@ onMounted(() => {
.benefit-drawer-footer-btns {
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #e8eaec;
text-align: right;
display: flex;
justify-content: flex-end;
gap: 10px;
}
.benefit-drawer-footer-btns .el-button + .el-button {
margin-left: 8px;
margin-left: 0;
}
.link-text {
@@ -1953,6 +1898,21 @@ onMounted(() => {
<style lang="scss">
.benefit-form-drawer {
max-width: 100vw;
.el-drawer__header {
margin-bottom: 0;
padding: 20px 24px;
border-bottom: 1px solid var(--el-border-color-lighter);
}
.el-drawer__body { padding: 24px; }
.el-drawer__footer {
padding: 16px 24px;
border-top: 1px solid var(--el-border-color-lighter);
}
.el-form-item__content { min-width: 0; }
}
.benefit-logo-thumb {

View File

@@ -10,7 +10,7 @@
<span class="val">{{ cp.price }}</span>
</div>
<div class="right-info">
<span class="title">满{{ cp.consumeThreshold }}可用</span>
<span class="title">{{ cp.consumeThreshold > 0 ? '满' + cp.consumeThreshold + '可用' : '无门槛使用' }}</span>
<span class="scope" v-if="cp.title">{{ cp.title }}</span>
<span class="btn">立即领取</span>
</div>

View File

@@ -91,7 +91,7 @@
<el-table-column label="优惠券类型" width="130" align="center">
<template #default="{ row }">
<el-tag v-if="row" size="small" effect="light" :type="row.couponType === 'DISCOUNT' ? 'warning' : 'danger'">
{{ couponTypeText(row.couponType) }}
{{ couponTypeText(row) }}
</el-tag>
</template>
</el-table-column>
@@ -181,9 +181,9 @@ onMounted(() => {
getCouponActivity();
});
function couponTypeText(v) {
if (v === "DISCOUNT") return "打折券";
if (v === "PRICE") return "减免现金券";
function couponTypeText(row) {
if (row.couponType === "DISCOUNT") return "满折优惠券";
if (row.couponType === "PRICE") return Number(row.consumeThreshold) === 0 ? "立减优惠券" : "满减优惠券";
return "未知类型";
}

View File

@@ -25,13 +25,6 @@
/>
</el-form-item>
<el-form-item label="优惠券活动类型" prop="couponActivityType">
<el-radio-group v-model="form.couponActivityType">
<el-radio-button value="REGISTERED">新人发券</el-radio-button>
<el-radio-button value="SPECIFY">精确发券</el-radio-button>
<el-radio-button value="AUTO_COUPON">自动赠券</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
label="领取频率"
v-if="form.couponActivityType === 'AUTO_COUPON'"
@@ -170,8 +163,8 @@
</template>
<script setup>
import { ref, reactive } from "vue";
import { useRouter } from "vue-router";
import { ref, reactive, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import couponTemplate from "@/views/promotions/coupon/coupon";
import userList from "@/views/member/list/index";
import { saveActivityCoupon } from "@/api/promotion";
@@ -182,6 +175,7 @@ import { unixToDate } from "@/utils/filters";
defineOptions({ name: "add-coupon-activity" });
const router = useRouter();
const route = useRoute();
const appStore = useAppStore();
const options = reactive({
@@ -205,6 +199,15 @@ const form = reactive({
couponActivityItems: [],
couponFrequencyEnum: "",
});
watch(
() => route.query.couponActivityType,
(type) => {
if (["REGISTERED", "SPECIFY", "AUTO_COUPON"].includes(type)) {
form.couponActivityType = type;
}
},
{ immediate: true }
);
const submitLoading = ref(false);
const selectCouponList = ref([]);
const formRule = reactive({

View File

@@ -2,7 +2,9 @@
<div class="search">
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="add">添加活动</el-button>
<el-button type="primary" plain @click="addRegistered">注册赠券</el-button>
<el-button type="primary" plain @click="addSpecify">精准发券</el-button>
<el-button type="primary" plain @click="addAutoCoupon">自动赠券</el-button>
</div>
<el-table
@@ -105,7 +107,7 @@ function activityTypeText(type) {
REGISTERED: "注册赠券",
AUTO_COUPON: "自动发券",
};
return map[type] || "精确发券";
return map[type] || "精准发券";
}
function activityScopeText(scope) {
return scope === "DESIGNATED" ? "指定会员" : "全部会员";
@@ -145,8 +147,23 @@ function promotionStatusTagType(status) {
function init() {
getDataList();
}
function add() {
router.push({ name: "add-coupon-activity" });
function addRegistered() {
router.push({
name: "add-coupon-activity",
query: { couponActivityType: "REGISTERED" },
});
}
function addSpecify() {
router.push({
name: "add-coupon-activity",
query: { couponActivityType: "SPECIFY" },
});
}
function addAutoCoupon() {
router.push({
name: "add-coupon-activity",
query: { couponActivityType: "AUTO_COUPON" },
});
}
function info(v) {
router.push({ name: "coupon-activity-info", query: { id: v.id } });

File diff suppressed because it is too large Load Diff

View File

@@ -72,7 +72,7 @@
<el-table-column label="面额/折扣" width="100">
<template #default="{ row }">
<priceColorScheme
v-if="row && row.price"
v-if="row && row.couponType === 'PRICE'"
:value="row.price"
:color="$mainColor"
/>

View File

@@ -93,7 +93,7 @@
<el-table-column label="面额/折扣" width="150">
<template #default="{ row }">
<span v-if="row">
<span v-if="row.price" :style="{ color: $mainColor }">
<span v-if="row.couponType === 'PRICE'" :style="{ color: $mainColor }">
{{ $filters.unitPrice(row.price, "¥") }}</span>
<span v-else>{{ row.couponDiscount }}折</span>
</span>
@@ -118,7 +118,7 @@
<el-table-column label="优惠券类型" width="120">
<template #default="{ row }">
<el-tag v-if="row" :type="couponTypeTagType(row.couponType)">
{{ couponTypeText(row.couponType) }}
{{ couponTypeText(row) }}
</el-tag>
</template>
</el-table-column>
@@ -362,12 +362,10 @@ function getTypeTagType(type) {
};
return map[type] || "";
}
function couponTypeText(type) {
const map = {
DISCOUNT: "打折",
PRICE: "减免现金",
};
return map[type] || "未知";
function couponTypeText(row) {
if (row.couponType === "DISCOUNT") return "满折优惠券";
if (row.couponType === "PRICE") return Number(row.consumeThreshold) === 0 ? "立减优惠券" : "满减优惠券";
return "未知";
}
function couponTypeTagType(type) {
const map = {