|
@@ -12,9 +12,16 @@
|
|
|
<span class="header-sub">消费送积分体系规则管理</span>
|
|
<span class="header-sub">消费送积分体系规则管理</span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <el-tag :type="form.enabled === 1 ? 'success' : 'info'" size="small" effect="plain">
|
|
|
|
|
- {{ form.enabled === 1 ? '已启用' : '已禁用' }}
|
|
|
|
|
- </el-tag>
|
|
|
|
|
|
|
+ <div class="header-right">
|
|
|
|
|
+ <span v-if="meta.updateTime" class="header-meta">
|
|
|
|
|
+ <i class="el-icon-time"></i>
|
|
|
|
|
+ 最后更新:<b>{{ meta.updateTime }}</b>
|
|
|
|
|
+ <span v-if="meta.updateBy"> · {{ meta.updateBy }}</span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <el-tag :type="form.enabled === 1 ? 'success' : 'info'" size="small" effect="plain">
|
|
|
|
|
+ {{ form.enabled === 1 ? '已启用' : '已禁用' }}
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<el-form ref="form" :model="form" :rules="rules" label-width="150px" size="small">
|
|
<el-form ref="form" :model="form" :rules="rules" label-width="150px" size="small">
|
|
@@ -119,8 +126,16 @@
|
|
|
<span class="section-icon deduct"><i class="el-icon-s-finance"></i></span>
|
|
<span class="section-icon deduct"><i class="el-icon-s-finance"></i></span>
|
|
|
<span class="section-label">积分抵扣配置</span>
|
|
<span class="section-label">积分抵扣配置</span>
|
|
|
<span class="section-desc">设置积分抵现规则</span>
|
|
<span class="section-desc">设置积分抵现规则</span>
|
|
|
|
|
+ <el-switch
|
|
|
|
|
+ v-model="form.deductEnabled"
|
|
|
|
|
+ :active-value="1"
|
|
|
|
|
+ :inactive-value="0"
|
|
|
|
|
+ active-color="#13ce66"
|
|
|
|
|
+ inactive-color="#ff4949"
|
|
|
|
|
+ class="section-switch"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="section-body">
|
|
|
|
|
|
|
+ <div class="section-body" :class="{ 'section-disabled': form.deductEnabled === 0 }">
|
|
|
<el-form-item label="积分支付比例" prop="payRate">
|
|
<el-form-item label="积分支付比例" prop="payRate">
|
|
|
<el-input-number
|
|
<el-input-number
|
|
|
v-model="form.payRate"
|
|
v-model="form.payRate"
|
|
@@ -136,17 +151,21 @@
|
|
|
</span>
|
|
</span>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
|
|
|
- <el-form-item label="最高抵扣积分" prop="maxDeduct">
|
|
|
|
|
|
|
+ <el-form-item label="最高抵扣比例" prop="maxDeductPercent">
|
|
|
<el-input-number
|
|
<el-input-number
|
|
|
- v-model="form.maxDeduct"
|
|
|
|
|
|
|
+ v-model="form.maxDeductPercent"
|
|
|
|
|
+ :precision="0"
|
|
|
:min="0"
|
|
:min="0"
|
|
|
- :max="999999"
|
|
|
|
|
- :step="10"
|
|
|
|
|
|
|
+ :max="100"
|
|
|
|
|
+ :step="5"
|
|
|
class="input-number-sm"
|
|
class="input-number-sm"
|
|
|
/>
|
|
/>
|
|
|
- <span class="tip-box tip-default">
|
|
|
|
|
- <i class="el-icon-info"></i>
|
|
|
|
|
- 每笔订单最多可用 <b>{{ form.maxDeduct || '不限' }}</b> 积分抵扣{{ form.maxDeduct > 0 ? ',超出部分不可使用' : '' }}
|
|
|
|
|
|
|
+ <span class="unit-suffix">%</span>
|
|
|
|
|
+ <span class="tip-box tip-warning">
|
|
|
|
|
+ <i class="el-icon-warning-outline"></i>
|
|
|
|
|
+ {{ form.maxDeductPercent > 0
|
|
|
|
|
+ ? '每笔订单积分抵扣金额不超过订单金额的 ' + form.maxDeductPercent + '%,防止 0 元购买'
|
|
|
|
|
+ : '不限制抵扣比例,存在 0 元购买风险,建议设置为 50%~90%' }}
|
|
|
</span>
|
|
</span>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
|
|
@@ -164,6 +183,23 @@
|
|
|
{{ form.minDeductAmount > 0 ? '订单满 ' + form.minDeductAmount + ' 元才可使用积分抵扣' : '不限制,任意金额均可使用积分抵扣' }}
|
|
{{ form.minDeductAmount > 0 ? '订单满 ' + form.minDeductAmount + ' 元才可使用积分抵扣' : '不限制,任意金额均可使用积分抵扣' }}
|
|
|
</span>
|
|
</span>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="最低起用积分" prop="minUseIntegral">
|
|
|
|
|
+ <el-input-number
|
|
|
|
|
+ v-model="form.minUseIntegral"
|
|
|
|
|
+ :precision="0"
|
|
|
|
|
+ :min="0"
|
|
|
|
|
+ :max="999999"
|
|
|
|
|
+ :step="10"
|
|
|
|
|
+ class="input-number-sm"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span class="tip-box tip-default">
|
|
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
|
|
+ {{ form.minUseIntegral > 0
|
|
|
|
|
+ ? '用户可用积分不足 ' + form.minUseIntegral + ' 时不可抵扣,防止零碎积分滥用'
|
|
|
|
|
+ : '不限制,1 积分即可起用' }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </el-form-item>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -231,6 +267,64 @@
|
|
|
</div>
|
|
</div>
|
|
|
</el-form>
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
+ <!-- 5. 积分计算示例 -->
|
|
|
|
|
+ <div class="section-block section-preview">
|
|
|
|
|
+ <div class="section-header">
|
|
|
|
|
+ <span class="section-icon preview"><i class="el-icon-cpu"></i></span>
|
|
|
|
|
+ <span class="section-label">积分计算示例</span>
|
|
|
|
|
+ <span class="section-desc">实时模拟规则效果,计算逻辑与后端一致</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="section-body preview-body">
|
|
|
|
|
+ <div class="preview-inputs">
|
|
|
|
|
+ <div class="preview-input-item">
|
|
|
|
|
+ <span class="preview-input-label">消费金额</span>
|
|
|
|
|
+ <el-input-number
|
|
|
|
|
+ v-model="preview.amount"
|
|
|
|
|
+ :precision="2"
|
|
|
|
|
+ :min="0"
|
|
|
|
|
+ :step="10"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ class="preview-input-num"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span class="preview-unit">元</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="preview-input-item">
|
|
|
|
|
+ <span class="preview-input-label">用户积分余额</span>
|
|
|
|
|
+ <el-input-number
|
|
|
|
|
+ v-model="preview.integral"
|
|
|
|
|
+ :min="0"
|
|
|
|
|
+ :step="100"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ class="preview-input-num"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span class="preview-unit">积分</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="preview-result">
|
|
|
|
|
+ <div class="result-card result-earn">
|
|
|
|
|
+ <div class="result-label"><i class="el-icon-coin"></i> 本次消费可获积分</div>
|
|
|
|
|
+ <div class="result-value">{{ previewResult.earnIntegral }}</div>
|
|
|
|
|
+ <div class="result-tip">消费 {{ previewAmountText }} 元 × {{ form.rate || 0 }}(四舍五入取整)</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="result-arrow"><i class="el-icon-right"></i></div>
|
|
|
|
|
+ <div class="result-card result-deduct">
|
|
|
|
|
+ <div class="result-label"><i class="el-icon-s-finance"></i> 积分可抵扣金额</div>
|
|
|
|
|
+ <div class="result-value">¥{{ previewResult.deductAmount }}</div>
|
|
|
|
|
+ <div class="result-tip">{{ previewResult.deductTip }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="result-arrow"><i class="el-icon-right"></i></div>
|
|
|
|
|
+ <div class="result-card result-pay">
|
|
|
|
|
+ <div class="result-label"><i class="el-icon-wallet"></i> 订单实付金额</div>
|
|
|
|
|
+ <div class="result-value">¥{{ previewResult.payAmount }}</div>
|
|
|
|
|
+ <div class="result-tip">消费金额 − 抵扣金额</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-if="form.enabled === 0" class="preview-warn">
|
|
|
|
|
+ <i class="el-icon-warning"></i> 当前规则已禁用,实际下单时不会发放积分
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 底部操作 -->
|
|
<!-- 底部操作 -->
|
|
|
<div class="form-footer">
|
|
<div class="form-footer">
|
|
|
<el-button size="medium" @click="handleReset" icon="el-icon-refresh">重 置</el-button>
|
|
<el-button size="medium" @click="handleReset" icon="el-icon-refresh">重 置</el-button>
|
|
@@ -276,6 +370,14 @@ export default {
|
|
|
productLoading: false,
|
|
productLoading: false,
|
|
|
categoryOptions: [],
|
|
categoryOptions: [],
|
|
|
productOptions: [],
|
|
productOptions: [],
|
|
|
|
|
+ meta: {
|
|
|
|
|
+ updateTime: '',
|
|
|
|
|
+ updateBy: ''
|
|
|
|
|
+ },
|
|
|
|
|
+ preview: {
|
|
|
|
|
+ amount: 100,
|
|
|
|
|
+ integral: 500
|
|
|
|
|
+ },
|
|
|
form: {
|
|
form: {
|
|
|
rate: 1.00,
|
|
rate: 1.00,
|
|
|
payRate: 100,
|
|
payRate: 100,
|
|
@@ -285,8 +387,10 @@ export default {
|
|
|
refundDeduct: 1,
|
|
refundDeduct: 1,
|
|
|
dailyLimit: 0,
|
|
dailyLimit: 0,
|
|
|
monthlyLimit: 0,
|
|
monthlyLimit: 0,
|
|
|
- maxDeduct: 0,
|
|
|
|
|
|
|
+ maxDeductPercent: 50,
|
|
|
minDeductAmount: 0,
|
|
minDeductAmount: 0,
|
|
|
|
|
+ minUseIntegral: 0,
|
|
|
|
|
+ deductEnabled: 1,
|
|
|
enabled: 1
|
|
enabled: 1
|
|
|
},
|
|
},
|
|
|
rules: {
|
|
rules: {
|
|
@@ -315,18 +419,92 @@ export default {
|
|
|
monthlyLimit: [
|
|
monthlyLimit: [
|
|
|
{ required: true, message: '请输入每月积分上限', trigger: 'blur' }
|
|
{ required: true, message: '请输入每月积分上限', trigger: 'blur' }
|
|
|
],
|
|
],
|
|
|
- maxDeduct: [
|
|
|
|
|
- { required: true, message: '请输入最高抵扣积分', trigger: 'blur' }
|
|
|
|
|
|
|
+ maxDeductPercent: [
|
|
|
|
|
+ { required: true, message: '请输入最高抵扣比例', trigger: 'blur' },
|
|
|
|
|
+ { type: 'number', min: 0, max: 100, message: '比例必须在 0~100 之间', trigger: 'blur' }
|
|
|
],
|
|
],
|
|
|
minDeductAmount: [
|
|
minDeductAmount: [
|
|
|
{ required: true, message: '请输入满减门槛', trigger: 'blur' }
|
|
{ required: true, message: '请输入满减门槛', trigger: 'blur' }
|
|
|
],
|
|
],
|
|
|
|
|
+ minUseIntegral: [
|
|
|
|
|
+ { required: true, message: '请输入最低起用积分', trigger: 'blur' },
|
|
|
|
|
+ { type: 'number', min: 0, message: '起用积分数不能为负', trigger: 'blur' }
|
|
|
|
|
+ ],
|
|
|
enabled: [
|
|
enabled: [
|
|
|
{ required: true, message: '请选择启用状态', trigger: 'change' }
|
|
{ required: true, message: '请选择启用状态', trigger: 'change' }
|
|
|
]
|
|
]
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ previewAmountText() {
|
|
|
|
|
+ const v = Number(this.preview.amount) || 0
|
|
|
|
|
+ return v.toFixed(2)
|
|
|
|
|
+ },
|
|
|
|
|
+ previewResult() {
|
|
|
|
|
+ const amount = Number(this.preview.amount) || 0
|
|
|
|
|
+ const integral = Number(this.preview.integral) || 0
|
|
|
|
|
+ const rate = Number(this.form.rate) || 0
|
|
|
|
|
+ const payRate = Number(this.form.payRate) || 1
|
|
|
|
|
+ const maxDeductPercent = Number(this.form.maxDeductPercent) || 0
|
|
|
|
|
+ const minDeductAmount = Number(this.form.minDeductAmount) || 0
|
|
|
|
|
+ const minUseIntegral = Number(this.form.minUseIntegral) || 0
|
|
|
|
|
+ const deductEnabled = Number(this.form.deductEnabled)
|
|
|
|
|
+
|
|
|
|
|
+ // 发放积分:消费金额 × rate,四舍五入取整(与后端 setScale(0, HALF_UP) 一致)
|
|
|
|
|
+ const earnIntegral = Math.round(amount * rate)
|
|
|
|
|
+
|
|
|
|
|
+ // 积分抵扣功能关闭
|
|
|
|
|
+ if (deductEnabled === 0) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ earnIntegral,
|
|
|
|
|
+ deductAmount: '0.00',
|
|
|
|
|
+ deductTip: '积分抵扣功能已关闭',
|
|
|
|
|
+ payAmount: amount.toFixed(2)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 抵扣门槛校验:minDeductAmount=0 表示不限制
|
|
|
|
|
+ const canDeduct = minDeductAmount > 0 ? amount >= minDeductAmount : true
|
|
|
|
|
+ let usableIntegral = 0
|
|
|
|
|
+ let deductAmountVal = 0
|
|
|
|
|
+ let deductTip = ''
|
|
|
|
|
+
|
|
|
|
|
+ if (!canDeduct) {
|
|
|
|
|
+ deductTip = `未满 ${minDeductAmount.toFixed(2)} 元门槛,不可使用积分抵扣`
|
|
|
|
|
+ } else if (integral <= 0) {
|
|
|
|
|
+ deductTip = '用户无可用积分'
|
|
|
|
|
+ } else if (minUseIntegral > 0 && integral < minUseIntegral) {
|
|
|
|
|
+ // 最低起用积分校验:用户积分不足起用门槛,不可抵扣
|
|
|
|
|
+ deductTip = `用户积分 ${integral} 不足起用门槛 ${minUseIntegral},不可抵扣`
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 可用积分 = 用户全部积分(maxDeduct 已废弃,改用 maxDeductPercent 按比例限制)
|
|
|
|
|
+ usableIntegral = integral
|
|
|
|
|
+ // 抵扣金额 = 可用积分 / payRate,保留2位小数四舍五入(与后端 divide(payRate, 2, HALF_UP) 一致)
|
|
|
|
|
+ let deduct = usableIntegral / payRate
|
|
|
|
|
+ // 抵扣金额不超过订单金额(后端有此约束)
|
|
|
|
|
+ deduct = Math.min(deduct, amount)
|
|
|
|
|
+ // 最高抵扣比例限制:抵扣金额不超过订单金额的 maxDeductPercent%
|
|
|
|
|
+ if (maxDeductPercent > 0) {
|
|
|
|
|
+ const maxDeductAmount = amount * maxDeductPercent / 100
|
|
|
|
|
+ if (deduct > maxDeductAmount) {
|
|
|
|
|
+ deduct = maxDeductAmount
|
|
|
|
|
+ // 反推实际可用积分(向下取整,保证不超额)
|
|
|
|
|
+ usableIntegral = Math.floor(deduct * payRate)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ deductAmountVal = deduct
|
|
|
|
|
+ const percentTip = maxDeductPercent > 0 ? `·比例上限${maxDeductPercent}%` : ''
|
|
|
|
|
+ deductTip = `可用 ${usableIntegral} 积分(用户${integral}${percentTip})÷ ${payRate}`
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const deductAmount = deductAmountVal.toFixed(2)
|
|
|
|
|
+ // 实付金额 = 消费金额 - 抵扣金额,不低于 0
|
|
|
|
|
+ const payAmount = Math.max(amount - deductAmountVal, 0).toFixed(2)
|
|
|
|
|
+
|
|
|
|
|
+ return { earnIntegral, deductAmount, deductTip, payAmount }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
mounted() {
|
|
mounted() {
|
|
|
this.loadCategoryDict()
|
|
this.loadCategoryDict()
|
|
|
this.loadConfig()
|
|
this.loadConfig()
|
|
@@ -352,15 +530,22 @@ export default {
|
|
|
refundDeduct: config.refundDeduct ?? 1,
|
|
refundDeduct: config.refundDeduct ?? 1,
|
|
|
dailyLimit: config.dailyLimit ?? 0,
|
|
dailyLimit: config.dailyLimit ?? 0,
|
|
|
monthlyLimit: config.monthlyLimit ?? 0,
|
|
monthlyLimit: config.monthlyLimit ?? 0,
|
|
|
- maxDeduct: config.maxDeduct ?? 0,
|
|
|
|
|
|
|
+ maxDeductPercent: config.maxDeductPercent ?? 50,
|
|
|
minDeductAmount: config.minDeductAmount ?? 0,
|
|
minDeductAmount: config.minDeductAmount ?? 0,
|
|
|
|
|
+ minUseIntegral: config.minUseIntegral ?? 0,
|
|
|
|
|
+ deductEnabled: config.deductEnabled ?? 1,
|
|
|
enabled: config.enabled ?? 1
|
|
enabled: config.enabled ?? 1
|
|
|
}
|
|
}
|
|
|
|
|
+ // 保存配置元信息(来自 sys_config 表 BaseEntity 字段)
|
|
|
|
|
+ this.meta.updateTime = response.data.updateTime || ''
|
|
|
|
|
+ this.meta.updateBy = response.data.updateBy || ''
|
|
|
if (config.excludeProductIds && config.excludeProductIds.length > 0) {
|
|
if (config.excludeProductIds && config.excludeProductIds.length > 0) {
|
|
|
this.loadSelectedProducts(config.excludeProductIds)
|
|
this.loadSelectedProducts(config.excludeProductIds)
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
this.configId = response.data ? response.data.configId : null
|
|
this.configId = response.data ? response.data.configId : null
|
|
|
|
|
+ this.meta.updateTime = response.data ? (response.data.updateTime || '') : ''
|
|
|
|
|
+ this.meta.updateBy = response.data ? (response.data.updateBy || '') : ''
|
|
|
}
|
|
}
|
|
|
}).catch(() => {
|
|
}).catch(() => {
|
|
|
this.$message.warning('配置加载失败,将使用默认值')
|
|
this.$message.warning('配置加载失败,将使用默认值')
|
|
@@ -429,6 +614,8 @@ export default {
|
|
|
this.configId = response.data ? response.data.configId : null
|
|
this.configId = response.data ? response.data.configId : null
|
|
|
}
|
|
}
|
|
|
this.$message.success('积分规则配置保存成功')
|
|
this.$message.success('积分规则配置保存成功')
|
|
|
|
|
+ // 保存成功后重新加载以刷新更新时间/更新人
|
|
|
|
|
+ this.loadConfig()
|
|
|
}
|
|
}
|
|
|
this.submitLoading = false
|
|
this.submitLoading = false
|
|
|
}).catch(() => {
|
|
}).catch(() => {
|
|
@@ -452,8 +639,10 @@ export default {
|
|
|
refundDeduct: 1,
|
|
refundDeduct: 1,
|
|
|
dailyLimit: 0,
|
|
dailyLimit: 0,
|
|
|
monthlyLimit: 0,
|
|
monthlyLimit: 0,
|
|
|
- maxDeduct: 0,
|
|
|
|
|
|
|
+ maxDeductPercent: 50,
|
|
|
minDeductAmount: 0,
|
|
minDeductAmount: 0,
|
|
|
|
|
+ minUseIntegral: 0,
|
|
|
|
|
+ deductEnabled: 1,
|
|
|
enabled: 1
|
|
enabled: 1
|
|
|
}
|
|
}
|
|
|
this.categoryOptions = []
|
|
this.categoryOptions = []
|
|
@@ -475,6 +664,9 @@ export default {
|
|
|
padding: 0;
|
|
padding: 0;
|
|
|
border-bottom: none;
|
|
border-bottom: none;
|
|
|
}
|
|
}
|
|
|
|
|
+.main-card >>> .el-card__body {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
/* ===== 卡片头部 ===== */
|
|
/* ===== 卡片头部 ===== */
|
|
|
.card-header {
|
|
.card-header {
|
|
@@ -515,6 +707,22 @@ export default {
|
|
|
font-size: 13px;
|
|
font-size: 13px;
|
|
|
color: #909399;
|
|
color: #909399;
|
|
|
}
|
|
}
|
|
|
|
|
+.header-right {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+.header-meta {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+}
|
|
|
|
|
+.header-meta i {
|
|
|
|
|
+ margin-right: 3px;
|
|
|
|
|
+}
|
|
|
|
|
+.header-meta b {
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
/* ===== 分区块 ===== */
|
|
/* ===== 分区块 ===== */
|
|
|
.section-block {
|
|
.section-block {
|
|
@@ -527,6 +735,9 @@ export default {
|
|
|
.section-block:hover {
|
|
.section-block:hover {
|
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
|
|
}
|
|
}
|
|
|
|
|
+.section-block >>> .el-form {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
.section-header {
|
|
.section-header {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -547,10 +758,11 @@ export default {
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
flex-shrink: 0;
|
|
flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
-.section-icon.earn { background: linear-gradient(135deg, #67C23A, #529b2e); }
|
|
|
|
|
-.section-icon.scope { background: linear-gradient(135deg, #409EFF, #337ECC); }
|
|
|
|
|
-.section-icon.deduct { background: linear-gradient(135deg, #E6A23C, #cf9236); }
|
|
|
|
|
-.section-icon.rules { background: linear-gradient(135deg, #9B59B6, #7d3c98); }
|
|
|
|
|
|
|
+.section-icon.earn { background: linear-gradient(135deg, #67C23A, #529b2e); }
|
|
|
|
|
+.section-icon.scope { background: linear-gradient(135deg, #409EFF, #337ECC); }
|
|
|
|
|
+.section-icon.deduct { background: linear-gradient(135deg, #E6A23C, #cf9236); }
|
|
|
|
|
+.section-icon.rules { background: linear-gradient(135deg, #9B59B6, #7d3c98); }
|
|
|
|
|
+.section-icon.preview { background: linear-gradient(135deg, #00B8A9, #00857a); }
|
|
|
|
|
|
|
|
.section-label {
|
|
.section-label {
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
@@ -562,6 +774,19 @@ export default {
|
|
|
color: #909399;
|
|
color: #909399;
|
|
|
margin-left: 4px;
|
|
margin-left: 4px;
|
|
|
}
|
|
}
|
|
|
|
|
+.section-switch {
|
|
|
|
|
+ margin-left: auto;
|
|
|
|
|
+}
|
|
|
|
|
+.section-disabled {
|
|
|
|
|
+ opacity: 0.5;
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+}
|
|
|
|
|
+.unit-suffix {
|
|
|
|
|
+ margin-left: 4px;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
.section-body {
|
|
.section-body {
|
|
|
padding: 16px 20px 4px;
|
|
padding: 16px 20px 4px;
|
|
@@ -632,6 +857,115 @@ export default {
|
|
|
border: 1px solid #e4e7ed;
|
|
border: 1px solid #e4e7ed;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* ===== 积分计算示例 ===== */
|
|
|
|
|
+.section-preview .section-header {
|
|
|
|
|
+ background: linear-gradient(135deg, #f0fffe 0%, #e6faf8 100%);
|
|
|
|
|
+}
|
|
|
|
|
+.preview-body {
|
|
|
|
|
+ padding: 20px 20px 16px;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-inputs {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 32px;
|
|
|
|
|
+ padding: 8px 0 20px;
|
|
|
|
|
+ border-bottom: 1px dashed #EBEEF5;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-input-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-input-label {
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-input-num {
|
|
|
|
|
+ width: 160px;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-unit {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-result {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: stretch;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+}
|
|
|
|
|
+.result-card {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-width: 180px;
|
|
|
|
|
+ padding: 16px 18px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ border: 1px solid #EBEEF5;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+}
|
|
|
|
|
+.result-card .result-label {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+.result-card .result-value {
|
|
|
|
|
+ font-size: 26px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ line-height: 1.2;
|
|
|
|
|
+}
|
|
|
|
|
+.result-card .result-tip {
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ color: #C0C4CC;
|
|
|
|
|
+ line-height: 1.5;
|
|
|
|
|
+}
|
|
|
|
|
+.result-earn {
|
|
|
|
|
+ border-color: #e1f3d8;
|
|
|
|
|
+ background: linear-gradient(135deg, #f0f9eb 0%, #ffffff 100%);
|
|
|
|
|
+}
|
|
|
|
|
+.result-earn .result-value { color: #67C23A; }
|
|
|
|
|
+.result-earn .result-label i { color: #67C23A; }
|
|
|
|
|
+
|
|
|
|
|
+.result-deduct {
|
|
|
|
|
+ border-color: #faecd8;
|
|
|
|
|
+ background: linear-gradient(135deg, #fdf6ec 0%, #ffffff 100%);
|
|
|
|
|
+}
|
|
|
|
|
+.result-deduct .result-value { color: #E6A23C; }
|
|
|
|
|
+.result-deduct .result-label i { color: #E6A23C; }
|
|
|
|
|
+
|
|
|
|
|
+.result-pay {
|
|
|
|
|
+ border-color: #d9ecff;
|
|
|
|
|
+ background: linear-gradient(135deg, #ecf5ff 0%, #ffffff 100%);
|
|
|
|
|
+}
|
|
|
|
|
+.result-pay .result-value { color: #409EFF; }
|
|
|
|
|
+.result-pay .result-label i { color: #409EFF; }
|
|
|
|
|
+
|
|
|
|
|
+.result-arrow {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ width: 28px;
|
|
|
|
|
+ color: #C0C4CC;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-warn {
|
|
|
|
|
+ margin-top: 14px;
|
|
|
|
|
+ padding: 8px 14px;
|
|
|
|
|
+ background: #fef0f0;
|
|
|
|
|
+ color: #F56C6C;
|
|
|
|
|
+ border: 1px solid #fde2e2;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+.preview-warn i {
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/* ===== 底部操作栏 ===== */
|
|
/* ===== 底部操作栏 ===== */
|
|
|
.form-footer {
|
|
.form-footer {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -691,4 +1025,33 @@ export default {
|
|
|
text-overflow: ellipsis;
|
|
text-overflow: ellipsis;
|
|
|
white-space: nowrap;
|
|
white-space: nowrap;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 响应式 ===== */
|
|
|
|
|
+@media (max-width: 768px) {
|
|
|
|
|
+ .section-block {
|
|
|
|
|
+ margin: 0 12px 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .section-body {
|
|
|
|
|
+ padding: 16px 12px 4px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .select-wide,
|
|
|
|
|
+ .select-wide-x {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+ .preview-inputs {
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .preview-result {
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ }
|
|
|
|
|
+ .result-arrow {
|
|
|
|
|
+ transform: rotate(90deg);
|
|
|
|
|
+ width: auto;
|
|
|
|
|
+ height: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .form-footer {
|
|
|
|
|
+ margin: 0 12px 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|