|
|
@@ -1,386 +1,328 @@
|
|
|
<template>
|
|
|
<ele-page flex-table :bodyStyle="{ padding: '0 20px' }">
|
|
|
- <goods-search ref="searchRef" @search="reload" />
|
|
|
+ <goods-search ref="searchRef" @search="handleSearch" />
|
|
|
|
|
|
<div class="px-4 py-2 bg-white">
|
|
|
- <el-tabs v-model="activeTab" @tab-change="handleTabChange" :head-style="{marginBottom: '0'}">
|
|
|
- <el-tab-pane label="全部" name="all" />
|
|
|
- <el-tab-pane label="出售中" name="on_sale" />
|
|
|
- <el-tab-pane label="仓库中" name="in_warehouse" />
|
|
|
- <el-tab-pane label="销售黑名单" name="blacklist" />
|
|
|
- <el-tab-pane label="待上架列表" name="pending_listing" />
|
|
|
+ <el-tabs v-model="activeTab" type="card" @tab-change="handleTabChange" :head-style="{ marginBottom: '0' }">
|
|
|
+ <el-tab-pane label="全部" name="" />
|
|
|
+ <el-tab-pane label="出售中" name="1" />
|
|
|
+ <el-tab-pane label="已下架(仓库中)" name="2" />
|
|
|
+ <el-tab-pane label="销售黑名单" name="3" />
|
|
|
+ <el-tab-pane label="待上架列表" name="0" />
|
|
|
</el-tabs>
|
|
|
</div>
|
|
|
|
|
|
- <common-table ref="tableRef" :pageConfig="pageConfig" :columns="columns" :tools="false" :datasource="mockDatasource" :bodyStyle="{paddingTop:0}">
|
|
|
+ <common-table ref="tableRef" :pageConfig="pageConfig" :columns="columns" :tools="false"
|
|
|
+ :bodyStyle="{ paddingTop: 0 }">
|
|
|
<template #toolbar>
|
|
|
<div class="flex gap-2">
|
|
|
<el-button type="primary" plain @click="openNewBookModal">新建图书商品</el-button>
|
|
|
<el-button type="primary" plain @click="openNewOtherModal">新建其他商品</el-button>
|
|
|
<el-button type="danger" plain @click="openUpdatePriceModal">更新价格</el-button>
|
|
|
<el-button type="warning" plain @click="openListDelistModal">上架/下架</el-button>
|
|
|
- <el-button type="primary" plain v-if="activeTab === 'pending_listing'"
|
|
|
- @click="handleOneClickListing">一键上架</el-button>
|
|
|
<el-button color="#bd3124" plain @click="handleExport">导出</el-button>
|
|
|
<el-button type="warning" plain @click="handleOperationLog">操作日志</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
- <!-- Columns Slots -->
|
|
|
+ <!-- 列插槽 -->
|
|
|
<template #cover="{ row }">
|
|
|
- <el-image style="width: 80px; height: 80px; border-radius: 4px" fit="cover"
|
|
|
- :src="row.cover || row.image" :preview-src-list="[row.cover || row.image]" preview-teleported />
|
|
|
+ <el-image style="width: 60px; height: 80px; border-radius: 4px" fit="cover" :src="row.cover"
|
|
|
+ :preview-src-list="[row.cover]" preview-teleported>
|
|
|
+ <template #error>
|
|
|
+ <div class="flex items-center justify-center w-full h-full bg-gray-100 text-gray-400">
|
|
|
+ <el-icon>
|
|
|
+ <Picture />
|
|
|
+ </el-icon>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-image>
|
|
|
</template>
|
|
|
|
|
|
<template #info="{ row }">
|
|
|
<goods-info :row="row" />
|
|
|
</template>
|
|
|
|
|
|
+ <template #stock="{ row }">
|
|
|
+ <div class="text-left">
|
|
|
+ <div>中等: {{ row.mediumNum || 0 }}</div>
|
|
|
+ <div>良好: {{ row.goodNum || 0 }}</div>
|
|
|
+ <div>次品: {{ row.badNum || 0 }}</div>
|
|
|
+ <div>合计: {{ (row.mediumNum || 0) + (row.goodNum || 0) + (row.badNum || 0) }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
<template #price="{ row }">
|
|
|
<div class="flex items-center justify-center">
|
|
|
- <span>¥{{ row.price }}</span>
|
|
|
- <el-icon class="ml-1 cursor-pointer text-blue-500" @click="handleEditPrice(row)">
|
|
|
+ <span>¥{{ row.productPrice }}</span>
|
|
|
+ <el-icon class="ml-1 cursor-pointer" style="color:#409eef" @click="handleEditPrice(row)">
|
|
|
<EditPen />
|
|
|
</el-icon>
|
|
|
</div>
|
|
|
- <div v-if="row.schedule" class="text-xs text-green-500 mt-1">
|
|
|
- 谢程婧: {{ row.schedule }}
|
|
|
- </div>
|
|
|
</template>
|
|
|
|
|
|
- <template #stock="{ row }">
|
|
|
- <div class="text-xs text-left">
|
|
|
- <div>中等: {{ row.stockMedium || 0 }}</div>
|
|
|
- <div>良好: {{ row.stockGood || 0 }}</div>
|
|
|
- <div>次品: {{ row.stockDefective || 0 }}</div>
|
|
|
- <div>合计: {{ row.stockTotal || 0 }}</div>
|
|
|
- </div>
|
|
|
+ <template #status="{ row }">
|
|
|
+ <el-tag v-if="row.sellStatus == '1'" type="success">出售中</el-tag>
|
|
|
+ <el-tag v-else-if="row.sellStatus == '0'" type="warning">待上架</el-tag>
|
|
|
+ <el-tag v-else-if="row.sellStatus == '2'" type="info">已下架</el-tag>
|
|
|
+ <el-tag v-else-if="row.sellStatus == '3'" type="danger">黑名单</el-tag>
|
|
|
+ <el-tag v-else type="warning">-</el-tag>
|
|
|
</template>
|
|
|
|
|
|
<template #action="{ row }">
|
|
|
- <div class="flex flex-wrap gap-1 button-group">
|
|
|
- <!-- Common Actions -->
|
|
|
- <el-button type="success" size="small" @click="handleModify(row)">修改</el-button>
|
|
|
-
|
|
|
- <!-- Specific Actions based on Tab/Status -->
|
|
|
- <template v-if="activeTab === 'pending_listing'">
|
|
|
- <el-button type="primary" size="small" @click="handleListing(row)">上架</el-button>
|
|
|
- <el-button color="#e99d42" size="small" @click="handleRecycleLog(row)">回收日志</el-button>
|
|
|
- <el-button type="primary" size="small" @click="handlePriceLog(row)">售价日志</el-button>
|
|
|
-
|
|
|
- <el-button color="#f37607" size="small" @click="handleViewTaobao(row)">查看淘宝</el-button>
|
|
|
- <el-button color="#951d1d" size="small" @click="handleViewKongfz(row)">查看孔网</el-button>
|
|
|
- <el-button type="primary" size="small"
|
|
|
- @click="handleToggleRecycleList(row)">移除/加入回收书单</el-button>
|
|
|
- <el-button type="danger" size="small" @click="handleToggleRecycle(row)">暂停/开启回收</el-button>
|
|
|
-
|
|
|
- <el-button color="#7728f5" size="small"
|
|
|
- @click="handleSetIndependentParams(row)">设置独立参数</el-button>
|
|
|
- <el-button color="#333333" size="small" @click="handleToggleBlacklist(row)">加入/移除黑名单</el-button>
|
|
|
+ <div class="flex flex-wrap gap-2 button-group">
|
|
|
+ <!-- 其他状态保持原有逻辑 -->
|
|
|
+ <el-button type="warning" @click="handleSalesDetail(row)">销售明细</el-button>
|
|
|
+ <el-button type="primary" plain @click="handleRecycleDetail(row)">回收明细</el-button>
|
|
|
+
|
|
|
+ <template v-if="row.sellStatus == '1'">
|
|
|
+ <el-button type="warning" @click="handleDelist(row)">下架</el-button>
|
|
|
</template>
|
|
|
|
|
|
- <template v-else>
|
|
|
- <el-button type="danger" size="small" @click="handlePriceLog(row)">售价日志</el-button>
|
|
|
- <el-button type="warning" size="small" @click="handleDelist(row)">下架</el-button>
|
|
|
- <el-button type="warning" size="small" @click="handleSalesDetail(row)">销售明细</el-button>
|
|
|
- <el-button type="danger" size="small" @click="handleRecycleDetail(row)">回收明细</el-button>
|
|
|
+ <template v-else-if="row.sellStatus == '2'">
|
|
|
+ <el-button type="success" @click="handleListing(row)">上架</el-button>
|
|
|
</template>
|
|
|
+
|
|
|
+ <el-button v-if="row.sellStatus == '3'" type="danger"
|
|
|
+ @click="handleToggleBlacklist(row, false)">移出黑名单</el-button>
|
|
|
+ <el-button v-else color="#606066" @click="handleToggleBlacklist(row, true)">加入黑名单</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #others="{ row }">
|
|
|
+ <div class="flex flex-wrap gap-2">
|
|
|
+ <!-- 待上架状态显示特定按钮组 -->
|
|
|
+ <el-button color="#e99d42" @click="handleRecycleLog(row)"
|
|
|
+ v-permission="'recycle:bookStat:recycleLog'">回收日志</el-button>
|
|
|
+ <el-button color="#0f7dc7" @click="handleSalesLog(row)"
|
|
|
+ v-permission="'recycle:bookStat:salesLog'">售价日志</el-button>
|
|
|
+ <el-button color="#f27606" @click="handleViewUrl(row, 'tb')">查看淘宝</el-button>
|
|
|
+ <el-button color="#951d1d" @click="handleViewUrl(row, 'kw')">查看孔网</el-button>
|
|
|
+
|
|
|
+ <!-- 移除/加入回收书单 -->
|
|
|
+ <el-button color="#4095e5" @click="handleOptBooklist('remove', row)"
|
|
|
+ v-permission="'recycle:bookStat:removeBooklist'"
|
|
|
+ v-if="row.recycleStatus && row.recycleStatus > 0">
|
|
|
+ 移除回收书单
|
|
|
+ </el-button>
|
|
|
+ <el-button color="#bd3124" @click="handleOptBooklist('add', row)"
|
|
|
+ v-permission="'recycle:bookStat:addBooklist'" v-else>
|
|
|
+ 加入回收书单
|
|
|
+ </el-button>
|
|
|
+
|
|
|
+ <!-- 暂停/开启回收 -->
|
|
|
+ <template v-if="row.recycleStatus && row.recycleStatus > 0">
|
|
|
+ <el-button v-if="row.recycleStatus == 1" color="#bd3124" @click="handleOptRecycle('pause', row)"
|
|
|
+ v-permission="'recycle:bookStat:pauseRecycle'">
|
|
|
+ 暂停回收
|
|
|
+ </el-button>
|
|
|
+ <el-button v-else color="#bd3124" @click="handleOptRecycle('start', row)"
|
|
|
+ v-permission="'recycle:bookStat:startRecycle'">
|
|
|
+ 开启回收
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <el-button color="#7728f5" @click="handleSetParams(row)">设置独立参数</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</common-table>
|
|
|
|
|
|
- <!-- Modals -->
|
|
|
- <new-book-modal v-model="newBookVisible" @done="reload" />
|
|
|
+ <!-- 弹窗 -->
|
|
|
+ <new-book-modal ref="newBookModalRef" @done="reload" />
|
|
|
+ <edit-price-modal ref="editPriceModalRef" @done="reload" />
|
|
|
+ <sales-detail-modal ref="salesDetailModalRef" />
|
|
|
+ <recycle-detail-modal ref="recycleDetailModalRef" />
|
|
|
+ <operation-log-modal ref="operationLogModalRef" />
|
|
|
|
|
|
- <common-import-modal v-model="updatePriceVisible" title="更新价格" template-name="更新价格模板"
|
|
|
- template-url="https://example.com/price_template.xlsx" upload-url="/goods/price/import"
|
|
|
- instruction-title="更新规则" :instructions="[
|
|
|
+ <common-import-modal ref="updatePriceModalRef" title="更新价格" template-name="更新价格模板"
|
|
|
+ template-url="https://shuhi.oss-cn-qingdao.aliyuncs.com/default/shop_book_price_import.xlsx"
|
|
|
+ upload-url="/shop/shopbook/importPrice" instruction-title="更新规则" :instructions="[
|
|
|
'文件ISBN不存在或者错误,会自动过滤掉',
|
|
|
'导入文件第一行需与模版完全一致'
|
|
|
]" @done="reload" />
|
|
|
|
|
|
- <common-import-modal v-model="listDelistVisible" title="上架/下架" template-name="上架/下架模板"
|
|
|
- template-url="https://example.com/list_delist_template.xlsx" upload-url="/goods/status/import"
|
|
|
+ <common-import-modal ref="listDelistModalRef" title="批量上/下架" template-name="上架/下架模板"
|
|
|
+ template-url="https://example.com/list_delist_template.xlsx" upload-url="/shop/shopbook/batchShelf"
|
|
|
instruction-title="上架/下架规则" :instructions="[
|
|
|
'文件ISBN不存在或者错误,会自动过滤掉',
|
|
|
'导入文件第一行需与模版完全一致'
|
|
|
]" @done="reload" />
|
|
|
|
|
|
- <edit-price-modal ref="editPriceModalRef" v-model="editPriceVisible" @done="reload" />
|
|
|
-
|
|
|
- <sales-detail-modal ref="salesDetailModalRef" v-model="salesDetailVisible" />
|
|
|
-
|
|
|
- <recycle-detail-modal ref="recycleDetailModalRef" v-model="recycleDetailVisible" />
|
|
|
-
|
|
|
- <operation-log-modal ref="operationLogModalRef" v-model="operationLogVisible" />
|
|
|
-
|
|
|
+ <books-edit ref="booksEditRef" @success="reload" />
|
|
|
+ <set-params ref="paramsRef" @refresh="reload" />
|
|
|
+ <order-recycle-log ref="recycleLogRef" />
|
|
|
+ <order-sales-log ref="salesLogRef" />
|
|
|
</ele-page>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, reactive, computed } from 'vue';
|
|
|
-import CommonTable from '@/components/CommonPage/CommonTable.vue';
|
|
|
-import GoodsSearch from './components/goods-search.vue';
|
|
|
-import GoodsInfo from './components/goods-info.vue';
|
|
|
-import NewBookModal from './components/new-book-modal.vue';
|
|
|
-import CommonImportModal from './components/common-import-modal.vue';
|
|
|
-import EditPriceModal from './components/edit-price-modal.vue';
|
|
|
-import SalesDetailModal from './components/sales-detail-modal.vue';
|
|
|
-import RecycleDetailModal from './components/recycle-detail-modal.vue';
|
|
|
-import OperationLogModal from './components/operation-log-modal.vue';
|
|
|
-import { EditPen } from '@element-plus/icons-vue';
|
|
|
-import { EleMessage } from 'ele-admin-plus/es';
|
|
|
-
|
|
|
-defineOptions({ name: 'GoodsList' });
|
|
|
-
|
|
|
-// State
|
|
|
-const activeTab = ref('all');
|
|
|
-const tableRef = ref(null);
|
|
|
-const searchRef = ref(null);
|
|
|
-
|
|
|
-// Modals State
|
|
|
-const newBookVisible = ref(false);
|
|
|
-const updatePriceVisible = ref(false);
|
|
|
-const listDelistVisible = ref(false);
|
|
|
-const editPriceVisible = ref(false);
|
|
|
-const salesDetailVisible = ref(false);
|
|
|
-const recycleDetailVisible = ref(false);
|
|
|
-const operationLogVisible = ref(false);
|
|
|
-
|
|
|
-const editPriceModalRef = ref(null);
|
|
|
-const salesDetailModalRef = ref(null);
|
|
|
-const recycleDetailModalRef = ref(null);
|
|
|
-const operationLogModalRef = ref(null);
|
|
|
-
|
|
|
-// Page Config
|
|
|
-const pageConfig = reactive({
|
|
|
- pageUrl: '/goods/list', // Mock URL
|
|
|
- fileName: '商品列表',
|
|
|
- cacheKey: 'goods-list-data',
|
|
|
- params: {
|
|
|
- status: 'all'
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-// Mock Datasource
|
|
|
-const mockDatasource = ({ page, limit, where }) => {
|
|
|
- // Simulate API delay
|
|
|
- return new Promise((resolve) => {
|
|
|
- setTimeout(() => {
|
|
|
- const list = [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- cover: 'https://img3.doubanio.com/view/subject/s/public/s34049753.jpg',
|
|
|
- title: 'Vue.js设计与实现',
|
|
|
- author: '霍春阳',
|
|
|
- isbn: '9787115583648',
|
|
|
- publisher: '人民邮电出版社',
|
|
|
- productType: '图书',
|
|
|
- price: 89.00,
|
|
|
- stock: 100,
|
|
|
- stockMedium: 50,
|
|
|
- stockGood: 30,
|
|
|
- stockDefective: 20,
|
|
|
- stockTotal: 100,
|
|
|
- salesVolume: 500,
|
|
|
- listingTime: '2023-01-01',
|
|
|
- status: 'on_sale'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- cover: 'https://img9.doubanio.com/view/subject/s/public/s29653655.jpg',
|
|
|
- title: '深入浅出Node.js',
|
|
|
- author: '朴灵',
|
|
|
- isbn: '9787115323562',
|
|
|
- publisher: '人民邮电出版社',
|
|
|
- productType: '图书',
|
|
|
- price: 69.00,
|
|
|
- stock: 0,
|
|
|
- stockMedium: 0,
|
|
|
- stockGood: 0,
|
|
|
- stockDefective: 0,
|
|
|
- stockTotal: 0,
|
|
|
- salesVolume: 1200,
|
|
|
- listingTime: '2022-05-20',
|
|
|
- status: 'in_warehouse'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- cover: 'https://img1.doubanio.com/view/subject/s/public/s28359307.jpg',
|
|
|
- title: 'JavaScript高级程序设计',
|
|
|
- author: '马特·弗里斯比',
|
|
|
- isbn: '9787115545381',
|
|
|
- publisher: '人民邮电出版社',
|
|
|
- productType: '图书',
|
|
|
- price: 99.00,
|
|
|
- stock: 50,
|
|
|
- stockMedium: 20,
|
|
|
- stockGood: 20,
|
|
|
- stockDefective: 10,
|
|
|
- stockTotal: 50,
|
|
|
- salesVolume: 300,
|
|
|
- listingTime: '2023-06-01',
|
|
|
- status: 'pending_listing'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 4,
|
|
|
- cover: 'https://img2.doubanio.com/view/subject/s/public/s34049753.jpg',
|
|
|
- title: 'CSS世界',
|
|
|
- author: '张鑫旭',
|
|
|
- isbn: '9787115472199',
|
|
|
- publisher: '人民邮电出版社',
|
|
|
- productType: '图书',
|
|
|
- price: 59.00,
|
|
|
- stock: 20,
|
|
|
- stockMedium: 10,
|
|
|
- stockGood: 5,
|
|
|
- stockDefective: 5,
|
|
|
- stockTotal: 20,
|
|
|
- salesVolume: 150,
|
|
|
- listingTime: '2021-12-12',
|
|
|
- status: 'blacklist'
|
|
|
- }
|
|
|
- ];
|
|
|
-
|
|
|
- // Filter by tab status (simulated)
|
|
|
- let filteredList = list;
|
|
|
- if (activeTab.value !== 'all') {
|
|
|
- if (activeTab.value === 'pending_listing') {
|
|
|
- // For demo purposes, let's make sure we have data for pending_listing
|
|
|
- // Or just filter by status if it matches
|
|
|
- filteredList = list.filter(item => item.status === activeTab.value);
|
|
|
- // If empty for demo, just show item 3
|
|
|
- if (filteredList.length === 0) filteredList = [list[2]];
|
|
|
- } else {
|
|
|
- filteredList = list.filter(item => item.status === activeTab.value);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- resolve({
|
|
|
- code: 0,
|
|
|
- msg: 'success',
|
|
|
- count: list.length,
|
|
|
- data: filteredList
|
|
|
- });
|
|
|
- }, 500);
|
|
|
+ import { ref, reactive } from 'vue';
|
|
|
+ import CommonTable from '@/components/CommonPage/CommonTable.vue';
|
|
|
+ import CommonImportModal from './components/common-import-modal.vue';
|
|
|
+ import GoodsSearch from './components/goods-search.vue';
|
|
|
+ import GoodsInfo from './components/goods-info.vue';
|
|
|
+ import NewBookModal from './components/new-book-modal.vue';
|
|
|
+ import EditPriceModal from './components/edit-price-modal.vue';
|
|
|
+ import SalesDetailModal from '@/views/recycle/inventory/components/sale-detail.vue';
|
|
|
+ import RecycleDetailModal from '@/views/recycle/inventory/components/recycle-detail.vue';
|
|
|
+ import OperationLogModal from './components/operation-log-modal.vue';
|
|
|
+ import BooksEdit from '@/views/data/books/components/books-edit.vue';
|
|
|
+ import SetParams from '@/views/recycle/components/set-params.vue';
|
|
|
+ import OrderRecycleLog from '@/views/recycleOrder/detail/order-recycle-log.vue';
|
|
|
+ import OrderSalesLog from '@/views/recycleOrder/detail/order-sales-log.vue';
|
|
|
+ import { EditPen, Picture } from '@element-plus/icons-vue';
|
|
|
+ import { EleMessage } from 'ele-admin-plus/es';
|
|
|
+ import request from '@/utils/request';
|
|
|
+ import { useBookOperation } from '@/utils/use-book-operation';
|
|
|
+
|
|
|
+ defineOptions({ name: 'GoodsList' });
|
|
|
+
|
|
|
+ // 状态
|
|
|
+ const activeTab = ref('');
|
|
|
+ const tableRef = ref(null);
|
|
|
+ const searchRef = ref(null);
|
|
|
+ const searchParams = ref({});
|
|
|
+
|
|
|
+ // 弹窗状态
|
|
|
+ const newBookModalRef = ref(null);
|
|
|
+ const editPriceModalRef = ref(null);
|
|
|
+ const salesDetailModalRef = ref(null);
|
|
|
+ const recycleDetailModalRef = ref(null);
|
|
|
+ const operationLogModalRef = ref(null);
|
|
|
+ const updatePriceModalRef = ref(null);
|
|
|
+ const listDelistModalRef = ref(null);
|
|
|
+ const booksEditRef = ref(null);
|
|
|
+ // const setParamsRef = ref(null);
|
|
|
+ const recycleLogRef = ref(null);
|
|
|
+ const salesLogRef = ref(null);
|
|
|
+
|
|
|
+ // Page Config
|
|
|
+ const pageConfig = reactive({
|
|
|
+ pageUrl: '/shop/shopbook/shopPageList',
|
|
|
+ exportUrl: '/shop/shopbook/export',
|
|
|
+ fileName: '商品列表',
|
|
|
+ cacheKey: 'goods-list-data',
|
|
|
+ params: {
|
|
|
+ sellStatus: ''
|
|
|
+ }
|
|
|
});
|
|
|
-};
|
|
|
-
|
|
|
-// Columns
|
|
|
-const columns = computed(() => [
|
|
|
- { type: 'selection', width: 50, align: 'center', fixed: 'left' },
|
|
|
- { label: '商品图', prop: 'cover', width: 100, slot: 'cover', align: 'center' },
|
|
|
- { label: '商品名称', prop: 'info', minWidth: 200, slot: 'info' },
|
|
|
- { label: '商品类型', prop: 'productType', width: 100, align: 'center' },
|
|
|
- { label: '售价', prop: 'price', width: 120, slot: 'price', align: 'center', sortable: 'custom' },
|
|
|
- { label: '库存', prop: 'stock', width: 150, slot: 'stock', align: 'center', sortable: 'custom' },
|
|
|
- { label: '销量', prop: 'salesVolume', width: 100, align: 'center', sortable: 'custom' },
|
|
|
- { label: '上架时间', prop: 'listingTime', width: 160, align: 'center', sortable: 'custom' },
|
|
|
- { label: '操作', prop: 'action', width: 280, slot: 'action', align: 'center', fixed: 'right' }
|
|
|
-]);
|
|
|
-
|
|
|
-// Methods
|
|
|
-const reload = (params = {}) => {
|
|
|
- tableRef.value?.reload(params);
|
|
|
-};
|
|
|
-
|
|
|
-const handleTabChange = (name) => {
|
|
|
- pageConfig.params.status = name;
|
|
|
- reload();
|
|
|
-};
|
|
|
-
|
|
|
-// Modal Openers
|
|
|
-const openNewBookModal = () => {
|
|
|
- newBookVisible.value = true;
|
|
|
-};
|
|
|
-
|
|
|
-const openNewOtherModal = () => {
|
|
|
- EleMessage.info('功能开发中...');
|
|
|
-};
|
|
|
-
|
|
|
-const openUpdatePriceModal = () => {
|
|
|
- updatePriceVisible.value = true;
|
|
|
-};
|
|
|
-
|
|
|
-const openListDelistModal = () => {
|
|
|
- listDelistVisible.value = true;
|
|
|
-};
|
|
|
-
|
|
|
-const handleEditPrice = (row) => {
|
|
|
- editPriceVisible.value = true;
|
|
|
- editPriceModalRef.value?.open(row);
|
|
|
-};
|
|
|
-
|
|
|
-// Actions
|
|
|
-const handleOneClickListing = () => {
|
|
|
- EleMessage.success('一键上架指令已发送');
|
|
|
-};
|
|
|
-
|
|
|
-const handleExport = () => {
|
|
|
- EleMessage.success('开始导出...');
|
|
|
-};
|
|
|
-
|
|
|
-const handleOperationLog = () => {
|
|
|
- operationLogVisible.value = true;
|
|
|
- operationLogModalRef.value?.open();
|
|
|
-};
|
|
|
-
|
|
|
-const handleModify = (row) => {
|
|
|
- EleMessage.info(`修改商品: ${row.title}`);
|
|
|
-};
|
|
|
-
|
|
|
-const handlePriceLog = (row) => {
|
|
|
- EleMessage.info(`查看售价日志: ${row.title}`);
|
|
|
-};
|
|
|
-
|
|
|
-const handleDelist = (row) => {
|
|
|
- EleMessage.warning(`下架商品: ${row.title}`);
|
|
|
-};
|
|
|
-
|
|
|
-const handleListing = (row) => {
|
|
|
- EleMessage.success(`上架商品: ${row.title}`);
|
|
|
-};
|
|
|
-
|
|
|
-const handleSalesDetail = (row) => {
|
|
|
- salesDetailVisible.value = true;
|
|
|
- salesDetailModalRef.value?.open(row);
|
|
|
-};
|
|
|
-
|
|
|
-const handleRecycleDetail = (row) => {
|
|
|
- recycleDetailVisible.value = true;
|
|
|
- recycleDetailModalRef.value?.open(row);
|
|
|
-};
|
|
|
-
|
|
|
-const handleRecycleLog = (row) => {
|
|
|
- EleMessage.info(`回收日志: ${row.title}`);
|
|
|
-};
|
|
|
-
|
|
|
-const handleViewTaobao = (row) => {
|
|
|
- window.open(`https://s.taobao.com/search?q=${row.isbn}`, '_blank');
|
|
|
-};
|
|
|
-
|
|
|
-const handleViewKongfz = (row) => {
|
|
|
- window.open(`https://search.kongfz.com/product_result/?key=${row.isbn}`, '_blank');
|
|
|
-};
|
|
|
-
|
|
|
-const handleToggleRecycleList = (row) => {
|
|
|
- EleMessage.info('切换回收书单状态');
|
|
|
-};
|
|
|
-
|
|
|
-const handleToggleRecycle = (row) => {
|
|
|
- EleMessage.info('切换回收状态');
|
|
|
-};
|
|
|
-
|
|
|
-const handleSetIndependentParams = (row) => {
|
|
|
- EleMessage.info('设置独立参数');
|
|
|
-};
|
|
|
-
|
|
|
-const handleToggleBlacklist = (row) => {
|
|
|
- EleMessage.info('切换黑名单状态');
|
|
|
-};
|
|
|
|
|
|
+ const columns = ref([
|
|
|
+ { label: '封面', prop: 'cover', slot: 'cover', width: 100, align: 'center' },
|
|
|
+ { label: '商品信息', prop: 'info', slot: 'info', minWidth: 200 },
|
|
|
+ { label: '库存', prop: 'stock', slot: 'stock', width: 150, align: 'center' },
|
|
|
+ { label: '售价', prop: 'productPrice', slot: 'price', width: 120, align: 'center' },
|
|
|
+ { label: '销量', prop: 'salesNum', width: 100, align: 'center' },
|
|
|
+ { label: '状态', prop: 'sellStatus', slot: 'status', width: 100, align: 'center' },
|
|
|
+ { label: '上架时间', prop: 'onSaleTime', width: 160, align: 'center' },
|
|
|
+ { columnKey: 'action', label: '操作', width: 220, align: 'center', slot: 'action', fixed: 'right' },
|
|
|
+ { columnKey: 'others', label: '其他操作', minWidth: 160, align: 'center', slot: 'others', fixed: 'right' }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 方法
|
|
|
+ const reload = (where) => {
|
|
|
+ tableRef.value?.reload(where);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 图书操作 Hook
|
|
|
+ const {
|
|
|
+ paramsRef,
|
|
|
+ handleOptBooklist,
|
|
|
+ handleOptRecycle,
|
|
|
+ handleSetParams,
|
|
|
+ handleViewUrl
|
|
|
+ } = useBookOperation(tableRef);
|
|
|
+
|
|
|
+ const handleRecycleLog = (row) => {
|
|
|
+ recycleLogRef.value?.handleOpen(row);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSalesLog = (row) => {
|
|
|
+ salesLogRef.value?.handleOpen(row);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSearch = (where) => {
|
|
|
+ searchParams.value = where;
|
|
|
+ reload(where);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleTabChange = (name) => {
|
|
|
+ let status = name;
|
|
|
+ // 直接更新参数
|
|
|
+ pageConfig.params.sellStatus = status;
|
|
|
+ reload();
|
|
|
+ };
|
|
|
+
|
|
|
+ // 操作
|
|
|
+ const openNewBookModal = () => {
|
|
|
+ newBookModalRef.value?.open();
|
|
|
+ };
|
|
|
+
|
|
|
+ const openUpdatePriceModal = () => {
|
|
|
+ updatePriceModalRef.value?.open();
|
|
|
+ };
|
|
|
+
|
|
|
+ const openListDelistModal = () => {
|
|
|
+ listDelistModalRef.value?.open();
|
|
|
+ };
|
|
|
+
|
|
|
+ const openNewOtherModal = () => {
|
|
|
+ EleMessage.info('开发中');
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleEditPrice = (row) => {
|
|
|
+ editPriceModalRef.value?.open(row);
|
|
|
+ };
|
|
|
+
|
|
|
+ const setShelfStatus = async (row, status, successMsg) => {
|
|
|
+ try {
|
|
|
+ await request.post('/shop/shopbook/setShelfStatus', {
|
|
|
+ isbn: row.isbn,
|
|
|
+ sellStatus: status
|
|
|
+ });
|
|
|
+ EleMessage.success(successMsg);
|
|
|
+ reload();
|
|
|
+ } catch (e) {
|
|
|
+ EleMessage.error(e.message || '操作失败');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleDelist = (row) => {
|
|
|
+ tableRef.value?.messageBoxConfirm({
|
|
|
+ message: '确认下架该商品吗?',
|
|
|
+ fetch: () => request.post('/shop/shopbook/setShelfStatus', { isbn: row.isbn, sellStatus: '2' }),
|
|
|
+ successMessage: '下架成功'
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleListing = (row) => {
|
|
|
+ setShelfStatus(row, '1', '上架成功');
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleToggleBlacklist = (row, isAdd) => {
|
|
|
+ const status = isAdd ? '3' : '2'; // Remove from blacklist -> In Warehouse
|
|
|
+ const msg = isAdd ? '确认加入黑名单?' : '确认移出黑名单?';
|
|
|
+
|
|
|
+ tableRef.value?.messageBoxConfirm({
|
|
|
+ message: msg,
|
|
|
+ fetch: () => request.post('/shop/shopbook/setShelfStatus', { isbn: row.isbn, sellStatus: status }),
|
|
|
+ successMessage: '操作成功'
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleExport = () => {
|
|
|
+ tableRef.value?.exportData('商品列表');
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleOperationLog = () => {
|
|
|
+ operationLogModalRef.value?.open();
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSalesDetail = (row) => {
|
|
|
+ salesDetailModalRef.value?.handleOpen(row);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleRecycleDetail = (row) => {
|
|
|
+ recycleDetailModalRef.value?.handleOpen(row);
|
|
|
+ };
|
|
|
</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-/* Custom styles if needed */
|
|
|
-</style>
|