first commit: 初始化1818-admin项目
This commit is contained in:
222
src/views/config/points.vue
Normal file
222
src/views/config/points.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div class="points-page">
|
||||
<div class="page-header">
|
||||
<h2>积分套餐管理</h2>
|
||||
<a-button type="primary" @click="handleAdd">新增套餐</a-button>
|
||||
</div>
|
||||
|
||||
<a-alert
|
||||
message="套餐名称格式说明"
|
||||
description="套餐名称使用逗号分隔,第一个为Tab显示名称,后面的为描述内容。例如:体验版,新手体验,小额充值,有效期365天"
|
||||
type="info"
|
||||
show-icon
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
|
||||
<a-table :dataSource="packages" :loading="loading" :columns="columns" rowKey="id">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<div>
|
||||
<div style="font-weight: bold">{{ getTabName(record.name) }}</div>
|
||||
<div style="color: #999; font-size: 12px">{{ getDescriptions(record.name) }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag :color="record.status === 1 ? 'green' : 'default'">
|
||||
{{ record.status === 1 ? '上架' : '下架' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="handleEdit(record)">编辑</a>
|
||||
<a @click="handleToggleStatus(record)">{{ record.status === 1 ? '下架' : '上架' }}</a>
|
||||
<a-popconfirm title="确定删除该套餐?" @confirm="handleDelete(record.id)">
|
||||
<a style="color: #ff4d4f">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="modalVisible"
|
||||
:title="isEdit ? '编辑套餐' : '新增套餐'"
|
||||
:confirmLoading="submitLoading"
|
||||
@ok="handleSubmit"
|
||||
width="600px"
|
||||
>
|
||||
<a-form :model="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||
<a-form-item label="套餐名称" required>
|
||||
<a-input v-model:value="form.name" placeholder="格式:套餐名,描述1,描述2..." />
|
||||
</a-form-item>
|
||||
<a-form-item label="积分数量" required>
|
||||
<a-input-number v-model:value="form.points" :min="1" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="价格(元)" required>
|
||||
<a-input-number v-model:value="form.price" :min="0" :precision="2" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="原价(元)">
|
||||
<a-input-number v-model:value="form.originalPrice" :min="0" :precision="2" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="赠送积分">
|
||||
<a-input-number v-model:value="form.bonusPoints" :min="0" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="有效期(天)">
|
||||
<a-input-number v-model:value="form.validDays" :min="1" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="排序">
|
||||
<a-input-number v-model:value="form.sort" :min="0" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="1">上架</a-radio>
|
||||
<a-radio :value="0">下架</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import {
|
||||
getPointsPackages,
|
||||
createPointsPackage,
|
||||
updatePointsPackage,
|
||||
deletePointsPackage,
|
||||
updatePointsPackageStatus
|
||||
} from '@/api/points'
|
||||
|
||||
const loading = ref(false)
|
||||
const packages = ref([])
|
||||
const modalVisible = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const isEdit = ref(false)
|
||||
|
||||
const defaultForm = {
|
||||
id: null,
|
||||
name: '',
|
||||
points: 1000,
|
||||
price: 10,
|
||||
originalPrice: null,
|
||||
bonusPoints: 0,
|
||||
validDays: 365,
|
||||
sort: 0,
|
||||
status: 1
|
||||
}
|
||||
const form = ref({ ...defaultForm })
|
||||
|
||||
const columns = [
|
||||
{ title: 'ID', dataIndex: 'id', width: 60 },
|
||||
{ title: '套餐名称', key: 'name', width: 250 },
|
||||
{ title: '积分', dataIndex: 'points', width: 80 },
|
||||
{ title: '赠送', dataIndex: 'bonusPoints', width: 80 },
|
||||
{ title: '价格', dataIndex: 'price', width: 80 },
|
||||
{ title: '原价', dataIndex: 'originalPrice', width: 80 },
|
||||
{ title: '排序', dataIndex: 'sort', width: 60 },
|
||||
{ title: '状态', key: 'status', width: 80 },
|
||||
{ title: '操作', key: 'action', width: 150 }
|
||||
]
|
||||
|
||||
const getTabName = (name) => {
|
||||
if (!name) return '-'
|
||||
return name.split(/[,,]+/)[0]
|
||||
}
|
||||
|
||||
const getDescriptions = (name) => {
|
||||
if (!name) return ''
|
||||
const parts = name.split(/[,,]+/)
|
||||
return parts.length > 1 ? parts.slice(1).join(' | ') : ''
|
||||
}
|
||||
|
||||
const loadPackages = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getPointsPackages()
|
||||
packages.value = res || []
|
||||
} catch (e) {
|
||||
message.error('获取套餐列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleAdd = () => {
|
||||
isEdit.value = false
|
||||
form.value = { ...defaultForm }
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
const handleEdit = (record) => {
|
||||
isEdit.value = true
|
||||
form.value = { ...record }
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!form.value.name || !form.value.points || !form.value.price) {
|
||||
message.warning('请填写必填项')
|
||||
return
|
||||
}
|
||||
submitLoading.value = true
|
||||
try {
|
||||
if (isEdit.value) {
|
||||
await updatePointsPackage(form.value)
|
||||
message.success('更新成功')
|
||||
} else {
|
||||
await createPointsPackage(form.value)
|
||||
message.success('创建成功')
|
||||
}
|
||||
modalVisible.value = false
|
||||
loadPackages()
|
||||
} catch (e) {
|
||||
message.error(e.message || '操作失败')
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
try {
|
||||
await deletePointsPackage(id)
|
||||
message.success('删除成功')
|
||||
loadPackages()
|
||||
} catch (e) {
|
||||
message.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleToggleStatus = async (record) => {
|
||||
const newStatus = record.status === 1 ? 0 : 1
|
||||
try {
|
||||
await updatePointsPackageStatus(record.id, newStatus)
|
||||
message.success(newStatus === 1 ? '已上架' : '已下架')
|
||||
loadPackages()
|
||||
} catch (e) {
|
||||
message.error('操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadPackages()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.points-page {
|
||||
padding: 20px;
|
||||
}
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.page-header h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user