From fa403c58d2bea76a7131ea9dbb1d60247ea9ca77 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 30 四月 2026 09:43:25 +0800
Subject: [PATCH] 生产计划和生产订单模块开发(仅查看)

---
 src/pages/productionManagement/productionOrder/index.vue |  293 ++++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 222 insertions(+), 71 deletions(-)

diff --git a/src/pages/productionManagement/productionOrder/index.vue b/src/pages/productionManagement/productionOrder/index.vue
index 7adcc4d..7f7ae4f 100644
--- a/src/pages/productionManagement/productionOrder/index.vue
+++ b/src/pages/productionManagement/productionOrder/index.vue
@@ -9,8 +9,8 @@
 				<view class="search-input">
 					<up-input
 						class="search-text"
-						placeholder="璇疯緭鍏ュ鎴峰悕绉版悳绱�"
-						v-model="searchForm.customerName"
+						placeholder="璇疯緭鍏ヨ鍗曞彿鎴栦骇鍝佸悕绉�"
+						v-model="searchForm.keyword"
 						@change="handleQuery"
 						clearable
 					/>
@@ -21,8 +21,8 @@
 			</view>
 		</view>
 		
-		<!-- 鐢熶骇璁㈠崟鍒楄〃 -->
-		<view class="ledger-list" v-if="tableData.length > 0">
+		<!-- 鍒楄〃鍖哄煙 -->
+		<scroll-view scroll-y class="list-container" v-if="tableData.length > 0" @scrolltolower="loadMore">
 			<view v-for="(item, index) in tableData" :key="item.id || index">
 				<view class="ledger-item">
 					<view class="item-header">
@@ -30,54 +30,55 @@
 							<view class="document-icon">
 								<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
 							</view>
-							<text class="item-id">{{ item.salesContractNo }}</text>
+							<text class="item-id">{{ item.npsNo }}</text>
+						</view>
+						<view class="item-right">
+							<up-tag :text="getStatusText(item.status)" :type="getStatusType(item.status)" size="mini" />
 						</view>
 					</view>
 					<up-divider></up-divider>
 					
 					<view class="item-details">
 						<view class="detail-row">
-							<text class="detail-label">褰曞叆鏃ユ湡</text>
-							<text class="detail-value">{{ item.entryDate }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">瀹㈡埛鍚堝悓鍙�</text>
-							<text class="detail-value">{{ item.customerContractNo }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">瀹㈡埛鍚嶇О</text>
-							<text class="detail-value">{{ item.customerName }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">椤圭洰鍚嶇О</text>
-							<text class="detail-value">{{ item.projectName }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">浜у搧澶х被</text>
-							<text class="detail-value">{{ item.productCategory }}</text>
+							<text class="detail-label">浜у搧鍚嶇О</text>
+							<text class="detail-value font-bold">{{ item.productName || '-' }}</text>
 						</view>
 						<view class="detail-row">
 							<text class="detail-label">瑙勬牸鍨嬪彿</text>
-							<text class="detail-value">{{ item.specificationModel }}</text>
+							<text class="detail-value">{{ item.model || '-' }}</text>
 						</view>
 						<view class="detail-row">
-							<text class="detail-label">鏁伴噺</text>
-							<text class="detail-value">{{ item.quantity }} {{ item.unit }}</text>
+							<text class="detail-label">璁㈠崟鏁伴噺</text>
+							<text class="detail-value">{{ item.quantity || 0 }}</text>
 						</view>
 						<view class="detail-row">
-							<text class="detail-label">鎺掍骇鏁伴噺</text>
-							<text class="detail-value highlight">{{ item.schedulingNum }}</text>
+							<text class="detail-label">瀹屾垚杩涘害</text>
+							<view class="progress-box">
+								<up-line-progress :percentage="toProgressPercentage(item.completionStatus)" 
+												:activeColor="progressColor(item.completionStatus)" 
+												height="10"></up-line-progress>
+								<text class="progress-text">{{ item.completeQuantity || 0 }} / {{ item.quantity || 0 }}</text>
+							</view>
 						</view>
 						<view class="detail-row">
-							<text class="detail-label">瀹屽伐鏁伴噺</text>
-							<text class="detail-value highlight">{{ item.successNum }}</text>
+							<text class="detail-label">璁″垝瀹屾垚</text>
+							<text class="detail-value">{{ formatDate(item.planCompleteTime) }}</text>
+						</view>
+					</view>
+					
+					<view class="item-footer">
+						<view class="action-btns">
+							<up-button type="primary" size="mini" plain text="鏉ユ簮" @click="goSource(item)"></up-button>
+							<up-button type="success" size="mini" plain text="棰嗘枡璇︽儏" @click="goPickingDetail(item)"></up-button>
 						</view>
 					</view>
 				</view>
 			</view>
-		</view>
+			<up-loadmore :status="loadStatus" v-if="tableData.length >= page.size" />
+		</scroll-view>
+		
 		<view v-else class="no-data">
-			<text>鏆傛棤鐢熶骇璁㈠崟鏁版嵁</text>
+			<up-empty mode="data" text="鏆傛棤鐢熶骇璁㈠崟鏁版嵁"></up-empty>
 		</view>
 	</view>
 </template>
@@ -86,70 +87,126 @@
 import { ref, reactive, toRefs, getCurrentInstance } from "vue";
 import { onShow } from '@dcloudio/uni-app';
 import dayjs from "dayjs";
-import {schedulingListPage} from "@/api/productionManagement/productionOrder.js";
+import { productOrderListPage } from "@/api/productionManagement/productionOrder.js";
 import PageHeader from "@/components/PageHeader.vue";
+
 const { proxy } = getCurrentInstance();
 
 // 鍔犺浇鐘舵��
 const loading = ref(false);
+const loadStatus = ref('loadmore');
 // 鍒楄〃鏁版嵁
 const tableData = ref([]);
 
 // 鍒嗛〉閰嶇疆
 const page = reactive({
-	current: -1,
-	size: -1,
+	current: 1,
+	size: 10,
 	total: 0,
 });
 
 // 鎼滅储琛ㄥ崟鏁版嵁
 const data = reactive({
 	searchForm: {
-		customerName: "",
+		keyword: "",
 	},
 });
 const { searchForm } = toRefs(data);
-
-// 閫氱敤鎻愮ず鍑芥暟
-const showLoadingToast = (message) => {
-	uni.showLoading({
-		title: message,
-		mask: true
-	});
-};
-
-const closeToast = () => {
-	uni.hideLoading();
-};
 
 // 杩斿洖涓婁竴椤�
 const goBack = () => {
 	uni.navigateBack();
 };
 
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (date) => {
+	return date ? dayjs(date).format('YYYY-MM-DD') : '-';
+};
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+	const statusMap = {
+		1: "寰呭紑濮�",
+		2: "杩涜涓�",
+		3: "宸插畬鎴�",
+		4: "宸插彇娑�",
+	};
+	return statusMap[status] || "鏈煡";
+};
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+	const typeMap = {
+		1: "primary",
+		2: "warning",
+		3: "success",
+		4: "danger",
+	};
+	return typeMap[status] || "info";
+};
+
+// 瀹屾垚杩涘害鐧惧垎姣�
+const toProgressPercentage = (val) => {
+	const n = Number(val);
+	if (!Number.isFinite(n)) return 0;
+	if (n <= 0) return 0;
+	if (n >= 100) return 100;
+	return Math.round(n);
+};
+
+// 杩涘害鏉¢鑹�
+const progressColor = (percentage) => {
+	const p = toProgressPercentage(percentage);
+	if (p < 30) return "#f56c6c";
+	if (p < 50) return "#e6a23c";
+	if (p < 80) return "#409eff";
+	return "#67c23a";
+};
+
 // 鏌ヨ鍒楄〃
 const handleQuery = () => {
 	page.current = 1;
-	tableData.value = []; // 閲嶇疆鍒楄〃鏁版嵁
+	tableData.value = [];
+	getList();
+};
+
+// 鍔犺浇鏇村
+const loadMore = () => {
+	if (loadStatus.value === 'nomore' || loading.value) return;
+	page.current++;
 	getList();
 };
 
 // 鑾峰彇鍒楄〃鏁版嵁
 const getList = () => {
 	loading.value = true;
-	showLoadingToast('鍔犺浇涓�...');
+	loadStatus.value = 'loading';
 	
-	// 鏋勯�犺姹傚弬鏁�
-	const params = { ...searchForm.value, ...page };
+	const params = { 
+		current: page.current,
+		size: page.size,
+		npsNo: searchForm.value.keyword,
+		productName: searchForm.value.keyword
+	};
 	
-	schedulingListPage(params).then((res) => {
+	productOrderListPage(params).then((res) => {
 		loading.value = false;
-		closeToast();
+		const records = res.data.records || [];
+		if (page.current === 1) {
+			tableData.value = records;
+		} else {
+			tableData.value = [...tableData.value, ...records];
+		}
 		
-		tableData.value = res.data.records || [];
+		if (records.length < page.size) {
+			loadStatus.value = 'nomore';
+		} else {
+			loadStatus.value = 'loadmore';
+		}
+		page.total = res.data.total || 0;
 	}).catch(() => {
 		loading.value = false;
-		closeToast();
+		loadStatus.value = 'loadmore';
 		uni.showToast({
 			title: '鍔犺浇澶辫触',
 			icon: 'error'
@@ -157,37 +214,131 @@
 	});
 };
 
+// 璺宠浆鏉ユ簮
+const goSource = (item) => {
+	uni.navigateTo({
+		url: `/pages/productionManagement/productionOrder/source?id=${item.id}&productName=${encodeURIComponent(item.productName)}&model=${encodeURIComponent(item.model)}&quantity=${item.quantity}`
+	});
+};
+
+// 璺宠浆棰嗘枡璇︽儏
+const goPickingDetail = (item) => {
+	uni.navigateTo({
+		url: `/pages/productionManagement/productionOrder/pickingDetail?id=${item.id}&npsNo=${item.npsNo}`
+	});
+};
+
 // 椤甸潰鏄剧ず鏃跺姞杞芥暟鎹�
 onShow(() => {
-	// 鍔犺浇鍒楄〃鏁版嵁
-	getList();
+	handleQuery();
 });
 </script>
 
 <style scoped lang="scss">
 @import '@/styles/sales-common.scss';
 
-// 鐢熶骇璁㈠崟椤甸潰鏍峰紡
 .production-order {
 	min-height: 100vh;
 	background: #f8f9fa;
-	position: relative;
+	display: flex;
+	flex-direction: column;
 }
 
-// 閲嶅啓閮ㄥ垎鏍峰紡浠ラ�傞厤鐢熶骇璁㈠崟
+.list-container {
+	flex: 1;
+	height: 0;
+}
+
 .ledger-item {
-	.detail-value.highlight {
-		color: #ff6b35;
-		font-weight: 600;
+	background: #fff;
+	margin: 20rpx;
+	padding: 24rpx;
+	border-radius: 16rpx;
+	box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
+	
+	.item-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding-bottom: 12rpx;
+		
+		.item-left {
+			display: flex;
+			align-items: center;
+			
+			.document-icon {
+				width: 44rpx;
+				height: 44rpx;
+				background: #3c9cff;
+				border-radius: 10rpx;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				margin-right: 20rpx;
+			}
+			
+			.item-id {
+				font-size: 30rpx;
+				font-weight: bold;
+				color: #333;
+			}
+		}
+	}
+	
+	.item-details {
+		padding: 16rpx 0;
+		
+		.detail-row {
+			display: flex;
+			justify-content: space-between;
+			align-items: flex-start;
+			margin-bottom: 16rpx;
+			
+			.detail-label {
+				font-size: 26rpx;
+				color: #999;
+				min-width: 140rpx;
+			}
+			
+			.detail-value {
+				font-size: 26rpx;
+				color: #333;
+				text-align: right;
+				
+				&.font-bold {
+					font-weight: bold;
+				}
+			}
+			
+			.progress-box {
+				flex: 1;
+				margin-left: 40rpx;
+				
+				.progress-text {
+					font-size: 22rpx;
+					color: #999;
+					margin-top: 4rpx;
+					display: block;
+					text-align: right;
+				}
+			}
+		}
+	}
+	
+	.item-footer {
+		padding-top: 20rpx;
+		border-top: 1rpx solid #f0f0f0;
+		display: flex;
+		justify-content: flex-end;
+		
+		.action-btns {
+			display: flex;
+			gap: 20rpx;
+		}
 	}
 }
 
-// 閫傞厤 uView 缁勪欢鏍峰紡
-:deep(.up-input) {
-	background: transparent;
-}
-
-:deep(.up-datetime-picker) {
-	width: 100%;
+.no-data {
+	padding-top: 200rpx;
 }
 </style>

--
Gitblit v1.9.3