|
|
@@ -4,7 +4,7 @@
|
|
|
<div class="cfg-banner-icon teal"><i class="el-icon-s-operation"></i></div>
|
|
|
<div>
|
|
|
<div class="cfg-banner-title">运营自动化</div>
|
|
|
- <div class="cfg-banner-desc">配置定时推送商品、红包、抽奖与优惠券等自动化任务</div>
|
|
|
+ <div class="cfg-banner-desc">配置定时推送商品、红包、抽奖、优惠券与签到等自动化任务</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="cfg-panel">
|
|
|
@@ -103,7 +103,7 @@
|
|
|
<el-table-column label="任务类型" align="center" prop="taskType" :formatter="taskTypeFormatter" />
|
|
|
<el-table-column label="触发类型" align="center" prop="triggerType" :formatter="triggerTypeFormatter" />
|
|
|
<el-table-column label="触发时间" align="center" prop="triggerValue" :formatter="triggerValueFormatter" />
|
|
|
- <el-table-column label="产品名称" align="center" prop="productName" :formatter="productNameFormatter" />
|
|
|
+ <el-table-column label="关联内容" align="center" prop="productName" :formatter="productNameFormatter" />
|
|
|
<el-table-column label="状态" align="center" prop="status" :formatter="statusFormatter" />
|
|
|
<el-table-column label="创建时间" align="center" prop="createdTime" width="180">
|
|
|
<template slot-scope="scope">
|
|
|
@@ -144,8 +144,8 @@
|
|
|
/>
|
|
|
|
|
|
<!-- 添加或修改直播间自动化任务配置对话框 -->
|
|
|
- <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
|
|
- <el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
|
|
+ <el-dialog :title="title" :visible.sync="open" width="620px" append-to-body>
|
|
|
+ <el-form ref="form" :model="form" :rules="rules" label-width="90px">
|
|
|
<el-form-item label="直播间ID" prop="liveId">
|
|
|
<el-input :disabled="liveAbled" v-model="form.liveId" placeholder="请输入直播间ID" />
|
|
|
</el-form-item>
|
|
|
@@ -237,9 +237,28 @@
|
|
|
<el-option v-for="i in goodsStatusOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
-<!-- <el-form-item label="序号" prop="signNo" v-if="form.taskType == 7">-->
|
|
|
-<!-- <el-input v-model.number="form.signNo" placeholder="请输入签到序号" oninput="value=value.replace(/[^\d]/g,'')" />-->
|
|
|
-<!-- </el-form-item>-->
|
|
|
+ <el-form-item label="签到奖励" v-if="form.taskType == 7">
|
|
|
+ <div class="sign-reward-list">
|
|
|
+ <div class="sign-reward-item" v-for="(item, index) in form.rewards" :key="index">
|
|
|
+ <el-select v-model="item.rewardType" placeholder="奖励类型" style="width: 120px; margin-right: 8px;" @change="onSignRewardTypeChange(item, index)">
|
|
|
+ <el-option v-for="i in rewardTypeOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-select v-if="item.rewardType == 2" v-model="item.rewardId" placeholder="请选择积分红包" style="width: 180px; margin-right: 8px;">
|
|
|
+ <el-option v-for="i in redOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <template v-else-if="item.rewardType == 5">
|
|
|
+ <el-select v-model="item.rewardId" placeholder="请选择优惠券" style="width: 160px; margin-right: 8px;">
|
|
|
+ <el-option v-for="i in couponOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-input-number v-model="item.couponCount" :min="1" :max="99" controls-position="right" placeholder="数量" style="width: 110px; margin-right: 8px;"></el-input-number>
|
|
|
+ <span style="margin-right: 8px; color: #909399;">张</span>
|
|
|
+ </template>
|
|
|
+ <el-input v-else-if="item.rewardType == 6" v-model="item.amount" placeholder="金额精确到0.1元" style="width: 180px; margin-right: 8px;" @input="onCashAmountInput(item)"></el-input>
|
|
|
+ <el-button type="text" icon="el-icon-delete" @click="removeSignReward(index)" v-if="form.rewards.length > 1">删除</el-button>
|
|
|
+ </div>
|
|
|
+ <el-button type="text" icon="el-icon-plus" @click="addSignReward">添加奖励</el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="触发时间" prop="content">
|
|
|
<el-time-picker
|
|
|
default-value="2025-01-01 00:00:00"
|
|
|
@@ -309,11 +328,17 @@ export default {
|
|
|
{
|
|
|
value: 6,
|
|
|
label: "定时商品上下架"
|
|
|
- },{
|
|
|
+ },
|
|
|
+ {
|
|
|
value: 7,
|
|
|
- label: "签到"
|
|
|
+ label: "签到任务"
|
|
|
}
|
|
|
],
|
|
|
+ rewardTypeOptions: [
|
|
|
+ { value: 2, label: "积分红包" },
|
|
|
+ { value: 5, label: "优惠券" },
|
|
|
+ { value: 6, label: "金额红包" }
|
|
|
+ ],
|
|
|
statusOptions:[{
|
|
|
value: "0",
|
|
|
label: "禁用"
|
|
|
@@ -470,6 +495,8 @@ export default {
|
|
|
return "定时优惠券";
|
|
|
case 6:
|
|
|
return "定时商品上下架";
|
|
|
+ case 7:
|
|
|
+ return "签到任务";
|
|
|
default:
|
|
|
return "--";
|
|
|
}
|
|
|
@@ -490,6 +517,29 @@ export default {
|
|
|
if(content.productName) {
|
|
|
return content.productName
|
|
|
}
|
|
|
+ if (row.taskType == 7) {
|
|
|
+ const rewards = Array.isArray(content.rewards) ? content.rewards : null;
|
|
|
+ if (rewards && rewards.length) {
|
|
|
+ return rewards.map(r => {
|
|
|
+ if (!r) return '';
|
|
|
+ if (r.rewardType == 2) return (r.reward && r.reward.desc) || '积分红包';
|
|
|
+ if (r.rewardType == 5) {
|
|
|
+ const title = (r.reward && r.reward.title) || '优惠券';
|
|
|
+ const count = r.couponCount > 0 ? r.couponCount : 1;
|
|
|
+ return title + '×' + count;
|
|
|
+ }
|
|
|
+ if (r.rewardType == 6) return '金额红包¥' + (r.amount != null ? r.amount : '--');
|
|
|
+ return '';
|
|
|
+ }).filter(Boolean).join('、') || '--';
|
|
|
+ }
|
|
|
+ if (content.reward) {
|
|
|
+ if (content.rewardType == 2) return content.reward.desc || '--';
|
|
|
+ if (content.rewardType == 5) return content.reward.title || '--';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (row.taskType == 2 && content.desc) return content.desc;
|
|
|
+ if (row.taskType == 4 && content.desc) return content.desc;
|
|
|
+ if (row.taskType == 5 && content.title) return content.title;
|
|
|
return "--";
|
|
|
},
|
|
|
triggerValueFormatter(row, column, value) {
|
|
|
@@ -525,6 +575,12 @@ export default {
|
|
|
pageSize: 10,
|
|
|
liveId: null
|
|
|
}
|
|
|
+ this.form.content = null;
|
|
|
+ this.form.goodsId = null;
|
|
|
+ this.form.goodsStatus = null;
|
|
|
+ this.form.rewardType = null;
|
|
|
+ this.form.rewardId = null;
|
|
|
+ this.form.rewards = this.form.taskType == 7 ? [{ rewardType: null, rewardId: null, couponCount: 1, amount: null }] : [];
|
|
|
if (this.isLoading || !this.hasMore) return;
|
|
|
this.isLoading = true;
|
|
|
this.listParams.liveId = this.liveId;
|
|
|
@@ -544,6 +600,8 @@ export default {
|
|
|
await this.addCouponList();
|
|
|
}else if(this.form.taskType == 6){
|
|
|
await this.addGoodsList();
|
|
|
+ }else if(this.form.taskType == 7){
|
|
|
+ await this.preloadAllSignRewardOptions();
|
|
|
}
|
|
|
}catch ( err){
|
|
|
console.error('加载数据失败:', err);
|
|
|
@@ -551,6 +609,66 @@ export default {
|
|
|
this.isLoading = false;
|
|
|
}
|
|
|
},
|
|
|
+ async preloadAllSignRewardOptions() {
|
|
|
+ await this.addRedList();
|
|
|
+ this.listParams.pageNum = 1;
|
|
|
+ this.hasMore = true;
|
|
|
+ await this.addCouponList();
|
|
|
+ },
|
|
|
+ async onSignRewardTypeChange(item) {
|
|
|
+ item.rewardId = null;
|
|
|
+ item.couponCount = 1;
|
|
|
+ item.amount = null;
|
|
|
+ if (!item.rewardType) return;
|
|
|
+ const others = (this.form.rewards || []).filter(r => r !== item);
|
|
|
+ if (item.rewardType == 2 && others.some(r => r.rewardType == 2)) {
|
|
|
+ this.msgError("积分红包只能配置一个");
|
|
|
+ item.rewardType = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (item.rewardType == 6 && others.some(r => r.rewardType == 6)) {
|
|
|
+ this.msgError("金额红包只能配置一个");
|
|
|
+ item.rewardType = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.listParams = { pageNum: 1, pageSize: 10, liveId: this.liveId };
|
|
|
+ this.hasMore = true;
|
|
|
+ if (item.rewardType == 2) await this.addRedList();
|
|
|
+ else if (item.rewardType == 5) await this.addCouponList();
|
|
|
+ },
|
|
|
+ onCashAmountInput(item) {
|
|
|
+ if (item.amount == null || item.amount === '') return;
|
|
|
+ let val = String(item.amount).replace(/[^\d.]/g, '');
|
|
|
+ const parts = val.split('.');
|
|
|
+ if (parts.length > 2) {
|
|
|
+ val = parts[0] + '.' + parts.slice(1).join('');
|
|
|
+ }
|
|
|
+ // 金额红包精确到 0.1 元(一位小数)
|
|
|
+ if (parts.length === 2) {
|
|
|
+ val = parts[0] + '.' + parts[1].slice(0, 1);
|
|
|
+ }
|
|
|
+ item.amount = val;
|
|
|
+ },
|
|
|
+ addSignReward() {
|
|
|
+ if (!this.form.rewards) this.form.rewards = [];
|
|
|
+ this.form.rewards.push({ rewardType: null, rewardId: null, couponCount: 1, amount: null });
|
|
|
+ },
|
|
|
+ removeSignReward(index) {
|
|
|
+ this.form.rewards.splice(index, 1);
|
|
|
+ },
|
|
|
+ async loadSignRewardOptions(rewardType) {
|
|
|
+ this.hasMore = true;
|
|
|
+ this.listParams = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ liveId: this.liveId
|
|
|
+ }
|
|
|
+ if (rewardType == 2) {
|
|
|
+ await this.addRedList();
|
|
|
+ } else if (rewardType == 5) {
|
|
|
+ await this.addCouponList();
|
|
|
+ }
|
|
|
+ },
|
|
|
addGoodsList() {
|
|
|
if(this.haveData.goods) return
|
|
|
listLiveGoods(this.listParams).then(res => {
|
|
|
@@ -683,7 +801,9 @@ export default {
|
|
|
content: null,
|
|
|
goodsId: null,
|
|
|
goodsStatus: null,
|
|
|
- // signNo:null,
|
|
|
+ rewardType: null,
|
|
|
+ rewardId: null,
|
|
|
+ rewards: [],
|
|
|
status: 1,
|
|
|
createdTime: null,
|
|
|
updatedTime: null
|
|
|
@@ -733,7 +853,7 @@ export default {
|
|
|
await this.addGoodsList();
|
|
|
}
|
|
|
const id = row.id || this.ids
|
|
|
- getTask(id).then(response => {
|
|
|
+ getTask(id).then(async response => {
|
|
|
this.form = response.data;
|
|
|
let content = JSON.parse( response.data.content)
|
|
|
if (this.form.taskType == 1) {
|
|
|
@@ -748,7 +868,37 @@ export default {
|
|
|
this.form.goodsId = content.goodsId;
|
|
|
this.form.goodsStatus = content.status;
|
|
|
}else if(this.form.taskType == 7){
|
|
|
- // this.form.signNo = content.signNo;
|
|
|
+ await this.preloadAllSignRewardOptions();
|
|
|
+ const rewards = [];
|
|
|
+ if (Array.isArray(content.rewards) && content.rewards.length) {
|
|
|
+ content.rewards.forEach(r => {
|
|
|
+ let rewardId = r.rewardId;
|
|
|
+ if (rewardId == null && r.reward) {
|
|
|
+ if (r.rewardType == 2) rewardId = r.reward.redId;
|
|
|
+ else if (r.rewardType == 5) rewardId = r.reward.couponId;
|
|
|
+ }
|
|
|
+ rewards.push({
|
|
|
+ rewardType: r.rewardType != null ? Number(r.rewardType) : null,
|
|
|
+ rewardId: rewardId,
|
|
|
+ couponCount: r.couponCount > 0 ? Number(r.couponCount) : 1,
|
|
|
+ amount: r.amount != null ? r.amount : null
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else if (content.rewardType != null) {
|
|
|
+ // 兼容旧单奖励结构
|
|
|
+ let rewardId = content.rewardId;
|
|
|
+ if (rewardId == null && content.reward) {
|
|
|
+ if (content.rewardType == 2) rewardId = content.reward.redId;
|
|
|
+ else if (content.rewardType == 5) rewardId = content.reward.couponId;
|
|
|
+ }
|
|
|
+ rewards.push({
|
|
|
+ rewardType: Number(content.rewardType),
|
|
|
+ rewardId: rewardId,
|
|
|
+ couponCount: content.couponCount > 0 ? Number(content.couponCount) : 1,
|
|
|
+ amount: content.amount != null ? content.amount : null
|
|
|
+ });
|
|
|
+ }
|
|
|
+ this.form.rewards = rewards.length ? rewards : [{ rewardType: null, rewardId: null, couponCount: 1, amount: null }];
|
|
|
}
|
|
|
this.open = true;
|
|
|
this.title = "修改直播间自动化任务配置";
|
|
|
@@ -773,14 +923,54 @@ export default {
|
|
|
|
|
|
}
|
|
|
if(this.form.taskType == 7){
|
|
|
- // if(this.form.signNo == null) {
|
|
|
- // this.msgError("必须填写签到序号");
|
|
|
- // return;
|
|
|
- // }
|
|
|
- // 序号后端自己生成,
|
|
|
- this.form.content = JSON.stringify({
|
|
|
- signNo: 1
|
|
|
- })
|
|
|
+ const rewards = [];
|
|
|
+ let hasPointRed = false;
|
|
|
+ let hasCashRed = false;
|
|
|
+ for (const r of (this.form.rewards || [])) {
|
|
|
+ if (!r || r.rewardType == null) continue;
|
|
|
+ if (r.rewardType == 2) {
|
|
|
+ if (r.rewardId == null) {
|
|
|
+ this.msgError("请选择积分红包");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (hasPointRed) {
|
|
|
+ this.msgError("积分红包只能配置一个");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ hasPointRed = true;
|
|
|
+ rewards.push({ rewardType: 2, rewardId: r.rewardId });
|
|
|
+ } else if (r.rewardType == 5) {
|
|
|
+ if (r.rewardId == null) {
|
|
|
+ this.msgError("请选择优惠券");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const couponCount = r.couponCount > 0 ? Number(r.couponCount) : 1;
|
|
|
+ rewards.push({ rewardType: 5, rewardId: r.rewardId, couponCount });
|
|
|
+ } else if (r.rewardType == 6) {
|
|
|
+ if (hasCashRed) {
|
|
|
+ this.msgError("金额红包只能配置一个");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const amount = Number(r.amount);
|
|
|
+ if (!amount || amount <= 0) {
|
|
|
+ this.msgError("请输入正确的金额红包金额");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 精确到 0.1 元
|
|
|
+ const normalized = Math.round(amount * 10) / 10;
|
|
|
+ if (Math.abs(amount - normalized) > 1e-8) {
|
|
|
+ this.msgError("金额红包需精确到0.1元");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ hasCashRed = true;
|
|
|
+ rewards.push({ rewardType: 6, amount: normalized.toFixed(1) });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!rewards.length) {
|
|
|
+ this.msgError("请至少配置一个签到奖励");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.form.content = JSON.stringify({ rewards })
|
|
|
}
|
|
|
|
|
|
this.$refs["form"].validate(valid => {
|
|
|
@@ -874,4 +1064,14 @@ export default {
|
|
|
from { transform: rotate(0deg); }
|
|
|
to { transform: rotate(360deg); }
|
|
|
}
|
|
|
+
|
|
|
+.sign-reward-list {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.sign-reward-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
</style>
|