|
|
@@ -0,0 +1,241 @@
|
|
|
+<template>
|
|
|
+<div class="supplier-product-manage admin-page">
|
|
|
+ <el-card>
|
|
|
+ <div slot="header" class="admin-page-header">
|
|
|
+ <span class="admin-page-title">商品管理</span>
|
|
|
+ <div class="admin-page-actions">
|
|
|
+ <el-input
|
|
|
+ v-model="filters.keyword"
|
|
|
+ placeholder="搜索商品名称"
|
|
|
+ prefix-icon="el-icon-search"
|
|
|
+ clearable
|
|
|
+ class="header-search"
|
|
|
+ @clear="loadList"
|
|
|
+ @keyup.enter.native="loadList"
|
|
|
+ />
|
|
|
+ <el-select v-model="filters.status" placeholder="商品状态" @change="loadList" clearable>
|
|
|
+ <el-option label="全部状态" value="" />
|
|
|
+ <el-option label="待上架" value="approved" />
|
|
|
+ <el-option label="已上架" value="on_shelf" />
|
|
|
+ <el-option label="已下架" value="off_shelf" />
|
|
|
+ </el-select>
|
|
|
+ <el-button type="primary" size="mini" @click="loadList">查询</el-button>
|
|
|
+ <el-button type="success" size="mini" icon="el-icon-plus" @click="handleAdd">新增商品</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="table-scroll-wrap-sm">
|
|
|
+ <div style="overflow:auto;max-height:calc(100vh - 300px);">
|
|
|
+ <el-table style="max-height:calc(100vh - 300px);" :data="list" v-loading="loading" border stripe>
|
|
|
+ <el-table-column prop="id" label="ID" width="70" />
|
|
|
+ <el-table-column label="商品图片" width="80">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <img
|
|
|
+ v-if="row.coverImage"
|
|
|
+ :src="row.coverImage"
|
|
|
+ class="product-thumb"
|
|
|
+ @click="previewImage(row.coverImage)"
|
|
|
+ />
|
|
|
+ <span v-else style="color:#999">-</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="name" label="商品名称" min-width="150" show-overflow-tooltip />
|
|
|
+ <el-table-column label="类型" width="90">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ {{ typeLabel(row.productType) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="售价(元)" width="90">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ {{ formatPriceWithSymbol(row.price || 0) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="stock" label="库存" width="80">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span :class="{ 'stock-warning': row.stock !== null && row.stock < 10 }">
|
|
|
+ {{ row.stock }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="salesCount" label="销量" width="70" />
|
|
|
+ <el-table-column label="状态" width="90">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag :type="statusType(row.status)" size="mini">{{ statusLabel(row.status) }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="createdAt" label="创建时间" width="160">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ {{ formatTime(row.createdAt) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" width="200" fixed="right">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
|
|
|
+ <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
|
|
|
+ <el-button size="mini">
|
|
|
+ 更多<i class="el-icon-arrow-down el-icon--right"></i>
|
|
|
+ </el-button>
|
|
|
+ <el-dropdown-menu slot="dropdown">
|
|
|
+ <el-dropdown-item v-if="row.status === 'on_shelf'" command="offShelf" icon="el-icon-download">下架</el-dropdown-item>
|
|
|
+ <el-dropdown-item v-if="row.status === 'off_shelf'" command="onShelf" icon="el-icon-upload2">上架</el-dropdown-item>
|
|
|
+ </el-dropdown-menu>
|
|
|
+ </el-dropdown>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-pagination
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handlePageChange"
|
|
|
+ :current-page="pagination.page"
|
|
|
+ :page-sizes="[10, 20, 50]"
|
|
|
+ :page-size="pagination.size"
|
|
|
+ :total="pagination.total"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ class="pagination-wrap"
|
|
|
+ />
|
|
|
+ </el-card>
|
|
|
+</div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getSupplierProductList, shelveSupplierProduct } from '@/api/admin'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'SupplierProductManage',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ list: [],
|
|
|
+ loading: false,
|
|
|
+ filters: {
|
|
|
+ keyword: '',
|
|
|
+ status: ''
|
|
|
+ },
|
|
|
+ pagination: {
|
|
|
+ page: 1,
|
|
|
+ size: 20,
|
|
|
+ total: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.loadList()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async loadList() {
|
|
|
+ this.loading = true
|
|
|
+ try {
|
|
|
+ const params = {
|
|
|
+ page: this.pagination.page,
|
|
|
+ size: this.pagination.size,
|
|
|
+ status: this.filters.status || null,
|
|
|
+ keyword: this.filters.keyword || null
|
|
|
+ }
|
|
|
+ const res = await getSupplierProductList(params)
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.list = res.data.records || []
|
|
|
+ this.pagination.total = res.data.total || 0
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ this.$message.error('加载失败')
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleSizeChange(size) {
|
|
|
+ this.pagination.size = size
|
|
|
+ this.pagination.page = 1
|
|
|
+ this.loadList()
|
|
|
+ },
|
|
|
+ handlePageChange(page) {
|
|
|
+ this.pagination.page = page
|
|
|
+ this.loadList()
|
|
|
+ },
|
|
|
+ statusType(status) {
|
|
|
+ const map = {
|
|
|
+ approved: 'info',
|
|
|
+ on_shelf: 'success',
|
|
|
+ off_shelf: 'warning'
|
|
|
+ }
|
|
|
+ return map[status] || 'info'
|
|
|
+ },
|
|
|
+ statusLabel(status) {
|
|
|
+ const map = {
|
|
|
+ approved: '待上架',
|
|
|
+ on_shelf: '已上架',
|
|
|
+ off_shelf: '已下架'
|
|
|
+ }
|
|
|
+ return map[status] || status
|
|
|
+ },
|
|
|
+ typeLabel(type) {
|
|
|
+ const map = {
|
|
|
+ physical: '实物商品',
|
|
|
+ virtual: '虚拟商品',
|
|
|
+ coupon: '优惠券',
|
|
|
+ assessment: '测评商品'
|
|
|
+ }
|
|
|
+ return map[type] || type
|
|
|
+ },
|
|
|
+ formatTime(t) {
|
|
|
+ if (!t) return '-'
|
|
|
+ return t.replace ? t.replace('T', ' ').substring(0, 19) : t
|
|
|
+ },
|
|
|
+ formatPriceWithSymbol(price) {
|
|
|
+ if (price === 0) return '免费'
|
|
|
+ return '¥' + (price / 100).toFixed(2)
|
|
|
+ },
|
|
|
+ previewImage(url) {
|
|
|
+ if (!url) return
|
|
|
+ this.$alert('<img src="' + url + '" style="max-width:100%;" />', '商品图片', {
|
|
|
+ dangerouslyUseHTMLString: true,
|
|
|
+ closeOnClickModal: true
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleAdd() {
|
|
|
+ // 新增商品 - 默认进入编辑页,无需指定ID
|
|
|
+ this.$router.push('/product-edit')
|
|
|
+ },
|
|
|
+ handleEdit(row) {
|
|
|
+ this.$router.push('/product-edit?id=' + row.id)
|
|
|
+ },
|
|
|
+ async handleShelve(row, shelve) {
|
|
|
+ try {
|
|
|
+ await this.$confirm('确认' + (shelve ? '上架' : '下架') + '该商品?', '提示')
|
|
|
+ await shelveSupplierProduct(row.id, { shelve })
|
|
|
+ this.$message.success('操作成功')
|
|
|
+ this.loadList()
|
|
|
+ } catch (e) {
|
|
|
+ if (e !== 'cancel') this.$message.error('操作失败')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleActionCmd(row, cmd) {
|
|
|
+ switch (cmd) {
|
|
|
+ case 'offShelf': this.handleShelve(row, false); break;
|
|
|
+ case 'onShelf': this.handleShelve(row, true); break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.supplier-product-manage {
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+.product-thumb {
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+ object-fit: cover;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+.stock-warning {
|
|
|
+ color: #f56c6c;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+.header-search {
|
|
|
+ width: 180px;
|
|
|
+}
|
|
|
+</style>
|