add: 优化优惠券问题
This commit is contained in:
parent
350a314feb
commit
9eb3b8e306
|
|
@ -126,4 +126,20 @@ export function deleteRecord(params) {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
params
|
params
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 智慧充值 配置信息修改
|
||||||
|
export function shopRecharge(data) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl + "/admin/shopRecharge"}`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 智慧充值 配置信息获取
|
||||||
|
export function shopRechargeGet() {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl + "/admin/shopRecharge"}`,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
* @param {string} cls
|
* @param {string} cls
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export function hasClass(ele: HTMLElement, cls: string) {
|
export function hasClass(ele : HTMLElement, cls : string) {
|
||||||
return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
|
return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,8 +13,8 @@ export function hasClass(ele: HTMLElement, cls: string) {
|
||||||
* @param {HTMLElement} ele
|
* @param {HTMLElement} ele
|
||||||
* @param {string} cls
|
* @param {string} cls
|
||||||
*/
|
*/
|
||||||
export function addClass(ele: HTMLElement, cls: string) {
|
export function addClass(ele : HTMLElement, cls : string) {
|
||||||
if (!hasClass(ele, cls)) ele.className += " " + cls;
|
if (!hasClass(ele, cls)) ele.className += " " + cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -22,11 +22,11 @@ export function addClass(ele: HTMLElement, cls: string) {
|
||||||
* @param {HTMLElement} ele
|
* @param {HTMLElement} ele
|
||||||
* @param {string} cls
|
* @param {string} cls
|
||||||
*/
|
*/
|
||||||
export function removeClass(ele: HTMLElement, cls: string) {
|
export function removeClass(ele : HTMLElement, cls : string) {
|
||||||
if (hasClass(ele, cls)) {
|
if (hasClass(ele, cls)) {
|
||||||
const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
|
const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
|
||||||
ele.className = ele.className.replace(reg, " ");
|
ele.className = ele.className.replace(reg, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,9 +35,9 @@ export function removeClass(ele: HTMLElement, cls: string) {
|
||||||
* @param {string} path
|
* @param {string} path
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
export function isExternal(path: string) {
|
export function isExternal(path : string) {
|
||||||
const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
|
const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
|
||||||
return isExternal;
|
return isExternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -46,15 +46,15 @@ export function isExternal(path: string) {
|
||||||
* @param growthRate
|
* @param growthRate
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function formatGrowthRate(growthRate: number) {
|
export function formatGrowthRate(growthRate : number) {
|
||||||
if (growthRate === 0) {
|
if (growthRate === 0) {
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
const formattedRate = Math.abs(growthRate * 100)
|
const formattedRate = Math.abs(growthRate * 100)
|
||||||
.toFixed(2)
|
.toFixed(2)
|
||||||
.replace(/\.?0+$/, "");
|
.replace(/\.?0+$/, "");
|
||||||
return formattedRate + "%";
|
return formattedRate + "%";
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Parse the time to string
|
* Parse the time to string
|
||||||
|
|
@ -62,83 +62,174 @@ export function formatGrowthRate(growthRate: number) {
|
||||||
* @param {string} cFormat
|
* @param {string} cFormat
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function parseTime(time: string | number | Date | null, cFormat: string | undefined) {
|
export function parseTime(time : string | number | Date | null, cFormat : string | undefined) {
|
||||||
if (arguments.length === 0) {
|
if (arguments.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
|
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
|
||||||
let date;
|
let date;
|
||||||
if (typeof time === "undefined" || time === null || time === "null") {
|
if (typeof time === "undefined" || time === null || time === "null") {
|
||||||
return "";
|
return "";
|
||||||
} else if (typeof time === "object") {
|
} else if (typeof time === "object") {
|
||||||
date = time;
|
date = time;
|
||||||
} else {
|
} else {
|
||||||
if (typeof time === "string" && /^[0-9]+$/.test(time)) {
|
if (typeof time === "string" && /^[0-9]+$/.test(time)) {
|
||||||
time = parseInt(time);
|
time = parseInt(time);
|
||||||
}
|
}
|
||||||
if (typeof time === "number" && time.toString().length === 10) {
|
if (typeof time === "number" && time.toString().length === 10) {
|
||||||
time = time * 1000;
|
time = time * 1000;
|
||||||
}
|
}
|
||||||
date = new Date(time);
|
date = new Date(time);
|
||||||
}
|
}
|
||||||
const formatObj = {
|
const formatObj = {
|
||||||
y: date.getFullYear(),
|
y: date.getFullYear(),
|
||||||
m: date.getMonth() + 1,
|
m: date.getMonth() + 1,
|
||||||
d: date.getDate(),
|
d: date.getDate(),
|
||||||
h: date.getHours(),
|
h: date.getHours(),
|
||||||
i: date.getMinutes(),
|
i: date.getMinutes(),
|
||||||
s: date.getSeconds(),
|
s: date.getSeconds(),
|
||||||
a: date.getDay()
|
a: date.getDay()
|
||||||
};
|
};
|
||||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key: keyof typeof formatObj): string => {
|
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key : keyof typeof formatObj) : string => {
|
||||||
let value = formatObj[key];
|
let value = formatObj[key];
|
||||||
// Note: getDay() returns 0 on Sunday
|
// Note: getDay() returns 0 on Sunday
|
||||||
if (key === "a") {
|
if (key === "a") {
|
||||||
return ["日", "一", "二", "三", "四", "五", "六"][value];
|
return ["日", "一", "二", "三", "四", "五", "六"][value];
|
||||||
}
|
}
|
||||||
if (result.length > 0 && value < 10) {
|
if (result.length > 0 && value < 10) {
|
||||||
value = Number("0" + value.toString());
|
value = Number("0" + value.toString());
|
||||||
}
|
}
|
||||||
return value.toString() || "0";
|
return value.toString() || "0";
|
||||||
});
|
});
|
||||||
return time_str;
|
return time_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载文件
|
// 下载文件
|
||||||
export function downloadFile(obj: BlobPart, name: string, suffix: string, useUnix = true) {
|
export function downloadFile(obj : BlobPart, name : string, suffix : string, useUnix = true) {
|
||||||
const url = window.URL.createObjectURL(new Blob([obj]));
|
const url = window.URL.createObjectURL(new Blob([obj]));
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.style.display = "none";
|
link.style.display = "none";
|
||||||
link.href = url;
|
link.href = url;
|
||||||
const newFilename = useUnix ? (parseTime(new Date(), undefined) + "-") : '' + name.trim()
|
const newFilename = useUnix ? (parseTime(new Date(), undefined) + "-") : '' + name.trim()
|
||||||
const fileName = newFilename + "." + suffix;
|
const fileName = newFilename + "." + suffix;
|
||||||
link.setAttribute("download", fileName);
|
link.setAttribute("download", fileName);
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断主店同步是否启用
|
* 判断主店同步是否启用
|
||||||
*/
|
*/
|
||||||
export function isSyncStatus() {
|
export function isSyncStatus() {
|
||||||
let userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || '{}'))
|
let userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || '{}'))
|
||||||
if (userInfo.value.isHeadShop == 0 && userInfo.value.isEnableProdSync == 1 && userInfo.value.isEnableVipSync == 1 && userInfo.value.isEnableConsSync == 1) {
|
if (userInfo.value.isHeadShop == 0 && userInfo.value.isEnableProdSync == 1 && userInfo.value.isEnableVipSync == 1 && userInfo.value.isEnableConsSync == 1) {
|
||||||
return true
|
return true
|
||||||
}else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否有某权限
|
* 判断是否有某权限
|
||||||
*/
|
*/
|
||||||
export function hasPermission(params: any) {
|
export function hasPermission(params : any) {
|
||||||
let $PermissionObj = JSON.parse(localStorage.getItem("permission") || '[]' )
|
let $PermissionObj = JSON.parse(localStorage.getItem("permission") || '[]')
|
||||||
const obj = $PermissionObj.find((v: any) => v == params || v == params)
|
const obj = $PermissionObj.find((v : any) => v == params || v == params)
|
||||||
if (obj) {
|
if (obj) {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤输入,只允许数字和最多两位小数
|
||||||
|
* @param {string} value - 输入框当前值
|
||||||
|
* @param {boolean} isIntegerOnly - 是否只允许正整数(无小数点),开启时最小值为1
|
||||||
|
* @returns {string} 过滤后的合法值
|
||||||
|
*/
|
||||||
|
export function filterNumberInput(value, isIntegerOnly = false) {
|
||||||
|
// 第一步就过滤所有非数字和非小数点的字符(包括字母)
|
||||||
|
let filtered = value.replace(/[^\d.]/g, "");
|
||||||
|
|
||||||
|
// 整数模式处理
|
||||||
|
if (isIntegerOnly) {
|
||||||
|
// 移除所有小数点
|
||||||
|
filtered = filtered.replace(/\./g, "");
|
||||||
|
|
||||||
|
// 处理前导零
|
||||||
|
filtered = filtered.replace(/^0+(\d)/, "$1") || filtered;
|
||||||
|
|
||||||
|
// 空值处理(允许临时删除)
|
||||||
|
if (filtered === "") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最小值限制
|
||||||
|
if (filtered === "0" || parseInt(filtered, 10) < 1) {
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 小数模式处理
|
||||||
|
const parts = filtered.split(".");
|
||||||
|
if (parts.length > 1) {
|
||||||
|
filtered = parts[0] + "." + (parts[1].substring(0, 2) || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理前导零
|
||||||
|
if (filtered.startsWith("0") && filtered.length > 1 && !filtered.startsWith("0.")) {
|
||||||
|
filtered = filtered.replace(/^0+(\d)/, "$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将时分秒字符串转换为完整日期格式
|
||||||
|
* @param {string} timeStr - 时分秒字符串,格式需为 HH:mm:ss(如 '00:53:00')
|
||||||
|
* @param {Object} options - 可选配置项
|
||||||
|
* @param {string} [options.customDate] - 自定义日期,格式为 YYYY-MM-DD(默认使用当前日期)
|
||||||
|
* @param {string} [options.format='YYYY-MM-DD HH:mm:ss'] - 输出的日期格式
|
||||||
|
* @returns {string|null} 转换后的日期字符串,失败时返回 null
|
||||||
|
*/
|
||||||
|
export function convertTimeToDate(timeStr, options = {}) {
|
||||||
|
// 解构配置项,设置默认值
|
||||||
|
const { customDate, format = "YYYY-MM-DD HH:mm:ss" } = options;
|
||||||
|
|
||||||
|
// 1. 校验时分秒格式(必须为 HH:mm:ss,允许数字1-2位)
|
||||||
|
const timeRegex = /^\d{1,2}:\d{1,2}:\d{1,2}$/;
|
||||||
|
if (!timeRegex.test(timeStr)) {
|
||||||
|
console.error("时分秒格式错误,请使用 HH:mm:ss 格式(如 00:53:00)");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 确定日期部分(自定义日期或当前日期)
|
||||||
|
let datePart;
|
||||||
|
if (customDate) {
|
||||||
|
// 校验自定义日期格式
|
||||||
|
if (!dayjs(customDate, "YYYY-MM-DD", true).isValid()) {
|
||||||
|
console.error("自定义日期格式错误,请使用 YYYY-MM-DD 格式(如 2024-05-20)");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
datePart = customDate;
|
||||||
|
} else {
|
||||||
|
// 使用当前日期(格式:YYYY-MM-DD)
|
||||||
|
datePart = dayjs().format("YYYY-MM-DD");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 组合日期和时分秒,生成完整日期对象
|
||||||
|
const fullDateTime = `${datePart} ${timeStr}`;
|
||||||
|
const dateObj = dayjs(fullDateTime);
|
||||||
|
|
||||||
|
// 4. 校验完整日期是否有效(如避免 2024-02-30 这种无效日期)
|
||||||
|
if (!dateObj.isValid()) {
|
||||||
|
console.error("生成的日期无效,请检查日期或时分秒是否合理");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 按指定格式返回日期字符串
|
||||||
|
return dateObj.format(format);
|
||||||
|
}
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="giveNum" label="总发放数量" width="100">
|
<el-table-column prop="giveNum" label="总发放数量" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.giveNum == -10086 ? "无限" : scope.row.giftNum }}
|
{{ scope.row.giveNum == -10086 ? "无限" : scope.row.giveNum }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="giftNum" label="已领取" width="180">
|
<el-table-column prop="giftNum" label="已领取" width="180">
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
label-width="160px"
|
label-width="160px"
|
||||||
class="dialog-form"
|
class="dialog-form"
|
||||||
>
|
>
|
||||||
<el-form-item label="优惠券名称" prop="title">
|
<el-form-item :label="titleOptions.name" prop="title">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.title"
|
v-model="form.title"
|
||||||
:maxlength="20"
|
:maxlength="20"
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
placeholder="请输入使用门槛"
|
placeholder="请输入使用门槛"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="8"
|
||||||
@input="(e) => (form.fullAmount = filterNumberInput(e))"
|
@input="(e) => (form.fullAmount = filterNumberInput(e))"
|
||||||
>
|
>
|
||||||
<template #prepend>满</template>
|
<template #prepend>满</template>
|
||||||
|
|
@ -40,6 +41,7 @@
|
||||||
placeholder="请输入满减金额"
|
placeholder="请输入满减金额"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="8"
|
||||||
@input="(e) => (form.discountAmount = filterNumberInput(e))"
|
@input="(e) => (form.discountAmount = filterNumberInput(e))"
|
||||||
>
|
>
|
||||||
<template #prepend>减</template>
|
<template #prepend>减</template>
|
||||||
|
|
@ -56,6 +58,7 @@
|
||||||
placeholder="请输入使用门槛"
|
placeholder="请输入使用门槛"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="8"
|
||||||
@input="(e) => (form.fullAmount = filterNumberInput(e))"
|
@input="(e) => (form.fullAmount = filterNumberInput(e))"
|
||||||
>
|
>
|
||||||
<template #prepend>满</template>
|
<template #prepend>满</template>
|
||||||
|
|
@ -63,10 +66,10 @@
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="指定门槛商品">
|
<el-form-item label="可用商品">
|
||||||
<el-radio-group v-model="goodsType">
|
<el-radio-group v-model="goodsType">
|
||||||
<el-radio label="全部商品参与计算门槛" :value="1"></el-radio>
|
<el-radio label="全部商品可用" :value="1"></el-radio>
|
||||||
<el-radio label="部分商品参与计算门槛" :value="2"></el-radio>
|
<el-radio label="部分商品可用" :value="2"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="goodsType" v-if="goodsType == 2">
|
<el-form-item prop="goodsType" v-if="goodsType == 2">
|
||||||
|
|
@ -78,7 +81,7 @@
|
||||||
:max-collapse-tags="3"
|
:max-collapse-tags="3"
|
||||||
collapse-tags
|
collapse-tags
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 300px"
|
||||||
@change="selectFoodsConfirm"
|
@change="selectFoodsConfirm"
|
||||||
></el-cascader>
|
></el-cascader>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -113,6 +116,7 @@
|
||||||
placeholder="请输入使用门槛"
|
placeholder="请输入使用门槛"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="8"
|
||||||
@input="(e) => (form.discountAmount = filterNumberInput(e))"
|
@input="(e) => (form.discountAmount = filterNumberInput(e))"
|
||||||
>
|
>
|
||||||
<template #prepend>满</template>
|
<template #prepend>满</template>
|
||||||
|
|
@ -126,6 +130,7 @@
|
||||||
v-model="form.maxDiscountAmount"
|
v-model="form.maxDiscountAmount"
|
||||||
placeholder="请输入金额"
|
placeholder="请输入金额"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
|
:maxlength="8"
|
||||||
@input="(e) => (form.maxDiscountAmount = filterNumberInput(e))"
|
@input="(e) => (form.maxDiscountAmount = filterNumberInput(e))"
|
||||||
>
|
>
|
||||||
<template #append>可用</template>
|
<template #append>可用</template>
|
||||||
|
|
@ -133,7 +138,33 @@
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="form.couponType == 4"></div>
|
<div v-if="form.couponType == 4 || form.couponType == 6">
|
||||||
|
<el-form-item label="可用商品">
|
||||||
|
<el-radio-group v-model="goodsType">
|
||||||
|
<el-radio label="全部商品可用" :value="1"></el-radio>
|
||||||
|
<el-radio label="部分商品可用" :value="2"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="goodsType" v-if="goodsType == 2">
|
||||||
|
<el-cascader
|
||||||
|
v-model="goodsTypeCascaderValue"
|
||||||
|
:options="goodsList"
|
||||||
|
:props="cascaderProps"
|
||||||
|
:show-all-levels="false"
|
||||||
|
:max-collapse-tags="3"
|
||||||
|
collapse-tags
|
||||||
|
clearable
|
||||||
|
style="width: 300px"
|
||||||
|
@change="selectFoodsConfirm"
|
||||||
|
></el-cascader>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="使用规则">
|
||||||
|
<el-radio-group v-model="form.useRule">
|
||||||
|
<el-radio label="从最低价开始抵扣" value="price_asc"></el-radio>
|
||||||
|
<el-radio label="从最高价开始抵扣" value="price_desc"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
<div v-if="form.couponType == 6"></div>
|
<div v-if="form.couponType == 6"></div>
|
||||||
<div class="title">指定设置</div>
|
<div class="title">指定设置</div>
|
||||||
<el-form-item label="选择门店" prop="useShopType" v-if="shopInfo.isHeadShop">
|
<el-form-item label="选择门店" prop="useShopType" v-if="shopInfo.isHeadShop">
|
||||||
|
|
@ -150,6 +181,7 @@
|
||||||
clearable
|
clearable
|
||||||
placeholder="请选择门店"
|
placeholder="请选择门店"
|
||||||
@change="shopsChange"
|
@change="shopsChange"
|
||||||
|
style="width: 300px"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
:label="item.shopName"
|
:label="item.shopName"
|
||||||
|
|
@ -159,11 +191,11 @@
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="form.couponType != 2">
|
<div v-if="form.couponType != 2 && form.couponType != 4 && form.couponType != 6">
|
||||||
<el-form-item label="指定门槛商品" prop="goodsType">
|
<el-form-item label="指定门槛商品" prop="goodsType">
|
||||||
<el-radio-group v-model="goodsType">
|
<el-radio-group v-model="goodsType">
|
||||||
<el-radio label="全部商品参与计算门槛" :value="1"></el-radio>
|
<el-radio label="全部商品可用" :value="1"></el-radio>
|
||||||
<el-radio label="部分商品参与计算门槛" :value="2"></el-radio>
|
<el-radio label="部分商品可用" :value="2"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="goodsType == 2">
|
<el-form-item v-if="goodsType == 2">
|
||||||
|
|
@ -175,7 +207,7 @@
|
||||||
:max-collapse-tags="3"
|
:max-collapse-tags="3"
|
||||||
collapse-tags
|
collapse-tags
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 300px"
|
||||||
@change="selectFoodsConfirm"
|
@change="selectFoodsConfirm"
|
||||||
></el-cascader>
|
></el-cascader>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -200,6 +232,7 @@
|
||||||
v-model="form.validDays"
|
v-model="form.validDays"
|
||||||
placeholder="请输入有效期"
|
placeholder="请输入有效期"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
|
:maxlength="5"
|
||||||
v-if="form.validType == 'fixed'"
|
v-if="form.validType == 'fixed'"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
@input="validDaysInput"
|
@input="validDaysInput"
|
||||||
|
|
@ -229,6 +262,7 @@
|
||||||
placeholder="请输入隔天生效日期"
|
placeholder="请输入隔天生效日期"
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="5"
|
||||||
@input="daysToTakeEffectInput"
|
@input="daysToTakeEffectInput"
|
||||||
>
|
>
|
||||||
<template #prepend>隔</template>
|
<template #prepend>隔</template>
|
||||||
|
|
@ -301,6 +335,7 @@
|
||||||
placeholder="请输入总发放数量"
|
placeholder="请输入总发放数量"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="5"
|
||||||
@input="giveNumInput"
|
@input="giveNumInput"
|
||||||
>
|
>
|
||||||
<template #append>张</template>
|
<template #append>张</template>
|
||||||
|
|
@ -322,6 +357,7 @@
|
||||||
placeholder="请输入每人限领量"
|
placeholder="请输入每人限领量"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="5"
|
||||||
@input="getLimitInput"
|
@input="getLimitInput"
|
||||||
>
|
>
|
||||||
<template #append>张</template>
|
<template #append>张</template>
|
||||||
|
|
@ -346,6 +382,7 @@
|
||||||
placeholder="需小于或等于每人限领量"
|
placeholder="需小于或等于每人限领量"
|
||||||
style="width: 255px"
|
style="width: 255px"
|
||||||
input-style="text-align: center;"
|
input-style="text-align: center;"
|
||||||
|
:maxlength="5"
|
||||||
@input="useLimitInput"
|
@input="useLimitInput"
|
||||||
>
|
>
|
||||||
<template #append>张/每人1天</template>
|
<template #append>张/每人1天</template>
|
||||||
|
|
@ -420,12 +457,14 @@
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { dayjs } from "element-plus";
|
import { dayjs } from "element-plus";
|
||||||
import { ref, reactive, onMounted } from "vue";
|
import { ref, reactive, onMounted } from "vue";
|
||||||
|
import { filterNumberInput } from "@/utils";
|
||||||
import { getBranchPage, getProductList, getCategoryList, addCoupon } from "@/api/coupon/index.js";
|
import { getBranchPage, getProductList, getCategoryList, addCoupon } from "@/api/coupon/index.js";
|
||||||
|
|
||||||
const shopInfo = ref("");
|
const shopInfo = ref("");
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
|
|
||||||
const titleOptions = reactive({
|
const titleOptions = reactive({
|
||||||
|
name: "优惠券名称",
|
||||||
title: "添加优惠券",
|
title: "添加优惠券",
|
||||||
couponTypeList: [
|
couponTypeList: [
|
||||||
{
|
{
|
||||||
|
|
@ -566,7 +605,7 @@ const form = ref({
|
||||||
discountRate: "", // 折扣%
|
discountRate: "", // 折扣%
|
||||||
maxDiscountAmount: "", // 可抵扣最大金额 元
|
maxDiscountAmount: "", // 可抵扣最大金额 元
|
||||||
useRule: "price_asc", // 使用规则:price_asc-价格低到高,price_desc-高到低
|
useRule: "price_asc", // 使用规则:price_asc-价格低到高,price_desc-高到低
|
||||||
discountNum: "", // 抵扣数量
|
discountNum: 1, // 抵扣数量
|
||||||
otherCouponShare: 1, // 与其它优惠共享:0-否,1-是
|
otherCouponShare: 1, // 与其它优惠共享:0-否,1-是
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -585,7 +624,7 @@ function reset() {
|
||||||
|
|
||||||
// 自定义校验使用门槛
|
// 自定义校验使用门槛
|
||||||
const fullAmountValidate = (rule, value, callback) => {
|
const fullAmountValidate = (rule, value, callback) => {
|
||||||
if (form.value.fullAmount <= 0) {
|
if (form.value.fullAmount < 0) {
|
||||||
callback(new Error("请输入使用门槛"));
|
callback(new Error("请输入使用门槛"));
|
||||||
} else if (form.value.discountAmount <= 0) {
|
} else if (form.value.discountAmount <= 0) {
|
||||||
callback(new Error("请输入满减金额"));
|
callback(new Error("请输入满减金额"));
|
||||||
|
|
@ -594,7 +633,7 @@ const fullAmountValidate = (rule, value, callback) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const fullAmountValidate2 = (rule, value, callback) => {
|
const fullAmountValidate2 = (rule, value, callback) => {
|
||||||
if (form.value.fullAmount <= 0) {
|
if (form.value.fullAmount < 0 || form.value.fullAmount == "") {
|
||||||
callback(new Error("请输入使用门槛"));
|
callback(new Error("请输入使用门槛"));
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
|
|
@ -812,6 +851,7 @@ function show(t, obj = null) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let m = titleOptions.couponTypeList.find((item) => item.value == t);
|
let m = titleOptions.couponTypeList.find((item) => item.value == t);
|
||||||
|
titleOptions.name = `${m.label}名称`;
|
||||||
if (obj && obj.id) {
|
if (obj && obj.id) {
|
||||||
titleOptions.title = `编辑${m.label}`;
|
titleOptions.title = `编辑${m.label}`;
|
||||||
|
|
||||||
|
|
@ -919,6 +959,9 @@ function convertTimeToDate(timeStr, options = {}) {
|
||||||
const time = 500;
|
const time = 500;
|
||||||
const discountNumInput = _.debounce(function (value) {
|
const discountNumInput = _.debounce(function (value) {
|
||||||
form.value.discountNum = filterNumberInput(value, true);
|
form.value.discountNum = filterNumberInput(value, true);
|
||||||
|
if (form.value.discountNum == "") {
|
||||||
|
form.value.discountNum = 1;
|
||||||
|
}
|
||||||
}, time);
|
}, time);
|
||||||
|
|
||||||
const discountRateInput = _.debounce(function (value) {
|
const discountRateInput = _.debounce(function (value) {
|
||||||
|
|
@ -957,51 +1000,6 @@ const useLimitInput = _.debounce(function (value) {
|
||||||
}
|
}
|
||||||
}, time);
|
}, time);
|
||||||
|
|
||||||
/**
|
|
||||||
* 过滤输入,只允许数字和最多两位小数
|
|
||||||
* @param {string} value - 输入框当前值
|
|
||||||
* @param {boolean} isIntegerOnly - 是否只允许正整数(无小数点),开启时最小值为1
|
|
||||||
* @returns {string} 过滤后的合法值
|
|
||||||
*/
|
|
||||||
function filterNumberInput(value, isIntegerOnly = false) {
|
|
||||||
// 第一步就过滤所有非数字和非小数点的字符(包括字母)
|
|
||||||
let filtered = value.replace(/[^\d.]/g, "");
|
|
||||||
|
|
||||||
// 整数模式处理
|
|
||||||
if (isIntegerOnly) {
|
|
||||||
// 移除所有小数点
|
|
||||||
filtered = filtered.replace(/\./g, "");
|
|
||||||
|
|
||||||
// 处理前导零
|
|
||||||
filtered = filtered.replace(/^0+(\d)/, "$1") || filtered;
|
|
||||||
|
|
||||||
// 空值处理(允许临时删除)
|
|
||||||
if (filtered === "") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最小值限制
|
|
||||||
if (filtered === "0" || parseInt(filtered, 10) < 1) {
|
|
||||||
return "1";
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 小数模式处理
|
|
||||||
const parts = filtered.split(".");
|
|
||||||
if (parts.length > 1) {
|
|
||||||
filtered = parts[0] + "." + (parts[1].substring(0, 2) || "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理前导零
|
|
||||||
if (filtered.startsWith("0") && filtered.length > 1 && !filtered.startsWith("0.")) {
|
|
||||||
filtered = filtered.replace(/^0+(\d)/, "$1");
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
show,
|
show,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,100 +1,105 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-between box">
|
<div class="flex justify-between box">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<img :src="getIconPath(props.icon)" class="icon" />
|
<img :src="getIconPath(props.icon)" class="icon" />
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="name">{{ props.name }}</div>
|
<div class="name">{{ props.name }}</div>
|
||||||
<div class="intro">
|
<div class="intro">
|
||||||
{{ props.intro }}
|
{{ props.intro }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-switch v-model="isOpen" v-if="props.showSwitch" />
|
<el-switch
|
||||||
</div>
|
:active-value="1"
|
||||||
</div>
|
:inactive-value="0"
|
||||||
|
v-model="isOpen"
|
||||||
|
v-if="props.showSwitch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import defaultIcon from "@/assets/logo.png";
|
import defaultIcon from "@/assets/logo.png";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
defautl: "",
|
defautl: "",
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
intro: {
|
intro: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
showSwitch: {
|
showSwitch: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const isOpen = defineModel("isOpen", {
|
const isOpen = defineModel("isOpen", {
|
||||||
type: Boolean,
|
type: [Boolean, String, Number],
|
||||||
default: false,
|
default: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 动态获取PNG图标路径
|
// 动态获取PNG图标路径
|
||||||
const getIconPath = (iconName) => {
|
const getIconPath = (iconName) => {
|
||||||
try {
|
try {
|
||||||
// 直接导入对应PNG文件
|
// 直接导入对应PNG文件
|
||||||
return new URL(`/src/assets/applocation/${iconName}.png`, import.meta.url).href;
|
return new URL(`/src/assets/applocation/${iconName}.png`, import.meta.url).href;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`图标 ${iconName}.png 不存在`);
|
console.warn(`图标 ${iconName}.png 不存在`);
|
||||||
return defaultIcon; // 图标不存在时使用默认图标
|
return defaultIcon; // 图标不存在时使用默认图标
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.box {
|
.box {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
transition: all 0.1s ease-in-out;
|
transition: all 0.1s ease-in-out;
|
||||||
}
|
}
|
||||||
.item {
|
.item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
// &:hover {
|
// &:hover {
|
||||||
// cursor: pointer;
|
// cursor: pointer;
|
||||||
// background-color: #d5ebff;
|
// background-color: #d5ebff;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
.name {
|
.name {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.intro {
|
.intro {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: #666;
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
line-clamp: 1;
|
line-clamp: 1;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ async function relevanceCouponAjax() {
|
||||||
try {
|
try {
|
||||||
tableData.loading = true;
|
tableData.loading = true;
|
||||||
const res = await relevanceCoupon({
|
const res = await relevanceCoupon({
|
||||||
couponId: row.value.syncId ? row.value.syncId : row.value.id,
|
couponId: row.value.id,
|
||||||
type: tableData.type,
|
type: tableData.type,
|
||||||
page: tableData.page,
|
page: tableData.page,
|
||||||
size: tableData.pageSize,
|
size: tableData.pageSize,
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,28 @@
|
||||||
class="dialog-form"
|
class="dialog-form"
|
||||||
>
|
>
|
||||||
<el-form-item label="赠券门槛" prop="fullAmount">
|
<el-form-item label="赠券门槛" prop="fullAmount">
|
||||||
<el-input
|
<div class="center">
|
||||||
v-model="form.fullAmount"
|
<el-input
|
||||||
placeholder="请输入赠券门槛"
|
v-model="form.fullAmount"
|
||||||
style="width: 200px"
|
placeholder="请输入赠券门槛"
|
||||||
input-style="text-align: center;"
|
style="width: 240px"
|
||||||
@input="(e) => (form.fullAmount = filterNumberInput(e))"
|
input-style="text-align: center;"
|
||||||
>
|
@input="(e) => (form.fullAmount = filterNumberInput(e))"
|
||||||
<template #prepend>满</template>
|
>
|
||||||
<template #append>元</template>
|
<template #prepend>满</template>
|
||||||
</el-input>
|
<template #append>元</template>
|
||||||
|
</el-input>
|
||||||
|
<el-tooltip
|
||||||
|
class="box-item"
|
||||||
|
effect="dark"
|
||||||
|
content="每单消费满此金额后赠送券 "
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
<el-icon size="18">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="优惠券" prop="coupon">
|
<el-form-item label="优惠券" prop="coupon">
|
||||||
<div class="center">
|
<div class="center">
|
||||||
|
|
@ -39,16 +51,6 @@
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-input
|
|
||||||
v-model="couponGiveNum"
|
|
||||||
placeholder="请输入"
|
|
||||||
style="width: 250px"
|
|
||||||
input-style="text-align: center;"
|
|
||||||
@input="couponGiveNumInput"
|
|
||||||
>
|
|
||||||
<template #prepend>每次赠送</template>
|
|
||||||
<template #append>张</template>
|
|
||||||
</el-input>
|
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="title">指定设置</div>
|
<div class="title">指定设置</div>
|
||||||
|
|
@ -80,6 +82,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="每次赠送">
|
||||||
|
<el-input
|
||||||
|
v-model="couponGiveNum"
|
||||||
|
placeholder="请输入"
|
||||||
|
style="width: 200px"
|
||||||
|
input-style="text-align: center;"
|
||||||
|
@input="couponGiveNumInput"
|
||||||
|
>
|
||||||
|
<template #append>张</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="每人限量" prop="getLimit">
|
<el-form-item label="每人限量" prop="getLimit">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="center">
|
<div class="center">
|
||||||
|
|
@ -121,6 +134,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
|
import { filterNumberInput } from "@/utils";
|
||||||
import { addConsumerCoupon, couponPage, updateConsumerCouponById } from "@/api/coupon/index.js";
|
import { addConsumerCoupon, couponPage, updateConsumerCouponById } from "@/api/coupon/index.js";
|
||||||
const shopInfo = ref("");
|
const shopInfo = ref("");
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
|
|
@ -350,55 +364,13 @@ onMounted(() => {
|
||||||
couponPageAjax();
|
couponPageAjax();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* 过滤输入,只允许数字和最多两位小数
|
|
||||||
* @param {string} value - 输入框当前值
|
|
||||||
* @param {boolean} isIntegerOnly - 是否只允许正整数(无小数点),开启时最小值为1
|
|
||||||
* @returns {string} 过滤后的合法值
|
|
||||||
*/
|
|
||||||
function filterNumberInput(value, isIntegerOnly = false) {
|
|
||||||
// 第一步就过滤所有非数字和非小数点的字符(包括字母)
|
|
||||||
let filtered = value.replace(/[^\d.]/g, "");
|
|
||||||
|
|
||||||
// 整数模式处理
|
|
||||||
if (isIntegerOnly) {
|
|
||||||
// 移除所有小数点
|
|
||||||
filtered = filtered.replace(/\./g, "");
|
|
||||||
|
|
||||||
// 处理前导零
|
|
||||||
filtered = filtered.replace(/^0+(\d)/, "$1") || filtered;
|
|
||||||
|
|
||||||
// 空值处理(允许临时删除)
|
|
||||||
if (filtered === "") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最小值限制
|
|
||||||
if (filtered === "0" || parseInt(filtered, 10) < 1) {
|
|
||||||
return "1";
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 小数模式处理
|
|
||||||
const parts = filtered.split(".");
|
|
||||||
if (parts.length > 1) {
|
|
||||||
filtered = parts[0] + "." + (parts[1].substring(0, 2) || "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理前导零
|
|
||||||
if (filtered.startsWith("0") && filtered.length > 1 && !filtered.startsWith("0.")) {
|
|
||||||
filtered = filtered.replace(/^0+(\d)/, "$1");
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
// input过滤
|
// input过滤
|
||||||
const time = 500;
|
const time = 500;
|
||||||
const couponGiveNumInput = _.debounce(function (value) {
|
const couponGiveNumInput = _.debounce(function (value) {
|
||||||
couponGiveNum.value = filterNumberInput(value, true);
|
couponGiveNum.value = filterNumberInput(value, true);
|
||||||
|
if (couponGiveNum.value == "") {
|
||||||
|
couponGiveNum.value = 1;
|
||||||
|
}
|
||||||
}, time);
|
}, time);
|
||||||
|
|
||||||
const giveNumInput = _.debounce(function (value) {
|
const giveNumInput = _.debounce(function (value) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,11 @@
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="fullAmount" label="赠券门槛" width="180" />
|
<el-table-column prop="fullAmount" label="赠券门槛" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ `满${scope.row.fullAmount}元赠送` }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="getLimit" label="每人限量" width="180">
|
<el-table-column prop="getLimit" label="每人限量" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div v-if="scope.row.getLimit == -10086">无限</div>
|
<div v-if="scope.row.getLimit == -10086">无限</div>
|
||||||
|
|
@ -76,7 +80,6 @@
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
|
||||||
link
|
link
|
||||||
@click="DialogFormRef.show(couponType, scope.row)"
|
@click="DialogFormRef.show(couponType, scope.row)"
|
||||||
>
|
>
|
||||||
|
|
@ -87,7 +90,7 @@
|
||||||
@confirm="deleteHandle(scope.row)"
|
@confirm="deleteHandle(scope.row)"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button type="danger" link size="small">删除</el-button>
|
<el-button type="danger" link>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="giveNum" label="总发放数量" width="100">
|
<el-table-column prop="giveNum" label="总发放数量" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.giveNum == -10086 ? "无限" : scope.row.giftNum }}
|
{{ scope.row.giveNum == -10086 ? "无限" : scope.row.giveNum }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="giftNum" label="已领取" width="180">
|
<el-table-column prop="giftNum" label="已领取" width="180">
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ const menus = ref([
|
||||||
{ name: "弹窗广告", icon: "tcgg", pathName: "", intro: "设置弹窗广告" },
|
{ name: "弹窗广告", icon: "tcgg", pathName: "", intro: "设置弹窗广告" },
|
||||||
{ name: "超级会员", icon: "cjhy", pathName: "superVip", intro: "用户会员管理设置" },
|
{ name: "超级会员", icon: "cjhy", pathName: "superVip", intro: "用户会员管理设置" },
|
||||||
{ name: "新客立减", icon: "xklj", pathName: "newUserDiscount", intro: "首单下单减免金额" },
|
{ name: "新客立减", icon: "xklj", pathName: "newUserDiscount", intro: "首单下单减免金额" },
|
||||||
{ name: "智慧充值", icon: "zhcz", pathName: "", intro: "允许客户充值并使用余额支付" },
|
{ name: "智慧充值", icon: "zhcz", pathName: "wisdom_recharge", intro: "允许客户充值并使用余额支付" },
|
||||||
{ name: "分销", icon: "zhcz", pathName: "", intro: "允许客户充值并使用余额支付" },
|
{ name: "分销", icon: "zhcz", pathName: "", intro: "允许客户充值并使用余额支付" },
|
||||||
{
|
{
|
||||||
name: "消费返现",
|
name: "消费返现",
|
||||||
|
|
|
||||||
|
|
@ -1,149 +1,169 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-dialog title="购买会员方案" v-model="show" @close="reset" width="60%">
|
<el-dialog title="添加方案" v-model="show" @closed="reset" width="730px">
|
||||||
<el-form :model="form" label-width="120px">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
|
||||||
<el-form-item label="周期名称" required>
|
<el-form-item label="减免金额" prop="amount">
|
||||||
<el-input v-model="form.name" placeholder="周期名称" />
|
<el-input
|
||||||
</el-form-item>
|
v-model="form.amount"
|
||||||
<el-form-item label="周期价格" required>
|
placeholder="请输入减免金额"
|
||||||
<el-input v-model="form.price" placeholder="周期价格" type="number" />
|
style="width: 270px"
|
||||||
</el-form-item>
|
:maxlength="8"
|
||||||
<el-form-item label="赠送成长值" required>
|
@input="amountInput"
|
||||||
<el-input v-model="form.reward" placeholder="开通后立刻获得经验" type="number" />
|
>
|
||||||
</el-form-item>
|
<template #append>元</template>
|
||||||
|
</el-input>
|
||||||
<el-form-item label="周期时间" required>
|
</el-form-item>
|
||||||
<div class="flex">
|
<el-form-item label="概率" prop="probability">
|
||||||
<el-input-number
|
<div class="column">
|
||||||
style="width: 300px"
|
<div class="item">
|
||||||
v-model="form.circleTime"
|
<el-input
|
||||||
placeholder="周期时间"
|
v-model="form.probability"
|
||||||
type="number"
|
placeholder="请输入概率"
|
||||||
/>
|
style="width: 270px"
|
||||||
<el-select class="ml-2" v-model="form.circleUnit" placeholder="">
|
@input="probabilityInput"
|
||||||
<el-option label="年" value="年" />
|
>
|
||||||
<el-option label="月" value="月" />
|
<template #append>%</template>
|
||||||
<el-option label="周" value="周" />
|
</el-input>
|
||||||
<el-option label="天" value="天" />
|
</div>
|
||||||
</el-select>
|
<div class="item">
|
||||||
</div>
|
<span class="tips">所有概率相加必须等于100%</span>
|
||||||
</el-form-item>
|
</div>
|
||||||
</el-form>
|
</div>
|
||||||
<div style="text-align: right; margin-top: 20px">
|
</el-form-item>
|
||||||
<el-button @click="close">取消</el-button>
|
</el-form>
|
||||||
<el-button type="primary" @click="submit">{{ isedit ? "更新" : "提交" }}</el-button>
|
<div style="text-align: right; margin-top: 20px">
|
||||||
</div>
|
<el-button @click="close">取消</el-button>
|
||||||
</el-dialog>
|
<el-button type="primary" @click="submit">{{ isedit ? "更新" : "提交" }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import _ from "lodash";
|
||||||
import { ref, toRaw } from "vue";
|
import { ref, toRaw } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
// 控制主弹窗显示
|
// 控制主弹窗显示
|
||||||
const show = ref(false);
|
const show = ref(false);
|
||||||
|
|
||||||
// 控制优惠券选择弹窗显示
|
|
||||||
const couponDialogVisible = ref(false);
|
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
|
const formRef = ref(null);
|
||||||
const form = ref({
|
const form = ref({
|
||||||
name: "",
|
amount: "",
|
||||||
price: 0,
|
probability: "",
|
||||||
reward: 0,
|
});
|
||||||
couponList: [], // 存储已选择的优惠券
|
const rules = ref({
|
||||||
circleTime: 1, // 会员周期
|
amount: [{ required: true, message: "请输入减免金额", trigger: "blur" }],
|
||||||
circleUnit: "月", // 会员周期单位
|
probability: [{ required: true, message: "请输入概率", trigger: "blur" }],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 优惠券列表数据
|
const time = 500;
|
||||||
const couponList = ref([
|
const amountInput = _.debounce(function (value) {
|
||||||
{ id: 1, name: "满100减10", value: "10元" },
|
form.value.amount = filterNumberInput(value);
|
||||||
{ id: 2, name: "满200减30", value: "30元" },
|
}, time);
|
||||||
{ id: 3, name: "满500减100", value: "100元" },
|
const probabilityInput = _.debounce(function (value) {
|
||||||
]);
|
form.value.probability = filterNumberInput(value, true);
|
||||||
|
if (form.value.probability >= 100) {
|
||||||
// 已选择的优惠券
|
form.value.probability = 100;
|
||||||
const selectedCoupons = ref([]);
|
}
|
||||||
|
}, time);
|
||||||
// 打开优惠券选择弹窗
|
|
||||||
function openCouponDialog() {
|
|
||||||
couponDialogVisible.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭优惠券选择弹窗
|
|
||||||
function closeCouponDialog() {
|
|
||||||
couponDialogVisible.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认选择优惠券
|
|
||||||
function confirmCouponSelection() {
|
|
||||||
form.value.couponList = [...selectedCoupons.value];
|
|
||||||
closeCouponDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理优惠券选择
|
|
||||||
function handleCouponSelection(selection) {
|
|
||||||
selectedCoupons.value = selection;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置表单
|
// 重置表单
|
||||||
function reset() {
|
function reset() {
|
||||||
form.value = {
|
form.value = {
|
||||||
name: "",
|
amount: "",
|
||||||
price: 0,
|
probability: "",
|
||||||
reward: 0,
|
};
|
||||||
couponList: [],
|
|
||||||
circleTime: "",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const emits = defineEmits(["submitSuccess"]);
|
|
||||||
// 提交表单
|
// 提交表单
|
||||||
|
const emits = defineEmits(["submitSuccess"]);
|
||||||
function submit() {
|
function submit() {
|
||||||
if (!form.value.name) {
|
formRef.value.validate(async (valid) => {
|
||||||
ElMessage.error("请输入方案名称");
|
try {
|
||||||
return;
|
if (valid) {
|
||||||
}
|
emits("submitSuccess", form.value, dataIndex);
|
||||||
if (form.value.price <= 0) {
|
close();
|
||||||
ElMessage.error("请输入有效的价格");
|
}
|
||||||
return;
|
} catch (err) {
|
||||||
}
|
console.log(err);
|
||||||
if (!form.value.circleTime) {
|
}
|
||||||
ElMessage.error("请选择会员周期");
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
const ispass = form.value.couponList.every((item) => item.num && item.coupon.id);
|
|
||||||
if (!ispass) {
|
|
||||||
ElMessage.error("请选择优惠券并输入数量");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("提交表单数据:", form.value);
|
|
||||||
emits("submitSuccess", form.value, dataIndex);
|
|
||||||
// 在此处可以添加表单提交逻辑,例如调用 API
|
|
||||||
close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let isedit = ref(false);
|
let isedit = ref(false);
|
||||||
let dataIndex = null;
|
let dataIndex = null;
|
||||||
function open(data, index) {
|
function open(data = null, index = 0) {
|
||||||
data = toRaw(data);
|
if (data) {
|
||||||
console.log("data", data);
|
form.value = { ...data };
|
||||||
console.log("index", index);
|
dataIndex = index;
|
||||||
if (data) {
|
isedit.value = true;
|
||||||
form.value = data;
|
} else {
|
||||||
isedit.value = true;
|
dataIndex = null;
|
||||||
dataIndex = index;
|
isedit.value = false;
|
||||||
} else {
|
}
|
||||||
isedit.value = false;
|
console.log(data);
|
||||||
dataIndex = null;
|
show.value = true;
|
||||||
}
|
|
||||||
console.log(data);
|
|
||||||
show.value = true;
|
|
||||||
}
|
}
|
||||||
function close() {
|
function close() {
|
||||||
show.value = false;
|
show.value = false;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
defineExpose({ open, close, reset, submit });
|
defineExpose({ open });
|
||||||
</script>
|
|
||||||
|
/**
|
||||||
|
* 过滤输入,只允许数字和最多两位小数
|
||||||
|
* @param {string} value - 输入框当前值
|
||||||
|
* @param {boolean} isIntegerOnly - 是否只允许正整数(无小数点),开启时最小值为1
|
||||||
|
* @returns {string} 过滤后的合法值
|
||||||
|
*/
|
||||||
|
function filterNumberInput(value, isIntegerOnly = false) {
|
||||||
|
// 第一步就过滤所有非数字和非小数点的字符(包括字母)
|
||||||
|
let filtered = value.replace(/[^\d.]/g, "");
|
||||||
|
|
||||||
|
// 整数模式处理
|
||||||
|
if (isIntegerOnly) {
|
||||||
|
// 移除所有小数点
|
||||||
|
filtered = filtered.replace(/\./g, "");
|
||||||
|
|
||||||
|
// 处理前导零
|
||||||
|
filtered = filtered.replace(/^0+(\d)/, "$1") || filtered;
|
||||||
|
|
||||||
|
// 空值处理(允许临时删除)
|
||||||
|
if (filtered === "") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最小值限制
|
||||||
|
if (filtered === "0" || parseInt(filtered, 10) < 1) {
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 小数模式处理
|
||||||
|
const parts = filtered.split(".");
|
||||||
|
if (parts.length > 1) {
|
||||||
|
filtered = parts[0] + "." + (parts[1].substring(0, 2) || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理前导零
|
||||||
|
if (filtered.startsWith("0") && filtered.length > 1 && !filtered.startsWith("0.")) {
|
||||||
|
filtered = filtered.replace(/^0+(\d)/, "$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.item {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,151 +1,215 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="m-4 bg-white p-4">
|
<div class="m-4 bg-white p-4">
|
||||||
<HeaderCard
|
<HeaderCard
|
||||||
name="新客立减"
|
name="新客立减"
|
||||||
intro="首单下单减免金额"
|
intro="首单下单减免金额"
|
||||||
icon="new_user_discount"
|
icon="new_user_discount"
|
||||||
showSwitch
|
showSwitch
|
||||||
v-model:isOpen="isEnable"
|
v-model:isOpen="basicForm.isEnable"
|
||||||
></HeaderCard>
|
></HeaderCard>
|
||||||
<el-form ref="form" :model="basicForm">
|
<div style="padding-top: 40px">
|
||||||
<el-form-item label="减免方式">
|
<el-form
|
||||||
<div>
|
ref="formRef"
|
||||||
<el-radio-group v-model="basicForm.discountType">
|
:rules="rules"
|
||||||
<el-radio value="FIXED">固定金额</el-radio>
|
:model="basicForm"
|
||||||
<el-radio value="RANDOM">随机立减</el-radio>
|
label-width="120px"
|
||||||
</el-radio-group>
|
label-position="right"
|
||||||
<div v-if="basicForm.discountType === 'FIXED'">
|
>
|
||||||
<el-input type="number" v-model="basicForm.discountValue" placeholder="请输入金额">
|
<el-form-item label="活动时间">
|
||||||
<template #append>元</template>
|
<div style="width: 300px">
|
||||||
</el-input>
|
<el-date-picker
|
||||||
</div>
|
v-model="validityScope"
|
||||||
</div>
|
type="daterange"
|
||||||
</el-form-item>
|
range-separator="至"
|
||||||
<!-- 随机立减 -->
|
start-placeholder="开始时间"
|
||||||
<div v-if="basicForm.discountType == 'RANDOM'">
|
end-placeholder="结束时间"
|
||||||
<el-form-item label="会员周期列表">
|
@change="validityScopeChange"
|
||||||
<el-button type="primary" @click="refDialogPlans.open()">添加方案</el-button>
|
/>
|
||||||
</el-form-item>
|
</div>
|
||||||
<el-form-item label="">
|
</el-form-item>
|
||||||
<el-table :data="basicForm.randomDiscountList" border style="width: 60%">
|
<el-form-item label="减免方式">
|
||||||
<el-table-column prop="amount" label="减免金融(元)" align="center" />
|
<div>
|
||||||
<el-table-column prop="probability" label="概率(%)" align="center" />
|
<el-radio-group v-model="basicForm.discountType">
|
||||||
|
<el-radio value="FIXED">固定金额</el-radio>
|
||||||
|
<el-radio value="RANDOM">随机立减</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<div v-if="basicForm.discountType === 'FIXED'">
|
||||||
|
<el-input
|
||||||
|
v-model="basicForm.discountAmount"
|
||||||
|
placeholder="请输入金额"
|
||||||
|
:maxlength="8"
|
||||||
|
@input="discountAmountInput"
|
||||||
|
>
|
||||||
|
<template #append>元</template>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 随机立减 -->
|
||||||
|
<div v-if="basicForm.discountType == 'RANDOM'">
|
||||||
|
<el-form-item label="随机减免方案">
|
||||||
|
<el-button type="primary" @click="refDialogPlans.open()">
|
||||||
|
添加方案
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="randomDiscountList">
|
||||||
|
<el-table :data="basicForm.randomDiscountList" border style="width: 60%">
|
||||||
|
<el-table-column prop="amount" label="减免金融(元)" align="center" />
|
||||||
|
<el-table-column prop="probability" label="概率(%)" align="center" />
|
||||||
|
|
||||||
<el-table-column label="操作" align="center">
|
<el-table-column label="操作" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="text" @click="refDialogPlans.open(scope.row, scope.$index)">
|
<el-button
|
||||||
编辑
|
type="primary"
|
||||||
</el-button>
|
link
|
||||||
<el-button type="text" style="color: red" @click="deletePlan(scope.row)">
|
@click="refDialogPlans.open(scope.row, scope.$index)"
|
||||||
删除
|
>
|
||||||
</el-button>
|
编辑
|
||||||
</template>
|
</el-button>
|
||||||
</el-table-column>
|
<el-button
|
||||||
</el-table>
|
type="danger"
|
||||||
</el-form-item>
|
link
|
||||||
</div>
|
@click="
|
||||||
<div>
|
basicForm.randomDiscountList.splice(scope.$index, 1)
|
||||||
<el-form-item label="可使用类型">
|
"
|
||||||
<el-checkbox-group v-model="basicForm.useType">
|
>
|
||||||
<el-checkbox
|
删除
|
||||||
v-model="item.value"
|
</el-button>
|
||||||
:label="item.value"
|
</template>
|
||||||
v-for="item in useTypeList"
|
</el-table-column>
|
||||||
:key="item.value"
|
</el-table>
|
||||||
>
|
</el-form-item>
|
||||||
{{ item.label }}
|
</div>
|
||||||
</el-checkbox>
|
<div>
|
||||||
</el-checkbox-group>
|
<el-form-item label="可使用类型" prop="useTypeList">
|
||||||
</el-form-item>
|
<el-checkbox-group v-model="basicForm.useTypeList">
|
||||||
</div>
|
<el-checkbox
|
||||||
</el-form>
|
v-model="item.value"
|
||||||
|
:label="item.label"
|
||||||
<div class="flex mt-10 justify-center gap-10">
|
:value="item.value"
|
||||||
<el-button style="width: 100px" type="primary" @click="basicSubmit" size="large">
|
v-for="item in useTypeList"
|
||||||
保存
|
:key="item.value"
|
||||||
</el-button>
|
></el-checkbox>
|
||||||
<el-button @click="close" style="width: 100px" size="large">取消</el-button>
|
</el-checkbox-group>
|
||||||
</div>
|
</el-form-item>
|
||||||
|
</div>
|
||||||
<DialogPlans ref="refDialogPlans" @submitSuccess="submitSuccess"></DialogPlans>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex mt-10 justify-center gap-10">
|
||||||
|
<el-button style="width: 100px" type="primary" @click="basicSubmit" size="large">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="close" style="width: 100px" size="large">取消</el-button>
|
||||||
|
</div>
|
||||||
|
<DialogPlans ref="refDialogPlans" @submitSuccess="submitSuccess"></DialogPlans>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { dayjs } from "element-plus";
|
||||||
|
import _, { cloneDeep } from "lodash";
|
||||||
import shopApi from "@/api/account/shop";
|
import shopApi from "@/api/account/shop";
|
||||||
import consumeDiscountApi from "@/api/market/consumeDiscount";
|
import consumeDiscountApi from "@/api/market/consumeDiscount";
|
||||||
import HeaderCard from "../components/headerCard.vue";
|
import HeaderCard from "../components/headerCard.vue";
|
||||||
import DialogPlans from "./components/dialog-plans.vue";
|
import DialogPlans from "./components/dialog-plans.vue";
|
||||||
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted } from "vue";
|
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage, ElNotification } from "element-plus";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
import { filterNumberInput, convertTimeToDate } from "@/utils";
|
||||||
|
|
||||||
const inputStyle = {
|
const inputStyle = {
|
||||||
width: "340px",
|
width: "340px",
|
||||||
};
|
};
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
//是否开启超级会员
|
|
||||||
const isEnable = ref(false);
|
|
||||||
|
|
||||||
const refDialogPlans = ref();
|
const refDialogPlans = ref();
|
||||||
const configs = [
|
const configs = [
|
||||||
{ name: "basic", label: "会员基础设置" },
|
{ name: "basic", label: "会员基础设置" },
|
||||||
{ name: "lv", label: "会员等级设置" },
|
{ name: "lv", label: "会员等级设置" },
|
||||||
{ name: "order", label: "购买会员订单" },
|
{ name: "order", label: "购买会员订单" },
|
||||||
];
|
];
|
||||||
const activeTab = ref("basic");
|
const activeTab = ref("basic");
|
||||||
const useTypeList = ref([
|
const useTypeList = ref([
|
||||||
{ label: "堂食", value: "dine-in" },
|
{ label: "堂食", value: "dine-in" },
|
||||||
{ label: "外带", value: "take-out" },
|
{ label: "外带", value: "take-out" },
|
||||||
{ label: "外卖", value: "take-away" },
|
{ label: "外卖", value: "take-away" },
|
||||||
|
{ label: "快递", value: "post" },
|
||||||
]);
|
]);
|
||||||
|
const formRef = ref(null);
|
||||||
const basicForm = reactive({
|
const basicForm = reactive({
|
||||||
isEnable: 0,
|
isEnable: 1,
|
||||||
discountType: "RANDOM",
|
discountType: "RANDOM",
|
||||||
discountAmount: 0.0,
|
discountAmount: 0.0,
|
||||||
randomDiscountList: [],
|
randomDiscountList: [],
|
||||||
useType: [],
|
useTypeList: [],
|
||||||
shopId: 0,
|
shopId: 0,
|
||||||
|
startTime: "",
|
||||||
|
endTime: "",
|
||||||
});
|
});
|
||||||
function deletePlan(row) {
|
|
||||||
const index = basicForm.configList.indexOf(row);
|
const validityScope = ref([]);
|
||||||
if (index > -1) {
|
function validityScopeChange(e) {
|
||||||
basicForm.configList.splice(index, 1);
|
if (e && e.length) {
|
||||||
}
|
basicForm.startTime = dayjs(e[0]).format("YYYY-MM-DD 00:00:00");
|
||||||
|
basicForm.endTime = dayjs(e[1]).format("YYYY-MM-DD 23:59:59");
|
||||||
|
} else {
|
||||||
|
basicForm.startTime = "";
|
||||||
|
basicForm.endTime = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function submitSuccess(plans, index) {
|
|
||||||
if (!basicForm.configList) {
|
const rules = reactive({
|
||||||
basicForm.configList = [];
|
useTypeList: [
|
||||||
}
|
{
|
||||||
if (index !== null && index !== undefined) {
|
required: true,
|
||||||
basicForm.configList[index] = plans;
|
message: "请选择可使用类型",
|
||||||
return;
|
trigger: "change",
|
||||||
}
|
},
|
||||||
basicForm.configList.push(plans);
|
],
|
||||||
|
randomDiscountList: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (basicForm.randomDiscountList.length == 0) {
|
||||||
|
callback(new Error("请添加方案"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: "change",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const time = 500;
|
||||||
|
const discountAmountInput = _.debounce(function (e) {
|
||||||
|
basicForm.discountAmount = filterNumberInput(e);
|
||||||
|
}, time);
|
||||||
|
|
||||||
|
function submitSuccess(plans, index = null) {
|
||||||
|
if (index !== null && index !== undefined) {
|
||||||
|
basicForm.randomDiscountList[index] = plans;
|
||||||
|
} else {
|
||||||
|
basicForm.randomDiscountList.push(plans);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 会员基础设置提交
|
// 会员基础设置提交
|
||||||
function basicSubmit() {
|
function basicSubmit() {
|
||||||
const data = toRaw(basicForm);
|
formRef.value.validate(async (vaild) => {
|
||||||
// if (data.openType == "PAY") {
|
try {
|
||||||
// data.conditionList = null;
|
if (vaild) {
|
||||||
// }
|
console.log(basicForm);
|
||||||
// if (data.openType == "CONDITION") {
|
await consumeDiscountApi.editConfig(basicForm);
|
||||||
// data.configList = null;
|
ElNotification({
|
||||||
// }
|
title: "注意",
|
||||||
data.conditionList = useTypes.value
|
message: "保存成功",
|
||||||
.filter((v) => v.checked)
|
type: "success",
|
||||||
.map((v) => {
|
});
|
||||||
return {
|
}
|
||||||
code: v.code,
|
} catch (err) {
|
||||||
value: v.value,
|
console.log(err);
|
||||||
};
|
}
|
||||||
});
|
});
|
||||||
consumeDiscountApi.editConfig(data).then((res) => {
|
|
||||||
ElMessage.success("保存成功");
|
|
||||||
});
|
|
||||||
// ElMessage.success("保存成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 会员等级列表
|
// 会员等级列表
|
||||||
|
|
@ -156,135 +220,144 @@ const selectedLevel = ref(null);
|
||||||
|
|
||||||
// 优惠券列表
|
// 优惠券列表
|
||||||
const couponList = ref([
|
const couponList = ref([
|
||||||
{ id: 1, name: "满100减10" },
|
{ id: 1, name: "满100减10" },
|
||||||
{ id: 2, name: "满200减30" },
|
{ id: 2, name: "满200减30" },
|
||||||
]);
|
]);
|
||||||
let activeLevelId = ref(null);
|
let activeLevelId = ref(null);
|
||||||
// 添加会员等级
|
// 添加会员等级
|
||||||
function addLevel() {
|
function addLevel() {
|
||||||
const nowLastVip = levels.value[levels.value.length - 1];
|
const nowLastVip = levels.value[levels.value.length - 1];
|
||||||
let name = "VIP1";
|
let name = "VIP1";
|
||||||
if (levels.value.length) {
|
if (levels.value.length) {
|
||||||
name = "VIP" + (levels.value.length + 1);
|
name = "VIP" + (levels.value.length + 1);
|
||||||
}
|
}
|
||||||
if (nowLastVip && !nowLastVip.id) {
|
if (nowLastVip && !nowLastVip.id) {
|
||||||
ElMessage.error("请先保存当前等级");
|
ElMessage.error("请先保存当前等级");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newLevel = {
|
const newLevel = {
|
||||||
name,
|
name,
|
||||||
experienceValue: 0,
|
experienceValue: 0,
|
||||||
discount: 1,
|
discount: 1,
|
||||||
logo: "",
|
logo: "",
|
||||||
costRewardPoints: 1,
|
costRewardPoints: 1,
|
||||||
isCostRewardPoints: 1,
|
isCostRewardPoints: 1,
|
||||||
isCycleReward: 0,
|
isCycleReward: 0,
|
||||||
cycleTime: 1,
|
cycleTime: 1,
|
||||||
cycleUnit: "月",
|
cycleUnit: "月",
|
||||||
cycleRewardPoints: 1,
|
cycleRewardPoints: 1,
|
||||||
cycleRewardCouponList: [],
|
cycleRewardCouponList: [],
|
||||||
};
|
};
|
||||||
console.log(newLevel);
|
console.log(newLevel);
|
||||||
levels.value.push(newLevel);
|
levels.value.push(newLevel);
|
||||||
selectedLevel.value = newLevel;
|
selectedLevel.value = newLevel;
|
||||||
activeLevelId.value = levels.value.length - 1;
|
activeLevelId.value = levels.value.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑会员等级
|
// 编辑会员等级
|
||||||
function editLevel(level) {
|
function editLevel(level) {
|
||||||
selectedLevel.value = level;
|
selectedLevel.value = level;
|
||||||
}
|
}
|
||||||
// 删除会员等级
|
// 删除会员等级
|
||||||
async function removeLevel(index) {
|
async function removeLevel(index) {
|
||||||
const item = levels.value[index];
|
const item = levels.value[index];
|
||||||
const { id } = item;
|
const { id } = item;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
// 本地删除
|
// 本地删除
|
||||||
levels.value.splice(index, 1);
|
levels.value.splice(index, 1);
|
||||||
const newLevel = levels.value[index - 1];
|
const newLevel = levels.value[index - 1];
|
||||||
selectedLevel.value = newLevel;
|
selectedLevel.value = newLevel;
|
||||||
activeLevelId.value = index - 1;
|
activeLevelId.value = index - 1;
|
||||||
ElMessage.success("删除成功");
|
ElMessage.success("删除成功");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ElMessageBox.confirm("确定要删除吗?", "提示", {
|
ElMessageBox.confirm("确定要删除吗?", "提示", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
const res = await consumeDiscountApi.levelDel({ id: id });
|
const res = await consumeDiscountApi.levelDel({ id: id });
|
||||||
if (res) {
|
if (res) {
|
||||||
levels.value.splice(index, 1);
|
levels.value.splice(index, 1);
|
||||||
ElMessage.success("删除成功");
|
ElMessage.success("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
const newLevel = levels.value[index - 1];
|
const newLevel = levels.value[index - 1];
|
||||||
selectedLevel.value = newLevel;
|
selectedLevel.value = newLevel;
|
||||||
activeLevelId.value = index - 1;
|
activeLevelId.value = index - 1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 保存会员等级
|
// 保存会员等级
|
||||||
async function saveLevel(level) {
|
async function saveLevel(level) {
|
||||||
const isPass = level.cycleRewardCouponList.every((item) => item.num && item.coupon.id);
|
const isPass = level.cycleRewardCouponList.every((item) => item.num && item.coupon.id);
|
||||||
if (!isPass) {
|
if (!isPass) {
|
||||||
ElMessage.error("请选择优惠券并输入数量");
|
ElMessage.error("请选择优惠券并输入数量");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const res = level.id
|
const res = level.id
|
||||||
? await consumeDiscountApi.levelEdit(level)
|
? await consumeDiscountApi.levelEdit(level)
|
||||||
: await consumeDiscountApi.levelAdd(level);
|
: await consumeDiscountApi.levelAdd(level);
|
||||||
if (res) {
|
if (res) {
|
||||||
ElMessage.success("保存成功");
|
ElMessage.success("保存成功");
|
||||||
}
|
}
|
||||||
levelRefresh();
|
levelRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
const shops = ref([]);
|
const shops = ref([]);
|
||||||
|
|
||||||
async function levelRefresh() {
|
async function levelRefresh() {
|
||||||
consumeDiscountApi.levelList().then((res) => {
|
consumeDiscountApi.levelList().then((res) => {
|
||||||
if (res && res.length) {
|
if (res && res.length) {
|
||||||
levels.value = res;
|
levels.value = res;
|
||||||
if (res.length != 0) {
|
if (res.length != 0) {
|
||||||
selectedLevel.value = res[activeLevelId.value];
|
selectedLevel.value = res[activeLevelId.value];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function init() {
|
async function init() {
|
||||||
consumeDiscountApi.getConfig().then((res) => {
|
consumeDiscountApi.getConfig().then((res) => {
|
||||||
Object.assign(basicForm, res);
|
Object.assign(basicForm, res);
|
||||||
});
|
if (!res.useTypeList) {
|
||||||
|
basicForm.useTypeList = [];
|
||||||
|
}
|
||||||
|
if (!res.randomDiscountList) {
|
||||||
|
basicForm.randomDiscountList = [];
|
||||||
|
}
|
||||||
|
if (res.startTime) {
|
||||||
|
validityScope.value = [res.startTime, res.endTime];
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init();
|
init();
|
||||||
});
|
});
|
||||||
//计算总优惠券数量
|
//计算总优惠券数量
|
||||||
function totalCount(arr) {
|
function totalCount(arr) {
|
||||||
return arr.reduce((total, item) => {
|
return arr.reduce((total, item) => {
|
||||||
return total + item.num * 1;
|
return total + item.num * 1;
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
//返回
|
//返回
|
||||||
function close() {
|
function close() {
|
||||||
router.back();
|
router.back();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
:deep(.el-tabs--border-card) {
|
:deep(.el-tabs--border-card) {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
:deep(.el-tabs--border-card > .el-tabs__header) {
|
:deep(.el-tabs--border-card > .el-tabs__header) {
|
||||||
border: none;
|
border: none;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
:deep(.el-tabs--border-card > .el-tabs__header .el-tabs__item) {
|
:deep(.el-tabs--border-card > .el-tabs__header .el-tabs__item) {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
:deep(.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active) {
|
:deep(.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active) {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<el-table-column prop="id" label="ID" width="80" />
|
<el-table-column prop="id" label="ID" width="80" />
|
||||||
<el-table-column prop="title" label="名称" width="180" />
|
<el-table-column prop="title" label="名称" width="180" />
|
||||||
<el-table-column prop="fullAmount" label="使用门槛" width="180">
|
<el-table-column prop="fullAmount" label="使用门槛" width="180">
|
||||||
<template #default="scope">满{{ scope.row.discountAmount }}元</template>
|
<template #default="scope">满{{ scope.row.fullAmount }}元</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="validStartTime" label="有效期" width="320">
|
<el-table-column prop="validStartTime" label="有效期" width="320">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="giveNum" label="总发放数量" width="100">
|
<el-table-column prop="giveNum" label="总发放数量" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.giveNum == -10086 ? "无限" : scope.row.giftNum }}
|
{{ scope.row.giveNum == -10086 ? "无限" : scope.row.giveNum }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="giftNum" label="已领取" width="180">
|
<el-table-column prop="giftNum" label="已领取" width="180">
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,11 @@
|
||||||
<el-table :data="tableData.list" border stripe v-loading="tableData.loading">
|
<el-table :data="tableData.list" border stripe v-loading="tableData.loading">
|
||||||
<el-table-column prop="id" label="ID" width="80" />
|
<el-table-column prop="id" label="ID" width="80" />
|
||||||
<el-table-column prop="title" label="规则名称" width="180" />
|
<el-table-column prop="title" label="规则名称" width="180" />
|
||||||
<el-table-column prop="discountRate" label="折扣率" width="180" />
|
<el-table-column prop="discountRate" label="折扣率" width="180">
|
||||||
<el-table-column prop="fullAmount" label="使用门槛" width="180">
|
<template #default="scope">{{ scope.row.discountRate }}%</template>
|
||||||
<template #default="scope">满{{ scope.row.fullAmount }}元</template>
|
</el-table-column>
|
||||||
|
<el-table-column prop="discountAmount" label="使用门槛" width="180">
|
||||||
|
<template #default="scope">满{{ scope.row.discountAmount }}元</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="maxDiscountAmount"
|
prop="maxDiscountAmount"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,218 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog
|
||||||
|
v-model="show"
|
||||||
|
:title="editorIndex ? '编辑充值面额' : '添加充值面额'"
|
||||||
|
width="700"
|
||||||
|
@closed="reset"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
label-width="120px"
|
||||||
|
label-position="right"
|
||||||
|
>
|
||||||
|
<el-form-item label="充值面额" prop="amount">
|
||||||
|
<el-input
|
||||||
|
v-model="form.amount"
|
||||||
|
placeholder="请输入充值面额"
|
||||||
|
style="width: 270px"
|
||||||
|
:maxlength="8"
|
||||||
|
@input="amountInput"
|
||||||
|
>
|
||||||
|
<template #append>元</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="赠送金额">
|
||||||
|
<el-input
|
||||||
|
v-model="form.rewardAmount"
|
||||||
|
placeholder="请输入赠送金额"
|
||||||
|
style="width: 270px"
|
||||||
|
:maxlength="8"
|
||||||
|
@input="rewardAmountInput"
|
||||||
|
>
|
||||||
|
<template #append>元</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="赠送积分">
|
||||||
|
<el-input
|
||||||
|
v-model="form.rewardPoints"
|
||||||
|
placeholder="请输入赠送积分"
|
||||||
|
style="width: 270px"
|
||||||
|
@input="rewardPointsInput"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="赠送优惠券" prop="couponInfoList">
|
||||||
|
<div class="item">
|
||||||
|
<div
|
||||||
|
class="center"
|
||||||
|
v-for="(item, index) in form.couponInfoList"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<el-select v-model="item.id">
|
||||||
|
<el-option
|
||||||
|
v-for="val of props.couponList"
|
||||||
|
:key="val.id"
|
||||||
|
:value="val.id"
|
||||||
|
:label="val.title"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-input v-model="item.num" @input="numInput($event, index)">
|
||||||
|
<template #append>数量</template>
|
||||||
|
</el-input>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
text
|
||||||
|
@click="form.couponInfoList.splice(index, 1)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<el-button type="primary" link icon="CirclePlus" @click="addItemHandle">
|
||||||
|
新增券
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item></el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="show = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submitHandle">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import _, { cloneDeep } from "lodash";
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
import { filterNumberInput } from "@/utils";
|
||||||
|
|
||||||
|
const show = ref(false);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
couponList: {
|
||||||
|
type: Array,
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const editorIndex = ref(null);
|
||||||
|
const resetForm = ref("");
|
||||||
|
const formRef = ref(null);
|
||||||
|
const form = ref({
|
||||||
|
amount: "",
|
||||||
|
rewardAmount: "",
|
||||||
|
rewardPoints: "",
|
||||||
|
couponInfoList: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const rules = ref({
|
||||||
|
amount: [{ required: true, message: "请输入充值面额", trigger: "blur" }],
|
||||||
|
couponInfoList: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
let flag = true;
|
||||||
|
|
||||||
|
form.value.couponInfoList.map((item) => {
|
||||||
|
if (!item.id) {
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!flag) {
|
||||||
|
callback(new Error("请选择优惠券"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: "change",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 增加优惠券信息
|
||||||
|
function addItemHandle() {
|
||||||
|
form.value.couponInfoList.push({
|
||||||
|
id: "",
|
||||||
|
num: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加面额
|
||||||
|
const emits = defineEmits(["success"]);
|
||||||
|
function submitHandle() {
|
||||||
|
formRef.value.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
emits("success", {
|
||||||
|
data: { ...form.value },
|
||||||
|
index: editorIndex.value,
|
||||||
|
});
|
||||||
|
show.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = 500;
|
||||||
|
const amountInput = _.debounce(function (e) {
|
||||||
|
form.value.amount = filterNumberInput(e);
|
||||||
|
}, time);
|
||||||
|
|
||||||
|
const rewardAmountInput = _.debounce(function (e) {
|
||||||
|
form.value.rewardAmount = filterNumberInput(e);
|
||||||
|
}, time);
|
||||||
|
|
||||||
|
const rewardPointsInput = _.debounce(function (e) {
|
||||||
|
form.value.rewardPoints = filterNumberInput(e, true);
|
||||||
|
}, time);
|
||||||
|
|
||||||
|
const numInput = _.debounce(function (e, index) {
|
||||||
|
form.value.couponInfoList[index].num = filterNumberInput(e, true);
|
||||||
|
if (form.value.couponInfoList[index].num < 1) {
|
||||||
|
form.value.couponInfoList[index].num = 1;
|
||||||
|
}
|
||||||
|
}, time);
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
editorIndex.value = null;
|
||||||
|
form.value = cloneDeep(resetForm.value);
|
||||||
|
form.value.couponInfoList = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开
|
||||||
|
function open(obj = null, index = null) {
|
||||||
|
console.log(obj, index);
|
||||||
|
if (obj && obj.amount) {
|
||||||
|
form.value = cloneDeep(obj);
|
||||||
|
editorIndex.value = index;
|
||||||
|
}
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resetForm.value = { ...form.value };
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.item {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,331 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="content">
|
||||||
|
<HeaderCard
|
||||||
|
name="智慧充值"
|
||||||
|
intro="允许客户充值并使用余额支付"
|
||||||
|
icon="zhcz"
|
||||||
|
showSwitch
|
||||||
|
v-model:isOpen="form.isEnable"
|
||||||
|
></HeaderCard>
|
||||||
|
<div style="padding-top: 14px">
|
||||||
|
<el-tabs v-model="tabsValue">
|
||||||
|
<el-tab-pane label="基础设置" :name="1">
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
label-width="120"
|
||||||
|
label-position="right"
|
||||||
|
>
|
||||||
|
<el-form-item label="充值面额" required>
|
||||||
|
<el-button type="primary" @click="AddDialogRef.open()">
|
||||||
|
添加面额
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="rechargeDetailList">
|
||||||
|
<el-table :data="form.rechargeDetailList" border stripe>
|
||||||
|
<el-table-column label="ID" prop="id"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="充值金额(元)"
|
||||||
|
prop="amount"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="赠送金额"
|
||||||
|
prop="rewardAmount"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="赠送积分"
|
||||||
|
prop="rewardPoints"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column label="赠送优惠券" prop="couponInfoList">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="column">
|
||||||
|
<div v-for="item in scope.row.couponInfoList">
|
||||||
|
<el-tag type="primary" disable-transitions>
|
||||||
|
{{ couponListFilter(item.id) }}x{{
|
||||||
|
item.num
|
||||||
|
}}张
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
@click="AddDialogRef.open(scope.row, scope.$index)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
link
|
||||||
|
@click="
|
||||||
|
form.rechargeDetailList.splice(scope.$index, 1)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="选择门店"
|
||||||
|
prop="useType"
|
||||||
|
v-if="shopInfo.isHeadShop"
|
||||||
|
>
|
||||||
|
<el-radio-group v-model="form.useType">
|
||||||
|
<el-radio label="全部门店" value="all"></el-radio>
|
||||||
|
<el-radio label="指定门店可用" value="part"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="选择门店" v-if="form.useType == 'part'">
|
||||||
|
<el-select
|
||||||
|
v-model="form.shopIdList"
|
||||||
|
multiple
|
||||||
|
clearable
|
||||||
|
placeholder="请选择门店"
|
||||||
|
style="width: 300px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
:label="item.shopName"
|
||||||
|
:value="item.id"
|
||||||
|
v-for="item in branchList"
|
||||||
|
:key="item.id"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="自定义金额">
|
||||||
|
<div class="column">
|
||||||
|
<div class="center">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.isCustom"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
/>
|
||||||
|
<span class="tips">自定义金额不参与赠送优惠</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="充值并下单">
|
||||||
|
<div class="column">
|
||||||
|
<div class="center">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.isOrder"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
/>
|
||||||
|
<span class="tips">开启后,订单支付页面显示充值选项</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="充值说明" prop="remark">
|
||||||
|
<div class="column">
|
||||||
|
<div class="item">
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="250"
|
||||||
|
v-model="form.remark"
|
||||||
|
placeholder="填写内容"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
<div class="item textarea-num">
|
||||||
|
{{ form.remark.length }}/250字内,单文本
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div class="footer">
|
||||||
|
<el-button type="primary" size="large" @click="submitHandle">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
<el-button size="large" @click="back">取消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="充值记录" :name="2">
|
||||||
|
<ChargeList />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<AddDialog ref="AddDialogRef" :couponList="couponList" @success="addSuccess" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import HeaderCard from "../components/headerCard.vue";
|
||||||
|
import AddDialog from "./components/addDialog.vue";
|
||||||
|
import ChargeList from "@/views/user/charge/index.vue";
|
||||||
|
import { couponPage, getBranchPage, shopRecharge, shopRechargeGet } from "@/api/coupon/index.js";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { ElNotification } from "element-plus";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const AddDialogRef = ref(null);
|
||||||
|
const tabsValue = ref(1);
|
||||||
|
const formRef = ref(null);
|
||||||
|
const form = ref({
|
||||||
|
isEnable: 1,
|
||||||
|
id: "",
|
||||||
|
shopIdList: "",
|
||||||
|
useType: "all",
|
||||||
|
isCustom: 0,
|
||||||
|
isOrder: 0,
|
||||||
|
remark: "",
|
||||||
|
rechargeDetailList: [],
|
||||||
|
});
|
||||||
|
const rules = ref({
|
||||||
|
rechargeDetailList: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (form.value.rechargeDetailList.length == 0) {
|
||||||
|
callback(new Error("请添加面额"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: "change",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
remark: [{ required: true, message: "请输入充值说明", trigger: "blur" }],
|
||||||
|
});
|
||||||
|
|
||||||
|
function submitHandle() {
|
||||||
|
formRef.value.validate(async (valid) => {
|
||||||
|
try {
|
||||||
|
if (valid) {
|
||||||
|
await shopRecharge(form.value);
|
||||||
|
ElNotification({
|
||||||
|
title: "注意",
|
||||||
|
message: "保存成功",
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点前登录店铺信息
|
||||||
|
const shopInfo = ref("");
|
||||||
|
|
||||||
|
// 获取分店列表
|
||||||
|
const branchList = ref([]);
|
||||||
|
async function getBranchPageAjax() {
|
||||||
|
try {
|
||||||
|
const res = await getBranchPage();
|
||||||
|
branchList.value = res.records;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSuccess(data) {
|
||||||
|
console.log("addSuccess===", data);
|
||||||
|
if (data.index == null) {
|
||||||
|
form.value.rechargeDetailList.push(data.data);
|
||||||
|
} else {
|
||||||
|
form.value.rechargeDetailList[data.index] = data.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取优惠券列表
|
||||||
|
const couponList = ref([]);
|
||||||
|
async function couponPageAjax() {
|
||||||
|
try {
|
||||||
|
const res = await couponPage({
|
||||||
|
page: 1,
|
||||||
|
size: 500,
|
||||||
|
});
|
||||||
|
couponList.value = res.records;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用id寻找优惠券名称
|
||||||
|
function couponListFilter(id) {
|
||||||
|
if (id) {
|
||||||
|
let obj = couponList.value.find((item) => item.id == id);
|
||||||
|
return obj.title;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从本地获取商户信息
|
||||||
|
function getLocalShopInfo() {
|
||||||
|
shopInfo.value = JSON.parse(localStorage.getItem("userInfo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置信息获取
|
||||||
|
async function shopRechargeGetAjax() {
|
||||||
|
try {
|
||||||
|
const res = await shopRechargeGet();
|
||||||
|
res.rechargeDetailList.map((item) => {
|
||||||
|
item.couponInfoList.map((val) => {
|
||||||
|
val.id = val.coupon.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
form.value = res;
|
||||||
|
|
||||||
|
console.log(form.value);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await couponPageAjax();
|
||||||
|
getLocalShopInfo();
|
||||||
|
getBranchPageAjax();
|
||||||
|
shopRechargeGetAjax();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.container {
|
||||||
|
padding: 14px;
|
||||||
|
.content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.column {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
.item {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.tips {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.textarea-num {
|
||||||
|
color: #999;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue