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/purchase/index.vue

532 lines
13 KiB

<template>
<view class="purchase-page">
<view class="content">
<!-- 操作菜单 -->
<view class="menu-grid">
<view class="menu-item" @click="openPurchaseRequest">
<view class="menu-icon">
<text class="iconfont icon-fapiaoshenqing"></text>
</view>
<text class="menu-text">发起采购需求</text>
</view>
<view class="menu-item" @click="openPurchasePlan">
<view class="menu-icon">
<text class="iconfont icon-jihua"></text>
</view>
<text class="menu-text">查看采购计划</text>
</view>
<view class="menu-item" @click="openOrderTracking">
<view class="menu-icon">
<text class="iconfont icon-dingdan"></text>
</view>
<text class="menu-text">跟踪订单进度</text>
</view>
<view class="menu-item" @click="openQualityFeedback">
<view class="menu-icon">
<text class="iconfont icon-tousu"></text>
</view>
<text class="menu-text">质量问题反馈</text>
</view>
</view>
<!-- 采购需求表单 -->
<view class="form-section" v-if="activeForm === 'request'">
<view class="form-title">发起采购需求</view>
<view class="form-content">
<view class="form-item">
<text class="label">采购物品</text>
<input type="text" v-model="purchaseRequest.name" placeholder="请输入采购物品名称" />
</view>
<view class="form-item">
<text class="label">采购数量</text>
<input type="number" v-model="purchaseRequest.quantity" placeholder="请输入采购数量" />
</view>
<view class="form-item">
<text class="label">采购原因</text>
<textarea v-model="purchaseRequest.reason" placeholder="请输入采购原因" maxlength="200"></textarea>
</view>
<view class="form-item">
<text class="label">期望到货时间</text>
<input type="date" v-model="purchaseRequest.expectedTime" />
</view>
<view class="submit-btn" @click="submitPurchaseRequest"></view>
</view>
</view>
<!-- 订单跟踪 -->
<view class="tracking-section" v-if="activeForm === 'tracking'">
<view class="form-title">跟踪订单进度</view>
<view class="search-box">
<input type="text" v-model="orderKeyword" placeholder="输入订单号搜索" />
<view class="search-btn" @click="searchOrder"></view>
</view>
<view class="order-list">
<view class="order-item" v-for="(item, index) in orders" :key="index">
<view class="item-header">
<text class="order-no">订单号{{ item.orderNo }}</text>
<text class="order-status" :class="statusClassMap[item.status]">{{ item.status }}</text>
</view>
<view class="item-body">
<view class="info-item">
<text class="label">采购物品</text>
<text class="value">{{ item.name }}</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.orderTime }}</text>
</view>
<view class="info-item">
<text class="label">预计到货</text>
<text class="value">{{ item.expectedTime }}</text>
</view>
</view>
<view class="item-footer">
<view class="detail-btn" @click="viewOrderDetail(item.id)"></view>
</view>
</view>
</view>
</view>
<!-- 质量问题反馈 -->
<view class="feedback-section" v-if="activeForm === 'feedback'">
<view class="form-title">质量问题反馈</view>
<view class="form-content">
<view class="form-item">
<text class="label">订单号</text>
<input type="text" v-model="qualityFeedback.orderNo" placeholder="请输入订单号" />
</view>
<view class="form-item">
<text class="label">问题描述</text>
<textarea v-model="qualityFeedback.description" placeholder="请详细描述质量问题" maxlength="200"></textarea>
</view>
<view class="form-item">
<text class="label">上传照片</text>
<view class="upload-box">
<view class="upload-btn" @click="uploadQualityImage">
<text class="iconfont icon-tianjia"></text>
<text>添加图片</text>
</view>
<view class="image-list">
<view class="image-item" v-for="(img, index) in qualityFeedback.images" :key="index">
<image :src="img" mode="aspectFill"></image>
<text class="delete-btn" @click="deleteQualityImage(index)">×</text>
</view>
</view>
</view>
</view>
<view class="submit-btn" @click="submitQualityFeedback"></view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
activeForm: '',
orderKeyword: '',
purchaseRequest: {
name: '',
quantity: '',
reason: '',
expectedTime: ''
},
qualityFeedback: {
orderNo: '',
description: '',
images: []
},
statusClassMap: {
'已下单': 'status-ordered',
'配送中': 'status-delivering',
'已完成': 'status-completed'
},
orders: [
{ id: 1, orderNo: 'CG20260307001', name: '有机蔬菜', quantity: 100, status: '已下单', orderTime: '2026-03-07', expectedTime: '2026-03-09' },
{ id: 2, orderNo: 'CG20260307002', name: '新鲜水果', quantity: 50, status: '配送中', orderTime: '2026-03-06', expectedTime: '2026-03-08' },
{ id: 3, orderNo: 'CG20260307003', name: '肉类食材', quantity: 80, status: '已完成', orderTime: '2026-03-05', expectedTime: '2026-03-07' }
]
};
},
methods: {
openPurchaseRequest() {
this.activeForm = 'request';
this.purchaseRequest = {
name: '',
quantity: '',
reason: '',
expectedTime: ''
};
},
openPurchasePlan() {
uni.showToast({
title: '查看采购计划功能开发中',
icon: 'none'
});
},
openOrderTracking() {
this.activeForm = 'tracking';
this.orderKeyword = '';
},
openQualityFeedback() {
this.activeForm = 'feedback';
this.qualityFeedback = {
orderNo: '',
description: '',
images: []
};
},
submitPurchaseRequest() {
if (!this.purchaseRequest.name || !this.purchaseRequest.quantity || !this.purchaseRequest.reason) {
uni.showToast({
title: '请填写完整信息',
icon: 'none'
});
return;
}
// 模拟提交采购需求
uni.showToast({
title: '采购需求提交成功',
icon: 'success'
});
// 重置表单
setTimeout(() => {
this.activeForm = '';
this.purchaseRequest = {
name: '',
quantity: '',
reason: '',
expectedTime: ''
};
}, 1500);
},
searchOrder() {
uni.showToast({
title: '搜索功能开发中',
icon: 'none'
});
},
viewOrderDetail(id) {
uni.showToast({
title: '查看订单详情',
icon: 'none'
});
},
uploadQualityImage() {
// 模拟上传图片
this.qualityFeedback.images.push('https://via.placeholder.com/100x100');
uni.showToast({
title: '图片上传成功',
icon: 'success'
});
},
deleteQualityImage(index) {
this.qualityFeedback.images.splice(index, 1);
},
submitQualityFeedback() {
if (!this.qualityFeedback.orderNo || !this.qualityFeedback.description) {
uni.showToast({
title: '请填写完整信息',
icon: 'none'
});
return;
}
// 模拟提交质量反馈
uni.showToast({
title: '质量反馈提交成功',
icon: 'success'
});
// 重置表单
setTimeout(() => {
this.activeForm = '';
this.qualityFeedback = {
orderNo: '',
description: '',
images: []
};
}, 1500);
},
}
};
</script>
<style lang="scss">
.purchase-page {
.content {
padding: 30rpx;
.menu-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
margin-bottom: 40rpx;
.menu-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 10rpx;
padding: 40rpx 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.menu-icon {
width: 80rpx;
height: 80rpx;
background-color: #E6F7FF;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
.iconfont {
font-size: 40rpx;
color: #409EFF;
}
}
.menu-text {
font-size: 24rpx;
color: #333;
}
}
}
.form-section,
.tracking-section,
.feedback-section {
background-color: #fff;
border-radius: 10rpx;
padding: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.form-title {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 30rpx;
text-align: center;
}
.form-content {
.form-item {
margin-bottom: 30rpx;
.label {
display: block;
font-size: 26rpx;
color: #333;
margin-bottom: 10rpx;
font-weight: 600;
}
input,
textarea {
width: 100%;
border: 1rpx solid #ddd;
border-radius: 10rpx;
padding: 20rpx;
font-size: 24rpx;
}
textarea {
height: 150rpx;
}
.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);
}
}
.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;
}
}
.order-list {
.order-item {
background-color: #f9f9f9;
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 20rpx;
.item-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15rpx;
.order-no {
font-size: 24rpx;
color: #333;
font-weight: 600;
}
.order-status {
padding: 5rpx 15rpx;
border-radius: 15rpx;
font-size: 20rpx;
}
.status-ordered {
background-color: #E6F7FF;
color: #409EFF;
}
.status-delivering {
background-color: #FFF7E6;
color: #FA8C16;
}
.status-completed {
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;
}
}
}
}
}
}
}
</style>