|
|
@@ -0,0 +1,291 @@
|
|
|
+<template>
|
|
|
+ <div class="discount-rule-management admin-page">
|
|
|
+ <el-card>
|
|
|
+ <div slot="header" class="admin-page-header">
|
|
|
+ <span class="admin-page-title">限时折扣管理</span>
|
|
|
+ <div class="admin-page-actions">
|
|
|
+ <el-button type="primary" size="small" @click="handleCreate">新建规则</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="table-scroll-wrap-sm">
|
|
|
+ <el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
|
|
|
+ <el-table-column prop="id" label="ID" width="70" />
|
|
|
+ <el-table-column prop="name" label="规则名称" min-width="140" show-overflow-tooltip />
|
|
|
+ <el-table-column label="类型" width="90">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag size="mini" :type="typeTagType(row.type)">{{ typeLabel(row.type) }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="折扣值" width="100">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span v-if="row.type === 'PERCENT'">{{ row.value }}%</span>
|
|
|
+ <span v-else>{{ (row.value / 100).toFixed(2) }}元</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="满减门槛" width="100">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span v-if="row.type === 'THRESHOLD'">{{ row.thresholdAmount ? (row.thresholdAmount / 100).toFixed(2) + '元' : '-' }}</span>
|
|
|
+ <span v-else>-</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="时间范围" width="260">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span v-if="row.startTime">{{ formatTime(row.startTime) }}</span>
|
|
|
+ <span v-else>-</span>
|
|
|
+ <br />
|
|
|
+ <span v-if="row.endTime">{{ formatTime(row.endTime) }}</span>
|
|
|
+ <span v-else>-</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="使用次数" width="100">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span>{{ row.usedCount || 0 }}/{{ row.maxUses || '不限' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="状态" width="80">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-switch
|
|
|
+ :value="row.enabled"
|
|
|
+ @change="handleToggle(row)"
|
|
|
+ active-color="#67C23A"
|
|
|
+ inactive-color="#DCDFE6"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" width="120" fixed="right">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
|
|
|
+ <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-pagination
|
|
|
+ @current-change="onPageChange"
|
|
|
+ @size-change="onSizeChange"
|
|
|
+ :current-page="page"
|
|
|
+ :page-size="size"
|
|
|
+ :total="total"
|
|
|
+ layout="total, prev, pager, next"
|
|
|
+ class="pagination-wrap"
|
|
|
+ />
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <el-dialog :visible.sync="formDialogVisible" :title="isEdit ? '编辑折扣规则' : '新建折扣规则'" width="580px">
|
|
|
+ <el-form :model="form" label-width="130px" ref="ruleForm">
|
|
|
+ <el-form-item label="规则名称" required>
|
|
|
+ <el-input v-model="form.name" placeholder="请输入规则名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="折扣类型" required>
|
|
|
+ <el-select v-model="form.type" placeholder="请选择类型" style="width: 100%">
|
|
|
+ <el-option label="PERCENT - 按百分比减免" value="PERCENT" />
|
|
|
+ <el-option label="FIXED - 固定金额减免" value="FIXED" />
|
|
|
+ <el-option label="THRESHOLD - 满减折扣" value="THRESHOLD" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="折扣值" required>
|
|
|
+ <el-input-number v-model="form.value" :min="0" :step="1" style="width: 200px" />
|
|
|
+ <span class="form-item-tip" v-if="form.type === 'PERCENT'">(百分比,如20表示减免20%)</span>
|
|
|
+ <span class="form-item-tip" v-else>(金额,单位:分)</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="满减门槛" v-if="form.type === 'THRESHOLD'">
|
|
|
+ <el-input-number v-model="form.thresholdAmount" :min="0" :step="100" style="width: 200px" />
|
|
|
+ <span class="form-item-tip">(达到此金额后方可享受折扣,单位:分)</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="开始时间">
|
|
|
+ <el-date-picker v-model="form.startTimeStr" type="datetime" placeholder="选择开始时间" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="结束时间">
|
|
|
+ <el-date-picker v-model="form.endTimeStr" type="datetime" placeholder="选择结束时间" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="最大使用次数">
|
|
|
+ <el-input-number v-model="form.maxUses" :min="0" :step="1" style="width: 200px" />
|
|
|
+ <span class="form-item-tip">(0 表示不限)</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="适用类目ID">
|
|
|
+ <el-input-number v-model="form.categoryId" :min="1" :step="1" style="width: 200px" placeholder="留空=全部类目" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="适用体系ID">
|
|
|
+ <el-input-number v-model="form.distributionSystemId" :min="1" :step="1" style="width: 200px" placeholder="留空=全部体系" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="适用商品ID">
|
|
|
+ <el-input v-model="form.productIds" placeholder="逗号分隔的商品ID,如1,2,3;留空=全部商品" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="formDialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSubmit" :loading="submitting">保存</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getDiscountRuleList, createDiscountRule, updateDiscountRule, toggleDiscountRule, deleteDiscountRule } from '@/api/discount'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'DiscountRuleManagement',
|
|
|
+ computed: {
|
|
|
+ tableHeight() {
|
|
|
+ return window.innerHeight - 300
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ list: [],
|
|
|
+ loading: false,
|
|
|
+ page: 1,
|
|
|
+ size: 20,
|
|
|
+ total: 0,
|
|
|
+ formDialogVisible: false,
|
|
|
+ isEdit: false,
|
|
|
+ submitting: false,
|
|
|
+ form: this.getEmptyForm()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.loadData()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ typeLabel(val) {
|
|
|
+ const map = { PERCENT: '百分比', FIXED: '固定金额', THRESHOLD: '满减' }
|
|
|
+ return map[val] || val
|
|
|
+ },
|
|
|
+ typeTagType(val) {
|
|
|
+ const map = { PERCENT: 'warning', FIXED: 'success', THRESHOLD: '' }
|
|
|
+ return map[val] || ''
|
|
|
+ },
|
|
|
+ formatTime(t) {
|
|
|
+ if (!t) return '-'
|
|
|
+ return String(t).replace('T', ' ').substring(0, 19)
|
|
|
+ },
|
|
|
+ getEmptyForm() {
|
|
|
+ return {
|
|
|
+ id: null,
|
|
|
+ name: '',
|
|
|
+ type: 'PERCENT',
|
|
|
+ value: 20,
|
|
|
+ thresholdAmount: 0,
|
|
|
+ startTimeStr: '',
|
|
|
+ endTimeStr: '',
|
|
|
+ maxUses: 0,
|
|
|
+ categoryId: null,
|
|
|
+ distributionSystemId: null,
|
|
|
+ productIds: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async loadData() {
|
|
|
+ this.loading = true
|
|
|
+ try {
|
|
|
+ const res = await getDiscountRuleList({})
|
|
|
+ if (res.data) {
|
|
|
+ this.list = res.data
|
|
|
+ this.total = (res.data.length) || 0
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error(e)
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onPageChange(p) {
|
|
|
+ this.page = p
|
|
|
+ this.loadData()
|
|
|
+ },
|
|
|
+ onSizeChange(val) {
|
|
|
+ this.size = val
|
|
|
+ this.page = 1
|
|
|
+ this.loadData()
|
|
|
+ },
|
|
|
+ handleCreate() {
|
|
|
+ this.isEdit = false
|
|
|
+ this.form = this.getEmptyForm()
|
|
|
+ this.formDialogVisible = true
|
|
|
+ },
|
|
|
+ handleEdit(row) {
|
|
|
+ this.isEdit = true
|
|
|
+ this.form = {
|
|
|
+ id: row.id,
|
|
|
+ name: row.name,
|
|
|
+ type: row.type,
|
|
|
+ value: row.value,
|
|
|
+ thresholdAmount: row.thresholdAmount || 0,
|
|
|
+ startTimeStr: row.startTime ? this.formatTime(row.startTime) : '',
|
|
|
+ endTimeStr: row.endTime ? this.formatTime(row.endTime) : '',
|
|
|
+ maxUses: row.maxUses || 0,
|
|
|
+ categoryId: row.categoryId || null,
|
|
|
+ distributionSystemId: row.distributionSystemId || null,
|
|
|
+ productIds: row.productIds || ''
|
|
|
+ }
|
|
|
+ this.formDialogVisible = true
|
|
|
+ },
|
|
|
+ handleSubmit() {
|
|
|
+ if (!this.form.name) {
|
|
|
+ this.$message.warning('请输入规则名称')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.submitting = true
|
|
|
+ var payload = {
|
|
|
+ id: this.form.id,
|
|
|
+ name: this.form.name,
|
|
|
+ type: this.form.type,
|
|
|
+ value: this.form.value,
|
|
|
+ thresholdAmount: this.form.thresholdAmount,
|
|
|
+ maxUses: this.form.maxUses,
|
|
|
+ categoryId: this.form.categoryId,
|
|
|
+ distributionSystemId: this.form.distributionSystemId,
|
|
|
+ productIds: this.form.productIds || null
|
|
|
+ }
|
|
|
+ if (this.form.startTimeStr) {
|
|
|
+ payload.startTime = this.form.startTimeStr
|
|
|
+ }
|
|
|
+ if (this.form.endTimeStr) {
|
|
|
+ payload.endTime = this.form.endTimeStr
|
|
|
+ }
|
|
|
+ var apiFn = this.isEdit ? updateDiscountRule : createDiscountRule
|
|
|
+ apiFn(payload).then((res) => {
|
|
|
+ this.$message.success(res.message || '保存成功')
|
|
|
+ this.formDialogVisible = false
|
|
|
+ this.loadData()
|
|
|
+ }).catch(() => {
|
|
|
+ this.$message.error('操作失败')
|
|
|
+ }).finally(() => {
|
|
|
+ this.submitting = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleToggle(row) {
|
|
|
+ toggleDiscountRule({ id: row.id }).then((res) => {
|
|
|
+ this.$message.success(res.message || '操作成功')
|
|
|
+ this.loadData()
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
+ handleDelete(row) {
|
|
|
+ this.$confirm('确认删除该折扣规则?删除后不可恢复。', '提示', { type: 'warning' }).then(() => {
|
|
|
+ deleteDiscountRule({ id: row.id }).then(() => {
|
|
|
+ this.$message.success('删除成功')
|
|
|
+ this.loadData()
|
|
|
+ }).catch(() => {})
|
|
|
+ }).catch(() => {})
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.admin-page-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.form-item-tip {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+.pagination-wrap {
|
|
|
+ margin-top: 16px;
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+</style>
|