380 lines
9.2 KiB
Vue
380 lines
9.2 KiB
Vue
<template>
|
|
<view class="container">
|
|
<!-- 顶部导航栏 -->
|
|
<view class="navbar">
|
|
<view class="nav-back" @tap="goBack">
|
|
<uni-icons type="back" size="18" color="#fff"></uni-icons>
|
|
</view>
|
|
<view class="nav-title">批量删除</view>
|
|
<view class="nav-more">
|
|
<uni-icons type="more-filled" size="18" color="#fff"></uni-icons>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 搜索栏 -->
|
|
<view class="search-bar">
|
|
<view class="search-input">
|
|
<uni-icons type="search" size="18" color="#999"></uni-icons>
|
|
<input
|
|
type="text"
|
|
placeholder="搜索商品名称、条码"
|
|
placeholder-class="placeholder"
|
|
v-model="searchText"
|
|
@confirm="onSearch"
|
|
/>
|
|
<uni-icons type="scan" size="18" color="#999"></uni-icons>
|
|
</view>
|
|
<view class="filter-btn" @tap="showFilter = !showFilter">
|
|
<uni-icons type="filter" size="18" color="#999"></uni-icons>
|
|
<text>筛选</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 商品列表 -->
|
|
<scroll-view class="goods-list" scroll-y="true">
|
|
<!-- 空列表提示 -->
|
|
<view v-if="goodsList.length === 0" class="empty-tip">
|
|
<text>暂无商品数据</text>
|
|
</view>
|
|
<!-- 商品项 -->
|
|
<view
|
|
class="goods-item"
|
|
v-for="item in goodsList"
|
|
:key="item.id"
|
|
>
|
|
<view class="checkbox-wrap" @tap="toggleSelect(item.id)">
|
|
<view
|
|
class="custom-checkbox"
|
|
:class="{ checked: selectedIds.includes(String(item.id)) }"
|
|
>
|
|
<text v-if="selectedIds.includes(String(item.id))" class="check-icon">✓</text>
|
|
</view>
|
|
</view>
|
|
<view class="goods-info">
|
|
<image
|
|
:src="item.mainImage ? 'http://193.112.94.36:8081' + item.mainImage : '/static/default-goods.png'"
|
|
class="goods-img"
|
|
mode="aspectFill"
|
|
/>
|
|
<view class="goods-details">
|
|
<text class="goods-name">{{ item.productName || '未命名商品' }}</text>
|
|
<text class="goods-barcode">{{ item.productBarCode || '无条码' }}</text>
|
|
<text class="goods-price">¥{{ item.storePrice ? Number(item.storePrice).toFixed(2) : '0.00' }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<!-- 底部操作栏 -->
|
|
<view class="bottom-bar" v-if="goodsList.length > 0">
|
|
<view class="select-all" @tap="toggleSelectAll">
|
|
<view class="custom-checkbox" :class="{ checked: isAllSelected }">
|
|
<text v-if="isAllSelected" class="check-icon">✓</text>
|
|
</view>
|
|
<text>全选 (已选{{ selectedIds.length }})</text>
|
|
</view>
|
|
<button
|
|
class="delete-btn"
|
|
:class="{ disabled: selectedIds.length === 0 }"
|
|
:disabled="selectedIds.length === 0"
|
|
@tap="onDeleteSelected"
|
|
>
|
|
删除商品
|
|
</button>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { getProductList as fetchProductList, batchDeleteProduct } from '@/api/product'
|
|
import { getToken, getStoreId } from '@/utils/auth'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
searchText: '',
|
|
showFilter: false,
|
|
storeId: null,
|
|
goodsList: [],
|
|
selectedIds: []
|
|
}
|
|
},
|
|
computed: {
|
|
allCheckboxValues() {
|
|
return this.goodsList.map(item => ({
|
|
text: '',
|
|
value: String(item.id)
|
|
}));
|
|
},
|
|
isAllSelected() {
|
|
return this.goodsList.length > 0 && this.selectedIds.length === this.goodsList.length;
|
|
}
|
|
},
|
|
onLoad() {
|
|
const storeId = getStoreId();
|
|
if (storeId) {
|
|
this.storeId = storeId;
|
|
this.getProductList();
|
|
} else {
|
|
uni.showToast({ title: '请先选择门店', icon: 'none', duration: 1500 });
|
|
setTimeout(() => uni.navigateBack(), 1500);
|
|
}
|
|
},
|
|
methods: {
|
|
goBack() {
|
|
uni.navigateBack();
|
|
},
|
|
// 加载商品列表
|
|
async getProductList(searchParams = {}) {
|
|
try {
|
|
if (this.storeId) {
|
|
searchParams.storeId = this.storeId;
|
|
}
|
|
const res = await fetchProductList(searchParams);
|
|
if (res && res.code === 200 && Array.isArray(res.data)) {
|
|
this.goodsList = res.data;
|
|
this.selectedIds = [];
|
|
} else {
|
|
uni.showToast({ title: res?.msg || '获取商品失败', icon: 'none' });
|
|
}
|
|
} catch (error) {
|
|
console.error('获取商品异常:', error);
|
|
uni.showToast({ title: '网络错误', icon: 'none' });
|
|
}
|
|
},
|
|
// 搜索
|
|
onSearch() {
|
|
const keyword = this.searchText.trim();
|
|
if (!keyword) {
|
|
this.getProductList();
|
|
return;
|
|
}
|
|
const searchParams = /^\d+$/.test(keyword)
|
|
? { productBarCode: keyword }
|
|
: { productName: keyword };
|
|
this.getProductList(searchParams);
|
|
},
|
|
// 单个商品选中/取消
|
|
toggleSelect(id) {
|
|
const idStr = String(id);
|
|
const index = this.selectedIds.indexOf(idStr);
|
|
if (index > -1) {
|
|
this.selectedIds.splice(index, 1);
|
|
} else {
|
|
this.selectedIds.push(idStr);
|
|
}
|
|
},
|
|
// 全选/取消全选
|
|
toggleSelectAll() {
|
|
if (this.isAllSelected) {
|
|
this.selectedIds = [];
|
|
} else {
|
|
this.selectedIds = this.goodsList.map(item => String(item.id));
|
|
}
|
|
},
|
|
// 批量删除
|
|
async onDeleteSelected() {
|
|
if (this.selectedIds.length === 0) return;
|
|
|
|
uni.showModal({
|
|
title: '确认删除',
|
|
content: `确定删除选中的${this.selectedIds.length}个商品?删除后不可恢复!`,
|
|
success: async (res) => {
|
|
if (res.confirm) {
|
|
try {
|
|
const idsToDelete = this.selectedIds.map(id => Number(id));
|
|
const result = await batchDeleteProduct(idsToDelete);
|
|
if (result && result.code === 200) {
|
|
uni.showToast({ title: '删除成功', icon: 'success' });
|
|
this.getProductList();
|
|
} else {
|
|
uni.showToast({ title: result?.msg || '删除失败', icon: 'none' });
|
|
}
|
|
} catch (error) {
|
|
console.error('删除异常:', error);
|
|
uni.showToast({ title: '网络错误', icon: 'none' });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 全局容器 */
|
|
.container {
|
|
background-color: #f5f5f5;
|
|
min-height: 100vh;
|
|
padding-bottom: 80rpx;
|
|
}
|
|
|
|
/* 导航栏 */
|
|
.navbar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 16px;
|
|
background-color: #e63946;
|
|
color: #fff;
|
|
}
|
|
.nav-title { font-size: 18px; font-weight: 600; }
|
|
|
|
/* 搜索栏 */
|
|
.search-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 12px 16px;
|
|
background-color: #fff;
|
|
}
|
|
.search-input {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: #f5f5f5;
|
|
border-radius: 8px;
|
|
padding: 10px 12px;
|
|
margin-right: 12px;
|
|
}
|
|
.search-input input {
|
|
flex: 1;
|
|
margin-left: 8px;
|
|
font-size: 14px;
|
|
border: none;
|
|
outline: none;
|
|
}
|
|
.placeholder { color: #999; }
|
|
.filter-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 14px;
|
|
color: #666;
|
|
}
|
|
.filter-btn text { margin-left: 4px; }
|
|
|
|
/* 商品列表 */
|
|
.goods-list {
|
|
height: calc(100vh - 200px);
|
|
padding: 16px;
|
|
}
|
|
.empty-tip {
|
|
text-align: center;
|
|
padding: 40px 0;
|
|
color: #999;
|
|
font-size: 14px;
|
|
}
|
|
.goods-item {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: #fff;
|
|
border-radius: 8px;
|
|
padding: 12px;
|
|
margin-bottom: 12px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
|
}
|
|
|
|
/* 复选框容器 */
|
|
.checkbox-wrap {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-right: 12px;
|
|
}
|
|
|
|
/* 自定义复选框样式 */
|
|
.custom-checkbox {
|
|
width: 28rpx;
|
|
height: 28rpx;
|
|
border-radius: 4rpx;
|
|
border: 2rpx solid #ddd;
|
|
background-color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.custom-checkbox.checked {
|
|
background-color: #e63946;
|
|
border-color: #e63946;
|
|
}
|
|
|
|
.check-icon {
|
|
color: #fff;
|
|
font-size: 18rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 商品信息 */
|
|
.goods-info {
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
.goods-img {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 8rpx;
|
|
margin-right: 12px;
|
|
}
|
|
.goods-details { flex: 1; }
|
|
.goods-name {
|
|
display: block;
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: #333;
|
|
margin-bottom: 4px;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.goods-barcode {
|
|
font-size: 12px;
|
|
color: #999;
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
}
|
|
.goods-price {
|
|
font-size: 12px;
|
|
color: #e63946;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* 底部操作栏 */
|
|
.bottom-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 16px;
|
|
background-color: #fff;
|
|
border-top: 1px solid #eee;
|
|
z-index: 99;
|
|
}
|
|
.select-all {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 14px;
|
|
color: #333;
|
|
}
|
|
.select-all text { margin-left: 6px; }
|
|
.delete-btn {
|
|
padding: 10px 24px;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
background-color: #e63946;
|
|
color: #fff;
|
|
border: none;
|
|
}
|
|
.delete-btn.disabled {
|
|
background-color: #ccc;
|
|
color: #999;
|
|
cursor: not-allowed;
|
|
}
|
|
</style> |