2025-07-19 20:00:08 +08:00

303 lines
7.6 KiB
Vue

<template>
<view class="newproduct-container">
<common-header title="新品首发" theme="newproduct" @back="goBack" />
<view class="newproduct-content">
<!-- 统计卡片 -->
<uni-card title="新品统计" :is-shadow="false">
<view class="stats-row">
<view class="stat-item">
<text class="stat-value">{{statsData.totalCount || 0}}</text>
<text class="stat-label">总新品数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{statsData.onlineCount || 0}}</text>
<text class="stat-label">已上架</text>
</view>
<view class="stat-item">
<text class="stat-value">{{statsData.pendingCount || 0}}</text>
<text class="stat-label">待发布</text>
</view>
</view>
</uni-card>
<!-- 搜索栏 -->
<uni-search-bar v-model="searchText" placeholder="搜索新品名称" @confirm="searchNewProduct" />
<!-- 筛选标签 -->
<uni-segmented-control :current="currentTab" :values="tabList" @clickItem="switchTab" />
<!-- 操作按钮 -->
<view class="action-bar">
<uni-button type="primary" size="small" @click="addNewProduct">发布新品</uni-button>
<uni-button type="default" size="small" @click="getNewProductList">刷新</uni-button>
</view>
<!-- 新品列表 -->
<uni-list>
<uni-list-item v-for="(item, index) in newProductList" :key="index"
:title="item.productName"
:note="item.description"
:rightText="`¥${item.price}`"
:badgeText="getStatusText(item.status)"
:badge-type="getStatusType(item.status)"
@click="viewNewProduct(item)">
<template v-slot:header>
<image class="product-image" :src="item.image" mode="aspectFill" />
</template>
<template v-slot:footer>
<view class="item-footer">
<text class="time">首发时间: {{formatTime(item.releaseTime)}}</text>
<view class="actions">
<uni-button size="mini" type="primary" @click.stop="editNewProduct(item)">编辑</uni-button>
<uni-button v-if="item.status === 0" size="mini" type="success" @click.stop="publishNewProduct(item)">发布</uni-button>
<uni-button v-if="item.status === 1" size="mini" type="success" @click.stop="onlineNewProduct(item)">上架</uni-button>
<uni-button v-if="item.status === 2" size="mini" type="warn" @click.stop="offlineNewProduct(item)">下架</uni-button>
</view>
</view>
</template>
</uni-list-item>
</uni-list>
<!-- 加载更多 -->
<uni-load-more :status="loadStatus" />
</view>
</view>
</template>
<script>
import { getNewProductList, getNewProductStats, publishNewProduct, onlineNewProduct, offlineNewProduct } from '@/api/brewery/newproduct'
import CommonHeader from '@/components/common-header/common-header.vue'
export default {
components: {
CommonHeader
},
data() {
return {
searchText: '',
newProductList: [],
statsData: {},
loadStatus: 'more',
pageNum: 1,
pageSize: 10,
currentTab: 0,
tabList: ['全部', '待发布', '已发布', '已上架', '已下架']
}
},
onLoad() {
this.getStatsData()
this.getNewProductList()
},
onReachBottom() {
if (this.loadStatus === 'more') {
this.pageNum++
this.getNewProductList()
}
},
methods: {
goBack() {
uni.navigateBack()
},
async getStatsData() {
try {
const res = await getNewProductStats()
this.statsData = res.data
} catch (error) {
console.log('获取统计数据失败', error)
}
},
async getNewProductList() {
try {
this.loadStatus = 'loading'
const params = {
pageNum: this.pageNum,
pageSize: this.pageSize,
productName: this.searchText,
status: this.currentTab === 0 ? '' : this.currentTab - 1
}
const res = await getNewProductList(params)
if (this.pageNum === 1) {
this.newProductList = res.rows
} else {
this.newProductList = [...this.newProductList, ...res.rows]
}
this.loadStatus = res.rows.length < this.pageSize ? 'noMore' : 'more'
} catch (error) {
this.loadStatus = 'more'
this.$modal.showToast('获取新品列表失败')
}
},
switchTab(e) {
this.currentTab = e.currentIndex
this.pageNum = 1
this.getNewProductList()
},
searchNewProduct() {
this.pageNum = 1
this.getNewProductList()
},
addNewProduct() {
uni.navigateTo({
url: '/subpages/newproduct/add'
})
},
viewNewProduct(item) {
uni.navigateTo({
url: `/subpages/newproduct/detail?id=${item.id}`
})
},
editNewProduct(item) {
uni.navigateTo({
url: `/subpages/newproduct/edit?id=${item.id}`
})
},
async publishNewProduct(item) {
try {
const res = await this.$modal.showConfirm('确定发布此新品吗?')
if (res.confirm) {
await publishNewProduct(item.id)
this.$modal.showToast('发布成功')
this.pageNum = 1
this.getNewProductList()
}
} catch (error) {
this.$modal.showToast('发布失败')
}
},
async onlineNewProduct(item) {
try {
const res = await this.$modal.showConfirm('确定上架此新品吗?')
if (res.confirm) {
await onlineNewProduct(item.id)
this.$modal.showToast('上架成功')
this.pageNum = 1
this.getNewProductList()
}
} catch (error) {
this.$modal.showToast('上架失败')
}
},
async offlineNewProduct(item) {
try {
const res = await this.$modal.showConfirm('确定下架此新品吗?')
if (res.confirm) {
await offlineNewProduct(item.id)
this.$modal.showToast('下架成功')
this.pageNum = 1
this.getNewProductList()
}
} catch (error) {
this.$modal.showToast('下架失败')
}
},
getStatusText(status) {
const statusMap = {
0: '待发布',
1: '已发布',
2: '已上架',
3: '已下架'
}
return statusMap[status] || '未知'
},
getStatusType(status) {
const typeMap = {
0: 'warning',
1: 'primary',
2: 'success',
3: 'error'
}
return typeMap[status] || 'default'
},
formatTime(time) {
if (!time) return ''
return time.substring(0, 16)
}
}
}
</script>
<style lang="scss" scoped>
.newproduct-container {
min-height: 100vh;
background: #f5f7fa;
}
.newproduct-content {
// padding由CommonHeader全局样式提供
}
.stats-row {
display: flex;
justify-content: space-around;
.stat-item {
text-align: center;
.stat-value {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #007aff;
}
.stat-label {
display: block;
font-size: 24rpx;
color: #666;
margin-top: 10rpx;
}
}
}
.action-bar {
display: flex;
justify-content: space-between;
padding: 20rpx 0;
gap: 20rpx;
}
.product-image {
width: 100rpx;
height: 100rpx;
border-radius: 10rpx;
margin-right: 20rpx;
}
.item-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 0;
.time {
font-size: 24rpx;
color: #999;
}
.actions {
display: flex;
gap: 10rpx;
}
}
</style>