ry_app/pages/addProduct/addProduct.vue

467 lines
16 KiB
Vue

<template>
<view class="add-product-page">
<!-- 头部 -->
<view class="page-header">
<text class="header-title">添加商品</text>
</view>
<!-- 表单区域 -->
<view class="form-container">
<!-- 商品名称 -->
<view class="form-item">
<text class="item-label">商品名称</text>
<input
class="item-input"
type="text"
placeholder="农夫山泉东方树叶乌龙茶500ml"
v-model="productInfo.name"
/>
</view>
<!-- 条码/条码扫码 -->
<view class="form-item">
<text class="item-label">条码</text>
<view class="barcode-section">
<input
class="item-input barcode-input"
type="text"
placeholder="6921168558032"
v-model="productInfo.barcode"
/>
<view class="scan-btn" @tap="handleScan">
<text class="scan-text">扫码</text>
</view>
</view>
</view>
<!-- 商品图 -->
<view class="form-item">
<text class="item-label">商品图</text>
<view class="image-upload-section">
<view class="upload-placeholder" @tap="chooseImage">
<text class="upload-icon">+</text>
<text class="upload-text">点击上传商品图片</text>
</view>
<image
v-if="productInfo.image"
:src="productInfo.image"
class="product-image"
mode="aspectFit"
></image>
</view>
</view>
<view class="divider"></view>
<!-- 售价 -->
<view class="form-item">
<text class="item-label">售价</text>
<view class="price-section">
<input
class="item-input price-input"
type="digit"
placeholder="5.0"
v-model="productInfo.price"
/>
<text class="price-unit">元</text>
</view>
</view>
<!-- 推荐价格 -->
<view class="recommend-price-section">
<text class="recommend-title">推荐价格(点击快速设置售价)</text>
<view class="recommend-list">
<view class="recommend-item" @tap="setPrice(5.0)">
<text class="recommend-percent">82%商家卖</text>
<text class="recommend-price">5.0元</text>
</view>
<view class="recommend-item" @tap="setPrice(5.5)">
<text class="recommend-percent">9%商家卖</text>
<text class="recommend-price">5.5元</text>
</view>
<view class="recommend-item" @tap="setPrice(4.5)">
<text class="recommend-percent">2%商家卖</text>
<text class="recommend-price">4.5元</text>
</view>
</view>
</view>
<view class="divider"></view>
<!-- 进货数量 -->
<view class="form-item">
<text class="item-label">进货数量</text>
<view class="quantity-section">
<input
class="item-input"
type="number"
placeholder="请输入进货数量"
v-model="productInfo.quantity"
/>
<text class="quantity-unit">件</text>
</view>
</view>
<!-- 进货价 -->
<view class="form-item">
<text class="item-label">进货价</text>
<view class="cost-section">
<input
class="item-input"
type="digit"
placeholder="请输入进货价"
v-model="productInfo.cost"
/>
<text class="cost-unit">元</text>
</view>
</view>
<!-- ✅ 保质期管理 - 红色滑动开关 完美匹配截图 -->
<view class="form-item">
<text class="item-label">保质期管理</text>
<switch
:checked="productInfo.expirationManagement"
@change="toggleExpirationManagement"
color="#F53F3F"
/>
</view>
<!-- 保质期天数 -->
<view class="form-item" v-if="productInfo.expirationManagement">
<text class="item-label">保质期天数</text>
<view class="expiration-options">
<view
class="expiration-item"
:class="{ active: productInfo.expirationDays === 365 }"
@tap="setExpirationDays(365)"
>
<text class="expiration-text">1年</text>
<text class="expiration-days">36天</text>
</view>
<view
class="expiration-item"
:class="{ active: productInfo.expirationDays === 270 }"
@tap="setExpirationDays(270)"
>
<text class="expiration-text">9个月</text>
<text class="expiration-days">27天</text>
</view>
<view
class="expiration-item"
:class="{ active: productInfo.expirationDays === 180 }"
@tap="setExpirationDays(180)"
>
<text class="expiration-text">6个月</text>
<text class="expiration-days">18天</text>
</view>
<view
class="expiration-item"
:class="{ active: productInfo.expirationDays === 240 }"
@tap="setExpirationDays(240)"
>
<text class="expiration-text">8个月</text>
<text class="expiration-days">24天</text>
</view>
<view
class="expiration-item"
:class="{ active: productInfo.expirationDays === 300 }"
@tap="setExpirationDays(300)"
>
<text class="expiration-text">10个月</text>
<text class="expiration-days">30天</text>
</view>
</view>
</view>
<!-- 临期提醒天数 -->
<view class="form-item" v-if="productInfo.expirationManagement">
<text class="item-label">临期提醒天数</text>
<view class="warning-days-display">
<text class="warning-days-value">{{ warningDaysDisplay }}</text>
<text class="warning-days-unit">天</text>
</view>
</view>
<!-- 生产日期 -->
<view class="form-item" v-if="productInfo.expirationManagement">
<text class="item-label">生产日期</text>
<uni-datetime-picker
type="date"
v-model="productInfo.productionDate"
:start="startDate"
:end="endDate"
placeholder="请选择生产日期"
/>
</view>
<!-- 货架码 -->
<view class="form-item">
<text class="item-label">货架码</text>
<input
class="item-input"
type="text"
placeholder="请输入货架码"
v-model="productInfo.shelfCode"
/>
</view>
<!-- 商品编码 -->
<view class="form-item">
<text class="item-label">商品编码</text>
<input
class="item-input"
type="text"
placeholder="请输入商品编码"
v-model="productInfo.productCode"
/>
</view>
</view>
<!-- 保存按钮 -->
<view class="save-button-container">
<button class="save-button" @tap="handleSave"></button>
</view>
</view>
</template>
<script>
import { addProductWithFile } from '@/api/product'
import { getStoreId } from '@/utils/auth'
export default {
data() {
return {
productInfo: {
name: '',
barcode: '',
image: '',
price: '',
quantity: '',
cost: '',
expirationManagement: false,
shelfCode: '',
productCode: '',
expirationDays: '',
warningDays: '',
productionDate: ''
}
}
},
computed: {
warningDaysDisplay() {
if (!this.productInfo.expirationDays) return '';
const days = parseInt(this.productInfo.expirationDays);
return days.toString().substring(0, 2);
},
startDate() {
return '2020-01-01';
},
endDate() {
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, '0');
const day = now.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
}
},
onLoad(options) {
console.log('页面参数:', options);
if (options.fromData) {
try {
const fromData = JSON.parse(decodeURIComponent(options.fromData));
console.log('接收到的商品数据:', fromData);
this.productInfo.name = fromData.productName || '';
this.productInfo.barcode = fromData.productBarCode || '';
this.productInfo.price = fromData.storePrice || '';
this.productInfo.quantity = fromData.stockQuantity || '';
this.productInfo.productCode = fromData.productCode || '';
this.productInfo.image = fromData.mainImage || '';
} catch (error) {
console.error('解析商品数据失败:', error);
}
}
},
methods: {
// 扫码功能
handleScan() {
uni.showToast({ title: '扫码功能(模拟)', icon: 'none' })
setTimeout(() => {
this.productInfo.barcode = '6921168558032'
uni.showToast({ title: '扫码成功', icon: 'success' })
}, 500)
},
// 选择图片
chooseImage() {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
this.productInfo.image = res.tempFilePaths[0]
}
})
},
// 设置推荐价格
setPrice(price) {
this.productInfo.price = price.toString()
uni.showToast({ title: `已设置为${price}`, icon: 'success', duration: 1500 })
},
// ✅ 切换保质期管理-适配红色滑动开关 极简写法
toggleExpirationManagement(e) {
this.productInfo.expirationManagement = e.detail.value
},
// 设置保质期天数
setExpirationDays(days) {
this.productInfo.expirationDays = days.toString()
const warningDays = days.toString().substring(0, 2);
this.productInfo.warningDays = warningDays;
uni.showToast({ title: `已设置为${days}`, icon: 'success', duration: 1500 })
},
// 表单验证-完整校验
validateForm() {
if (!this.productInfo.name.trim()) { uni.showToast({ title: '请输入商品名称', icon: 'none' });return false }
if (!this.productInfo.price) { uni.showToast({ title: '请输入售价', icon: 'none' });return false }
// 开启保质期管理 必校验三项
if (this.productInfo.expirationManagement) {
if (!this.productInfo.expirationDays) { uni.showToast({ title: '请选择保质期天数', icon: 'none' });return false }
// 临期提醒天数自动设置,不需要手动输入
if (!this.productInfo.productionDate) { uni.showToast({ title: '请选择生产日期', icon: 'none' });return false }
}
return true
},
// 保存商品-完整传参
async handleSave() {
if (!this.validateForm()) return
const storeId = getStoreId();
if (!storeId) { uni.showToast({ title: '请先选择门店', icon: 'none' });return }
uni.showLoading({ title: '保存中...' });
try {
const formData = {
productName: this.productInfo.name,
productBarCode: this.productInfo.barcode,
storePrice: this.productInfo.price,
stockQuantity: this.productInfo.quantity,
costPrice: this.productInfo.cost,
productCode: this.productInfo.productCode,
shelfCode: this.productInfo.shelfCode,
expirationManagement: this.productInfo.expirationManagement ? 1 : 0,
shelfLife: this.productInfo.expirationDays,
productionDate: this.productInfo.productionDate,
approaching: this.productInfo.warningDays,
storeId: storeId
};
const res = await addProductWithFile(this.productInfo.image || '', formData);
uni.hideLoading();
if (res.code === 200) {
uni.showToast({ title: '商品添加成功', icon: 'success', duration: 2000 });
setTimeout(() => { uni.navigateBack({ delta: 1 }); }, 2000);
} else {
uni.showToast({ title: res.msg || '商品添加失败', icon: 'none' });
}
} catch (error) {
uni.hideLoading();
console.error('添加商品失败:', error);
uni.showToast({ title: '网络请求失败', icon: 'none' });
}
}
}
}
</script>
<style scoped>
.add-product-page {
background-color: #f5f5f5;
min-height: 100vh;
padding-bottom: 120rpx;
}
/* 头部 */
.page-header {
background-color: #ffffff;
padding: 40rpx 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.header-title { font-size: 36rpx;font-weight: 600;color: #333333; }
/* 表单容器 */
.form-container { background-color: #ffffff;margin-top: 20rpx; }
/* 表单项 */
.form-item {
padding: 32rpx;
border-bottom: 1rpx solid #f0f0f0;
display: flex;
align-items: center;
justify-content: space-between;
}
.item-label { font-size: 32rpx;color: #333333;font-weight: 500;min-width: 160rpx; }
.item-input { flex:1;font-size:32rpx;color:#333;text-align:right;padding:0 20rpx; }
.item-input::placeholder { color: #999999; }
/* 条码区域 */
.barcode-section { display:flex;align-items:center;flex:1; }
.barcode-input { flex:1;margin-right:20rpx; }
.scan-btn { background:#07C160;padding:16rpx 32rpx;border-radius:8rpx; }
.scan-text { color:#fff;font-size:28rpx; }
/* 图片上传区域 */
.image-upload-section { flex:1;display:flex;justify-content:flex-end; }
.upload-placeholder { width:200rpx;height:200rpx;border:2rpx dashed #ccc;border-radius:8rpx;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#f9f9f9; }
.upload-icon { font-size:48rpx;color:#999;margin-bottom:16rpx; }
.upload-text { font-size:24rpx;color:#999; }
.product-image { width:200rpx;height:200rpx;border-radius:8rpx; }
/* 价格区域 */
.price-section { display:flex;align-items:center;flex:1;justify-content:flex-end; }
.price-input { flex:none;width:120rpx;text-align:center; }
.price-unit { font-size:32rpx;color:#333;margin-left:10rpx; }
/* 推荐价格 */
.recommend-price-section { padding:32rpx;border-bottom:1rpx solid #f0f0f0; }
.recommend-title { font-size:28rpx;color:#666;margin-bottom:24rpx;display:block; }
.recommend-list { display:flex;justify-content:space-between; }
.recommend-item { display:flex;flex-direction:column;align-items:center;padding:20rpx 24rpx;background:#f9f9f9;border-radius:8rpx;flex:1;margin:0 10rpx; }
.recommend-percent { font-size:26rpx;color:#666;margin-bottom:8rpx; }
.recommend-price { font-size:30rpx;color:#07C160;font-weight:500; }
/* 数量/进货价 单位 */
.quantity-section,.cost-section { display:flex;align-items:center;flex:1;justify-content:flex-end; }
.quantity-unit,.cost-unit { font-size:32rpx;color:#333;margin-left:10rpx; }
/* ✅ 保质期相关样式 完美匹配 */
.expiration-options { display:flex;flex-wrap:wrap;gap:20rpx;flex:1;justify-content:flex-end; }
.expiration-item { display:flex;flex-direction:column;align-items:center;padding:16rpx 20rpx;background:#f9f9f9;border-radius:8rpx;min-width:100rpx;border:2rpx solid transparent;transition:all 0.3s; }
.expiration-item.active { background:#F53F3F;border-color:#F53F3F; }
.expiration-item.active .expiration-text { color:#fff; }
.expiration-item.active .expiration-days { color:#fff; }
.expiration-text { font-size:28rpx;color:#333; }
.expiration-days { font-size:24rpx;color:#999;margin-top:4rpx; }
/* 临期提醒天数样式 */
.warning-days-display { display:flex;align-items:center;flex:1;justify-content:flex-end; }
.warning-days-value { font-size:36rpx;color:#F53F3F;font-weight:600;margin-right:8rpx; }
.warning-days-unit { font-size:28rpx;color:#666; }
/* 分隔线 */
.divider { height:20rpx;background:#f5f5f5;border-top:1rpx solid #f0f0f0;border-bottom:1rpx solid #f0f0f0; }
/* 保存按钮 */
.save-button-container { position:fixed;bottom:0;left:0;right:0;background:#fff;padding:20rpx 32rpx;border-top:1rpx solid #f0f0f0; }
.save-button { background:#F53F3F;color:#ffffff;font-size:34rpx;height:88rpx;line-height:88rpx;border-radius:8rpx; }
.save-button::after { border:none; }
/* 响应式调整 */
@media (max-width:750px) {
.recommend-list { flex-direction:column; }
.recommend-item { margin:10rpx 0; }
}
</style>