|
|
@@ -1,22 +1,33 @@
|
|
|
<template>
|
|
|
<view class="app-main app-content">
|
|
|
<view class="rule-list">
|
|
|
- <view class="rule-card" v-for="(item, index) in rules" :key="index">
|
|
|
- <view class="form-item">
|
|
|
- <view class="label">充值金额</view>
|
|
|
- <input class="input" type="digit" v-model="item.amount" placeholder="请输入金额" />
|
|
|
+ <view class="amount-card">
|
|
|
+ <view class="card-header">
|
|
|
+ <text class="title">充值金额</text>
|
|
|
+ <text class="desc">满足此金额即可获赠红包</text>
|
|
|
</view>
|
|
|
- <view class="form-item">
|
|
|
- <view class="label">送红包数</view>
|
|
|
- <input class="input" type="number" v-model="item.num" placeholder="请填写数量" />
|
|
|
+ <view class="input-container">
|
|
|
+ <text class="currency">¥</text>
|
|
|
+ <input class="amount-input" type="digit" v-model="amount" placeholder="0.00" placeholder-class="placeholder-style" />
|
|
|
</view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="section-header">
|
|
|
+ <view class="decoration"></view>
|
|
|
+ <text class="title">赠送红包设置</text>
|
|
|
+ </view>
|
|
|
+ <view class="rule-card" v-for="(item, index) in rules" :key="index">
|
|
|
<view class="form-item">
|
|
|
- <view class="label">单个包金额</view>
|
|
|
+ <view class="label">红包金额</view>
|
|
|
<input class="input" type="digit" v-model="item.hbAmount" placeholder="请输入金额" />
|
|
|
</view>
|
|
|
+ <view class="form-item">
|
|
|
+ <view class="label">红包数量</view>
|
|
|
+ <input class="input" type="digit" v-model="item.hbNum" placeholder="请输入数量" />
|
|
|
+ </view>
|
|
|
<view class="form-item">
|
|
|
<view class="label">有效时长</view>
|
|
|
- <input class="input" type="number" v-model="item.duration" placeholder="请输入天数,填0永不过期" />
|
|
|
+ <input class="input" type="number" v-model="item.duration" placeholder="请输入天数,填0是永不过期" />
|
|
|
</view>
|
|
|
<view class="form-item">
|
|
|
<view class="label">最低消费</view>
|
|
|
@@ -25,10 +36,41 @@
|
|
|
<view class="form-item action-row">
|
|
|
<view class="label">生效时间</view>
|
|
|
<view class="right-content">
|
|
|
- <view class="value">马上生效</view>
|
|
|
+ <view class="type-selector">
|
|
|
+ <view class="type-btn" :class="{'active': Number(item.effectiveType) === 2}" @click="changeEffectiveType(index, 2)">指定天数</view>
|
|
|
+ <view class="type-btn" :class="{'active': Number(item.effectiveType) !== 2}" @click="changeEffectiveType(index, 1)">指定日期</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item action-row" v-if="Number(item.effectiveType) !== 2">
|
|
|
+ <view class="label">选择日期</view>
|
|
|
+ <view class="right-content">
|
|
|
+ <view class="value" @click="openDatePicker(index)">
|
|
|
+ <text v-if="!item.effectiveDate" style="color:#ccc;">马上生效</text>
|
|
|
+ <text v-else>{{item.effectiveDate}}</text>
|
|
|
+ </view>
|
|
|
<view class="btn-group">
|
|
|
<button v-if="index > 0" class="mini-btn delete-btn" @click="deleteRule(index)">删除</button>
|
|
|
- <button class="mini-btn add-btn" @click="addRule">添加</button>
|
|
|
+ <button v-if="index == rules.length - 1" class="mini-btn add-btn" @click="addRule">添加</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item action-row" v-else>
|
|
|
+ <view class="label">充值成功后</view>
|
|
|
+ <view class="right-content">
|
|
|
+ <view style="display:flex;align-items:center;">
|
|
|
+ <view class="number-box">
|
|
|
+ <view class="num-btn minus" @click="changeDays(index, -1)">-</view>
|
|
|
+ <input class="num-input" type="number" v-model="item.effectiveDays" @input="onDaysInput(index, $event)" />
|
|
|
+ <view class="num-btn plus" @click="changeDays(index, 1)">+</view>
|
|
|
+ </view>
|
|
|
+ <view class="days-text">天后生效</view>
|
|
|
+ </view>
|
|
|
+ <view class="btn-group">
|
|
|
+ <button v-if="index > 0" class="mini-btn delete-btn" @click="deleteRule(index)">删除</button>
|
|
|
+ <button v-if="index == rules.length - 1" class="mini-btn add-btn" @click="addRule">添加</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -40,47 +82,66 @@
|
|
|
<button class="cancel-btn" @click="cancel">取消</button>
|
|
|
<button class="confirm-btn" @click="save">保存</button>
|
|
|
</view>
|
|
|
+
|
|
|
+ <!-- 日期选择器蒙板 -->
|
|
|
+ <view v-if="datePickerShow" class="date-picker-mask" @click="datePickerShow = false"></view>
|
|
|
+ <mx-date-picker :show="datePickerShow" format="yyyy-mm-dd" type="date" :value="datePickerValue" :show-tips="true" @confirm="confirmDatePicker" @cancel="datePickerShow = false" />
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { hbRulesList, sendHbRule, deleteHbRule } from '@/api/hb';
|
|
|
+import { hbRuleDetail, sendHbRule, deleteHbRule } from '@/api/hb';
|
|
|
+import MxDatePicker from '@/components/mx-datepicker/mx-datepicker.vue';
|
|
|
|
|
|
export default {
|
|
|
+ components: {
|
|
|
+ MxDatePicker
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
+ id: '',
|
|
|
+ amount: '', //充值金额
|
|
|
rules: [
|
|
|
{
|
|
|
- id: '',
|
|
|
- amount: '',
|
|
|
- num: '',
|
|
|
hbAmount: '',
|
|
|
+ hbNum: '',
|
|
|
+ miniCost: '',
|
|
|
duration: '',
|
|
|
- miniCost: ''
|
|
|
+ effectiveDate: '',
|
|
|
+ effectiveType: 2, // 1: 日期 2: 天数
|
|
|
+ effectiveDays: 0
|
|
|
}
|
|
|
- ]
|
|
|
+ ],
|
|
|
+ datePickerShow: false,
|
|
|
+ datePickerValue: '',
|
|
|
+ currentRuleIndex: -1
|
|
|
};
|
|
|
},
|
|
|
+ onLoad(options) {
|
|
|
+ this.id = options.id || null;
|
|
|
+ if(this.id) {
|
|
|
+ uni.setNavigationBarTitle({title: '修改充值送红包规则'});
|
|
|
+ this.getHbRuleDetail(this.id)
|
|
|
+ } else {
|
|
|
+ uni.setNavigationBarTitle({title: '创建充值送红包规则'});
|
|
|
+ }
|
|
|
+ },
|
|
|
methods: {
|
|
|
- init() {
|
|
|
- this.getHbRulesList()
|
|
|
- },
|
|
|
- getHbRulesList() {
|
|
|
- hbRulesList().then(res => {
|
|
|
+ init(){},
|
|
|
+ getHbRuleDetail(id) {
|
|
|
+ hbRuleDetail({id: id}).then(res => {
|
|
|
if(res.code == 1) {
|
|
|
- if(res.data.list.length == 0) {
|
|
|
- this.rules = [
|
|
|
- {
|
|
|
- id: '',
|
|
|
- amount: '',
|
|
|
- num: '',
|
|
|
- hbAmount: '',
|
|
|
- duration: '',
|
|
|
- miniCost: ''
|
|
|
+ if (res.data) {
|
|
|
+ if (res.data.amount !== undefined) {
|
|
|
+ this.amount = res.data.amount;
|
|
|
+ }
|
|
|
+ if (res.data.rules) {
|
|
|
+ try {
|
|
|
+ this.rules = typeof res.data.rules === 'string' ? JSON.parse(res.data.rules) : res.data.rules;
|
|
|
+ } catch (e) {
|
|
|
+ console.error('解析rules出错', e);
|
|
|
}
|
|
|
- ]
|
|
|
- } else {
|
|
|
- this.rules = res.data.list
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
this.$msg(res.msg);
|
|
|
@@ -89,14 +150,45 @@ export default {
|
|
|
},
|
|
|
addRule() {
|
|
|
this.rules.push({
|
|
|
- id: '',
|
|
|
- amount: '',
|
|
|
- num: '',
|
|
|
hbAmount: '',
|
|
|
+ hbNum: '',
|
|
|
duration: '',
|
|
|
- miniCost: ''
|
|
|
+ miniCost: '',
|
|
|
+ effectiveDate: '',
|
|
|
+ effectiveType: 2,
|
|
|
+ effectiveDays: 0
|
|
|
});
|
|
|
},
|
|
|
+ changeEffectiveType(index, type) {
|
|
|
+ this.$set(this.rules[index], 'effectiveType', type);
|
|
|
+ if (type === 2 && this.rules[index].effectiveDays === undefined) {
|
|
|
+ this.$set(this.rules[index], 'effectiveDays', 0);
|
|
|
+ }
|
|
|
+ if (type === 1 && this.rules[index].effectiveDate === undefined) {
|
|
|
+ this.$set(this.rules[index], 'effectiveDate', '');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ changeDays(index, delta) {
|
|
|
+ let currentDays = parseInt(this.rules[index].effectiveDays || 0);
|
|
|
+ let newDays = currentDays + delta;
|
|
|
+ if (newDays < 0) newDays = 0;
|
|
|
+ this.$set(this.rules[index], 'effectiveDays', newDays);
|
|
|
+ },
|
|
|
+ onDaysInput(index, event) {
|
|
|
+ let val = parseInt(event.detail.value);
|
|
|
+ if (isNaN(val) || val < 0) val = 0;
|
|
|
+ this.$set(this.rules[index], 'effectiveDays', val);
|
|
|
+ return val;
|
|
|
+ },
|
|
|
+ openDatePicker(index) {
|
|
|
+ this.currentRuleIndex = index;
|
|
|
+ this.datePickerValue = this.rules[index].effectiveDate || '';
|
|
|
+ this.datePickerShow = true;
|
|
|
+ },
|
|
|
+ confirmDatePicker(e) {
|
|
|
+ this.$set(this.rules[this.currentRuleIndex], 'effectiveDate', e.value);
|
|
|
+ this.datePickerShow = false;
|
|
|
+ },
|
|
|
deleteRule(index) {
|
|
|
//确认提示
|
|
|
this.$util.confirmModal({title: '提示', content: '确定删除该规则吗?'},() => {
|
|
|
@@ -120,18 +212,19 @@ export default {
|
|
|
uni.navigateBack();
|
|
|
},
|
|
|
save() {
|
|
|
+ if (!this.amount) {
|
|
|
+ this.$msg('请输入充值金额');
|
|
|
+ return;
|
|
|
+ }
|
|
|
for (let i = 0; i < this.rules.length; i++) {
|
|
|
const rule = this.rules[i];
|
|
|
- if (!rule.amount) {
|
|
|
- this.$msg(`请输入第${i+1}项充值金额`);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (!rule.num) {
|
|
|
- this.$msg(`请输入第${i+1}项送红包数`);
|
|
|
+
|
|
|
+ if (!rule.hbAmount) {
|
|
|
+ this.$msg(`请输入第${i+1}项单个红包金额`);
|
|
|
return;
|
|
|
}
|
|
|
- if (!rule.hbAmount) {
|
|
|
- this.$msg(`请输入第${i+1}项单个包金额`);
|
|
|
+ if (!rule.hbNum) {
|
|
|
+ this.$msg(`请输入第${i+1}项红包数量`);
|
|
|
return;
|
|
|
}
|
|
|
if (rule.duration === '') {
|
|
|
@@ -144,7 +237,7 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- sendHbRule(this.rules).then(res => {
|
|
|
+ sendHbRule({id: this.id, amount: this.amount, rules: this.rules}).then(res => {
|
|
|
if(res.code == 1) {
|
|
|
this.$msg('保存成功');
|
|
|
setTimeout(() => {
|
|
|
@@ -167,6 +260,84 @@ export default {
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
+.amount-card {
|
|
|
+ background: linear-gradient(135deg, #ffffff 0%, #f8fdfa 100%);
|
|
|
+ border-radius: 20upx;
|
|
|
+ padding: 40upx 30upx;
|
|
|
+ margin-bottom: 30upx;
|
|
|
+ box-shadow: 0 4upx 20upx rgba(9, 197, 103, 0.08);
|
|
|
+ border: 2upx solid rgba(9, 197, 103, 0.1);
|
|
|
+
|
|
|
+ .card-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: flex-end;
|
|
|
+ margin-bottom: 30upx;
|
|
|
+
|
|
|
+ .title {
|
|
|
+ font-size: 34upx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .desc {
|
|
|
+ font-size: 24upx;
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .input-container {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+ border-bottom: 2upx solid #09C567;
|
|
|
+ padding-bottom: 10upx;
|
|
|
+
|
|
|
+ .currency {
|
|
|
+ font-size: 48upx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #09C567;
|
|
|
+ margin-right: 16upx;
|
|
|
+ margin-bottom: 4upx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .amount-input {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 64upx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ height: 80upx;
|
|
|
+ line-height: 80upx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .placeholder-style {
|
|
|
+ color: #ccc;
|
|
|
+ font-size: 48upx;
|
|
|
+ font-weight: normal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.section-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 24upx;
|
|
|
+ padding: 0 10upx;
|
|
|
+
|
|
|
+ .decoration {
|
|
|
+ width: 8upx;
|
|
|
+ height: 32upx;
|
|
|
+ background-color: #09C567;
|
|
|
+ border-radius: 4upx;
|
|
|
+ margin-right: 16upx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .title {
|
|
|
+ font-size: 30upx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.rule-list {
|
|
|
padding-bottom: 20upx;
|
|
|
}
|
|
|
@@ -213,12 +384,88 @@ export default {
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
}
|
|
|
+
|
|
|
+ .type-selector {
|
|
|
+ display: flex;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-radius: 8upx;
|
|
|
+ padding: 4upx;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .type-btn {
|
|
|
+ flex: 1;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 26upx;
|
|
|
+ color: #666;
|
|
|
+ padding: 10upx 0;
|
|
|
+ border-radius: 6upx;
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background-color: #fff;
|
|
|
+ color: #09C567;
|
|
|
+ font-weight: bold;
|
|
|
+ box-shadow: 0 2upx 8upx rgba(0,0,0,0.05);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .number-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ border: 1upx solid #ddd;
|
|
|
+ border-radius: 8upx;
|
|
|
+ height: 60upx;
|
|
|
+
|
|
|
+ .num-btn {
|
|
|
+ width: 60upx;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 32upx;
|
|
|
+ color: #333;
|
|
|
+ background-color: #f8f8f8;
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: #e8e8e8;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.minus {
|
|
|
+ border-right: 1upx solid #ddd;
|
|
|
+ border-radius: 8upx 0 0 8upx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.plus {
|
|
|
+ border-left: 1upx solid #ddd;
|
|
|
+ border-radius: 0 8upx 8upx 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .num-input {
|
|
|
+ width: 80upx;
|
|
|
+ height: 100%;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .days-text {
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #333;
|
|
|
+ margin-left: 10upx;
|
|
|
+ margin-right: auto;
|
|
|
+ }
|
|
|
+
|
|
|
.value {
|
|
|
color: #333;
|
|
|
}
|
|
|
.btn-group {
|
|
|
display: flex;
|
|
|
- gap: 20upx;
|
|
|
+ .mini-btn + .mini-btn {
|
|
|
+ margin-left: 20upx;
|
|
|
+ }
|
|
|
}
|
|
|
.mini-btn {
|
|
|
margin: 0;
|
|
|
@@ -259,6 +506,15 @@ export default {
|
|
|
box-shadow: 0 -2upx 10upx rgba(0,0,0,0.05);
|
|
|
z-index: 99;
|
|
|
|
|
|
+ @keyframes fadeIn {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
.cancel-btn {
|
|
|
width: 45%;
|
|
|
background-color: #fff;
|
|
|
@@ -279,4 +535,15 @@ export default {
|
|
|
&::after { border: none; }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.date-picker-mask {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
+ z-index: 99;
|
|
|
+ animation: fadeIn 0.3s ease-in-out;
|
|
|
+}
|
|
|
</style>
|