ry_app/pages/expired/expired.vue

858 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="container">
<!-- 顶部状态栏/时间 -->
<view class="status-bar">
<text class="time">9:41</text>
</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>
<!-- 筛选标签 -->
<view class="filter-tabs">
<scroll-view class="tabs-scroll" scroll-x="true">
<view
class="tab-item"
:class="{ active: currentTab === 'all' }"
@tap="switchTab('all')"
>
全部
</view>
<view
class="tab-item"
:class="{ active: currentTab === 'expiring' }"
@tap="navigateToExpiredPage"
>
临期/过期<text class="badge">0</text>
</view>
<view
class="tab-item"
:class="{ active: currentTab === 'outstock' }"
@tap="switchTab('outstock')"
>
缺货<text class="badge">0</text>
</view>
<view class="tab-item filter-btn" @tap="showFilter = !showFilter">
<text>筛选</text>
<uni-icons type="arrowdown" size="14" color="#666"></uni-icons>
</view>
</scroll-view>
</view>
<!-- 微店状态栏 -->
<view class="store-status">
<view class="status-left-content">
<!-- 快速处理卡片 -->
<view class="dui">
<image class="dui-img" src="http://193.112.94.36:8099/static/images/Mask group.png"></image>
</view>
<view class="status-left">
<text class="status-text">快速处理</text>
<text class="status-num">临期/过期食品</text>
</view>
</view>
<view class="status-right-buttons">
<!-- 临期促销按钮 -->
<view class="quick-btn pink-btn" @tap="goToPromotion">
<text class="btn-text">临期促销</text>
<uni-icons type="arrowright" size="12" color="#fff"></uni-icons>
</view>
<!-- 过期出库按钮 -->
<view class="quick-btn pink-btn" @tap="goToExpiredOut">
<text class="btn-text">过期出库</text>
<uni-icons type="arrowright" size="12" color="#fff"></uni-icons>
</view>
</view>
</view>
<!-- 商品列表 -->
<scroll-view class="goods-list" scroll-y="true">
<view class="goods-item" v-for="item in goodsList" :key="item.id">
<view class="goods-more-icon" @tap="toggleDeleteMenu(item)">
<uni-icons type="more-filled" size="18"></uni-icons>
</view>
<view class="goods-delete-menu" v-if="item.showDeleteMenu" @tap="showDeleteConfirm(item)">
<text class="delete-menu-text">删除商品</text>
</view>
<view class="goods-top" @tap="goToStockDetail(item)">
<view class="goods-tou">
<image :src="item.mainImage ? 'http://193.112.94.36:8081' + item.mainImage : '/static/687b6f95b14eff60f4b77147b3726ab2.jpg'"></image>
</view>
<view class="goods-info">
<text class="goods-name">{{ item.productName }}</text>
<text class="goods-barcode">{{ item.productBarCode }}</text>
<text class="goods-price">¥{{ item.storePrice ? item.storePrice.toFixed(2) : '0.00' }}</text>
</view>
</view>
<view class="goods-divider"></view>
<view class="goods-stock" >
<text class="stock-label">总库存</text>
<text class="stock-num">{{ item.stockQuantity }} 件</text>
<text class="stock-arrow">></text>
</view>
<!-- <view class="goods-actions">
<view class="action-btn add-btn" @tap="addGoodsStock(item)">
<text>添加商品/库存</text>
</view>
</view> -->
</view>
</scroll-view>
<!-- 底部操作按钮 -->
<view class="bottom-actions">
<view class="action-btn more-btn" @tap="showMoreActions(item)">
<text>更多</text>
</view>
<button class="action-button primary" @tap="addNewGoods">
添加商品/库存
</button>
<!-- <button class="action-button" @tap="batchOperation">
批量操作
</button> -->
</view>
<!-- 更多操作弹窗 -->
<uni-popup ref="popup" type="bottom">
<view class="popup-content">
<view class="popup-item" @tap="goToInventoryCount">
<uni-icons type="scan" size="20" color="#333"></uni-icons>
<text>盘点库存</text>
</view>
<view class="popup-item" @tap="goToOutbound">
<uni-icons type="arrowright" size="20" color="#333"></uni-icons>
<text>出库</text>
</view>
<view class="popup-item" @tap="batchDeleteGoods">
<uni-icons type="trash" size="20" color="#333"></uni-icons>
<text>批量删除商品</text>
</view>
<view class="popup-item" @tap="goToCategoryManagement">
<uni-icons type="apps" size="20" color="#333"></uni-icons>
<text>分类管理</text>
</view>
<view class="popup-item" @tap="goToBrandManagement">
<uni-icons type="navigate" size="20" color="#333"></uni-icons>
<text>品牌管理</text>
</view>
<view class="popup-item" @tap="goToBarcodeSettings">
<uni-icons type="settings" size="20" color="#333"></uni-icons>
<text>条码规则设置</text>
</view>
<view class="popup-item cancel" @tap="$refs.popup.close()">
<text>取消</text>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { getProductList as fetchProductList, deleteProduct } from '@/api/product'
import { getToken, getStoreId } from '@/utils/auth'
export default {
data() {
return {
currentTab: 'expiring',
searchText: '',
showFilter: false,
selectedGoods: null,
storeId: null, // 门店ID
goodsList: [
{
id: null,
productName: '',
productBarCode: '',
storePrice: 0.00,
stockQuantity: 0,
}
]
}
},
onLoad() {
// 获取门店ID
const storeId = getStoreId();
if (storeId) {
this.storeId = storeId;
console.log('当前门店ID:', storeId);
} else {
uni.showToast({
title: '请先选择门店',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
return;
}
this.getProductList();
},
onShow() {
this.getProductList();
},
methods: {
async getProductList(searchParams = {}) {
try {
const token = getToken();
console.log('当前Token:', token);
console.log('Token是否存在:', !!token);
console.log('查询参数:', searchParams);
// 添加门店ID参数
if (this.storeId) {
searchParams.storeId = this.storeId;
}
const res = await fetchProductList(searchParams);
console.log('商品列表接口返回:', res);
if (res && res.code === 200 && res.data) {
this.goodsList = res.data.map(item => ({
...item,
showDeleteMenu: false
}));
console.log('处理后的商品列表:', this.goodsList);
} else {
uni.showToast({
title: res?.msg || '获取商品列表失败',
icon: 'none'
});
}
} catch (error) {
console.error('获取商品列表失败:', error);
console.error('错误详情:', JSON.stringify(error));
uni.showToast({
title: '网络请求失败',
icon: 'none'
});
}
},
switchTab(tab) {
if (tab === 'all') {
// 跳转到商品列表页面,并传递当前标签
uni.navigateTo({
url: `/pages/product/product?tab=${tab}`
});
} else if (tab === 'outstock') {
// 跳转到缺货页面
uni.navigateTo({
url: `/pages/navailable/navailable?tab=${tab}`
});
} else {
this.currentTab = tab;
// 这里可以添加筛选逻辑
console.log('切换到标签:', tab);
}
},
onSearch() {
console.log('搜索关键词:', this.searchText);
if (!this.searchText || this.searchText.trim() === '') {
this.getProductList();
return;
}
const searchText = this.searchText.trim();
let searchParams = {};
if (/^\d+$/.test(searchText)) {
searchParams = { productName: searchText };
console.log('商品名称模糊查询:', searchParams);
} else {
searchParams = { productBarCode: searchText };
console.log('按条形码精准查询按:', searchParams);
}
this.getProductList(searchParams);
},
goToSettings() {
uni.navigateTo({
url: '/pages/settings/index'
});
},
showMoreActions(goods) {
this.selectedGoods = goods;
this.$refs.popup.open();
},
addGoodsStock(goods) {
console.log('添加商品库存:', goods);
uni.showModal({
title: '添加库存',
content: `${goods.name} 添加库存`,
success: (res) => {
if (res.confirm) {
// 执行添加库存操作
}
}
});
},
goToStockDetail(item) {
// 跳转到编辑页面传递商品ID
uni.navigateTo({
url: `/pages/edit/edit?id=${item.id}`
});
},
toggleDeleteMenu(item) {
item.showDeleteMenu = !item.showDeleteMenu;
},
showDeleteConfirm(item) {
uni.showModal({
title: '确认删除',
content: `确定要删除商品"${item.productName}"吗?`,
success: async (res) => {
if (res.confirm) {
try {
const result = await deleteProduct(item.id);
console.log('删除商品结果:', result);
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'
});
}
}
}
});
},
addNewGoods() {
uni.navigateTo({
url: '/pages/enter/enter'
// url: '/pages/addProduct/addProduct'
});
},
// 临期/过期商品页面,不需要跳转
navigateToExpiredPage() {
console.log('当前已是临期/过期商品页面');
},
batchOperation() {
uni.showActionSheet({
itemList: ['批量修改价格', '批量修改库存', '批量下架'],
success: (res) => {
console.log('选择了操作:', res.tapIndex);
}
});
},
editGoods(goods) {
this.$refs.popup.close();
uni.navigateTo({
url: `/pages/goods/edit?id=${goods.id}`
});
},
adjustStock(goods) {
this.$refs.popup.close();
uni.showModal({
title: '调整库存',
content: `调整 ${goods.name} 的库存数量`,
editable: true,
placeholderText: '请输入调整数量',
success: (res) => {
if (res.confirm && res.content) {
console.log('调整库存数量:', res.content);
}
}
});
},
deleteGoods(goods) {
this.$refs.popup.close();
uni.showModal({
title: '确认删除',
content: `确定要删除商品"${goods.name}"吗?`,
success: (res) => {
if (res.confirm) {
console.log('删除商品:', goods);
uni.showToast({
title: '删除成功',
icon: 'success'
});
}
}
});
},
// 批量删除商品
batchDeleteGoods() {
this.$refs.popup.close();
uni.navigateTo({
url: '/pages/batchDeleteProduct/batchDeleteProduct'
});
},
// 分类管理
goToCategoryManagement() {
this.$refs.popup.close();
uni.navigateTo({
url: '/pages/category/category'
});
},
// 品牌管理
goToBrandManagement() {
this.$refs.popup.close();
uni.navigateTo({
url: '/pages/addBrand/addBrand'
});
},
// 条码规则设置
goToBarcodeSettings() {
this.$refs.popup.close();
uni.navigateTo({
url: '/pages/barcodeSettings/barcodeSettings'
});
},
// 盘点库存
goToInventoryCount() {
this.$refs.popup.close();
uni.navigateTo({
url: '/pages/inventoryCount/inventoryCount'
});
},
// 出库
goToOutbound() {
this.$refs.popup.close();
uni.navigateTo({
url: '/pages/outbound/outbound'
});
}
}
}
</script>
<style scoped>
.container {
background-color: #f5f5f5;
min-height: 100vh;
}
.goods-tou{
width: 100rpx;
height: 100rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.goods-tou image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
/* 状态栏 */
.status-bar {
padding: 10px 16px;
background-color: #fff;
}
.time {
font-size: 16px;
font-weight: 600;
}
/* 快速操作整行容器 */
.quick-actions-bar {
display: flex;
align-items: center;
background: #fff;
padding: 12rpx 16rpx;
margin: 16rpx;
border-radius: 12rpx;
gap: 12rpx;
}
/* 快速处理卡片 */
.quick-card {
display: flex;
align-items: center;
background: #ff4d4f;
padding: 12rpx 20rpx;
border-radius: 30rpx;
color: #fff;
flex-shrink: 0;
}
.card-icon {
margin-right: 8rpx;
}
.icon-img {
width: 24rpx;
height: 24rpx;
}
.card-text {
display: flex;
flex-direction: column;
}
.main-text {
font-size: 26rpx;
font-weight: 500;
line-height: 1.2;
}
.sub-text {
font-size: 20rpx;
opacity: 0.9;
line-height: 1.2;
}
/* 搜索栏 */
.search-bar {
padding: 12px 16px;
background-color: #fff;
}
.search-input {
display: flex;
align-items: center;
background-color: #f5f5f5;
border-radius: 8px;
padding: 10px 12px;
}
.search-input input {
flex: 1;
margin-left: 8px;
font-size: 14px;
}
.placeholder {
color: #999;
}
/* 筛选标签 */
.filter-tabs {
background-color: #fff;
padding: 12px 16px;
border-bottom: 1px solid #eee;
}
.tabs-scroll {
white-space: nowrap;
}
.tab-item {
display: inline-block;
padding: 6px 12px;
margin-right: 10px;
border-radius: 16px;
font-size: 14px;
background-color: #f5f5f5;
color: #666;
}
.tab-item.active {
background-color: #e8f4ff;
color: #007aff;
}
.badge {
margin-left: 4px;
color: #ff4444;
}
.filter-btn {
display: inline-flex;
align-items: center;
}
/* 微店状态栏 */
.store-status {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background-color: #fff;
border-radius: 20rpx;
margin-top: 8px;
border-bottom: 1px solid #eee;
}
.status-left-content {
display: flex;
align-items: center;
}
.status-right-buttons {
display: flex;
align-items: center;
gap: 12rpx;
}
.dui {
margin-right: 12rpx;
}
.dui-img {
width: 24rpx;
height: 24rpx;
}
.status-left {
display: flex;
flex-direction: column;
margin-left: 0;
}
.status-text {
font-size: 14px;
color: #333;
}
.status-num {
font-size: 12px;
color: #666;
margin-top: 4px;
}
.status-right {
display: flex;
align-items: center;
margin-right: 1rpx;
}
.set-text {
font-size: 14px;
color: #666;
margin-right: 4px;
}
/* 右侧粉色按钮通用样式 */
.quick-btn {
display: flex;
align-items: center;
background: red;
padding: 8rpx 16rpx;
border-radius: 20rpx;
color: white;
font-size: 22rpx;
gap: 4rpx;
flex-shrink: 0;
}
.btn-text {
font-size: 22rpx;
}
/* 商品列表 */
.goods-list {
height: calc(100vh - 320px);
padding: 16px;
}
.goods-item {
background-color: #fff;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
position: relative;
}
.goods-more-icon {
position: absolute;
top: 12px;
right: 12px;
z-index: 10;
}
.goods-delete-menu {
position: absolute;
top: 40px;
right: 12px;
background-color: #fff;
border-radius: 8rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
padding: 12rpx 24rpx;
z-index: 9;
}
.delete-menu-text {
font-size: 28rpx;
color: #ff4444;
}
.goods-top {
display: flex;
align-items: flex-start;
margin-bottom: 12px;
}
.goods-info {
flex: 1;
margin-bottom: 0;
}
.goods-name {
display: block;
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 6px;
}
.goods-barcode {
font-size: 12px;
color: #999;
display: block;
margin-bottom: 8px;
}
.goods-price {
font-size: 18px;
color: #ff4444;
font-weight: 600;
}
.goods-divider {
height: 1px;
border-bottom: 1px dashed #e0e0e0;
margin-bottom: 12px;
}
.goods-stock {
display: flex;
align-items: center;
padding: 8px 0;
margin-bottom: 4px;
}
.stock-arrow {
font-size: 20px;
color: #999;
margin-left: auto;
}
.stock-label {
font-size: 14px;
color: #666;
}
.stock-num {
font-size: 16px;
color: #333;
font-weight: 500;
}
.goods-actions {
display: flex;
justify-content: space-between;
}
.action-btn {
padding: 8px 16px;
border-radius: 6px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
}
.more-btn {
background-color: #f5f5f5;
color: #666;
}
.add-btn {
background-color: #e8f4ff;
color: #007aff;
}
/* 底部操作按钮 */
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
padding: 16px;
background-color: #fff;
border-top: 1px solid #eee;
}
.action-button {
flex: 1;
margin: 0 8px;
padding: 12px;
border-radius: 8px;
font-size: 16px;
background-color: #f5f5f5;
color: #333;
border: none;
}
.action-button.primary {
background-color: #007aff;
color: #fff;
}
/* 弹窗样式 */
.popup-content {
background-color: #fff;
border-radius: 16px 16px 0 0;
padding: 20px;
}
.popup-item {
display: flex;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid #f5f5f5;
font-size: 16px;
}
.popup-item:last-child {
border-bottom: none;
}
.popup-item text {
margin-left: 12px;
}
.popup-item.cancel {
justify-content: center;
color: #666;
}
</style>