Files
cashier-web/src/views/marketing_center/components/couponDialog.vue
2025-10-10 11:49:58 +08:00

1076 lines
31 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-dialog
v-model="dialogVisible"
:title="titleOptions.title"
width="80%"
top="4vh"
@closed="closedReset"
>
<div class="scroll" ref="scrollRef">
<el-form
ref="formRef"
:model="form"
:rules="formRules"
label-width="160px"
class="dialog-form"
>
<el-form-item :label="titleOptions.name" prop="title">
<el-input
v-model="form.title"
:maxlength="20"
placeholder="请输入优惠券名称"
style="width: 300px"
/>
</el-form-item>
<div v-if="form.couponType == 1">
<el-form-item label="使用门槛" prop="fullAmount">
<div class="center">
<el-input
v-model="form.fullAmount"
placeholder="请输入使用门槛"
style="width: 240px"
input-style="text-align: center;"
:maxlength="8"
@input="(e) => (form.fullAmount = filterNumberInput(e))"
>
<template #prepend></template>
<template #append></template>
</el-input>
<el-input
v-model="form.discountAmount"
placeholder="请输入满减金额"
style="width: 240px"
input-style="text-align: center;"
:maxlength="8"
@input="(e) => (form.discountAmount = filterNumberInput(e))"
>
<template #prepend></template>
<template #append></template>
</el-input>
</div>
</el-form-item>
</div>
<div v-if="form.couponType == 2">
<el-form-item label="使用门槛" prop="fullAmount2">
<div class="center">
<el-input
v-model="form.fullAmount"
placeholder="请输入使用门槛"
style="width: 200px"
input-style="text-align: center;"
:maxlength="8"
@input="(e) => (form.fullAmount = filterNumberInput(e))"
>
<template #prepend></template>
<template #append>可用</template>
</el-input>
</div>
</el-form-item>
<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>
<el-form-item label="可抵扣商品件数" prop="discountNum">
<el-input
v-model="form.discountNum"
placeholder="请输入可抵扣商品件数"
style="width: 200px"
@input="discountNumInput"
/>
</el-form-item>
</div>
<div v-if="form.couponType == 3">
<el-form-item label="折扣" prop="discountRate">
<el-input
v-model="form.discountRate"
placeholder="输入折扣(%"
style="width: 200px"
@input="discountRateInput"
/>
</el-form-item>
<el-form-item label="使用门槛" prop="fullAmount2">
<div class="center">
<el-input
v-model="form.fullAmount"
placeholder="请输入使用门槛"
style="width: 300px"
input-style="text-align: center;"
:maxlength="8"
@input="(e) => (form.fullAmount = filterNumberInput(e))"
>
<template #prepend></template>
<template #append>可用</template>
</el-input>
</div>
</el-form-item>
<el-form-item label="可抵扣最大金额" prop="maxDiscountAmount">
<div class="center">
<el-input
v-model="form.maxDiscountAmount"
placeholder="请输入金额"
style="width: 200px"
:maxlength="8"
@input="(e) => (form.maxDiscountAmount = filterNumberInput(e))"
>
<template #append>可用</template>
</el-input>
</div>
</el-form-item>
</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 class="title">指定设置</div>
<el-form-item
label="选择门店"
prop="useShopType"
v-if="shopInfo.isHeadShop && shopInfo.shopType != 'only'"
>
<el-radio-group v-model="form.useShopType">
<el-radio label="仅本店可用" value="only"></el-radio>
<el-radio label="全部门店" value="all"></el-radio>
<el-radio label="指定门店可用" value="custom"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="选择门店" v-if="form.useShopType == 'custom'">
<el-select
v-model="shops"
multiple
clearable
placeholder="请选择门店"
@change="shopsChange"
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>
<div v-if="form.couponType != 2 && form.couponType != 4 && form.couponType != 6">
<el-form-item label="指定门槛商品" prop="goodsType">
<el-radio-group v-model="goodsType" @change="goodRadioChnage">
<el-radio label="全部商品可用" :value="1"></el-radio>
<el-radio label="部分商品可用" :value="2"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item 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>
</div>
<el-form-item label="可使用类型" prop="useType">
<el-checkbox-group v-model="form.useType">
<el-checkbox value="dine" label="堂食" />
<el-checkbox value="pickup" label="自取" />
<el-checkbox value="deliv" label="配送" />
<el-checkbox value="express" label="快递" />
</el-checkbox-group>
</el-form-item>
<div class="title">时效设置</div>
<el-form-item label="有效期类型">
<el-radio-group v-model="form.validType">
<el-radio label="领券后有效期内可用" value="fixed"></el-radio>
<el-radio label="固定有效期范围内可用" value="custom"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="有效期" prop="validDays">
<el-input
v-model="form.validDays"
placeholder="请输入有效期"
style="width: 200px"
:maxlength="5"
v-if="form.validType == 'fixed'"
input-style="text-align: center;"
@input="validDaysInput"
>
<template #append></template>
</el-input>
<div style="width: 200px">
<el-date-picker
v-model="validityScope"
type="daterange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
v-if="form.validType == 'custom'"
@change="validityScopeChange"
/>
</div>
</el-form-item>
<el-form-item
label="隔天生效"
prop="daysToTakeEffect"
v-if="form.validType == 'fixed'"
>
<div class="center">
<el-input
v-model="form.daysToTakeEffect"
placeholder="请输入隔天生效日期"
style="width: 300px"
input-style="text-align: center;"
:maxlength="5"
@input="daysToTakeEffectInput"
>
<template #prepend></template>
<template #append>天生效</template>
</el-input>
<el-tooltip
class="box-item"
effect="dark"
:content="`领取后${form.daysToTakeEffect}天后的0点0分生效`"
placement="top-start"
>
<el-icon size="18">
<QuestionFilled />
</el-icon>
</el-tooltip>
</div>
</el-form-item>
<el-form-item label="可用周期" prop="useDays">
<el-checkbox-group v-model="form.useDays">
<el-checkbox value="周一" label="周一" />
<el-checkbox value="周二" label="周二" />
<el-checkbox value="周三" label="周三" />
<el-checkbox value="周四" label="周四" />
<el-checkbox value="周五" label="周五" />
<el-checkbox value="周六" label="周六" />
<el-checkbox value="周七" label="周日" />
</el-checkbox-group>
</el-form-item>
<el-form-item label="指定时间段">
<el-radio-group v-model="form.useTimeType">
<el-radio label="全时段可用" value="all"></el-radio>
<el-radio label="指定时间段可用" value="custom"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.useTimeType == 'custom'" prop="useTimeType">
<div style="width: 200px">
<el-time-picker
v-model="useTimeScope"
is-range
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
@change="useTimeScopeChange"
/>
</div>
</el-form-item>
<div class="title">发放设置</div>
<el-form-item label="发放设置">
<el-radio-group v-model="form.getType">
<el-radio label="用户不可自行领取" value="no"></el-radio>
<el-radio label="用户可自行在小程序领取" value="yes"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户领取方式" v-if="form.getType == 'yes'" prop="getMode">
<el-checkbox-group v-model="form.getMode">
<el-checkbox value="home" label="首页-优惠券" />
<el-checkbox value="eat" label="点餐页-自动弹出" />
<el-checkbox value="order" label="订单支付页面" />
</el-checkbox-group>
</el-form-item>
<el-form-item label="总发放数量" prop="giveNum">
<div class="column">
<div class="center">
<el-switch v-model="infiniteGiveNum" @change="infiniteGiveNumChange" />
<span>关闭则为无限制</span>
</div>
<div v-if="infiniteGiveNum" style="margin-top: 10px">
<el-input
v-model="form.giveNum"
placeholder="请输入总发放数量"
style="width: 200px"
input-style="text-align: center;"
:maxlength="5"
@input="giveNumInput"
>
<template #append></template>
</el-input>
</div>
</div>
</el-form-item>
<div class="title">限量设置</div>
<el-form-item label="可领取用户">
<el-radio-group v-model="form.getUserType">
<el-radio label="全部用户可领" value="all"></el-radio>
<el-radio label="仅新用户可领取一张" value="new"></el-radio>
<el-radio label="仅会员可领取" value="vip"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="每人限领量" prop="getLimit">
<el-input
v-model="form.getLimit"
placeholder="请输入每人限领量"
style="width: 200px"
input-style="text-align: center;"
:maxlength="5"
@input="getLimitInput"
>
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="每人每日使用限量">
<div class="column">
<div class="center">
<el-radio-group
v-model="infiniteUseLimit"
@change="infiniteUseLimitChange"
>
<el-radio label="无限制" :value="true"></el-radio>
<el-radio label="每日限用" :value="false"></el-radio>
</el-radio-group>
</div>
</div>
</el-form-item>
<el-form-item label="限用数量" v-if="!infiniteUseLimit" prop="useLimit">
<el-input
v-model="form.useLimit"
placeholder="需小于或等于每人限领量"
style="width: 255px"
input-style="text-align: center;"
:maxlength="5"
@input="useLimitInput"
>
<template #append>/每人1天</template>
</el-input>
</el-form-item>
<div class="title">其他设置</div>
<el-form-item label="与限时折扣同享">
<div class="column">
<div class="center">
<el-switch
v-model="form.discountShare"
:active-value="1"
:inactive-value="0"
/>
<span>开启后计算门槛时将会计入已折扣的商品</span>
</div>
</div>
</el-form-item>
<el-form-item label="与会员价/会员折扣同享">
<div class="column">
<div class="center">
<el-switch
v-model="form.vipPriceShare"
:active-value="1"
:inactive-value="0"
/>
<span>开启后计算门槛时将会计入已享受会员价/会员折扣的商品</span>
</div>
</div>
</el-form-item>
<el-form-item label="与其他优惠券同享" v-if="form.couponType == 2">
<div class="column">
<div class="center">
<el-switch
v-model="form.otherCouponShare"
:active-value="1"
:inactive-value="0"
/>
<span>开启后可与其他优惠券同时使用</span>
</div>
</div>
</el-form-item>
<div class="title">规则附加说明</div>
<el-form-item label-width="0">
<div class="column">
<div class="item">
<el-input
type="textarea"
:rows="4"
maxlength="250"
v-model="form.ruleDetails"
placeholder="填写内容"
></el-input>
</div>
<div class="item textarea-num">
{{ form.ruleDetails.length }}/250字内单文本
</div>
</div>
</el-form-item>
</el-form>
</div>
<template #footer>
<div
class="dialog-footer"
v-if="(shopInfo.isHeadShop && shopInfo.shopType != 'only') || !form.syncId"
>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" :loading="loading" @click="submitHandle"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import _ from "lodash";
import { dayjs } from "element-plus";
import { ref, reactive, onMounted } from "vue";
import { filterNumberInput } from "@/utils";
import { getBranchPage, getProductList, getCategoryList, addCoupon } from "@/api/coupon/index.js";
const shopInfo = ref("");
const dialogVisible = ref(false);
const titleOptions = reactive({
name: "优惠券名称",
title: "添加优惠券",
couponTypeList: [
{
value: 1,
label: "满减券",
},
{
value: 2,
label: "商品兑换券",
},
{
value: 3,
label: "折扣券",
},
{
value: 4,
label: "第二件半价券",
},
{
value: 5,
label: "消费送券",
},
{
value: 6,
label: "买一送一券",
},
{
value: 7,
label: "固定价格券",
},
{
value: 8,
label: "免配送费券",
},
],
});
const cascaderProps = ref({
multiple: true,
emitPath: false,
value: "id",
label: "name",
});
// 选择指定商品
const goodsType = ref(1);
const goodsTypeCascaderValue = ref([]);
function selectFoodsConfirm(e) {
console.log(JSON.stringify(e));
form.value.foods = e.join(",");
}
// 切换商品类型
function goodRadioChnage(e) {
console.log(e);
form.value.foods = '';
goodsTypeCascaderValue.value = [];
}
// 选择的店铺列表
const shops = ref([]);
function shopsChange(e) {
form.value.useShops = e.join(",");
}
// 有效期时间
const validityScope = ref([]);
function validityScopeChange(e) {
console.log("validityScopeChange===", e);
if (e && e.length) {
form.value.validStartTime = dayjs(e[0]).format("YYYY-MM-DD 00:00:00");
form.value.validEndTime = dayjs(e[1]).format("YYYY-MM-DD 23:59:59");
} else {
form.value.validStartTime = "";
form.value.validEndTime = "";
}
}
// 可用时间
const useTimeScope = ref([]);
function useTimeScopeChange(e) {
console.log("useTimeScopeChange===", e);
if (e && e.length) {
form.value.useStartTime = dayjs(e[0]).format("HH:mm:00");
form.value.useEndTime = dayjs(e[1]).format("HH:mm:00");
} else {
form.value.useStartTime = "";
form.value.useEndTime = "";
}
}
// 是否为无限数量
const infiniteFlagNum = ref(-10086);
const infiniteGiveNum = ref(true);
function infiniteGiveNumChange(e) {
if (!e) {
form.value.giveNum = infiniteFlagNum.value;
} else {
form.value.giveNum = "";
}
}
// 是否为无限每人领取限量
const infiniteUseLimit = ref(true);
function infiniteUseLimitChange(e) {
if (e) {
form.value.useLimit = infiniteFlagNum.value;
} else {
form.value.useLimit = "";
}
}
const formRef = ref(null);
const form = ref({
id: "",
shopId: "",
syncId: "",
couponType: 1, // 1-满减券2-商品兑换券3-折扣券4-第二件半价券5-消费送券6-买一送一券7-固定价格券8-免配送费券
title: "", // 券名称
fullAmount: "", // 使用门槛
discountAmount: "", // 使用门槛:减多少金额
useShopType: "only", // only-仅本店 all-所有门店custom-指定门店
useShops: "", // id字符串拼接
goodsType: 1, // 1=全部商品参与计算门槛 2=部分商品参与计算门槛
foods: "", // 指定门槛商品 id拼接
useType: ["dine"], // 可使用类型dine堂食/pickup自取/deliv配送/express快递
validType: "fixed", // 有效期类型fixed固定时间custom自定义时间
validDays: "", // 有效期(天)
validStartTime: "", // 有效期开始时间
validEndTime: "", // 有效期结束时间
daysToTakeEffect: 0, // 隔天生效
useDays: ["周一", "周二", "周三", "周四", "周五", "周六", "周七"], // 可用周期,如:'周一','周二','周三' , '周四' , '周五', '周六' , '周七'
useTimeType: "all", // 可用时间段类型all-全时段custom-指定时段
useStartTime: "", // 可用开始时间
useEndTime: "", // 可用结束时间
getType: "no", // 发放设置:不可自行领取/no可领取/yes
getMode: ["eat"], // 用户领取方式 home/首页-优惠券 eat/点餐页-自动弹出 order/订单支付页面
giveNum: "", // 总发放数量,-10086为不限量
getUserType: "all", // 可领取用户:全部/all新用户一次/new仅会员/vip
getLimit: 1, // 每人领取限量,-10086为不限量
useLimit: -10086, // 每人每日使用限量,-10086为不限量
discountShare: 1, // 与限时折扣同享0-否1-是
vipPriceShare: 1, // 与会员价同享0-否1-是
ruleDetails: "", // 附加规则说明
status: 1, // 状态0-禁用1-启用
useNum: "", // 已使用数量
leftNum: "", // 剩余数量
discountRate: "", // 折扣%
maxDiscountAmount: "", // 可抵扣最大金额 元
useRule: "price_asc", // 使用规则price_asc-价格低到高price_desc-高到低
discountNum: 1, // 抵扣数量
otherCouponShare: 1, // 与其它优惠共享0-否1-是
});
// 初始化
const resetForm = ref(null);
function reset() {
goodsType.value = 1;
goodsTypeCascaderValue.value = [];
shops.value = [];
validityScope.value = [];
useTimeScope.value = [];
infiniteGiveNum.value = true;
infiniteUseLimit.value = true;
form.value = { ...resetForm.value };
}
// 自定义校验使用门槛
const fullAmountValidate = (rule, value, callback) => {
if (form.value.fullAmount < 0) {
callback(new Error("请输入使用门槛"));
} else if (form.value.discountAmount <= 0) {
callback(new Error("请输入满减金额"));
} else {
callback();
}
};
const fullAmountValidate2 = (rule, value, callback) => {
console.log(form.value.fullAmount);
if (form.value.fullAmount < 0 || form.value.fullAmount === "") {
callback(new Error("请输入使用门槛"));
} else {
callback();
}
};
// 自定义校验选择门店
const useShopTypeValidate = (rule, value, callback) => {
if (form.value.useShopType == "custom" && form.value.useShops === "") {
callback(new Error("请选择门店"));
} else {
callback();
}
};
// 自定义校验使用门槛
const goodsTypeValidate = (rule, value, callback) => {
if (goodsType.value == 2 && form.value.foods === "") {
callback(new Error("请选择商品"));
} else {
callback();
}
};
// 自定义校验有效期类型
const validDaysValidate = (rule, value, callback) => {
if (form.value.validType == "fixed" && form.value.validDays === "") {
callback(new Error("请输入有效期"));
} else if (form.value.validType == "custom" && form.value.validStartTime === "") {
callback(new Error("请选择日期范围"));
} else {
callback();
}
};
// 自定义校验隔天生效
const daysToTakeEffectValidate = (rule, value, callback) => {
if (form.value.daysToTakeEffect < 0) {
callback(new Error("请输入大于等于0的值"));
} else {
callback();
}
};
// 自定义校验固定有效期范围内可用
const useTimeTypeValidate = (rule, value, callback) => {
if (!form.value.useStartTime) {
callback(new Error("请选择指定可用时间段"));
} else {
callback();
}
};
// 自定义校验每人限量
const giveNumValidate = (rule, value, callback) => {
if (form.value.giveNum <= 0 && infiniteGiveNum.value) {
callback(new Error("请输入总发放数量"));
} else {
callback();
}
};
// 自定义校验每人每日使用限量
const useLimitValidate = (rule, value, callback) => {
if (form.value.useLimit <= 0 && !infiniteUseLimit.value) {
callback(new Error("请输入每人每日使用限量"));
} else {
callback();
}
};
const formRules = reactive({
title: [{ required: true, message: "请输入优惠券名称", trigger: "blur" }],
fullAmount: [{ required: true, validator: fullAmountValidate, trigger: "blur" }],
fullAmount2: [
{
required: true,
validator: fullAmountValidate2,
trigger: "blur",
},
],
useShopType: [
{
validator: useShopTypeValidate,
trigger: "change",
},
],
goodsType: [
{
validator: goodsTypeValidate,
trigger: "change",
},
],
discountNum: [{ required: true, message: "请输入可抵扣商品件数", trigger: "blur" }],
discountRate: [{ required: true, message: "输入折扣(%", trigger: "blur" }],
discountAmount: [{ required: true, message: "请输入使用门槛", trigger: "blur" }],
maxDiscountAmount: [{ required: true, message: "请输入金额", trigger: "blur" }],
useType: [{ required: true, message: "请选择可使用类型", trigger: "change" }],
validDays: [
{
required: true,
validator: validDaysValidate,
trigger: "change",
},
],
daysToTakeEffect: [
{
validator: daysToTakeEffectValidate,
trigger: "change",
},
],
useDays: [{ required: true, message: "请选择可用周期", trigger: "change" }],
useTimeType: [
{
validator: useTimeTypeValidate,
trigger: "change",
},
],
getMode: [{ required: true, message: "请选择用户领取方式", trigger: "change" }],
giveNum: [
{
validator: giveNumValidate,
trigger: "blur",
},
],
getLimit: [{ required: true, message: "请输入每人限领量", trigger: "blur" }],
useLimit: [
{
validator: useLimitValidate,
trigger: "blur",
},
],
});
// 开始提交
const emits = defineEmits(["success"]);
const loading = ref(false);
function submitHandle() {
formRef.value.validate(async (valid) => {
try {
if (valid) {
loading.value = true;
form.value.shopId = shopInfo.value.shopId;
await addCoupon(form.value);
emits("success");
dialogVisible.value = false;
}
} catch (err) {
console.log(err);
}
loading.value = false;
});
}
// 从本地获取商户信息
function getLocalShopInfo() {
shopInfo.value = JSON.parse(localStorage.getItem("userInfo"));
}
// 获取分店列表
const branchList = ref([]);
async function getBranchPageAjax() {
try {
const res = await getBranchPage();
branchList.value = res.records;
} catch (err) {
console.log(err);
}
}
// 获取商品列表
const goodsList = ref([]);
async function getProductListAjax() {
try {
const categorys = await getCategoryList();
const products = await getProductList();
goodsList.value = formatCategoryWithProducts(categorys, products);
} catch (err) {
console.log(err);
}
}
// 给分类组合相应的商品
function formatCategoryWithProducts(categories, products) {
// 步骤1遍历所有分类为每个分类匹配对应的商品
const allCategoriesWithProducts = categories.map((category) => {
// 匹配当前分类下的商品通过category.id === product.categoryId关联
const matchedProducts = products
.filter((product) => product.categoryId === category.id) // 关键按分类ID匹配商品
.map((product) => ({
id: product.id,
name: product.name, // 提取商品的id和name
}));
// 组装单个分类的结构
return {
id: category.id,
name: category.name,
children: matchedProducts, // 该分类下的商品(空数组表示无商品)
};
});
// 步骤2过滤掉“无商品”的分类children为空数组的分类
return allCategoriesWithProducts.filter((item) => item.children.length > 0);
}
// 显示弹窗
const scrollRef = ref(null);
function show(t, obj = null) {
nextTick(() => {
if (scrollRef.value) {
setTimeout(() => {
scrollRef.value.scrollTop = 0;
}, 50);
}
});
let m = titleOptions.couponTypeList.find((item) => item.value == t);
titleOptions.name = `${m.label}名称`;
if (obj && obj.id) {
titleOptions.title = `编辑${m.label}`;
form.value = { ...obj };
form.value.getMode = JSON.parse(form.value.getMode);
form.value.useDays = JSON.parse(form.value.useDays);
form.value.useType = JSON.parse(form.value.useType);
if (!!form.value.syncId) {
form.value.useShopType = "only";
}
if (form.value.foods != "") {
goodsType.value = 2;
goodsTypeCascaderValue.value = form.value.foods.split(",");
} else {
goodsType.value = 1;
}
if (form.value.useShops != "" && form.value.useShopType == "custom") {
shops.value = form.value.useShops.split(",");
}
if (form.value.validType == "custom") {
validityScope.value = [form.value.validStartTime, form.value.validEndTime];
}
if (form.value.useTimeType == "custom") {
useTimeScope.value = [
convertTimeToDate(form.value.useStartTime),
convertTimeToDate(form.value.useEndTime),
];
console.log(useTimeScope.value);
}
if (form.value.giveNum == infiniteFlagNum.value) {
infiniteGiveNum.value = false;
}
if (form.value.useLimit == infiniteFlagNum.value) {
infiniteUseLimit.value = true;
}
} else {
reset();
titleOptions.title = `添加${m.label}`;
}
form.value.couponType = t;
dialogVisible.value = true;
}
// 关闭后重置表单验证
function closedReset() {
formRef.value.resetFields();
}
/**
* 将时分秒字符串转换为完整日期格式
* @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
*/
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);
}
// input过滤
const time = 500;
const discountNumInput = _.debounce(function (value) {
form.value.discountNum = filterNumberInput(value, true);
if (form.value.discountNum == "") {
form.value.discountNum = 1;
}
}, time);
const discountRateInput = _.debounce(function (value) {
form.value.discountRate = filterNumberInput(value, true);
if (form.value.discountRate >= 100) {
form.value.discountRate = 100;
}
}, time);
const validDaysInput = _.debounce(function (value) {
form.value.validDays = filterNumberInput(value, true);
}, time);
const daysToTakeEffectInput = _.debounce(function (value) {
form.value.daysToTakeEffect = filterNumberInput(value, true);
if (form.value.daysToTakeEffect === "") {
form.value.daysToTakeEffect = 0;
}
}, time);
const giveNumInput = _.debounce(function (value) {
form.value.giveNum = filterNumberInput(value, true);
}, time);
const getLimitInput = _.debounce(function (value) {
form.value.getLimit = filterNumberInput(value, true);
if (form.value.getLimit == "") {
form.value.getLimit = 1;
}
}, time);
const useLimitInput = _.debounce(function (value) {
form.value.useLimit = filterNumberInput(value, true);
if (form.value.useLimit >= form.value.getLimit) {
form.value.useLimit = form.value.getLimit;
}
}, time);
defineExpose({
show,
});
onMounted(() => {
resetForm.value = { ...form.value };
getLocalShopInfo();
getBranchPageAjax();
getProductListAjax();
});
</script>
<style scoped lang="scss">
.title {
color: #000;
padding: 14px;
background-color: #f8f8f8;
margin-bottom: 14px;
font-size: 16px;
}
.column {
flex: 1;
display: flex;
flex-direction: column;
.item {
flex: 1;
}
}
.center {
display: flex;
align-items: center;
gap: 10px;
}
.scroll {
height: 76vh;
padding-bottom: 60px;
overflow-y: auto;
}
.dialog-footer {
position: relative;
&::after {
content: "";
width: 100%;
height: 60px;
position: absolute;
left: 0;
bottom: calc(100% + var(--el-dialog-padding-primary));
z-index: 9;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
}
}
.textarea-num {
color: #999;
display: flex;
justify-content: flex-end;
}
</style>