Files
medical-mall/pages/mall/admin/marketing/checkin/reward.uvue
2026-02-25 11:39:54 +08:00

272 lines
9.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="marketing-checkin-reward">
<view class="reward-card border-shadow">
<!-- Tabs -->
<view class="reward-tabs">
<view class="tab-item" :class="{ active: currentTab === 'continuous' }" @click="currentTab = 'continuous'">
<text class="tab-txt">连续签到奖励</text>
</view>
<view class="tab-item" :class="{ active: currentTab === 'cumulative' }" @click="currentTab = 'cumulative'">
<text class="tab-txt">累积签到奖励</text>
</view>
</view>
<view class="action-row">
<button v-if="currentTab === 'continuous'" class="btn-primary" @click="openModal('continuous')">添加连续签到奖励</button>
<button v-else class="btn-primary" @click="openModal('cumulative')">添加累积签到奖励</button>
</view>
<!-- Table -->
<view class="table-container">
<view class="table-head">
<view class="th cell-id">编号</view>
<view class="th cell-type">类型</view>
<view class="th cell-days">签到天数</view>
<view class="th cell-reward">奖励内容</view>
<view class="th cell-status">是否可用</view>
<view class="th cell-op">操作</view>
</view>
<view class="table-body">
<view v-for="item in displayList" :key="item.id" class="table-row">
<view class="td cell-id"><text class="td-txt">{{ item.id }}</text></view>
<view class="td cell-type"><text class="td-txt">{{ item.type === 'continuous' ? '连续签到' : '累积签到' }}</text></view>
<view class="td cell-days"><text class="td-txt">{{ item.days }}天</text></view>
<view class="td cell-reward">
<text class="td-txt">积分+{{ item.integral }}, 经验+{{ item.exp }}</text>
</view>
<view class="td cell-status">
<view class="switch-mock" :class="{ active: item.is_open }" @click="toggleStatus(item)">
<view class="switch-dot"></view>
</view>
</view>
<view class="td cell-op">
<text class="op-link" @click="handleEdit(item)">编辑</text>
<text class="op-link del ml-10" @click="handleDelete(item)">删除</text>
</view>
</view>
</view>
</view>
</view>
<!-- 奖励设置弹窗 -->
<view v-if="showModal" class="modal-mask">
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">{{ modalType === 'continuous' ? '连续签到奖励' : '累积签到奖励' }}</text>
<text class="modal-close" @click="showModal = false">×</text>
</view>
<view class="modal-body">
<view class="form-item">
<text class="form-label">{{ modalType === 'continuous' ? '连续签到天数' : '累积签到天数' }}</text>
<input class="form-input" v-model="formData.days" type="number" placeholder="0" />
</view>
<view class="form-item">
<text class="form-label">赠送积分:</text>
<input class="form-input" v-model="formData.integral" type="number" placeholder="0" />
</view>
<view class="form-item">
<text class="form-label">赠送经验:</text>
<input class="form-input" v-model="formData.exp" type="number" placeholder="0" />
</view>
</view>
<view class="modal-footer">
<button class="btn-cancel" @click="showModal = false">取消</button>
<button class="btn-submit" @click="handleSubmit">确定</button>
</view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive, computed } from 'vue'
const currentTab = ref('continuous')
const showModal = ref(false)
const modalType = ref('continuous')
const formData = reactive({
days: '',
integral: '',
exp: ''
})
const continuousList = ref([
{ id: 1, type: 'continuous', days: 3, integral: 20, exp: 2, is_open: true },
{ id: 2, type: 'continuous', days: 7, integral: 50, exp: 5, is_open: true }
])
const cumulativeList = ref([
{ id: 3, type: 'cumulative', days: 15, integral: 100, exp: 10, is_open: true },
{ id: 4, type: 'cumulative', days: 30, integral: 200, exp: 20, is_open: true }
])
const displayList = computed(() => {
return currentTab.value === 'continuous' ? continuousList.value : cumulativeList.value
})
const openModal = (type: string) => {
modalType.value = type
formData.days = ''
formData.integral = ''
formData.exp = ''
showModal.value = true
}
const toggleStatus = (item: any) => {
item.is_open = !item.is_open
uni.showToast({ title: '修改成功', icon: 'success' })
}
const handleEdit = (item: any) => {
uni.showToast({ title: '编辑功能暂未对接', icon: 'none' })
}
const handleDelete = (item: any) => {
uni.showModal({
title: '提示',
content: '确认删除该奖励配置吗?',
success: (res) => {
if (res.confirm) {
if (currentTab.value === 'continuous') {
continuousList.value = continuousList.value.filter(i => i.id !== item.id)
} else {
cumulativeList.value = cumulativeList.value.filter(i => i.id !== item.id)
}
uni.showToast({ title: '已删除', icon: 'success' })
}
}
})
}
const handleSubmit = () => {
if (!formData.days) {
uni.showToast({ title: '请输入天数', icon: 'none' })
return
}
const newItem = {
id: Date.now(),
type: modalType.value,
days: parseInt(formData.days.toString()),
integral: parseInt(formData.integral.toString() || '0'),
exp: parseInt(formData.exp.toString() || '0'),
is_open: true
}
if (modalType.value === 'continuous') {
continuousList.value.push(newItem)
} else {
cumulativeList.value.push(newItem)
}
showModal.value = false
uni.showToast({ title: '添加成功', icon: 'success' })
}
</script>
<style scoped lang="scss">
.marketing-checkin-reward {
padding: 0;
background: transparent;
min-height: auto;
}
.border-shadow {
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}
.reward-card { padding: 24px; }
.reward-tabs {
display: flex;
flex-direction: row;
border-bottom: 1px solid #e8eaec;
margin-bottom: 24px;
}
.tab-item {
padding: 12px 24px;
cursor: pointer;
position: relative;
}
.tab-txt { font-size: 14px; color: #515a6e; }
.tab-item.active .tab-txt { color: #1890ff; font-weight: bold; }
.tab-item.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: #1890ff;
}
.action-row { margin-bottom: 24px; }
.btn-primary {
background: #1890ff;
color: #fff;
border: none;
height: 32px;
line-height: 32px;
padding: 0 16px;
font-size: 14px;
border-radius: 4px;
cursor: pointer;
}
.table-head { display: flex; flex-direction: row; background: #f8f8f9; border-bottom: 1px solid #e8eaec; }
.th { padding: 12px 8px; font-size: 13px; color: #515a6e; font-weight: bold; }
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #e8eaec; align-items: center; }
.td { padding: 16px 8px; }
.td-txt { font-size: 13px; color: #515a6e; }
.cell-id { width: 80px; }
.cell-type { width: 120px; }
.cell-days { width: 120px; }
.cell-reward { flex: 1; }
.cell-status { width: 100px; text-align: center; }
.cell-op { width: 150px; text-align: right; }
.op-link { color: #1890ff; font-size: 13px; cursor: pointer; }
.op-link.del { color: #ff4d4f; }
.ml-10 { margin-left: 10px; }
.switch-mock {
width: 44px; height: 22px; background-color: #bfbfbf; border-radius: 11px;
display: flex; align-items: center; padding: 0 4px; position: relative;
transition: background-color 0.3s; cursor: pointer;
}
.switch-mock.active { background-color: #1890ff; }
.switch-dot {
width: 14px; height: 14px; background-color: #fff; border-radius: 50%;
position: absolute; left: 4px; transition: left 0.3s;
}
.switch-mock.active .switch-dot { left: 26px; }
/* Modal */
.modal-mask {
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 1000;
}
.modal-content { width: 500px; background: #fff; border-radius: 4px; }
.modal-header { padding: 16px 24px; border-bottom: 1px solid #e8eaec; display: flex; justify-content: space-between; align-items: center; }
.modal-title { font-size: 16px; font-weight: bold; }
.modal-close { font-size: 24px; color: #999; cursor: pointer; }
.modal-body { padding: 24px; }
.modal-footer { padding: 12px 24px; border-top: 1px solid #e8eaec; display: flex; justify-content: flex-end; }
.form-item { display: flex; flex-direction: row; margin-bottom: 20px; align-items: center; }
.form-label { width: 120px; font-size: 14px; color: #606266; }
.form-input { flex: 1; height: 32px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 12px; }
.btn-cancel { margin-right: 8px; height: 32px; line-height: 32px; padding: 0 16px; font-size: 14px; border-radius: 4px; border: 1px solid #dcdfe6; background: #fff; }
.btn-submit { height: 32px; line-height: 32px; padding: 0 16px; font-size: 14px; border-radius: 4px; background: #1890ff; color: #fff; border: none; }
</style>