From 5209c2fb7f9b764aed59f827420e151bf649bdb3 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 26 九月 2025 14:33:49 +0800
Subject: [PATCH] 生产派工页面开发联调

---
 src/pages/index.vue                                                               |   58 +-
 src/pages/productionManagement/productionDispatching/components/formDia.vue       |  169 +++++++++++
 src/pages.json                                                                    |    7 
 src/pages/productionManagement/productionDispatching/components/DispatchModal.vue |  399 ++++++++++++++++++++++++++
 src/pages/productionManagement/productionDispatching/index.vue                    |  235 +++++++++++++++
 5 files changed, 839 insertions(+), 29 deletions(-)

diff --git a/src/pages.json b/src/pages.json
index 00c7e56..4151447 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -406,6 +406,13 @@
         "navigationBarTitleText": "鐢熶骇璁㈠崟",
         "navigationStyle": "custom"
       }
+    },
+    {
+      "path": "pages/productionManagement/productionDispatching/index",
+      "style": {
+        "navigationBarTitleText": "鐢熶骇娲惧伐",
+        "navigationStyle": "custom"
+      }
     }
   ],
   "subPackages": [
diff --git a/src/pages/index.vue b/src/pages/index.vue
index b8fdbd2..0885a17 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -124,34 +124,34 @@
 		</view>
 		
 		<!-- 鐢熶骇绠℃帶妯″潡 -->
-		<view class="common-module production-module">
-			<view class="module-header">
-				<view class="module-title-container">
-					<text class="module-title">鐢熶骇绠℃帶</text>
-				</view>
-			</view>
-			<view class="module-content">
-				<up-grid
-					:border="false"
-					col="4"
-				>
-					<up-grid-item
-						v-for="(item, index) in productionItems"
-						:key="index"
-						@click="handleCommonItemClick(item)"
-					>
-						<view class="icon-container" :style="{ background: item.bgColor }">
-							<up-icon
-								:name="item.icon"
-								:size="58"
-								color="#ffffff"
-							></up-icon>
-						</view>
-						<text class="item-label">{{item.label}}</text>
-					</up-grid-item>
-				</up-grid>
-			</view>
-		</view>
+<!--		<view class="common-module production-module">-->
+<!--			<view class="module-header">-->
+<!--				<view class="module-title-container">-->
+<!--					<text class="module-title">鐢熶骇绠℃帶</text>-->
+<!--				</view>-->
+<!--			</view>-->
+<!--			<view class="module-content">-->
+<!--				<up-grid-->
+<!--					:border="false"-->
+<!--					col="4"-->
+<!--				>-->
+<!--					<up-grid-item-->
+<!--						v-for="(item, index) in productionItems"-->
+<!--						:key="index"-->
+<!--						@click="handleCommonItemClick(item)"-->
+<!--					>-->
+<!--						<view class="icon-container" :style="{ background: item.bgColor }">-->
+<!--							<up-icon-->
+<!--								:name="item.icon"-->
+<!--								:size="58"-->
+<!--								color="#ffffff"-->
+<!--							></up-icon>-->
+<!--						</view>-->
+<!--						<text class="item-label">{{item.label}}</text>-->
+<!--					</up-grid-item>-->
+<!--				</up-grid>-->
+<!--			</view>-->
+<!--		</view>-->
 		
 		<!-- 璁惧绠$悊妯″潡 -->
 		<view class="common-module equipment-module">
@@ -433,7 +433,7 @@
 			break;
 		case '鐢熶骇娲惧伐':
 			uni.navigateTo({
-				url: '/pages/productionManagement/productionDispatch/index'
+				url: '/pages/productionManagement/productionDispatching/index'
 			});
 			break;
 		case '宸ュ簭鎺掍骇':
diff --git a/src/pages/productionManagement/productionDispatching/components/DispatchModal.vue b/src/pages/productionManagement/productionDispatching/components/DispatchModal.vue
new file mode 100644
index 0000000..95c3705
--- /dev/null
+++ b/src/pages/productionManagement/productionDispatching/components/DispatchModal.vue
@@ -0,0 +1,399 @@
+<template>
+	<up-popup 
+		v-model:show="show" 
+		mode="bottom" 
+		:round="20"
+		:safeAreaInsetBottom="true"
+		@close="handleClose"
+		@open="handleOpen"
+	>
+		<view class="dispatch-modal">
+			<!-- 澶撮儴 -->
+			<view class="modal-header">
+				<text class="modal-title">鐢熶骇娲惧伐</text>
+				<view class="close-btn" @click="handleClose">
+					<up-icon name="close" size="20" color="#999"></up-icon>
+				</view>
+			</view>
+			
+			<!-- 琛ㄥ崟鍐呭 -->
+			<view class="modal-content">
+				<up-form 
+					:model="form" 
+					ref="formRef"
+					:rules="rules"
+					labelWidth="120"
+				>
+					<!-- 椤圭洰鍩烘湰淇℃伅 -->
+					<view class="form-section">
+						<text class="section-title">椤圭洰淇℃伅</text>
+						<up-form-item label="椤圭洰鍚嶇О" prop="projectName">
+							<up-input 
+								v-model="form.projectName" 
+								disabled 
+								placeholder="椤圭洰鍚嶇О"
+							/>
+						</up-form-item>
+						<up-form-item label="浜у搧澶х被" prop="productCategory">
+							<up-input 
+								v-model="form.productCategory" 
+								disabled 
+								placeholder="浜у搧澶х被"
+							/>
+						</up-form-item>
+					</view>
+					
+					<!-- 鏁伴噺淇℃伅 -->
+					<view class="form-section">
+						<text class="section-title">鏁伴噺淇℃伅</text>
+						<up-form-item label="鎬绘暟閲�" prop="quantity">
+							<up-input 
+								v-model="form.quantity" 
+								disabled 
+								placeholder="鎬绘暟閲�"
+							/>
+						</up-form-item>
+						<up-form-item label="寰呮帓浜ф暟閲�" prop="pendingQuantity">
+							<up-input 
+								v-model="form.pendingQuantity" 
+								disabled 
+								placeholder="寰呮帓浜ф暟閲�"
+							/>
+						</up-form-item>
+						<up-form-item label="鏈鎺掍骇鏁伴噺" prop="schedulingNum" required>
+							<up-number-box 
+								v-model="form.schedulingNum"
+								:min="0"
+								:max="form.pendingQuantity"
+								:step="0.1"
+								:precision="2"
+								@change="handleNumChange"
+							/>
+						</up-form-item>
+					</view>
+					
+					<!-- 娲惧伐淇℃伅 -->
+					<view class="form-section">
+						<text class="section-title">娲惧伐淇℃伅</text>
+						<up-form-item label="娲惧伐浜�" prop="schedulingUserId" required>
+							<up-input 
+								v-model="selectedUserName"
+								placeholder="璇烽�夋嫨娲惧伐浜�"
+								readonly
+								@click="showUserPicker = true"
+								suffixIcon="arrow-down"
+							/>
+						</up-form-item>
+						<up-form-item label="娲惧伐鏃ユ湡" prop="schedulingDate" required>
+							<up-input 
+								v-model="form.schedulingDate"
+								placeholder="璇烽�夋嫨娲惧伐鏃ユ湡"
+								readonly
+								@click="showDatePicker = true"
+								suffixIcon="calendar"
+							/>
+						</up-form-item>
+					</view>
+				</up-form>
+			</view>
+			
+			<!-- 搴曢儴鎸夐挳 -->
+			<view class="modal-footer">
+				<up-button 
+					@click="handleClose" 
+					text="鍙栨秷"
+					type="info"
+					plain
+					:customStyle="{ marginRight: '12px', flex: 1 }"
+				/>
+				<up-button 
+					@click="handleConfirm" 
+					text="纭娲惧伐"
+					type="primary"
+					:customStyle="{ flex: 1 }"
+					:loading="submitting"
+				/>
+			</view>
+		</view>
+		
+		<!-- 浜哄憳閫夋嫨鍣� -->
+		<up-picker
+			v-model="showUserPicker"
+			:columns="userColumns"
+			@confirm="handleUserSelect"
+			@cancel="showUserPicker = false"
+		/>
+		
+		<!-- 鏃ユ湡閫夋嫨鍣� -->
+		<up-datetime-picker
+			v-model="showDatePicker"
+			mode="date"
+			@confirm="handleDateSelect"
+			@cancel="showDatePicker = false"
+		/>
+	</up-popup>
+</template>
+
+<script setup>
+import { ref, reactive, computed, getCurrentInstance } from 'vue';
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { productionDispatch } from "@/api/productionManagement/productionOrder.js";
+import useUserStore from "@/store/modules/user";
+import dayjs from "dayjs";
+
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
+const emit = defineEmits(['confirm']);
+
+// 寮圭獥鏄剧ず鐘舵��
+const show = ref(false);
+const submitting = ref(false);
+
+// 閫夋嫨鍣ㄦ樉绀虹姸鎬�
+const showUserPicker = ref(false);
+const showDatePicker = ref(false);
+
+// 鐢ㄦ埛鍒楄〃
+const userList = ref([]);
+const userColumns = computed(() => [
+	userList.value.map(user => ({
+		label: user.nickName,
+		value: user.userId
+	}))
+]);
+
+// 閫変腑鐨勭敤鎴峰悕绉帮紙鐢ㄤ簬鏄剧ず锛�
+const selectedUserName = computed(() => {
+	const user = userList.value.find(u => u.userId === form.schedulingUserId);
+	return user ? user.nickName : '';
+});
+
+// 琛ㄥ崟鏁版嵁
+const form = reactive({
+	projectName: "",
+	productCategory: "",
+	quantity: "",
+	schedulingNum: 0,
+	schedulingUserId: "",
+	schedulingDate: "",
+	pendingQuantity: 0,
+	id: "" // 鍘熷璁板綍ID
+});
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = reactive({
+	schedulingNum: [
+		{ required: true, message: "璇疯緭鍏ユ帓浜ф暟閲�", trigger: "blur" }
+	],
+	schedulingUserId: [
+		{ required: true, message: "璇烽�夋嫨娲惧伐浜�", trigger: "change" }
+	],
+	schedulingDate: [
+		{ required: true, message: "璇烽�夋嫨娲惧伐鏃ユ湡", trigger: "change" }
+	]
+});
+
+// 琛ㄥ崟寮曠敤
+const formRef = ref();
+
+// 鎵撳紑寮圭獥
+const open = async (rowData) => {
+	try {
+		// 鍔犺浇鐢ㄦ埛鍒楄〃
+		const res = await userListNoPageByTenantId();
+		userList.value = res.data || [];
+		
+		// 濉厖琛ㄥ崟鏁版嵁
+		Object.assign(form, {
+			...rowData,
+			schedulingNum: 0,
+			schedulingUserId: userStore.id,
+			schedulingDate: dayjs().format("YYYY-MM-DD")
+		});
+		
+		show.value = true;
+	} catch (error) {
+		uni.showToast({
+			title: '鍔犺浇鐢ㄦ埛鍒楄〃澶辫触',
+			icon: 'error'
+		});
+	}
+};
+
+// 澶勭悊鏁伴噺鍙樺寲
+const handleNumChange = (value) => {
+	if (value > form.pendingQuantity) {
+		form.schedulingNum = form.pendingQuantity;
+		uni.showToast({
+			title: '鎺掍骇鏁伴噺涓嶅彲澶т簬寰呮帓浜ф暟閲�',
+			icon: 'none'
+		});
+	}
+};
+
+// 澶勭悊鐢ㄦ埛閫夋嫨
+const handleUserSelect = (params) => {
+	if (params.value && params.value.length > 0) {
+		form.schedulingUserId = params.value[0];
+	}
+	showUserPicker.value = false;
+};
+
+// 澶勭悊鏃ユ湡閫夋嫨
+const handleDateSelect = (params) => {
+	if (params.value) {
+		form.schedulingDate = dayjs(params.value).format("YYYY-MM-DD");
+	}
+	showDatePicker.value = false;
+};
+
+// 纭娲惧伐
+const handleConfirm = async () => {
+	try {
+		// 琛ㄥ崟楠岃瘉
+		const valid = await formRef.value?.validate();
+		if (!valid) return;
+		
+		if (form.schedulingNum <= 0) {
+			uni.showToast({
+				title: '鎺掍骇鏁伴噺蹇呴』澶т簬0',
+				icon: 'none'
+			});
+			return;
+		}
+		
+		submitting.value = true;
+		
+		// 鎻愪氦娲惧伐鏁版嵁
+		await productionDispatch(form);
+		
+		uni.showToast({
+			title: '娲惧伐鎴愬姛',
+			icon: 'success'
+		});
+		
+		handleClose();
+		emit('confirm');
+		
+	} catch (error) {
+		uni.showToast({
+			title: '娲惧伐澶辫触',
+			icon: 'error'
+		});
+	} finally {
+		submitting.value = false;
+	}
+};
+
+// 寮圭獥鎵撳紑浜嬩欢
+const handleOpen = () => {
+	// 寮圭獥鎵撳紑鏃剁殑澶勭悊
+};
+
+// 鍏抽棴寮圭獥
+const handleClose = () => {
+	show.value = false;
+	showUserPicker.value = false;
+	showDatePicker.value = false;
+	
+	// 閲嶇疆琛ㄥ崟
+	Object.assign(form, {
+		projectName: "",
+		productCategory: "",
+		quantity: "",
+		schedulingNum: 0,
+		schedulingUserId: "",
+		schedulingDate: "",
+		pendingQuantity: 0,
+		id: ""
+	});
+};
+
+// 鏆撮湶鏂规硶
+defineExpose({
+	open
+});
+</script>
+
+<style scoped lang="scss">
+.dispatch-modal {
+	background: #ffffff;
+	border-radius: 20px 20px 0 0;
+	max-height: 80vh;
+	overflow: hidden;
+	display: flex;
+	flex-direction: column;
+}
+
+.modal-header {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	padding: 20px 20px 0 20px;
+	border-bottom: 1px solid #f0f0f0;
+	padding-bottom: 16px;
+	margin-bottom: 20px;
+}
+
+.modal-title {
+	font-size: 18px;
+	font-weight: 600;
+	color: #333;
+}
+
+.close-btn {
+	padding: 4px;
+	
+	&:active {
+		opacity: 0.7;
+	}
+}
+
+.modal-content {
+	flex: 1;
+	padding: 0 20px;
+	overflow-y: auto;
+}
+
+.form-section {
+	margin-bottom: 24px;
+}
+
+.section-title {
+	display: block;
+	font-size: 16px;
+	font-weight: 600;
+	color: #333;
+	margin-bottom: 16px;
+	padding-left: 8px;
+	border-left: 3px solid #2979ff;
+}
+
+.modal-footer {
+	display: flex;
+	gap: 12px;
+	padding: 20px;
+	border-top: 1px solid #f0f0f0;
+	background: #fafafa;
+}
+
+// uView 缁勪欢鏍峰紡璋冩暣
+:deep(.up-form-item) {
+	margin-bottom: 20px;
+}
+
+:deep(.up-input) {
+	background: #f8f9fa;
+	border-radius: 8px;
+}
+
+:deep(.up-input--disabled) {
+	background: #f0f0f0;
+	color: #999;
+}
+
+:deep(.up-number-box) {
+	background: #f8f9fa;
+	border-radius: 8px;
+}
+</style>
diff --git a/src/pages/productionManagement/productionDispatching/components/formDia.vue b/src/pages/productionManagement/productionDispatching/components/formDia.vue
new file mode 100644
index 0000000..a60f751
--- /dev/null
+++ b/src/pages/productionManagement/productionDispatching/components/formDia.vue
@@ -0,0 +1,169 @@
+<template>
+  <div>
+    <el-dialog
+        v-model="dialogFormVisible"
+        title="鐢熶骇娲惧伐"
+        width="50%"
+        @close="closeDia"
+    >
+      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
+              <el-input v-model="form.projectName" placeholder="璇疯緭鍏�" clearable disabled/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
+              <el-input v-model="form.productCategory" placeholder="璇疯緭鍏�" clearable disabled/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鎬绘暟閲忥細" prop="quantity">
+              <el-input v-model="form.quantity" placeholder="璇疯緭鍏�" clearable disabled/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+						<el-form-item label="寰呮帓浜ф暟閲忥細" prop="pendingQuantity">
+							<el-input v-model="form.pendingQuantity" placeholder="璇疯緭鍏�" clearable disabled/>
+						</el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+						<el-form-item label="鏈鎺掍骇鏁伴噺锛�" prop="schedulingNum">
+							<el-input-number
+								v-model="form.schedulingNum"
+								placeholder="璇疯緭鍏�"
+								:min="0"
+								:step="0.1"
+								:precision="2"
+								clearable
+								@change="changeNum"
+								style="width: 100%"
+							/>
+						</el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="娲惧伐浜猴細" prop="schedulingUserId">
+							<el-select
+								v-model="form.schedulingUserId"
+								placeholder="閫夋嫨浜哄憳"
+								style="width: 100%;"
+							>
+								<el-option
+									v-for="user in userList"
+									:key="user.userId"
+									:label="user.nickName"
+									:value="user.userId"
+								/>
+							</el-select>
+						</el-form-item>
+					</el-col>
+          <el-col :span="12">
+            <el-form-item label="娲惧伐鏃ユ湡锛�" prop="schedulingDate">
+              <el-date-picker
+                  v-model="form.schedulingDate"
+                  type="date"
+                  placeholder="璇烽�夋嫨鏃ユ湡"
+                  value-format="YYYY-MM-DD"
+                  format="YYYY-MM-DD"
+                  clearable
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭</el-button>
+          <el-button @click="closeDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
+import {userListNoPageByTenantId} from "@/api/system/user.js";
+import {productionDispatch} from "@/api/productionManagement/productionOrder.js";
+import useUserStore from "@/store/modules/user.js";
+import dayjs from "dayjs";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const data = reactive({
+  form: {
+		projectName: "",
+		productCategory: "",
+		quantity: "",
+		schedulingNum: "",
+		schedulingUserId: "",
+		schedulingDate: "",
+		pendingQuantity: "",
+  },
+  rules: {
+		schedulingNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" },],
+		schedulingUserId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" },],
+		schedulingDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" },],
+  },
+});
+const { form, rules } = toRefs(data);
+const userList = ref([])
+const userStore = useUserStore()
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+  operationType.value = type;
+  dialogFormVisible.value = true;
+	userListNoPageByTenantId().then((res) => {
+		userList.value = res.data;
+	});
+	form.value = {...row}
+	form.value.schedulingNum = 0
+	form.value.schedulingUserId = userStore.id
+	form.value.schedulingDate = dayjs().format("YYYY-MM-DD");
+}
+
+//
+const changeNum = (value) => {
+	if (value > form.value.pendingQuantity) {
+		form.value.schedulingNum = form.value.pendingQuantity;
+		proxy.$modal.msgWarning('鎺掍骇鏁伴噺涓嶅彲澶т簬寰呮帓浜ф暟閲�')
+	}
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+  proxy.$refs.formRef.validate(valid => {
+    if (valid) {
+			productionDispatch(form.value).then(res => {
+				proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+				closeDia();
+			})
+    }
+  })
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+  proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+  emit('close')
+};
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/pages/productionManagement/productionDispatching/index.vue b/src/pages/productionManagement/productionDispatching/index.vue
new file mode 100644
index 0000000..7aea197
--- /dev/null
+++ b/src/pages/productionManagement/productionDispatching/index.vue
@@ -0,0 +1,235 @@
+<template>
+	<view class="production-dispatching">
+		<!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+		<PageHeader title="鐢熶骇娲惧伐" @back="goBack" />
+		
+		<!-- 鎼滅储鍖哄煙 -->
+		<view class="search-section">
+			<view class="search-bar">
+				<view class="search-input">
+					<up-input
+						class="search-text"
+						placeholder="璇疯緭鍏ュ鎴峰悕绉版悳绱�"
+						v-model="searchForm.customerName"
+						@change="handleQuery"
+						clearable
+					/>
+				</view>
+				<view class="filter-button" @click="handleQuery">
+					<up-icon name="search" size="24" color="#999"></up-icon>
+				</view>
+			</view>
+		</view>
+		
+		<!-- 鐢熶骇娲惧伐鍒楄〃 -->
+		<view class="ledger-list" v-if="tableData.length > 0">
+			<view v-for="(item, index) in tableData" :key="item.id || index">
+				<view class="ledger-item">
+					<view class="item-header">
+						<view class="item-left">
+							<view class="document-icon">
+								<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
+							</view>
+							<text class="item-id">{{ item.salesContractNo }}</text>
+						</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>
+						</view>
+						<view class="detail-row">
+							<text class="detail-label">瑙勬牸鍨嬪彿</text>
+							<text class="detail-value">{{ item.specificationModel }}</text>
+						</view>
+						<view class="detail-row">
+							<text class="detail-label">鎬绘暟閲�</text>
+							<text class="detail-value">{{ item.quantity }} {{ item.unit }}</text>
+						</view>
+						<view class="detail-row">
+							<text class="detail-label">鎺掍骇鏁伴噺</text>
+							<text class="detail-value highlight">{{ item.schedulingNum }}</text>
+						</view>
+						<view class="detail-row">
+							<text class="detail-label">寰呮帓鏁伴噺</text>
+							<text class="detail-value" :class="{ 'danger': item.pendingQuantity <= 0 }">{{ item.pendingQuantity }}</text>
+						</view>
+					</view>
+					
+					<!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
+					<view class="action-buttons">
+						<up-button
+							type="primary"
+							size="small"
+							@click="handleDispatch(item)"
+							class="action-btn"
+							:disabled="item.pendingQuantity <= 0"
+						>
+							鐢熶骇娲惧伐
+						</up-button>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view v-else class="no-data">
+			<text>鏆傛棤鐢熶骇娲惧伐鏁版嵁</text>
+		</view>
+		
+		<!-- 娲惧伐寮圭獥 -->
+		<DispatchModal ref="dispatchModalRef" @confirm="handleDispatchConfirm" />
+	</view>
+</template>
+
+<script setup>
+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 PageHeader from "@/components/PageHeader.vue";
+import DispatchModal from "./components/DispatchModal.vue";
+const { proxy } = getCurrentInstance();
+
+// 鍔犺浇鐘舵��
+const loading = ref(false);
+
+// 鍒楄〃鏁版嵁
+const tableData = ref([]);
+
+
+// 鎼滅储琛ㄥ崟鏁版嵁
+const data = reactive({
+	searchForm: {
+		customerName: "",
+	},
+});
+const { searchForm } = toRefs(data);
+
+// 鍒嗛〉閰嶇疆
+const page = reactive({
+	current: -1,
+	size: -1,
+});
+
+// 娲惧伐寮圭獥寮曠敤
+const dispatchModalRef = ref();
+
+// 閫氱敤鎻愮ず鍑芥暟
+const showLoadingToast = (message) => {
+	uni.showLoading({
+		title: message,
+		mask: true
+	});
+};
+
+const closeToast = () => {
+	uni.hideLoading();
+};
+
+// 杩斿洖涓婁竴椤�
+const goBack = () => {
+	uni.navigateBack();
+};
+
+// 鏌ヨ鍒楄〃
+const handleQuery = () => {
+	getList();
+};
+
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = () => {
+	loading.value = true;
+	showLoadingToast('鍔犺浇涓�...');
+	
+	// 鏋勯�犺姹傚弬鏁�
+	const params = { ...searchForm.value, ...page };
+	
+	schedulingListPage(params).then((res) => {
+		loading.value = false;
+		closeToast();
+		
+		// 澶勭悊姣忔潯鏁版嵁锛屽鍔爌endingQuantity瀛楁
+		tableData.value = (res.data.records || []).map(item => ({
+			...item,
+			pendingQuantity: (Number(item.quantity) || 0) - (Number(item.schedulingNum) || 0)
+		}));
+	}).catch(() => {
+		loading.value = false;
+		closeToast();
+		uni.showToast({
+			title: '鍔犺浇澶辫触',
+			icon: 'error'
+		});
+	});
+};
+
+// 澶勭悊娲惧伐鎿嶄綔
+const handleDispatch = (item) => {
+	if (item.pendingQuantity <= 0) {
+		uni.showToast({
+			title: '璇ラ」鐩棤闇�鍐嶆淳宸�',
+			icon: 'none'
+		});
+		return;
+	}
+	
+	dispatchModalRef.value?.open(item);
+};
+
+// 澶勭悊娲惧伐纭
+const handleDispatchConfirm = () => {
+	getList(); // 鍒锋柊鍒楄〃
+};
+
+// 椤甸潰鏄剧ず鏃跺姞杞芥暟鎹�
+onShow(() => {
+	// 鍔犺浇鍒楄〃鏁版嵁
+	getList();
+});
+</script>
+
+<style scoped lang="scss">
+@import '@/styles/sales-common.scss';
+
+// 鐢熶骇娲惧伐椤甸潰鏍峰紡
+.production-dispatching {
+	min-height: 100vh;
+	background: #f8f9fa;
+	position: relative;
+}
+
+// 鍒楄〃椤规牱寮�
+.ledger-item {
+	.detail-value.highlight {
+		color: #ff6b35;
+		font-weight: 600;
+	}
+	
+	.detail-value.danger {
+		color: #ee0a24;
+		font-weight: 600;
+	}
+}
+
+// 閫傞厤 uView 缁勪欢鏍峰紡
+:deep(.up-input) {
+	background: transparent;
+}
+</style>

--
Gitblit v1.9.3