1397 lines
38 KiB
Vue
1397 lines
38 KiB
Vue
<template>
|
||
<view class="container">
|
||
<!-- <view class="header">
|
||
<view class="title-container">
|
||
<text class="title">商品管理</text>
|
||
<text class="subtitle">{{ locationCode }}</text>
|
||
</view>
|
||
</view> -->
|
||
|
||
<!-- 日期选择器 -->
|
||
<view class="date-picker-bar">
|
||
<picker mode="date" :value="dateInput" @change="onDatePickerConfirm">
|
||
<view class="date-left">
|
||
<text class="date-day">{{displayDate.day}}</text>
|
||
<view class="date-info">
|
||
<text>{{displayDate.day}} 日 - {{displayDate.month}} 月 - {{displayDate.year}} 年</text>
|
||
<text class="date-arrow">▼</text>
|
||
</view>
|
||
</view>
|
||
</picker>
|
||
<text class="date-total">累计 {{ total }} 条</text>
|
||
</view>
|
||
|
||
<!-- 批量操作按钮 -->
|
||
<view class="batch-action-bar">
|
||
<view class="batch-btn" @click="toggleBatchMode">
|
||
<text>{{ isBatchMode ? '取消选择' : '批量修改' }}</text>
|
||
</view>
|
||
<view class="action-btns" v-if="isBatchMode">
|
||
<view class="action-btn" :class="{ 'disabled': selectedItems.length === 0 }" @click="batchDelete">
|
||
<text>删除</text>
|
||
</view>
|
||
<view class="action-btn" :class="{ 'disabled': selectedItems.length === 0 }" @click="batchEdit">
|
||
<text>修改</text>
|
||
</view>
|
||
<view class="select-all-btn" @click="toggleSelectAll">
|
||
<text>{{ isAllSelected ? '取消全选' : '全选' }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="isBatchMode" class="selected-count">
|
||
<text>已选择: {{ selectedItems.length }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 搜索框 -->
|
||
<!-- <view class="search-box">
|
||
<view class="search-input-wrap">
|
||
<u-icon name="search" size="40rpx" color="#999"></u-icon>
|
||
<input class="search-input" v-model="searchKeyword" placeholder="搜索商品名称" @confirm="searchGoods" />
|
||
</view>
|
||
<button class="search-btn" @click="searchGoods">搜索</button>
|
||
</view> -->
|
||
|
||
<!-- 加载中提示 -->
|
||
<view class="loading-state" v-if="loading">
|
||
<text>正在加载...</text>
|
||
</view>
|
||
|
||
<!-- 图片网格 -->
|
||
<scroll-view
|
||
scroll-y
|
||
style="height: calc(100vh - 300rpx)"
|
||
@scrolltolower="loadMore"
|
||
>
|
||
<view class="image-grid">
|
||
<view class="image-item" v-for="(goods, index) in goodsList" :key="index"
|
||
@click="isBatchMode ? selectItem(goods.id) : previewImage(goods.images)">
|
||
<!-- 选择框 -->
|
||
<view v-if="isBatchMode" class="select-box" @click.stop="selectItem(goods.id)">
|
||
<view class="select-circle" :class="{ 'selected': isItemSelected(goods.id) }">
|
||
<view v-if="isItemSelected(goods.id)" class="check-mark"></view>
|
||
</view>
|
||
</view>
|
||
<image :src="goods.image || '/static/default-book.png'" mode="aspectFill" class="book-image" @error="handleImageError"></image>
|
||
<view class="image-info">
|
||
<text class="book-name">{{goods.name}}</text>
|
||
<view class="book-details">
|
||
<text class="book-isbn">ISBN: {{goods.barcode || '无ISBN'}}</text>
|
||
</view>
|
||
<view class="book-details">
|
||
<text class="book-condition">品相: {{goods.condition || '未知'}}</text>
|
||
<text class="upload-time">{{goods.createTime || ''}}</text>
|
||
</view>
|
||
<view class="book-details">
|
||
<text v-if="goods.inventory !== undefined" class="book-stock">库存: {{goods.inventory}}</text>
|
||
<text class="book-price">{{formatPrice(goods.price)}}元</text>
|
||
</view>
|
||
<!--
|
||
<view class="book-details">
|
||
<text class="book-condition">拼多多:</text>
|
||
<text class="status-value" :class="goods.pddPublishedStatus === 1 ? 'published' : 'unpublished'">
|
||
{{goods.pddPublishedStatus === 1 ? '已发布' : '未发布'}}
|
||
</text>
|
||
</view>
|
||
<view class="book-details">
|
||
<text class="book-condition">孔夫子:</text>
|
||
<text class="status-value" :class="goods.kfzPublishedStatus === 1 ? 'published' : 'unpublished'">
|
||
{{goods.kfzPublishedStatus === 1 ? '已发布' : '未发布'}}
|
||
</text>
|
||
</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="loading-more" v-if="isLoadingMore">
|
||
<text>加载中...</text>
|
||
</view>
|
||
<view class="no-more" v-if="!hasMore && goodsList.length > 0">
|
||
<text>没有更多数据了</text>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 货区选择弹窗 -->
|
||
<view v-if="showLocationModal" class="modal-mask">
|
||
<view class="modal-content">
|
||
<view class="modal-header">
|
||
<text class="modal-title">选择目标货区</text>
|
||
<text class="modal-close" @click="closeLocationModal">×</text>
|
||
</view>
|
||
<view class="modal-body">
|
||
<!-- 一级货区选择 -->
|
||
<view class="location-select-item">
|
||
<text class="location-label">一级货区</text>
|
||
<view class="location-picker-wrap">
|
||
<picker @change="onWarehouseChange" :range="warehouseList" range-key="name">
|
||
<view class="picker-text">
|
||
<text v-if="selectedWarehouse">{{getWarehouseName(selectedWarehouse)}}</text>
|
||
<text v-else>请选择一级货区</text>
|
||
<text class="picker-arrow">▼</text>
|
||
</view>
|
||
</picker>
|
||
<view v-if="warehouseLoading" class="loading-indicator">加载中...</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 二级货架选择 -->
|
||
<view class="location-select-item">
|
||
<text class="location-label">二级货架</text>
|
||
<view class="location-picker-wrap">
|
||
<picker @change="onShelfChange" :range="shelfList" range-key="name" :disabled="!selectedWarehouse">
|
||
<view class="picker-text" :class="{'disabled': !selectedWarehouse}">
|
||
<text v-if="selectedShelf">{{getShelfName(selectedShelf)}}</text>
|
||
<text v-else>{{selectedWarehouse ? '请选择二级货架' : '请先选择一级货区'}}</text>
|
||
<text class="picker-arrow">▼</text>
|
||
</view>
|
||
</picker>
|
||
<view v-if="shelfLoading" class="loading-indicator">加载中...</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 三级货架选择 -->
|
||
<view class="location-select-item">
|
||
<text class="location-label">三级货架</text>
|
||
<view class="location-picker-wrap">
|
||
<picker @change="onFreightChange" :range="freightList" range-key="name" :disabled="!selectedShelf">
|
||
<view class="picker-text" :class="{'disabled': !selectedShelf}">
|
||
<text v-if="selectedFreight">{{getFreightName(selectedFreight)}}</text>
|
||
<text v-else>{{selectedShelf ? '请选择三级货架' : '请先选择二级货架'}}</text>
|
||
<text class="picker-arrow">▼</text>
|
||
</view>
|
||
</picker>
|
||
<view v-if="freightLoading" class="loading-indicator">加载中...</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="modal-footer">
|
||
<view class="modal-btn cancel-btn" @click="closeLocationModal">取消</view>
|
||
<view class="modal-btn confirm-btn" @click="confirmMoveItems">确认</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import config from '@/utils/config.js';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
locationCode: '', // 货区代码
|
||
goodsList: [], // 商品列表
|
||
loading: true,
|
||
isLoadingMore: false, // 加载更多状态
|
||
userId: '', // 用户ID
|
||
pageNum: 1, // 当前页码
|
||
pageSize: 10, // 每页数量
|
||
hasMore: true, // 是否有更多数据
|
||
totalPages: 1, // 总页数
|
||
searchKeyword: '', // 搜索关键词
|
||
originalData: [], // 保存原始数据用于搜索
|
||
dateInput: '', // 日期输入
|
||
displayDate: {
|
||
day: new Date().getDate().toString().padStart(2, '0'),
|
||
month: (new Date().getMonth() + 1).toString().padStart(2, '0'),
|
||
year: new Date().getFullYear()
|
||
},
|
||
total: 0, // 数据总条数
|
||
isBatchMode: false, // 批量选择模式
|
||
selectedItems: [], // 已选择的商品ID
|
||
isAllSelected: false, // 是否全选
|
||
|
||
// 货区选择弹窗相关
|
||
showLocationModal: false, // 是否显示货区选择弹窗
|
||
// 货区数据
|
||
warehouseList: [], // 一级货区列表
|
||
shelfList: [], // 二级货区列表
|
||
freightList: [], // 三级货区列表
|
||
selectedWarehouse: '', // 选中的一级货区ID
|
||
selectedShelf: '', // 选中的二级货区ID
|
||
selectedFreight: '', // 选中的三级货区ID
|
||
warehouseLoading: false, // 一级货区加载状态
|
||
shelfLoading: false, // 二级货区加载状态
|
||
freightLoading: false // 三级货区加载状态
|
||
}
|
||
},
|
||
onLoad(option) {
|
||
// 从路由参数获取货区代码
|
||
if (option.code) {
|
||
this.locationCode = option.code;
|
||
console.log('接收到的货区代码:', this.locationCode);
|
||
}
|
||
|
||
// 从本地存储获取用户ID
|
||
this.userId = uni.getStorageSync('userId');
|
||
|
||
// 加载商品数据
|
||
this.fetchGoodsData();
|
||
},
|
||
// 添加下拉刷新
|
||
onPullDownRefresh() {
|
||
this.pageNum = 1;
|
||
this.hasMore = true;
|
||
this.fetchGoodsData().then(() => {
|
||
uni.stopPullDownRefresh();
|
||
});
|
||
},
|
||
methods: {
|
||
// 切换批量选择模式
|
||
toggleBatchMode() {
|
||
this.isBatchMode = !this.isBatchMode;
|
||
if (!this.isBatchMode) {
|
||
// 退出批量模式时清空选择
|
||
this.selectedItems = [];
|
||
this.isAllSelected = false;
|
||
}
|
||
},
|
||
|
||
// 选择/取消选择商品
|
||
selectItem(itemId) {
|
||
const index = this.selectedItems.indexOf(itemId);
|
||
if (index === -1) {
|
||
// 添加到选中列表
|
||
this.selectedItems.push(itemId);
|
||
} else {
|
||
// 从选中列表移除
|
||
this.selectedItems.splice(index, 1);
|
||
}
|
||
// 更新全选状态
|
||
this.isAllSelected = this.selectedItems.length === this.goodsList.length;
|
||
|
||
// 打印选中的商品ID
|
||
console.log('当前选中的商品IDs:', this.selectedItems);
|
||
},
|
||
|
||
// 判断商品是否被选中
|
||
isItemSelected(itemId) {
|
||
return this.selectedItems.indexOf(itemId) !== -1;
|
||
},
|
||
|
||
// 切换全选/取消全选
|
||
toggleSelectAll() {
|
||
if (this.isAllSelected) {
|
||
// 取消全选
|
||
this.selectedItems = [];
|
||
} else {
|
||
// 全选
|
||
this.selectedItems = this.goodsList.map(item => item.id);
|
||
}
|
||
this.isAllSelected = !this.isAllSelected;
|
||
|
||
// 打印选中的商品ID
|
||
console.log('全选/取消全选后的商品IDs:', this.selectedItems);
|
||
},
|
||
|
||
// 批量删除
|
||
batchDelete() {
|
||
if (this.selectedItems.length === 0) {
|
||
return;
|
||
}
|
||
|
||
uni.showModal({
|
||
title: '确认删除',
|
||
content: `确定要删除选中的${this.selectedItems.length}个商品吗?`,
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 执行删除操作
|
||
console.log('执行批量删除:', this.selectedItems);
|
||
// TODO: 调用批量删除API
|
||
uni.showToast({
|
||
title: '删除操作待实现',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 批量编辑
|
||
batchEdit() {
|
||
if (this.selectedItems.length === 0) {
|
||
return;
|
||
}
|
||
|
||
// 加载一级货区数据
|
||
this.fetchWarehouses();
|
||
// 显示货区选择弹窗
|
||
this.showLocationModal = true;
|
||
},
|
||
|
||
// 获取一级货区列表
|
||
async fetchWarehouses() {
|
||
try {
|
||
this.warehouseLoading = true;
|
||
this.warehouseList = [];
|
||
this.shelfList = [];
|
||
this.freightList = [];
|
||
this.selectedWarehouse = '';
|
||
this.selectedShelf = '';
|
||
this.selectedFreight = '';
|
||
|
||
const [err, response] = await uni.request({
|
||
url: 'https://api.buzhiyushu.cn/shelves/shelves/namelist',
|
||
method: 'GET',
|
||
data: {
|
||
phoneNumber: uni.getStorageSync('phoneNumber')
|
||
}
|
||
});
|
||
|
||
this.warehouseLoading = false;
|
||
|
||
if (err) {
|
||
console.error('获取一级货区列表失败:', err);
|
||
uni.showToast({
|
||
title: '获取一级货区列表失败',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (response.statusCode === 200 && response.data && response.data.rows) {
|
||
this.warehouseList = response.data.rows;
|
||
console.log('一级货区列表:', this.warehouseList);
|
||
} else {
|
||
uni.showToast({
|
||
title: '暂无可用一级货区',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
this.warehouseLoading = false;
|
||
console.error('获取一级货区列表异常:', error);
|
||
uni.showToast({
|
||
title: '获取一级货区列表失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 获取二级货架数据
|
||
async fetchShelves(depotId) {
|
||
if (!depotId) {
|
||
this.shelfList = [];
|
||
this.freightList = [];
|
||
this.selectedShelf = '';
|
||
this.selectedFreight = '';
|
||
return;
|
||
}
|
||
|
||
try {
|
||
this.shelfLoading = true;
|
||
this.shelfList = [];
|
||
this.freightList = [];
|
||
this.selectedShelf = '';
|
||
this.selectedFreight = '';
|
||
|
||
const [err, response] = await uni.request({
|
||
url: 'https://api.buzhiyushu.cn/shelves/shelves/sheNamelist',
|
||
method: 'GET',
|
||
data: {
|
||
depotId: depotId
|
||
}
|
||
});
|
||
|
||
this.shelfLoading = false;
|
||
|
||
if (err) {
|
||
console.error('获取二级货架失败:', err);
|
||
uni.showToast({
|
||
title: '获取二级货架失败',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (response.statusCode === 200 && response.data && response.data.rows) {
|
||
this.shelfList = response.data.rows;
|
||
console.log('二级货架列表:', this.shelfList);
|
||
} else {
|
||
uni.showToast({
|
||
title: '暂无二级货架',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
this.shelfLoading = false;
|
||
console.error('获取二级货架失败:', error);
|
||
uni.showToast({
|
||
title: '获取二级货架失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 获取三级货架数据
|
||
async fetchFreights(sheId) {
|
||
if (!sheId) {
|
||
this.freightList = [];
|
||
this.selectedFreight = '';
|
||
return;
|
||
}
|
||
|
||
try {
|
||
this.freightLoading = true;
|
||
this.freightList = [];
|
||
this.selectedFreight = '';
|
||
|
||
const [err, response] = await uni.request({
|
||
url: 'https://api.buzhiyushu.cn/shelves/shelves/freNamelist',
|
||
method: 'GET',
|
||
data: {
|
||
sheId: sheId
|
||
}
|
||
});
|
||
|
||
this.freightLoading = false;
|
||
|
||
if (err) {
|
||
console.error('获取三级货架失败:', err);
|
||
uni.showToast({
|
||
title: '获取三级货架失败',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (response.statusCode === 200 && response.data && response.data.rows) {
|
||
this.freightList = response.data.rows;
|
||
console.log('三级货架列表:', this.freightList);
|
||
} else {
|
||
uni.showToast({
|
||
title: '暂无三级货架',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
this.freightLoading = false;
|
||
console.error('获取三级货架失败:', error);
|
||
uni.showToast({
|
||
title: '获取三级货架失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 一级货区选择改变
|
||
onWarehouseChange(e) {
|
||
const index = e.detail.value;
|
||
if (index >= 0 && this.warehouseList[index]) {
|
||
this.selectedWarehouse = this.warehouseList[index].id;
|
||
this.fetchShelves(this.selectedWarehouse);
|
||
} else {
|
||
this.selectedWarehouse = '';
|
||
this.shelfList = [];
|
||
this.freightList = [];
|
||
}
|
||
},
|
||
|
||
// 二级货架选择改变
|
||
onShelfChange(e) {
|
||
const index = e.detail.value;
|
||
if (index >= 0 && this.shelfList[index]) {
|
||
this.selectedShelf = this.shelfList[index].id;
|
||
this.fetchFreights(this.selectedShelf);
|
||
} else {
|
||
this.selectedShelf = '';
|
||
this.freightList = [];
|
||
}
|
||
},
|
||
|
||
// 三级货架选择改变
|
||
onFreightChange(e) {
|
||
const index = e.detail.value;
|
||
if (index >= 0 && this.freightList[index]) {
|
||
this.selectedFreight = this.freightList[index].id;
|
||
} else {
|
||
this.selectedFreight = '';
|
||
}
|
||
},
|
||
|
||
// 关闭货区选择弹窗
|
||
closeLocationModal() {
|
||
this.showLocationModal = false;
|
||
},
|
||
|
||
// 确认移动商品到新货区
|
||
async confirmMoveItems() {
|
||
if (!this.selectedWarehouse || !this.selectedShelf || !this.selectedFreight) {
|
||
uni.showToast({
|
||
title: '请选择完整的货区路径',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 获取选中的一级、二级、三级货区对象
|
||
const warehouse = this.warehouseList.find(item => item.id === this.selectedWarehouse);
|
||
const shelf = this.shelfList.find(item => item.id === this.selectedShelf);
|
||
const freight = this.freightList.find(item => item.id === this.selectedFreight);
|
||
|
||
if (!warehouse || !shelf || !freight) {
|
||
uni.showToast({
|
||
title: '获取货区信息失败',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 构建新的货区代码
|
||
const newLocationCode = `${warehouse.code || ''}${shelf.code || ''}${freight.code || ''}`;
|
||
console.log('新的货区代码:', newLocationCode);
|
||
|
||
// 打印将要移动的商品IDs
|
||
console.log('即将移动的商品IDs:', this.selectedItems);
|
||
|
||
// 确认对话框
|
||
uni.showModal({
|
||
title: '确认移动',
|
||
content: `确定要将选中的${this.selectedItems.length}个商品移动到 ${warehouse.name}-${shelf.name}-${freight.name} 吗?`,
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
try {
|
||
uni.showLoading({
|
||
title: '移动中...'
|
||
});
|
||
|
||
// 调用批量移动API
|
||
const [err, response] = await uni.request({
|
||
url: 'https://api.buzhiyushu.cn/zhishu/shopGoods/batchMoveItems',
|
||
method: 'POST',
|
||
header: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
data: {
|
||
itemIds: this.selectedItems.join(','),
|
||
warehouse: warehouse.code || '',
|
||
shelf: shelf.code || '',
|
||
freight: freight.code || '',
|
||
userId: this.userId
|
||
}
|
||
});
|
||
|
||
uni.hideLoading();
|
||
|
||
if (err) {
|
||
console.error('API调用失败:', err);
|
||
uni.showToast({
|
||
title: 'API调用失败: ' + (err.errMsg || '网络错误'),
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (response.statusCode === 200) {
|
||
// API调用成功
|
||
console.log('API响应:', response.data);
|
||
|
||
// 关闭弹窗
|
||
this.showLocationModal = false;
|
||
|
||
// 退出批量模式
|
||
this.isBatchMode = false;
|
||
this.selectedItems = [];
|
||
|
||
// 刷新数据
|
||
this.pageNum = 1;
|
||
this.fetchGoodsData();
|
||
|
||
uni.showToast({
|
||
title: '移动成功',
|
||
icon: 'success'
|
||
});
|
||
} else {
|
||
console.error('API返回错误状态码:', response.statusCode, response.data);
|
||
uni.showToast({
|
||
title: 'API调用失败: ' + (response.data?.message || '服务器错误'),
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
}
|
||
} catch (error) {
|
||
uni.hideLoading();
|
||
console.error('批量移动商品失败:', error);
|
||
uni.showToast({
|
||
title: '批量移动失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 日期选择器确认事件
|
||
onDatePickerConfirm(e) {
|
||
this.dateInput = e.detail.value;
|
||
console.log("获取日期", this.dateInput);
|
||
const [year, month, day] = this.dateInput.split('-');
|
||
this.displayDate = { day, month, year };
|
||
|
||
// 重置分页
|
||
this.pageNum = 1;
|
||
this.hasMore = true;
|
||
|
||
// 重新加载数据
|
||
this.fetchGoodsData();
|
||
},
|
||
|
||
// 重置日期筛选
|
||
resetDateFilter() {
|
||
const now = new Date();
|
||
this.displayDate = {
|
||
day: now.getDate().toString().padStart(2, '0'),
|
||
month: (now.getMonth() + 1).toString().padStart(2, '0'),
|
||
year: now.getFullYear()
|
||
};
|
||
this.dateInput = '';
|
||
|
||
// 重置分页
|
||
this.pageNum = 1;
|
||
this.hasMore = true;
|
||
|
||
// 重新加载数据
|
||
this.fetchGoodsData();
|
||
},
|
||
|
||
// 获取商品数据
|
||
async fetchGoodsData() {
|
||
if (!this.locationCode || !this.userId) {
|
||
uni.showToast({
|
||
title: '参数不完整',
|
||
icon: 'none'
|
||
});
|
||
this.loading = false;
|
||
return;
|
||
}
|
||
|
||
if (this.pageNum === 1) {
|
||
this.loading = true;
|
||
} else {
|
||
this.isLoadingMore = true;
|
||
}
|
||
|
||
try {
|
||
const [err, res] = await uni.request({
|
||
// url: `${config.baseURL}/zhishu/shopGoods/getGoodsData`,
|
||
url: 'https://api.buzhiyushu.cn/zhishu/shopGoods/getGoodsData',
|
||
method: 'GET',
|
||
header: {
|
||
'Content-Type': 'application/json',
|
||
'cientid': config.clientId,
|
||
'isToken': 'false',
|
||
'isEncrypt': 'false',
|
||
'repeatSubmit': 'false'
|
||
},
|
||
data: {
|
||
code: this.locationCode,
|
||
userId: this.userId,
|
||
pageNum: this.pageNum,
|
||
pageSize: this.pageSize,
|
||
date: this.dateInput // 添加日期参数
|
||
}
|
||
});
|
||
|
||
this.loading = false;
|
||
this.isLoadingMore = false;
|
||
|
||
if (err) {
|
||
console.error('获取商品数据失败:', err);
|
||
uni.showToast({
|
||
title: '获取商品数据失败',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
console.log('商品数据响应:', res);
|
||
|
||
// 检查响应数据结构
|
||
if (res.statusCode === 200 && res.data) {
|
||
// 获取商品数据列表,适应不同的数据结构
|
||
let goodsList = [];
|
||
let total = 0;
|
||
|
||
// 根据实际响应格式获取数据
|
||
// data.data.rows结构 (根据实际响应格式)
|
||
if (res.data.data && res.data.data.rows && Array.isArray(res.data.data.rows)) {
|
||
goodsList = res.data.data.rows;
|
||
total = res.data.data.total || goodsList.length;
|
||
}
|
||
// 检查res.data.data是否存在且是数组
|
||
else if (res.data.data && Array.isArray(res.data.data)) {
|
||
goodsList = res.data.data;
|
||
total = res.data.total || goodsList.length;
|
||
}
|
||
// 检查res.data.rows是否存在且是数组
|
||
else if (res.data.rows && Array.isArray(res.data.rows)) {
|
||
goodsList = res.data.rows;
|
||
total = res.data.total || goodsList.length;
|
||
}
|
||
// 检查res.data本身是否为数组
|
||
else if (Array.isArray(res.data)) {
|
||
goodsList = res.data;
|
||
total = goodsList.length;
|
||
}
|
||
// 其他可能的数据结构
|
||
else if (typeof res.data === 'object') {
|
||
// 尝试找到可能的数据数组
|
||
for (const key in res.data) {
|
||
if (Array.isArray(res.data[key])) {
|
||
goodsList = res.data[key];
|
||
break;
|
||
}
|
||
}
|
||
total = goodsList.length;
|
||
}
|
||
|
||
console.log('提取的商品列表:', goodsList);
|
||
console.log('总数:', total);
|
||
|
||
if (goodsList.length > 0) {
|
||
// 处理商品数据,添加必要的字段
|
||
const formattedGoods = goodsList.map(item => {
|
||
return {
|
||
...item,
|
||
image: item.image || item.bookPic || '/static/default-book.png',
|
||
images: item.bookPic ? [item.bookPic] : [item.image || '/static/default-book.png'],
|
||
name: item.goodsName || item.bookName || item.name || '未知商品',
|
||
barcode: item.isbn || item.barcode || '无ISBN',
|
||
createTime: item.createTime ? item.createTime.substring(0, 10) : '',
|
||
price: item.price || 0,
|
||
inventory: item.inventory || item.stock || 0,
|
||
condition: this.formatCondition(item.conditionCode) || item.condition || item.qualityText || '未知',
|
||
pddPublishedStatus: item.pddPublishedStatus || 0,
|
||
kfzPublishedStatus: item.kfzPublishedStatus || 0
|
||
};
|
||
});
|
||
|
||
if (this.pageNum === 1) {
|
||
this.goodsList = formattedGoods;
|
||
} else {
|
||
this.goodsList = [...this.goodsList, ...formattedGoods];
|
||
}
|
||
|
||
this.originalData = [...this.goodsList]; // 保存原始数据
|
||
|
||
// 计算总页数和是否有更多数据
|
||
this.total = total; // 更新总数
|
||
this.totalPages = Math.ceil(total / this.pageSize);
|
||
this.hasMore = this.goodsList.length < total;
|
||
|
||
// 清空选择
|
||
if (this.isBatchMode) {
|
||
this.selectedItems = [];
|
||
this.isAllSelected = false;
|
||
}
|
||
} else {
|
||
if (this.pageNum === 1) {
|
||
this.goodsList = [];
|
||
this.originalData = [];
|
||
}
|
||
this.totalPages = 1;
|
||
this.total = 0;
|
||
this.hasMore = false;
|
||
console.log('未找到商品数据');
|
||
}
|
||
} else {
|
||
if (this.pageNum === 1) {
|
||
this.goodsList = [];
|
||
this.originalData = [];
|
||
}
|
||
this.totalPages = 1;
|
||
this.total = 0;
|
||
this.hasMore = false;
|
||
console.log('接口返回错误状态码或数据格式不正确:', res.statusCode);
|
||
|
||
// 显示错误信息
|
||
uni.showToast({
|
||
title: '获取数据失败: ' + (res.data && res.data.message ? res.data.message : '未知错误'),
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
this.loading = false;
|
||
this.isLoadingMore = false;
|
||
console.error('获取商品数据异常:', error);
|
||
|
||
// 在控制台打印更详细的错误信息
|
||
if (error && error.stack) {
|
||
console.error('错误堆栈:', error.stack);
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '获取商品数据失败: ' + (error.message || '未知错误'),
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 加载更多数据
|
||
loadMore() {
|
||
if (!this.hasMore || this.loading || this.isLoadingMore) return;
|
||
|
||
this.pageNum++;
|
||
this.fetchGoodsData();
|
||
},
|
||
|
||
// 格式化价格
|
||
formatPrice(price) {
|
||
if (!price && price !== 0) return '0.00';
|
||
// 价格可能是以分为单位存储的,需要转换为元
|
||
const priceInYuan = parseFloat(price) / 100;
|
||
return priceInYuan.toFixed(2);
|
||
},
|
||
|
||
// 处理图片加载错误
|
||
handleImageError(e) {
|
||
// 使用默认图片替代
|
||
e.target.src = '/static/default-book.png';
|
||
},
|
||
|
||
// 将品相代码转换为对应的文本
|
||
formatCondition(conditionCode) {
|
||
if (!conditionCode) return '未知品相';
|
||
|
||
switch(conditionCode) {
|
||
case 'A': return '一品';
|
||
case 'B': return '二品';
|
||
case 'C': return '三品';
|
||
case 'D': return '四品';
|
||
case 'E': return '五品';
|
||
case 'F': return '六品';
|
||
case 'G': return '六五品';
|
||
case 'H': return '七品';
|
||
case 'I': return '七五品';
|
||
case 'J': return '八品';
|
||
case 'K': return '八五品';
|
||
case 'L': return '九品';
|
||
case 'M': return '九五品';
|
||
case 'N': return '全新';
|
||
default: return conditionCode;
|
||
}
|
||
},
|
||
|
||
// 预览图片
|
||
previewImage(images) {
|
||
if (!images || !images.length) return;
|
||
|
||
// 显示图片预览
|
||
uni.previewImage({
|
||
urls: images,
|
||
longPressActions: {
|
||
itemList: ['发送给朋友', '保存图片', '收藏'],
|
||
success: function(data) {
|
||
console.log('选中了第' + (data.tapIndex + 1) + '个按钮')
|
||
},
|
||
fail: function(err) {
|
||
console.log(err.errMsg)
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
// 搜索商品
|
||
searchGoods() {
|
||
if (!this.searchKeyword.trim()) {
|
||
// 如果搜索关键词为空,恢复原始数据
|
||
this.goodsList = [...this.originalData];
|
||
return;
|
||
}
|
||
|
||
// 在原始数据中过滤符合条件的商品
|
||
const keyword = this.searchKeyword.toLowerCase();
|
||
this.goodsList = this.originalData.filter(goods => {
|
||
return (
|
||
(goods.name && goods.name.toLowerCase().includes(keyword)) ||
|
||
(goods.barcode && goods.barcode.toLowerCase().includes(keyword))
|
||
);
|
||
});
|
||
},
|
||
|
||
// 获取一级货区名称
|
||
getWarehouseName(id) {
|
||
if (!id) return '请选择';
|
||
const item = this.warehouseList.find(item => item.id === id);
|
||
return item ? item.name : '请选择';
|
||
},
|
||
|
||
// 获取二级货架名称
|
||
getShelfName(id) {
|
||
if (!id) return '请选择';
|
||
const item = this.shelfList.find(item => item.id === id);
|
||
return item ? item.name : '请选择';
|
||
},
|
||
|
||
// 获取三级货架名称
|
||
getFreightName(id) {
|
||
if (!id) return '请选择';
|
||
const item = this.freightList.find(item => item.id === id);
|
||
return item ? item.name : '请选择';
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.container {
|
||
padding: 30rpx;
|
||
background-color: #f8f8f8;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.header {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.title-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.title {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.subtitle {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
/* 日期选择器样式 */
|
||
.date-picker-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: #fff;
|
||
padding: 24rpx 20rpx 0 20rpx;
|
||
margin-bottom: 10rpx;
|
||
border-radius: 12rpx;
|
||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.date-left {
|
||
display: flex;
|
||
align-items: baseline;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.date-day {
|
||
font-size: 64rpx;
|
||
font-weight: bold;
|
||
color: #222;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.date-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.date-arrow {
|
||
font-size: 24rpx;
|
||
color: #bbb;
|
||
margin-left: 8rpx;
|
||
}
|
||
|
||
.date-total {
|
||
font-size: 28rpx;
|
||
color: #007AFF;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 批量操作栏样式 */
|
||
.batch-action-bar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
background: #fff;
|
||
padding: 16rpx 20rpx;
|
||
margin-bottom: 20rpx;
|
||
border-radius: 12rpx;
|
||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.batch-btn {
|
||
padding: 8rpx 20rpx;
|
||
background-color: #007AFF;
|
||
color: #fff;
|
||
border-radius: 6rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.action-btns {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.action-btn {
|
||
padding: 8rpx 20rpx;
|
||
margin-right: 10rpx;
|
||
background-color: #f56c6c;
|
||
color: #fff;
|
||
border-radius: 6rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.action-btn:last-child {
|
||
margin-right: 0;
|
||
}
|
||
|
||
.action-btn.disabled {
|
||
background-color: #ccc;
|
||
color: #fff;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.select-all-btn {
|
||
padding: 8rpx 20rpx;
|
||
background-color: #4CAF50;
|
||
color: #fff;
|
||
border-radius: 6rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.selected-count {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
}
|
||
|
||
/* 选择框样式 */
|
||
.select-box {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-right: 10rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: absolute;
|
||
top: 10rpx;
|
||
left: 10rpx;
|
||
z-index: 2;
|
||
}
|
||
|
||
.select-circle {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
border-radius: 50%;
|
||
border: 2rpx solid #ccc;
|
||
background-color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.select-circle.selected {
|
||
border-color: #007AFF;
|
||
background-color: #007AFF;
|
||
}
|
||
|
||
.check-mark {
|
||
width: 20rpx;
|
||
height: 10rpx;
|
||
border-left: 2rpx solid #fff;
|
||
border-bottom: 2rpx solid #fff;
|
||
transform: rotate(-45deg);
|
||
}
|
||
|
||
.search-box {
|
||
display: flex;
|
||
margin-bottom: 30rpx;
|
||
background: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 20rpx;
|
||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.search-input-wrap {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
background-color: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
padding: 0 20rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.search-input {
|
||
flex: 1;
|
||
height: 70rpx;
|
||
font-size: 28rpx;
|
||
padding-left: 20rpx;
|
||
}
|
||
|
||
.search-btn {
|
||
width: 120rpx;
|
||
height: 70rpx;
|
||
line-height: 70rpx;
|
||
font-size: 28rpx;
|
||
text-align: center;
|
||
background-color: #007AFF;
|
||
color: #fff;
|
||
border-radius: 8rpx;
|
||
padding: 0;
|
||
}
|
||
|
||
/* 加载状态样式 */
|
||
.loading-state {
|
||
text-align: center;
|
||
padding: 40rpx 0;
|
||
color: #999;
|
||
}
|
||
|
||
/* 图片网格样式 */
|
||
.image-grid {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
padding: 12rpx;
|
||
}
|
||
|
||
.image-item {
|
||
width: 100%;
|
||
margin-bottom: 12rpx;
|
||
background: #fff;
|
||
border-radius: 8rpx;
|
||
overflow: hidden;
|
||
box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.08);
|
||
display: flex;
|
||
position: relative; /* 添加相对定位 */
|
||
padding-left: 10rpx; /* 为选择框留出空间 */
|
||
}
|
||
|
||
.image-item:nth-child(2n) {
|
||
margin-right: 0;
|
||
}
|
||
|
||
.book-image {
|
||
width: 180rpx;
|
||
height: 180rpx;
|
||
object-fit: cover;
|
||
flex-shrink: 0; /* 防止图片被压缩 */
|
||
}
|
||
|
||
.image-info {
|
||
padding: 10rpx 12rpx;
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-width: 0; /* 确保flex子元素可以正确缩小 */
|
||
overflow: hidden; /* 防止内容溢出 */
|
||
}
|
||
|
||
.book-name {
|
||
font-size: 24rpx;
|
||
color: #333;
|
||
display: block;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-weight: bold;
|
||
margin-bottom: 4rpx;
|
||
width: 100%; /* 确保宽度占满父容器 */
|
||
}
|
||
|
||
.book-details {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-top: 3rpx;
|
||
}
|
||
|
||
.book-isbn, .book-price, .book-condition, .upload-time, .book-artno {
|
||
font-size: 20rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.book-price {
|
||
color: #ff6b00;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.book-condition {
|
||
color: #007AFF;
|
||
}
|
||
|
||
.upload-time {
|
||
color: #999;
|
||
}
|
||
|
||
.book-artno, .book-item-number {
|
||
color: #999;
|
||
font-size: 20rpx;
|
||
}
|
||
|
||
.book-stock {
|
||
color: #4CAF50;
|
||
font-size: 20rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 空状态样式 */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 60rpx 0;
|
||
}
|
||
|
||
.empty-image {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.status-value.published {
|
||
color: #007aff;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.status-value.unpublished {
|
||
color: #ff4d4f;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
/* 添加新样式 */
|
||
.loading-more, .no-more {
|
||
text-align: center;
|
||
padding: 20rpx 0;
|
||
color: #999;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.no-more {
|
||
color: #666;
|
||
}
|
||
|
||
/* 货区选择弹窗样式 */
|
||
.modal-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 999;
|
||
}
|
||
|
||
.modal-content {
|
||
width: 80%;
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
max-height: 80vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #eee;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.modal-close {
|
||
font-size: 40rpx;
|
||
color: #999;
|
||
padding: 0 10rpx;
|
||
}
|
||
|
||
.modal-body {
|
||
padding: 30rpx;
|
||
max-height: 60vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.modal-footer {
|
||
display: flex;
|
||
border-top: 1rpx solid #eee;
|
||
}
|
||
|
||
.modal-btn {
|
||
flex: 1;
|
||
height: 90rpx;
|
||
line-height: 90rpx;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.cancel-btn {
|
||
background-color: #f5f5f5;
|
||
color: #333;
|
||
}
|
||
|
||
.confirm-btn {
|
||
background-color: #007AFF;
|
||
color: #fff;
|
||
}
|
||
|
||
/* 货区选择样式 */
|
||
.location-select-item {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.location-label {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.location-picker-wrap {
|
||
position: relative;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 8rpx;
|
||
height: 80rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.picker-text {
|
||
width: 100%;
|
||
height: 100%;
|
||
padding: 0 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.picker-text.disabled {
|
||
color: #999;
|
||
}
|
||
|
||
.picker-arrow {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.loading-indicator {
|
||
position: absolute;
|
||
right: 20rpx;
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
</style> |