You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
crmeb/app/pages/supply_chain/supply_query/index.vue

478 lines
12 KiB

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="supply-query-page">
<view class="content">
<!-- 标签页 -->
<view class="tabs">
<view class="tab" :class="activeTab === 'purchase' ? 'active' : ''" @click="activeTab = 'purchase'">采购计划</view>
<view class="tab" :class="activeTab === 'stock' ? 'active' : ''" @click="activeTab = 'stock'">库存状态</view>
<view class="tab" :class="activeTab === 'quality' ? 'active' : ''" @click="activeTab = 'quality'">质量反馈</view>
</view>
<!-- 采购计划 -->
<view class="tab-content" v-show="activeTab === 'purchase'">
<view class="search-box">
<input type="text" v-model="searchKeyword" placeholder="搜索采购计划" />
<view class="search-btn" @click="searchPurchase">搜索</view>
</view>
<view class="purchase-list">
<view class="purchase-item" v-for="(item, index) in purchasePlans" :key="index">
<view class="item-header">
<text class="plan-name">{{ item.name }}</text>
<text class="plan-status" :class="item.status === '进行中' ? 'status-active' : 'status-completed'">
{{ item.status }}
</text>
</view>
<view class="item-body">
<view class="info-item">
<text class="label">计划时间:</text>
<text class="value">{{ item.time }}</text>
</view>
<view class="info-item">
<text class="label">采购数量:</text>
<text class="value">{{ item.quantity }}件</text>
</view>
<view class="info-item">
<text class="label">负责人:</text>
<text class="value">{{ item.manager }}</text>
</view>
</view>
<view class="item-footer">
<view class="detail-btn" @click="viewPurchaseDetail(item.id)">查看详情</view>
</view>
</view>
</view>
</view>
<!-- 库存状态 -->
<view class="tab-content" v-show="activeTab === 'stock'">
<view class="search-box">
<input type="text" v-model="stockKeyword" placeholder="搜索库存物资" />
<view class="search-btn" @click="searchStock">搜索</view>
</view>
<view class="stock-list">
<view class="stock-item" v-for="(item, index) in stockItems" :key="index">
<view class="item-header">
<text class="item-name">{{ item.name }}</text>
<text class="stock-status" :class="item.stock <= item.minStock ? 'status-warning' : 'status-normal'">
{{ item.stock <= item.minStock ? '库存不足' : '库存正常' }}
</text>
</view>
<view class="item-body">
<view class="info-item">
<text class="label">当前库存:</text>
<text class="value">{{ item.stock }}件</text>
</view>
<view class="info-item">
<text class="label">最低库存:</text>
<text class="value">{{ item.minStock }}件</text>
</view>
<view class="info-item">
<text class="label">库存位置:</text>
<text class="value">{{ item.location }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 质量反馈 -->
<view class="tab-content" v-show="activeTab === 'quality'">
<view class="feedback-form">
<view class="form-item">
<text class="label">食材名称:</text>
<select v-model="feedbackFood">
<option v-for="food in foodList" :key="food.id" :value="food.name">{{ food.name }}</option>
</select>
</view>
<view class="form-item">
<text class="label">问题类型:</text>
<select v-model="feedbackType">
<option value="质量问题">质量问题</option>
<option value="数量问题">数量问题</option>
<option value="其他问题">其他问题</option>
</select>
</view>
<view class="form-item">
<text class="label">问题描述:</text>
<textarea v-model="feedbackDesc" placeholder="请详细描述问题..." maxlength="200"></textarea>
</view>
<view class="form-item">
<text class="label">上传图片:</text>
<view class="upload-box">
<view class="upload-btn" @click="uploadImage">
<text class="iconfont icon-tianjia"></text>
<text>添加图片</text>
</view>
<view class="image-list">
<view class="image-item" v-for="(img, index) in feedbackImages" :key="index">
<image :src="img" mode="aspectFill"></image>
<text class="delete-btn" @click="deleteImage(index)">×</text>
</view>
</view>
</view>
</view>
<view class="submit-btn" @click="submitFeedback"></view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
activeTab: 'purchase',
searchKeyword: '',
stockKeyword: '',
feedbackFood: '',
feedbackType: '质量问题',
feedbackDesc: '',
feedbackImages: [],
purchasePlans: [
{ id: 1, name: '蔬菜采购计划', status: '进行中', time: '2026-03-07', quantity: 100, manager: '张三' },
{ id: 2, name: '水果采购计划', status: '进行中', time: '2026-03-08', quantity: 50, manager: '李四' },
{ id: 3, name: '肉类采购计划', status: '已完成', time: '2026-03-05', quantity: 80, manager: '王五' }
],
stockItems: [
{ id: 1, name: '有机蔬菜', stock: 20, minStock: 30, location: '仓库A区' },
{ id: 2, name: '新鲜水果', stock: 40, minStock: 25, location: '仓库B区' },
{ id: 3, name: '肉类食材', stock: 15, minStock: 20, location: '冷库C区' },
{ id: 4, name: '海鲜产品', stock: 25, minStock: 15, location: '冷库D区' }
],
foodList: [
{ id: 1, name: '有机蔬菜' },
{ id: 2, name: '新鲜水果' },
{ id: 3, name: '肉类食材' },
{ id: 4, name: '海鲜产品' }
]
};
},
methods: {
searchPurchase() {
uni.showToast({
title: '搜索功能开发中',
icon: 'none'
});
},
searchStock() {
uni.showToast({
title: '搜索功能开发中',
icon: 'none'
});
},
viewPurchaseDetail(id) {
uni.showToast({
title: '查看采购详情',
icon: 'none'
});
},
uploadImage() {
// 模拟上传图片
this.feedbackImages.push('https://via.placeholder.com/100x100');
uni.showToast({
title: '图片上传成功',
icon: 'success'
});
},
deleteImage(index) {
this.feedbackImages.splice(index, 1);
},
submitFeedback() {
if (!this.feedbackFood || !this.feedbackDesc) {
uni.showToast({
title: '请填写完整信息',
icon: 'none'
});
return;
}
// 模拟提交反馈
uni.showToast({
title: '反馈提交成功',
icon: 'success'
});
// 重置表单
setTimeout(() => {
this.feedbackFood = '';
this.feedbackType = '质量问题';
this.feedbackDesc = '';
this.feedbackImages = [];
}, 1500);
}
}
};
</script>
<style lang="scss">
.supply-query-page {
.content {
padding: 30rpx;
.tabs {
display: flex;
margin-bottom: 15rpx;
background-color: #fff;
border-radius: 10rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.tab {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #666;
position: relative;
&.active {
color: #409EFF;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background-color: #409EFF;
border-radius: 2rpx;
}
}
}
}
.tab-content {
.search-box {
display: flex;
margin-bottom: 20rpx;
input {
flex: 1;
height: 60rpx;
border: 1rpx solid #ddd;
border-radius: 30rpx;
padding: 0 30rpx;
font-size: 24rpx;
}
.search-btn {
width: 120rpx;
height: 60rpx;
background-color: #409EFF;
color: #fff;
border-radius: 30rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: 20rpx;
font-size: 24rpx;
}
}
.purchase-list,
.stock-list {
.purchase-item,
.stock-item {
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.item-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15rpx;
.plan-name,
.item-name {
font-size: 26rpx;
font-weight: 600;
color: #333;
}
.plan-status,
.stock-status {
padding: 5rpx 15rpx;
border-radius: 15rpx;
font-size: 20rpx;
}
.status-active {
background-color: #E6F7FF;
color: #409EFF;
}
.status-completed {
background-color: #F6FFED;
color: #52C41A;
}
.status-warning {
background-color: #FFF7E6;
color: #FA8C16;
}
.status-normal {
background-color: #F6FFED;
color: #52C41A;
}
}
.item-body {
margin-bottom: 15rpx;
.info-item {
display: flex;
margin-bottom: 10rpx;
.label {
width: 120rpx;
font-size: 24rpx;
color: #666;
}
.value {
flex: 1;
font-size: 24rpx;
color: #333;
}
}
}
.item-footer {
display: flex;
justify-content: flex-end;
.detail-btn {
padding: 8rpx 16rpx;
background-color: #409EFF;
color: #fff;
border-radius: 16rpx;
font-size: 20rpx;
}
}
}
}
.feedback-form {
background-color: #fff;
border-radius: 10rpx;
padding: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.form-item {
margin-bottom: 30rpx;
.label {
display: block;
font-size: 26rpx;
color: #333;
margin-bottom: 10rpx;
font-weight: 600;
}
select {
width: 100%;
height: 60rpx;
border: 1rpx solid #ddd;
border-radius: 10rpx;
padding: 0 20rpx;
font-size: 24rpx;
}
textarea {
width: 100%;
height: 150rpx;
border: 1rpx solid #ddd;
border-radius: 10rpx;
padding: 20rpx;
font-size: 24rpx;
}
.upload-box {
display: flex;
flex-wrap: wrap;
.upload-btn {
width: 120rpx;
height: 120rpx;
border: 1rpx dashed #ddd;
border-radius: 10rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-right: 20rpx;
.iconfont {
font-size: 40rpx;
color: #ddd;
margin-bottom: 10rpx;
}
text {
font-size: 20rpx;
color: #999;
}
}
.image-list {
display: flex;
flex-wrap: wrap;
.image-item {
position: relative;
width: 120rpx;
height: 120rpx;
margin-right: 20rpx;
margin-bottom: 20rpx;
image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.delete-btn {
position: absolute;
top: -10rpx;
right: -10rpx;
width: 30rpx;
height: 30rpx;
background-color: #ff4d4f;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 24rpx;
font-weight: bold;
}
}
}
}
}
.submit-btn {
height: 80rpx;
background-color: #409EFF;
color: #fff;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 4rpx 12rpx rgba(64, 158, 255, 0.3);
}
}
}
}
}
</style>