|
|
@@ -44,29 +44,46 @@
|
|
|
<el-input v-model="activityModel.participationLimit" placeholder="请输入" maxlength="4" />
|
|
|
</el-form-item>
|
|
|
|
|
|
- <!-- 活动规则 -->
|
|
|
- <el-form-item label="活动规则" prop="activityRule">
|
|
|
- <el-cascader
|
|
|
- v-model="activityModel.activityRule"
|
|
|
- :options="ruleCascaderOptions"
|
|
|
- :props="cascaderProps"
|
|
|
+ <!-- 券类型 -->
|
|
|
+ <el-form-item label="券类型" prop="rewardType">
|
|
|
+ <el-radio-group v-model="activityModel.rewardType">
|
|
|
+ <el-radio label="COUPON"> 优惠券 </el-radio>
|
|
|
+ <el-radio label="VOUCHER"> 代金券 </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 优惠券/代金券 -->
|
|
|
+ <el-form-item
|
|
|
+ :label="activityModel.rewardType === 'VOUCHER' ? '代金券' : '优惠券'"
|
|
|
+ :prop="activityModel.rewardType === 'VOUCHER' ? 'voucherId' : 'couponId'"
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-if="activityModel.rewardType === 'VOUCHER'"
|
|
|
+ v-model="activityModel.voucherId"
|
|
|
class="form-input"
|
|
|
clearable
|
|
|
+ filterable
|
|
|
placeholder="请选择"
|
|
|
- style="width: 100%"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 优惠券 -->
|
|
|
- <el-form-item label="优惠券" prop="couponId">
|
|
|
- <el-select v-model="activityModel.couponId" class="form-input" clearable filterable placeholder="请选择">
|
|
|
+ >
|
|
|
+ <el-option v-for="item in couponList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ <el-select v-else v-model="activityModel.couponId" class="form-input" clearable filterable placeholder="请选择">
|
|
|
<el-option v-for="item in couponList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <!-- 优惠券发放数量 -->
|
|
|
- <el-form-item label="优惠券发放数量" prop="couponQuantity">
|
|
|
- <el-input v-model="activityModel.couponQuantity" placeholder="请输入" maxlength="5" />
|
|
|
+ <!-- 优惠券/代金券发放数量 -->
|
|
|
+ <el-form-item
|
|
|
+ :label="(activityModel.rewardType === 'VOUCHER' ? '代金券' : '优惠券') + '发放数量'"
|
|
|
+ :prop="activityModel.rewardType === 'VOUCHER' ? 'voucherQuantity' : 'couponQuantity'"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-if="activityModel.rewardType === 'VOUCHER'"
|
|
|
+ v-model="activityModel.voucherQuantity"
|
|
|
+ placeholder="请输入"
|
|
|
+ maxlength="5"
|
|
|
+ />
|
|
|
+ <el-input v-else v-model="activityModel.couponQuantity" placeholder="请输入" maxlength="5" />
|
|
|
</el-form-item>
|
|
|
</template>
|
|
|
|
|
|
@@ -118,7 +135,7 @@
|
|
|
<el-radio :label="1"> 本地上传 </el-radio>
|
|
|
<el-radio :label="2"> AI生成 </el-radio>
|
|
|
</el-radio-group>
|
|
|
- <div v-if="type !== 'add'" style=" margin-top: 4px;font-size: 12px; color: #909399">
|
|
|
+ <div v-if="type !== 'add'" style="margin-top: 4px; font-size: 12px; color: #909399">
|
|
|
编辑模式下固定为"本地上传",以便编辑图片
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
@@ -227,13 +244,7 @@ import type { FormInstance, UploadFile, UploadProps } from "element-plus";
|
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
import { Plus } from "@element-plus/icons-vue";
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
-import {
|
|
|
- addActivity,
|
|
|
- getActivityDetail,
|
|
|
- getActivityRuleOptions,
|
|
|
- getCouponList,
|
|
|
- updateActivity
|
|
|
-} from "@/api/modules/operationManagement";
|
|
|
+import { addActivity, getActivityDetail, getCouponList, updateActivity } from "@/api/modules/operationManagement";
|
|
|
import { uploadContractImage } from "@/api/modules/licenseManagement";
|
|
|
import { localGet } from "@/utils";
|
|
|
|
|
|
@@ -264,22 +275,6 @@ const imageViewerVisible = ref(false);
|
|
|
const imageViewerUrlList = ref<string[]>([]);
|
|
|
const imageViewerInitialIndex = ref(0);
|
|
|
|
|
|
-// 活动规则级联选择器选项
|
|
|
-const ruleCascaderOptions = ref<any[]>([]);
|
|
|
-
|
|
|
-// 级联选择器配置
|
|
|
-const cascaderProps = {
|
|
|
- expandTrigger: "hover" as const,
|
|
|
- emitPath: true,
|
|
|
- disabled: (data: any) => {
|
|
|
- // 除了 "当用户 > 核销并评论 > 优惠券" 这个路径,其余选项不可选择
|
|
|
- if (data.disabled !== undefined) {
|
|
|
- return data.disabled;
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
// 是否有未上传的图片
|
|
|
const hasUnuploadedImages = computed(() => {
|
|
|
return (
|
|
|
@@ -357,13 +352,13 @@ const rules = reactive({
|
|
|
trigger: "blur"
|
|
|
}
|
|
|
],
|
|
|
- activityRule: [
|
|
|
- { required: true, message: "请选择活动规则", trigger: "change" },
|
|
|
+ rewardType: [{ required: true, message: "请选择券类型", trigger: "change" }],
|
|
|
+ couponId: [
|
|
|
{
|
|
|
validator: (rule: any, value: any, callback: any) => {
|
|
|
- if (activityModel.value.activityType === 2) {
|
|
|
- if (!value || !Array.isArray(value) || value.length < 2) {
|
|
|
- callback(new Error("请选择完整的活动规则(至少选择角色和行为)"));
|
|
|
+ if (activityModel.value.activityType === 2 && activityModel.value.rewardType === "COUPON") {
|
|
|
+ if (!value) {
|
|
|
+ callback(new Error("请选择优惠券"));
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
@@ -372,13 +367,35 @@ const rules = reactive({
|
|
|
trigger: "change"
|
|
|
}
|
|
|
],
|
|
|
- couponId: [
|
|
|
- { required: true, message: "请选择优惠券", trigger: "change" },
|
|
|
+ couponQuantity: [
|
|
|
{
|
|
|
validator: (rule: any, value: any, callback: any) => {
|
|
|
- if (activityModel.value.activityType === 2) {
|
|
|
+ if (activityModel.value.activityType === 2 && activityModel.value.rewardType === "COUPON") {
|
|
|
if (!value) {
|
|
|
- callback(new Error("请选择优惠券"));
|
|
|
+ callback(new Error("请输入优惠券发放数量"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const numValue = Number(value);
|
|
|
+ if (isNaN(numValue) || !Number.isInteger(numValue) || numValue <= 0) {
|
|
|
+ callback(new Error("优惠券发放数量必须为正整数"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (numValue > 99999) {
|
|
|
+ callback(new Error("优惠券发放数量必须小于99999"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ callback();
|
|
|
+ },
|
|
|
+ trigger: "blur"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ voucherId: [
|
|
|
+ {
|
|
|
+ validator: (rule: any, value: any, callback: any) => {
|
|
|
+ if (activityModel.value.activityType === 2 && activityModel.value.rewardType === "VOUCHER") {
|
|
|
+ if (!value) {
|
|
|
+ callback(new Error("请选择代金券"));
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
@@ -387,22 +404,21 @@ const rules = reactive({
|
|
|
trigger: "change"
|
|
|
}
|
|
|
],
|
|
|
- couponQuantity: [
|
|
|
- { required: true, message: "请输入优惠券发放数量", trigger: "blur" },
|
|
|
+ voucherQuantity: [
|
|
|
{
|
|
|
validator: (rule: any, value: any, callback: any) => {
|
|
|
- if (activityModel.value.activityType === 2) {
|
|
|
+ if (activityModel.value.activityType === 2 && activityModel.value.rewardType === "VOUCHER") {
|
|
|
if (!value) {
|
|
|
- callback(new Error("请输入优惠券发放数量"));
|
|
|
+ callback(new Error("请输入代金券发放数量"));
|
|
|
return;
|
|
|
}
|
|
|
const numValue = Number(value);
|
|
|
if (isNaN(numValue) || !Number.isInteger(numValue) || numValue <= 0) {
|
|
|
- callback(new Error("优惠券发放数量必须为正整数"));
|
|
|
+ callback(new Error("代金券发放数量必须为正整数"));
|
|
|
return;
|
|
|
}
|
|
|
if (numValue > 99999) {
|
|
|
- callback(new Error("优惠券发放数量必须小于99999"));
|
|
|
+ callback(new Error("代金券发放数量必须小于99999"));
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
@@ -543,12 +559,20 @@ const activityModel = ref<any>({
|
|
|
activityTimeRange: [],
|
|
|
// 用户可参与次数(评论有礼)
|
|
|
participationLimit: "",
|
|
|
- // 活动规则(级联选择器的值数组)(评论有礼)
|
|
|
- activityRule: [],
|
|
|
+ // 券类型:'COUPON'-优惠券,'VOUCHER'-代金券(评论有礼)
|
|
|
+ rewardType: "COUPON",
|
|
|
// 优惠券ID(评论有礼)
|
|
|
couponId: "",
|
|
|
+ // 优惠券名称(评论有礼)
|
|
|
+ couponName: "",
|
|
|
// 优惠券发放数量(评论有礼)
|
|
|
couponQuantity: "",
|
|
|
+ // 代金券ID(评论有礼)
|
|
|
+ voucherId: "",
|
|
|
+ // 代金券名称(评论有礼)
|
|
|
+ voucherName: "",
|
|
|
+ // 代金券发放数量(评论有礼)
|
|
|
+ voucherQuantity: "",
|
|
|
// 报名时间范围(营销活动)
|
|
|
signupTimeRange: [],
|
|
|
// 活动限制人数(营销活动)
|
|
|
@@ -977,6 +1001,40 @@ const handlePictureCardPreview = (file: any) => {
|
|
|
imageViewerVisible.value = true;
|
|
|
};
|
|
|
|
|
|
+// ==================== 加载优惠券列表函数 ====================
|
|
|
+
|
|
|
+/**
|
|
|
+ * 根据券类型加载优惠券/代金券列表
|
|
|
+ */
|
|
|
+const loadCouponList = async () => {
|
|
|
+ if (activityModel.value.activityType !== 2) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const params = {
|
|
|
+ storeId: localGet("createdId"),
|
|
|
+ groupType: localGet("businessSection"),
|
|
|
+ couponType: activityModel.value.rewardType === "VOUCHER" ? "1" : "2", // 代金券传1,优惠券传2
|
|
|
+ couponStatus: "1",
|
|
|
+ couponsFromType: 1,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 99999
|
|
|
+ };
|
|
|
+ const res: any = await getCouponList(params);
|
|
|
+ if (res && res.code == 200) {
|
|
|
+ const isVoucher = activityModel.value.rewardType === "VOUCHER";
|
|
|
+ // 代金券(couponType传1):取 data.couponList;优惠券:取 discountList.records
|
|
|
+ if (isVoucher) {
|
|
|
+ const raw = res.data.couponList;
|
|
|
+ couponList.value = Array.isArray(raw) ? raw : (raw?.records ?? raw?.list ?? []) || [];
|
|
|
+ } else {
|
|
|
+ couponList.value = res.data?.discountList?.records || [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("加载优惠券列表失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
// ==================== 监听器 ====================
|
|
|
|
|
|
/**
|
|
|
@@ -994,11 +1052,23 @@ watch(
|
|
|
if (newVal === 1) {
|
|
|
// 切换到营销活动:清除评论有礼相关字段
|
|
|
activityModel.value.participationLimit = "";
|
|
|
- activityModel.value.activityRule = [];
|
|
|
+ activityModel.value.rewardType = "COUPON";
|
|
|
activityModel.value.couponId = "";
|
|
|
+ activityModel.value.couponName = "";
|
|
|
activityModel.value.couponQuantity = "";
|
|
|
+ activityModel.value.voucherId = "";
|
|
|
+ activityModel.value.voucherName = "";
|
|
|
+ activityModel.value.voucherQuantity = "";
|
|
|
+ couponList.value = [];
|
|
|
// 清除评论有礼字段的验证状态
|
|
|
- ruleFormRef.value?.clearValidate(["participationLimit", "activityRule", "couponId", "couponQuantity"]);
|
|
|
+ ruleFormRef.value?.clearValidate([
|
|
|
+ "participationLimit",
|
|
|
+ "rewardType",
|
|
|
+ "couponId",
|
|
|
+ "couponQuantity",
|
|
|
+ "voucherId",
|
|
|
+ "voucherQuantity"
|
|
|
+ ]);
|
|
|
} else if (newVal === 2) {
|
|
|
// 切换到评论有礼:清除营销活动相关字段
|
|
|
activityModel.value.signupTimeRange = [];
|
|
|
@@ -1006,6 +1076,8 @@ watch(
|
|
|
activityModel.value.activityDetails = "";
|
|
|
// 清除营销活动字段的验证状态
|
|
|
ruleFormRef.value?.clearValidate(["signupTimeRange", "activityLimitPeople", "activityDetails"]);
|
|
|
+ // 加载优惠券列表
|
|
|
+ loadCouponList();
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
@@ -1013,6 +1085,36 @@ watch(
|
|
|
);
|
|
|
|
|
|
/**
|
|
|
+ * 监听券类型变化,切换时重新加载列表并清空已选券
|
|
|
+ */
|
|
|
+watch(
|
|
|
+ () => activityModel.value.rewardType,
|
|
|
+ (newVal, oldVal) => {
|
|
|
+ if (oldVal === undefined) return; // 初始化时不处理
|
|
|
+ if (newVal === oldVal) return;
|
|
|
+ if (activityModel.value.activityType !== 2) return; // 只有评论有礼才处理
|
|
|
+
|
|
|
+ nextTick(() => {
|
|
|
+ // 清空已选券(根据类型清空对应字段)
|
|
|
+ if (newVal === "VOUCHER") {
|
|
|
+ activityModel.value.voucherId = "";
|
|
|
+ activityModel.value.voucherName = "";
|
|
|
+ activityModel.value.voucherQuantity = "";
|
|
|
+ ruleFormRef.value?.clearValidate(["voucherId", "voucherQuantity"]);
|
|
|
+ } else {
|
|
|
+ activityModel.value.couponId = "";
|
|
|
+ activityModel.value.couponName = "";
|
|
|
+ activityModel.value.couponQuantity = "";
|
|
|
+ ruleFormRef.value?.clearValidate(["couponId", "couponQuantity"]);
|
|
|
+ }
|
|
|
+ couponList.value = [];
|
|
|
+ // 重新加载列表
|
|
|
+ loadCouponList();
|
|
|
+ });
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+/**
|
|
|
* 监听上传图片方式变化,切换时清除相关数据并重新验证
|
|
|
*/
|
|
|
watch(
|
|
|
@@ -1099,34 +1201,9 @@ onMounted(async () => {
|
|
|
id.value = (route.query.id as string) || "";
|
|
|
type.value = (route.query.type as string) || "";
|
|
|
|
|
|
- // 加载优惠券列表
|
|
|
- try {
|
|
|
- const params = {
|
|
|
- storeId: localGet("createdId"),
|
|
|
- groupType: localGet("businessSection"),
|
|
|
- couponType: "2",
|
|
|
- couponStatus: "1",
|
|
|
- couponsFromType: 1,
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 99999
|
|
|
- };
|
|
|
- const res: any = await getCouponList(params);
|
|
|
- if (res && res.code == 200) {
|
|
|
- couponList.value = res.data?.discountList?.records || [];
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error("加载优惠券列表失败:", error);
|
|
|
- }
|
|
|
-
|
|
|
- // 加载活动规则级联选择器选项
|
|
|
- try {
|
|
|
- const res: any = await getActivityRuleOptions({ page: 1, size: 99999 });
|
|
|
- console.log("ruleCascaderOptions:", res.data);
|
|
|
- if (res && res.code == 200) {
|
|
|
- ruleCascaderOptions.value = res.data || [];
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error("加载活动规则选项失败:", error);
|
|
|
+ // 如果是评论有礼类型,初始化时加载优惠券列表
|
|
|
+ if (activityModel.value.activityType === 2) {
|
|
|
+ await loadCouponList();
|
|
|
}
|
|
|
|
|
|
// 编辑模式下加载数据
|
|
|
@@ -1170,20 +1247,34 @@ onMounted(async () => {
|
|
|
// 加载活动详情
|
|
|
activityModel.value.activityDetails = res.data.activityDetails || "";
|
|
|
} else if (activityModel.value.activityType === 2) {
|
|
|
- // 评论有礼:加载活动规则、优惠券、优惠券发放数量、用户可参与次数
|
|
|
- // 加载活动规则
|
|
|
- if (res.data.activityRule) {
|
|
|
- activityModel.value.activityRule = res.data.activityRule.split(",");
|
|
|
+ // 评论有礼:加载活动规则、券类型、优惠券/代金券、发放数量、用户可参与次数
|
|
|
+ // 加载券类型('COUPON'-优惠券,'VOUCHER'-代金券)
|
|
|
+ // 兼容旧数据:如果后端返回的是数字,转换为新格式
|
|
|
+ if (res.data.rewardType) {
|
|
|
+ activityModel.value.rewardType = res.data.rewardType;
|
|
|
+ } else if (res.data.couponType !== undefined) {
|
|
|
+ // 兼容旧数据格式:1->COUPON, 4->VOUCHER
|
|
|
+ activityModel.value.rewardType = res.data.couponType === 4 ? "VOUCHER" : "COUPON";
|
|
|
} else {
|
|
|
- activityModel.value.activityRule = [];
|
|
|
+ activityModel.value.rewardType = "COUPON";
|
|
|
}
|
|
|
- // 加载优惠券ID
|
|
|
- activityModel.value.couponId = res.data.couponId || "";
|
|
|
- // 加载优惠券发放数量
|
|
|
- if (res.data.couponQuantity !== undefined && res.data.couponQuantity !== null) {
|
|
|
- activityModel.value.couponQuantity = String(res.data.couponQuantity);
|
|
|
+ // 根据 rewardType 加载对应的字段
|
|
|
+ if (activityModel.value.rewardType === "VOUCHER") {
|
|
|
+ activityModel.value.voucherId = res.data.voucherId || "";
|
|
|
+ activityModel.value.voucherName = res.data.voucherName || "";
|
|
|
+ if (res.data.voucherQuantity !== undefined && res.data.voucherQuantity !== null) {
|
|
|
+ activityModel.value.voucherQuantity = String(res.data.voucherQuantity);
|
|
|
+ } else {
|
|
|
+ activityModel.value.voucherQuantity = "";
|
|
|
+ }
|
|
|
} else {
|
|
|
- activityModel.value.couponQuantity = "";
|
|
|
+ activityModel.value.couponId = res.data.couponId || "";
|
|
|
+ activityModel.value.couponName = res.data.couponName || "";
|
|
|
+ if (res.data.couponQuantity !== undefined && res.data.couponQuantity !== null) {
|
|
|
+ activityModel.value.couponQuantity = String(res.data.couponQuantity);
|
|
|
+ } else {
|
|
|
+ activityModel.value.couponQuantity = "";
|
|
|
+ }
|
|
|
}
|
|
|
// 加载用户可参与次数
|
|
|
if (res.data.participationLimit !== undefined && res.data.participationLimit !== null) {
|
|
|
@@ -1191,6 +1282,8 @@ onMounted(async () => {
|
|
|
} else {
|
|
|
activityModel.value.participationLimit = "";
|
|
|
}
|
|
|
+ // 根据券类型加载对应的列表
|
|
|
+ await loadCouponList();
|
|
|
}
|
|
|
// 编辑模式:默认使用本地上传模式(uploadImgType=1),以便编辑图片和banner图
|
|
|
activityModel.value.uploadImgType = 1; // 编辑时固定为1-本地上传
|
|
|
@@ -1308,15 +1401,21 @@ const handleSubmit = async () => {
|
|
|
params.activityDetails = activityModel.value.activityDetails;
|
|
|
// 确保不包含评论有礼的字段
|
|
|
delete params.participationLimit;
|
|
|
- delete params.activityRule;
|
|
|
+ delete params.rewardType;
|
|
|
delete params.couponId;
|
|
|
delete params.couponQuantity;
|
|
|
} else if (activityModel.value.activityType === 2) {
|
|
|
// 评论有礼:只添加评论有礼相关字段
|
|
|
params.participationLimit = activityModel.value.participationLimit;
|
|
|
- params.activityRule = activityModel.value.activityRule.join(",");
|
|
|
- params.couponId = activityModel.value.couponId;
|
|
|
- params.couponQuantity = activityModel.value.couponQuantity;
|
|
|
+ params.rewardType = activityModel.value.rewardType; // 'COUPON'-优惠券,'VOUCHER'-代金券
|
|
|
+ // 根据 rewardType 提交对应的字段
|
|
|
+ if (activityModel.value.rewardType === "VOUCHER") {
|
|
|
+ params.voucherId = activityModel.value.voucherId;
|
|
|
+ params.voucherQuantity = activityModel.value.voucherQuantity;
|
|
|
+ } else {
|
|
|
+ params.couponId = activityModel.value.couponId;
|
|
|
+ params.couponQuantity = activityModel.value.couponQuantity;
|
|
|
+ }
|
|
|
// 确保不包含营销活动的字段
|
|
|
delete params.signupStartTime;
|
|
|
delete params.signupEndTime;
|