|
|
@@ -30,12 +30,12 @@ import {
|
|
|
ElRadioButton,
|
|
|
ElAlert
|
|
|
} from "element-plus";
|
|
|
-import {
|
|
|
- initPagination,
|
|
|
- handlePageSizeChange,
|
|
|
- handleCurrentPageChange,
|
|
|
+import {
|
|
|
+ initPagination,
|
|
|
+ handlePageSizeChange,
|
|
|
+ handleCurrentPageChange,
|
|
|
resetPagination,
|
|
|
- updatePaginationData
|
|
|
+ updatePaginationData
|
|
|
} from "@/utils/paginationHelper";
|
|
|
|
|
|
interface SearchFormProps {
|
|
|
@@ -91,11 +91,11 @@ export function useCoupon() {
|
|
|
{
|
|
|
label: "优惠券ID",
|
|
|
prop: "id",
|
|
|
- width: 90
|
|
|
+ width: 200
|
|
|
},
|
|
|
{
|
|
|
label: "优惠券名称",
|
|
|
- prop: "name",
|
|
|
+ prop: "couponName",
|
|
|
minWidth: 150
|
|
|
},
|
|
|
{
|
|
|
@@ -116,7 +116,7 @@ export function useCoupon() {
|
|
|
{
|
|
|
label: "发放类型",
|
|
|
prop: "receiveType",
|
|
|
- minWidth: 110,
|
|
|
+ minWidth: 80,
|
|
|
cellRenderer: ({ row }) => {
|
|
|
if (row.receiveType === 'Collect') {
|
|
|
return <ElTag type="success">主动领取</ElTag>;
|
|
|
@@ -126,19 +126,19 @@ export function useCoupon() {
|
|
|
},
|
|
|
{
|
|
|
label: "优惠值",
|
|
|
- prop: "value",
|
|
|
- minWidth: 100,
|
|
|
+ prop: "discountValue",
|
|
|
+ minWidth: 80,
|
|
|
cellRenderer: ({ row }) => {
|
|
|
- if (row.type === 2) {
|
|
|
- return `${row.value}折`;
|
|
|
+ if (row.couponType === 2) {
|
|
|
+ return `${row.discountValue}折`;
|
|
|
}
|
|
|
- return `¥${row.value}`;
|
|
|
+ return `¥${row.discountValue}`;
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: "发放总量",
|
|
|
prop: "totalCount",
|
|
|
- minWidth: 100
|
|
|
+ minWidth: 90
|
|
|
},
|
|
|
{
|
|
|
label: "已领取",
|
|
|
@@ -183,12 +183,12 @@ export function useCoupon() {
|
|
|
page: pagination.currentPage,
|
|
|
pageSize: pagination.pageSize
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
if (form.name) searchParams.name = form.name;
|
|
|
if (form.type !== undefined) searchParams.type = form.type;
|
|
|
if (form.status !== undefined) searchParams.status = form.status;
|
|
|
if (form.receiveType) searchParams.receiveType = form.receiveType;
|
|
|
-
|
|
|
+
|
|
|
const { data } = await getCouponList(searchParams);
|
|
|
if (data) {
|
|
|
dataList.value = data.list || [];
|
|
|
@@ -225,7 +225,8 @@ export function useCoupon() {
|
|
|
function handleDistribute(row) {
|
|
|
const distributeForm = reactive({
|
|
|
targetType: "all", // all-全部用户, specific-指定用户
|
|
|
- userIds: []
|
|
|
+ userIds: [],
|
|
|
+ distributeCount: 1 // 发放数量
|
|
|
});
|
|
|
|
|
|
// 用户列表状态
|
|
|
@@ -282,9 +283,9 @@ export function useCoupon() {
|
|
|
<ElInput value={`${row.receivedCount || 0} / ${row.totalCount || 0}`} disabled />
|
|
|
</ElFormItem>
|
|
|
<ElFormItem label="目标用户" required>
|
|
|
- <ElSelect
|
|
|
- v-model={distributeForm.targetType}
|
|
|
- placeholder="请选择目标用户"
|
|
|
+ <ElSelect
|
|
|
+ v-model={distributeForm.targetType}
|
|
|
+ placeholder="请选择目标用户"
|
|
|
class="w-full"
|
|
|
onChange={() => {
|
|
|
// 切换时清空用户选择
|
|
|
@@ -297,11 +298,11 @@ export function useCoupon() {
|
|
|
<ElOption label="指定用户" value="specific" />
|
|
|
</ElSelect>
|
|
|
</ElFormItem>
|
|
|
-
|
|
|
+
|
|
|
{distributeForm.targetType === 'specific' && (
|
|
|
<ElFormItem label="选择用户" required>
|
|
|
- <ElSelect
|
|
|
- v-model={distributeForm.userIds}
|
|
|
+ <ElSelect
|
|
|
+ v-model={distributeForm.userIds}
|
|
|
class="w-full"
|
|
|
multiple
|
|
|
filterable
|
|
|
@@ -313,10 +314,10 @@ export function useCoupon() {
|
|
|
placeholder="请输入用户名或手机号搜索"
|
|
|
>
|
|
|
{userList.value.map((user: any) => (
|
|
|
- <ElOption
|
|
|
- key={user.id}
|
|
|
- label={`${user.nickname || user.phone || '未知用户'} (${user.phone || '无手机号'})`}
|
|
|
- value={user.id}
|
|
|
+ <ElOption
|
|
|
+ key={user.id}
|
|
|
+ label={`${user.nickname || user.phone || '未知用户'} (${user.phone || '无手机号'})`}
|
|
|
+ value={user.id}
|
|
|
/>
|
|
|
))}
|
|
|
</ElSelect>
|
|
|
@@ -325,38 +326,55 @@ export function useCoupon() {
|
|
|
</div>
|
|
|
</ElFormItem>
|
|
|
)}
|
|
|
-
|
|
|
+
|
|
|
<ElFormItem label="发放数量" required>
|
|
|
- <ElInputNumber
|
|
|
- placeholder="请输入发放数量"
|
|
|
- class="w-full"
|
|
|
- min={1}
|
|
|
- max={row.totalCount - (row.receivedCount || 0)}
|
|
|
+ <ElInputNumber
|
|
|
+ v-model={distributeForm.distributeCount}
|
|
|
+ placeholder="发放数量"
|
|
|
+ class="w-full"
|
|
|
+ min={1}
|
|
|
+ max={row.totalCount - (row.receivedCount || 0)}
|
|
|
/>
|
|
|
</ElFormItem>
|
|
|
-
|
|
|
+
|
|
|
<ElAlert
|
|
|
type="info"
|
|
|
closable={false}
|
|
|
showIcon={true}
|
|
|
style={{marginTop: '8px'}}
|
|
|
>
|
|
|
- {distributeForm.targetType === 'all'
|
|
|
- ? '将向平台所有用户发放该优惠券'
|
|
|
+ {distributeForm.targetType === 'all'
|
|
|
+ ? '将向平台所有用户发放该优惠券'
|
|
|
: `将向已选择的 ${distributeForm.userIds.length} 个用户发放该优惠券`}
|
|
|
</ElAlert>
|
|
|
</ElForm>
|
|
|
),
|
|
|
- beforeSure: done => {
|
|
|
+ beforeSure: async done => {
|
|
|
// 验证
|
|
|
if (distributeForm.targetType === 'specific' && distributeForm.userIds.length === 0) {
|
|
|
message("请选择至少一个用户", { type: "warning" });
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- message("发放成功", { type: "success" });
|
|
|
- done();
|
|
|
- onSearch();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 调用后端发放接口
|
|
|
+ const { code, message: errorMsg } = await distributeCoupon({
|
|
|
+ templateId: row.id, // 现在后端返回的是字符串,无需转换
|
|
|
+ targetType: distributeForm.targetType === 'all' ? 1 : 3, // 1-全部用户,3-指定用户
|
|
|
+ userIds: distributeForm.targetType === 'specific' ? distributeForm.userIds : undefined
|
|
|
+ });
|
|
|
+
|
|
|
+ if (code === 200) {
|
|
|
+ message("发放成功", { type: "success" });
|
|
|
+ done();
|
|
|
+ onSearch();
|
|
|
+ } else {
|
|
|
+ message(errorMsg || "发放失败", { type: "error" });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ const errorMsg = error?.response?.data?.message || "发放失败,请重试";
|
|
|
+ message(errorMsg, { type: "error" });
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
@@ -385,11 +403,11 @@ export function useCoupon() {
|
|
|
padding: 0;
|
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.form-block {
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.block-title {
|
|
|
font-size: 14px;
|
|
|
font-weight: 600;
|
|
|
@@ -398,26 +416,26 @@ export function useCoupon() {
|
|
|
padding-bottom: 8px;
|
|
|
border-bottom: 1px solid #e5e7eb;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.form-grid-2 {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
gap: 20px 24px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.form-grid-3 {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
gap: 20px 24px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-selector {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(4, 1fr);
|
|
|
gap: 12px;
|
|
|
margin-bottom: 18px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-btn {
|
|
|
padding: 12px 16px;
|
|
|
border: 1px solid #e5e7eb;
|
|
|
@@ -427,87 +445,87 @@ export function useCoupon() {
|
|
|
transition: all 0.15s ease;
|
|
|
text-align: center;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-btn:hover {
|
|
|
border-color: #3b82f6;
|
|
|
background: #f8fafc;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-btn.active {
|
|
|
border-color: #3b82f6;
|
|
|
background: #eff6ff;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-btn .name {
|
|
|
font-size: 14px;
|
|
|
font-weight: 600;
|
|
|
color: #374151;
|
|
|
margin-bottom: 4px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-btn .hint {
|
|
|
font-size: 12px;
|
|
|
color: #9ca3af;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.type-btn.active .name {
|
|
|
color: #3b82f6;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.scope-grid {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
gap: 16px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.scope-card {
|
|
|
background: #f9fafb;
|
|
|
border: 1px solid #e5e7eb;
|
|
|
border-radius: 8px;
|
|
|
padding: 14px 16px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.scope-card .card-header {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
margin-bottom: 12px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.scope-card .card-label {
|
|
|
font-size: 13px;
|
|
|
font-weight: 500;
|
|
|
color: #374151;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.scope-card .card-body {
|
|
|
min-height: 32px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.coupon-form .el-form-item {
|
|
|
margin-bottom: 0;
|
|
|
align-items: center;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.coupon-form .el-form-item__label {
|
|
|
font-size: 13px;
|
|
|
color: #606266;
|
|
|
padding-right: 8px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.coupon-form .el-input__wrapper,
|
|
|
.coupon-form .el-textarea__inner {
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.coupon-form .form-label-90 .el-form-item__label {
|
|
|
width: 90px !important;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.coupon-form .form-label-100 .el-form-item__label {
|
|
|
width: 100px !important;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.preview-box {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
@@ -520,11 +538,11 @@ export function useCoupon() {
|
|
|
font-size: 14px;
|
|
|
color: #374151;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.preview-box .value {
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@media (max-width: 1200px) {
|
|
|
.form-grid-3,
|
|
|
.scope-grid {
|
|
|
@@ -534,7 +552,7 @@ export function useCoupon() {
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@media (max-width: 768px) {
|
|
|
.form-grid-2,
|
|
|
.form-grid-3,
|
|
|
@@ -551,7 +569,7 @@ export function useCoupon() {
|
|
|
return (
|
|
|
<div class="coupon-form">
|
|
|
<style>{formStyles}</style>
|
|
|
-
|
|
|
+
|
|
|
<div class="form-block">
|
|
|
<div class="block-title">基本信息</div>
|
|
|
<ElForm label-width="90px" size="default">
|
|
|
@@ -580,8 +598,8 @@ export function useCoupon() {
|
|
|
showIcon={true}
|
|
|
style={{marginTop: '12px'}}
|
|
|
>
|
|
|
- {formData.receiveType === 'Collect'
|
|
|
- ? '主动领取:将显示在用户端小程序领券中心,用户可自行领取'
|
|
|
+ {formData.receiveType === 'Collect'
|
|
|
+ ? '主动领取:将显示在用户端小程序领券中心,用户可自行领取'
|
|
|
: '系统发放:创建后可在列表中点击发放,选择指定用户或全部用户'}
|
|
|
</ElAlert>
|
|
|
</ElForm>
|
|
|
@@ -591,7 +609,7 @@ export function useCoupon() {
|
|
|
<div class="block-title">优惠券类型</div>
|
|
|
<div class="type-selector">
|
|
|
{[1, 2, 3, 4].map(type => (
|
|
|
- <div
|
|
|
+ <div
|
|
|
class={`type-btn ${formData.type === type ? 'active' : ''}`}
|
|
|
onClick={() => { formData.type = type; }}
|
|
|
>
|
|
|
@@ -605,26 +623,26 @@ export function useCoupon() {
|
|
|
</div>
|
|
|
))}
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
{formData.type && (
|
|
|
<ElForm label-width="90px" size="default">
|
|
|
<div class="form-grid-3">
|
|
|
<ElFormItem label="优惠值" required>
|
|
|
- <ElInputNumber
|
|
|
- v-model={formData.value}
|
|
|
- min={0}
|
|
|
- precision={2}
|
|
|
- class="w-full!"
|
|
|
- placeholder={formData.type === 2 ? "折扣值如8表示8折" : "优惠金额"}
|
|
|
- prefix={formData.type !== 2 ? "¥" : ""}
|
|
|
+ <ElInputNumber
|
|
|
+ v-model={formData.value}
|
|
|
+ min={0}
|
|
|
+ precision={2}
|
|
|
+ class="w-full!"
|
|
|
+ placeholder={formData.type === 2 ? "折扣值如8表示8折" : "优惠金额"}
|
|
|
+ prefix={formData.type !== 2 ? "¥" : ""}
|
|
|
/>
|
|
|
</ElFormItem>
|
|
|
<ElFormItem label="发放总量" required>
|
|
|
- <ElInputNumber
|
|
|
- v-model={formData.totalCount}
|
|
|
- min={1}
|
|
|
- class="w-full!"
|
|
|
- placeholder="发放总数量"
|
|
|
+ <ElInputNumber
|
|
|
+ v-model={formData.totalCount}
|
|
|
+ min={1}
|
|
|
+ class="w-full!"
|
|
|
+ placeholder="发放总数量"
|
|
|
/>
|
|
|
</ElFormItem>
|
|
|
<ElFormItem label="有效期" required>
|
|
|
@@ -761,7 +779,7 @@ export function useCoupon() {
|
|
|
couponDesc: formData.description,
|
|
|
receiveLimit: 1
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
const { code, message: errorMsg } = await createCoupon(submitData);
|
|
|
if (code === 200) {
|
|
|
message("新增成功", { type: "success" });
|