admin模块接入数据库
This commit is contained in:
@@ -68,26 +68,32 @@
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view v-for="(item, index) in dataList" :key="item.id" class="table-row">
|
||||
<view class="td" style="width: 80px;"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view v-if="isLoading" class="table-loading" style="padding: 40px; text-align: center;">
|
||||
<text>数据加载中...</text>
|
||||
</view>
|
||||
<view v-else-if="dataList.length === 0" class="table-empty" style="padding: 40px; text-align: center;">
|
||||
<text>暂无优惠券数据</text>
|
||||
</view>
|
||||
<view v-else v-for="(item, index) in dataList" :key="item.id" class="table-row">
|
||||
<view class="td" style="width: 80px;"><text class="td-txt">{{ item.cid || '-' }}</text></view>
|
||||
<view class="td" style="width: 180px;"><text class="td-txt name-bold">{{ item.name }}</text></view>
|
||||
<view class="td" style="width: 120px;"><text class="td-txt">{{ item.type }}</text></view>
|
||||
<view class="td" style="width: 100px;"><text class="td-txt price-txt">{{ item.value.toFixed(2) }}</text></view>
|
||||
<view class="td" style="width: 120px;"><text class="td-txt">{{ item.receiveType }}</text></view>
|
||||
<view class="td" style="width: 150px;">
|
||||
<text v-if="item.id === 1628" class="td-txt date-small">2023-10-18 00:00 - 2025-11-05 00:00</text>
|
||||
<text v-else class="td-txt">{{ item.receiveDate }}</text>
|
||||
<view class="td" style="width: 120px;"><text class="td-txt">{{ getTypeName(item.coupon_type) }}</text></view>
|
||||
<view class="td" style="width: 100px;">
|
||||
<text class="td-txt price-txt">{{ item.discount_value }}{{ item.discount_type === 2 ? '%' : '元' }}</text>
|
||||
</view>
|
||||
<view class="td" style="width: 120px;"><text class="td-txt">{{ item.useTime }}</text></view>
|
||||
<view class="td" style="width: 120px;"><text class="td-txt">{{ getReceiveTypeName(1) }}</text></view>
|
||||
<view class="td" style="width: 150px;">
|
||||
<text class="td-txt date-small">{{ formatTime(item.start_time) }} 至 {{ formatTime(item.end_time) }}</text>
|
||||
</view>
|
||||
<view class="td" style="width: 120px;"><text class="td-txt">{{ item.usage_limit }} 次/人</text></view>
|
||||
<view class="td" style="width: 120px;">
|
||||
<view v-if="item.publishTotal > 0" class="pub-info">
|
||||
<text class="pub-txt">发布: {{ item.publishTotal }}</text>
|
||||
<text class="pub-txt danger">剩余: {{ item.publishRemain }}</text>
|
||||
<view v-if="item.total_quantity != null && item.total_quantity > 0" class="pub-info">
|
||||
<text class="pub-txt">总计: {{ item.total_quantity }}</text>
|
||||
</view>
|
||||
<text v-else class="td-txt">不限量</text>
|
||||
</view>
|
||||
<view class="td" style="width: 100px;">
|
||||
<view :class="['switch-box', item.isOpen ? 'active' : '']" @click="toggleStatus(index)">
|
||||
<view :class="['switch-box', item.status === 1 ? 'active' : '']" @click="toggleStatus(index)">
|
||||
<view class="switch-dot"></view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -97,9 +103,7 @@
|
||||
<text class="op-split">|</text>
|
||||
<text class="op-link">编辑</text>
|
||||
<text class="op-split">|</text>
|
||||
<text class="op-link">复制</text>
|
||||
<text class="op-split">|</text>
|
||||
<text class="op-link text-danger">删除</text>
|
||||
<text class="op-link" @click="handleDelete(item.id)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -108,20 +112,11 @@
|
||||
|
||||
<!-- 分页 -->
|
||||
<view class="pagination-footer">
|
||||
<text class="total-txt">共 16 条</text>
|
||||
<view class="page-select">
|
||||
<text class="page-val">15条/页 ▼</text>
|
||||
</view>
|
||||
<text class="total-txt">共 {{ total }} 条</text>
|
||||
<view class="page-btns">
|
||||
<text class="p-btn disabled"><</text>
|
||||
<text class="p-btn active">1</text>
|
||||
<text class="p-btn">2</text>
|
||||
<text class="p-btn">></text>
|
||||
</view>
|
||||
<view class="page-jump">
|
||||
<text class="jump-txt">前往</text>
|
||||
<input class="jump-input" placeholder="1" />
|
||||
<text class="jump-txt">页</text>
|
||||
<text :class="['p-btn', page <= 1 ? 'disabled' : '']" @click="prevPage"><</text>
|
||||
<text class="p-btn active">{{ page }}</text>
|
||||
<text :class="['p-btn', page >= totalPages ? 'disabled' : '']" @click="nextPage">></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -130,44 +125,145 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
interface CouponItem {
|
||||
id: number
|
||||
name: string
|
||||
type: string
|
||||
value: number
|
||||
receiveType: string
|
||||
receiveDate: string
|
||||
useTime: string
|
||||
publishTotal: number
|
||||
publishRemain: number
|
||||
isOpen: boolean
|
||||
}
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import {
|
||||
fetchAdminCoupons,
|
||||
toggleCouponStatus,
|
||||
deleteCouponTemplate,
|
||||
CouponTemplate,
|
||||
CouponQuery
|
||||
} from '@/services/admin/marketingService.uts'
|
||||
|
||||
const filter = reactive({
|
||||
name: ''
|
||||
name: '',
|
||||
type: null as number | null,
|
||||
status: null as number | null
|
||||
})
|
||||
|
||||
const dataList = ref<CouponItem[]>([
|
||||
{ id: 1643, name: '满100减30', type: '通用券', value: 30.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '10天', publishTotal: 0, publishRemain: 0, isOpen: false },
|
||||
{ id: 1642, name: '满10减7', type: '通用券', value: 7.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '10天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1641, name: '会员优惠券', type: '通用券', value: 200.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '200天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1640, name: '会员优惠券', type: '通用券', value: 29.90, receiveType: '用户领取', receiveDate: '不限时', useTime: '200天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1639, name: '会员优惠券', type: '通用券', value: 1.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '200天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1638, name: '商品券', type: '商品券', value: 1.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '200天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1636, name: '测试多个商品消耗一个券', type: '商品券', value: 500.00, receiveType: '系统赠送', receiveDate: '不限时', useTime: '3天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1635, name: '优惠券', type: '通用券', value: 10.00, receiveType: '系统赠送', receiveDate: '不限时', useTime: '10天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1634, name: '限时优惠', type: '通用券', value: 20.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '5天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1633, name: '店庆券', type: '品类券', value: 100.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '10天', publishTotal: 0, publishRemain: 0, isOpen: true },
|
||||
{ id: 1632, name: '优惠券', type: '品类券', value: 99.00, receiveType: '用户领取', receiveDate: '不限时', useTime: '10天', publishTotal: 8999, publishRemain: 8604, isOpen: true },
|
||||
{ id: 1628, name: '全场通用券', type: '通用券', value: 9.90, receiveType: '用户领取', receiveDate: 'RANGE', useTime: '不限时', publishTotal: 59999, publishRemain: 59331, isOpen: true }
|
||||
])
|
||||
const dataList = ref<CouponTemplate[]>([])
|
||||
const total = ref(0)
|
||||
const isLoading = ref(false)
|
||||
const page = ref(1)
|
||||
const pageSize = 15
|
||||
|
||||
const handleQuery = () => { console.log('Querying...') }
|
||||
const handleAdd = () => { console.log('Adding coupon...') }
|
||||
const toggleStatus = (index: number) => {
|
||||
dataList.value[index].isOpen = !dataList.value[index].isOpen
|
||||
const typeOptions = [
|
||||
{ label: '全部', value: null },
|
||||
{ label: '满减券', value: 1 },
|
||||
{ label: '折扣券', value: 2 },
|
||||
{ label: '免运费券', value: 3 }
|
||||
]
|
||||
const typeIndex = ref(0)
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '全部', value: null },
|
||||
{ label: '开启', value: 1 },
|
||||
{ label: '关闭', value: 2 },
|
||||
{ label: '已结束', value: 3 }
|
||||
]
|
||||
const statusIndex = ref(0)
|
||||
|
||||
const totalPages = computed((): number => {
|
||||
return Math.ceil(total.value / pageSize) || 1
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
|
||||
async function loadData() {
|
||||
isLoading.value = true
|
||||
try {
|
||||
const query: CouponQuery = {
|
||||
name: filter.name || null,
|
||||
type: typeOptions[typeIndex.value].value,
|
||||
status: statusOptions[statusIndex.value].value,
|
||||
page: page.value,
|
||||
pageSize: pageSize
|
||||
}
|
||||
const res = await fetchAdminCoupons(query)
|
||||
dataList.value = res.items
|
||||
total.value = res.total
|
||||
} catch (e) {
|
||||
uni.showToast({ title: '加载失败', icon: 'none' })
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuery() {
|
||||
page.value = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
uni.showToast({ title: '添加功能开发中', icon: 'none' })
|
||||
}
|
||||
|
||||
async function toggleStatus(index: number) {
|
||||
const item = dataList.value[index]
|
||||
if (item.id == null) return
|
||||
|
||||
const currentStatus = item.status === 1
|
||||
const success = await toggleCouponStatus(item.id!, !currentStatus)
|
||||
if (success) {
|
||||
uni.showToast({ title: '操作成功', icon: 'success' })
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(id: string | undefined) {
|
||||
if (id == null) return
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定删除该优惠券模板吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
const success = await deleteCouponTemplate(id)
|
||||
if (success) {
|
||||
uni.showToast({ title: '删除成功', icon: 'success' })
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
} as ShowModalOptions)
|
||||
}
|
||||
|
||||
function onTypeChange(e: any) {
|
||||
typeIndex.value = parseInt(String(e.detail.value))
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
function onStatusFilterChange(e: any) {
|
||||
statusIndex.value = parseInt(String(e.detail.value))
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
if (page.value > 1) {
|
||||
page.value--
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
if (page.value < totalPages.value) {
|
||||
page.value++
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeName(type: number): string {
|
||||
const found = typeOptions.find(o => o.value === type)
|
||||
return found ? found.label : '未知'
|
||||
}
|
||||
|
||||
function getReceiveTypeName(receiveType: number): string {
|
||||
return receiveType === 1 ? '用户领取' : '系统赠送'
|
||||
}
|
||||
|
||||
function formatTime(iso: string | null): string {
|
||||
if (!iso) return '-'
|
||||
return iso.substring(0, 16).replace('T', ' ')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user