From 927f9a4e4d26a2024c797ca0f29125556a514095 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 30 四月 2026 15:16:44 +0800
Subject: [PATCH] 生产排产
---
src/pages.json | 9 +
src/api/productionManagement/workOrder.js | 14 ++
src/pages/works.vue | 23 ++-
src/pages/productionManagement/productionScheduling/index.vue | 241 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 274 insertions(+), 13 deletions(-)
diff --git a/src/api/productionManagement/workOrder.js b/src/api/productionManagement/workOrder.js
index 7e8bd86..ffdd6a4 100644
--- a/src/api/productionManagement/workOrder.js
+++ b/src/api/productionManagement/workOrder.js
@@ -2,7 +2,7 @@
export function productWorkOrderPage(query) {
return request({
- url: "/productWorkOrder/page",
+ url: "/productionOperationTask/page",
method: "get",
params: query,
});
@@ -10,7 +10,7 @@
export function updateProductWorkOrder(data) {
return request({
- url: "/productWorkOrder/updateProductWorkOrder",
+ url: "/productionOperationTask/updateProductWorkOrder",
method: "post",
data: data,
});
@@ -24,10 +24,18 @@
});
}
+export function assignProductWorkOrder(data) {
+ return request({
+ url: "/productionOperationTask/assign",
+ method: "post",
+ data: data,
+ });
+}
+
// 涓嬭浇宸ュ崟娴佽浆鍗★紙杩斿洖鏂囦欢娴侊級
export function downProductWorkOrder(id) {
return request({
- url: "/productWorkOrder/down",
+ url: "/productionOperationTask/down",
method: "post",
data: { id },
responseType: "blob",
diff --git a/src/pages.json b/src/pages.json
index ce4058c..2677dc6 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -840,7 +840,14 @@
{
"path": "pages/productionManagement/mainProductionPlan/detail",
"style": {
- "navigationBarTitleText": "璁″垝璇︽儏",
+ "navigationBarTitleText": "鐢熶骇璁″垝璇︽儏",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/productionManagement/productionScheduling/index",
+ "style": {
+ "navigationBarTitleText": "鐢熶骇鎺掍骇",
"navigationStyle": "custom"
}
},
diff --git a/src/pages/productionManagement/productionScheduling/index.vue b/src/pages/productionManagement/productionScheduling/index.vue
new file mode 100644
index 0000000..5cc2c0c
--- /dev/null
+++ b/src/pages/productionManagement/productionScheduling/index.vue
@@ -0,0 +1,241 @@
+<template>
+ <view class="production-scheduling">
+ <!-- 閫氱敤椤甸潰澶撮儴 -->
+ <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.workOrderNo"
+ @confirm="handleQuery"
+ clearable />
+ </view>
+ <view class="filter-button"
+ @click="handleQuery">
+ <up-icon name="search"
+ size="24"
+ color="#999"></up-icon>
+ </view>
+ </view>
+ </view>
+ <!-- 鍒楄〃 -->
+ <scroll-view scroll-y
+ class="ledger-list"
+ v-if="tableData.length > 0"
+ @scrolltolower="loadMore">
+ <view v-for="(item, index) in tableData"
+ :key="item.id || index"
+ 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.workOrderNo }}</text>
+ </view>
+ <view class="item-right">
+ <up-tag :text="item.workOrderType"
+ size="mini"
+ type="primary"
+ plain></up-tag>
+ </view>
+ </view>
+ <up-divider></up-divider>
+ <view class="item-details">
+ <view class="detail-row">
+ <text class="detail-label">鐢熶骇璁㈠崟鍙�</text>
+ <text class="detail-value">{{ item.npsNo || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">浜у搧鍚嶇О</text>
+ <text class="detail-value">{{ item.productName || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">瑙勬牸鍨嬪彿</text>
+ <text class="detail-value">{{ item.model || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">鍗曚綅</text>
+ <text class="detail-value">{{ item.unit || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">宸ュ簭鍚嶇О</text>
+ <text class="detail-value">{{ item.operationName || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">闇�姹傛暟閲�</text>
+ <text class="detail-value">{{ item.planQuantity || 0 }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">瀹屾垚鏁伴噺</text>
+ <text class="detail-value">{{ item.completeQuantity || 0 }}</text>
+ </view>
+ <view class="progress-section">
+ <text class="detail-label">瀹屾垚杩涘害</text>
+ <view class="progress-bar">
+ <up-line-progress :percentage="toProgressPercentage(item.completionStatus)"
+ :activeColor="progressColor(item.completionStatus)"
+ :showText="true"></up-line-progress>
+ </view>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">璁″垝寮�濮�</text>
+ <text class="detail-value">{{ item.planStartTime || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">璁″垝缁撴潫</text>
+ <text class="detail-value">{{ item.planEndTime || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">瀹為檯寮�濮�</text>
+ <text class="detail-value">{{ item.actualStartTime || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">瀹為檯缁撴潫</text>
+ <text class="detail-value">{{ item.actualEndTime || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">鎸囧畾鎶ュ伐浜�</text>
+ <view class="detail-value tags-box">
+ <template v-if="item.userNames">
+ <up-tag v-for="(name, idx) in item.userNames.split(',')"
+ :key="idx"
+ :text="name"
+ size="mini"
+ type="info"
+ plain
+ class="user-tag"></up-tag>
+ </template>
+ <text v-else>-</text>
+ </view>
+ </view>
+ </view>
+ </view>
+ <up-loadmore :status="loadStatus" />
+ </scroll-view>
+ <view v-else-if="!loading"
+ class="no-data">
+ <up-empty mode="data"
+ text="鏆傛棤鏁版嵁"></up-empty>
+ </view>
+ </view>
+</template>
+
+<script setup>
+ import { ref, reactive, toRefs, getCurrentInstance } from "vue";
+ import { onShow } from "@dcloudio/uni-app";
+ import { productWorkOrderPage } from "@/api/productionManagement/workOrder.js";
+ import PageHeader from "@/components/PageHeader.vue";
+
+ const { proxy } = getCurrentInstance();
+
+ const loading = ref(false);
+ const tableData = ref([]);
+ const loadStatus = ref("loadmore");
+
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ const data = reactive({
+ searchForm: {
+ workOrderNo: "",
+ },
+ });
+ const { searchForm } = toRefs(data);
+
+ const goBack = () => {
+ uni.navigateBack();
+ };
+
+ const handleQuery = () => {
+ page.current = 1;
+ tableData.value = [];
+ getList();
+ };
+
+ const getList = () => {
+ if (loading.value) return;
+ loading.value = true;
+
+ const params = {
+ ...searchForm.value,
+ ...page,
+ };
+
+ productWorkOrderPage(params)
+ .then(res => {
+ loading.value = false;
+ const records = res.data.records || [];
+ tableData.value =
+ page.current === 1 ? records : [...tableData.value, ...records];
+ page.total = res.data.total;
+
+ if (tableData.value.length >= page.total) {
+ loadStatus.value = "nomore";
+ } else {
+ loadStatus.value = "loadmore";
+ }
+ })
+ .catch(() => {
+ loading.value = false;
+ uni.showToast({ title: "鍔犺浇澶辫触", icon: "error" });
+ });
+ };
+
+ const loadMore = () => {
+ if (loadStatus.value === "nomore" || loading.value) return;
+ page.current++;
+ getList();
+ };
+
+ 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";
+ };
+
+ onShow(() => {
+ handleQuery();
+ });
+</script>
+
+<style scoped lang="scss">
+ @import "@/styles/sales-common.scss";
+
+ .production-scheduling {
+ padding-bottom: 20rpx;
+ }
+ .progress-bar {
+ margin-top: 20rpx;
+ margin-bottom: 20rpx;
+ }
+
+ .tags-box {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8rpx;
+ justify-content: flex-end;
+ }
+
+ .user-tag {
+ margin-bottom: 4rpx;
+ }
+</style>
diff --git a/src/pages/works.vue b/src/pages/works.vue
index 202d9ca..bb7eeab 100644
--- a/src/pages/works.vue
+++ b/src/pages/works.vue
@@ -570,17 +570,17 @@
// 鐢熶骇绠℃帶鍔熻兘鏁版嵁
const productionItems = reactive([
{
- icon: "/static/images/icon/shengchandingdan@2x.svg",
+ icon: "/static/images/icon/shengchanbaogong.svg",
label: "鐢熶骇璁㈠崟",
},
// {
// icon: "/static/images/icon/shengchanpaigong@2x.svg",
// label: "鐢熶骇娲惧伐",
// },
- // {
- // icon: "/static/images/icon/shengchanpaichan@2x.svg",
- // label: "宸ュ簭鎺掍骇",
- // },
+ {
+ icon: "/static/images/icon/shengchanpaichan@2x.svg",
+ label: "鐢熶骇鎺掍骇",
+ },
{
icon: "/static/images/icon/shengchanbaogong.svg",
label: "涓荤敓浜ц鍒�",
@@ -589,10 +589,10 @@
icon: "/static/images/icon/shengchanbaogong.svg",
label: "鐢熶骇鎶ュ伐",
},
- {
- icon: "/static/images/icon/shengchanbaogong.svg",
- label: "鐢熶骇宸ュ崟",
- },
+ // {
+ // icon: "/static/images/icon/shengchanbaogong.svg",
+ // label: "鐢熶骇宸ュ崟",
+ // },
// {
// icon: "/static/images/icon/shengchanhesuan@2x.svg",
// label: "鐢熶骇鏍哥畻",
@@ -852,6 +852,11 @@
url: "/pages/productionManagement/mainProductionPlan/index",
});
break;
+ case "鐢熶骇鎺掍骇":
+ uni.navigateTo({
+ url: "/pages/productionManagement/productionScheduling/index",
+ });
+ break;
case "鐢熶骇鎶ュ伐":
getcode();
break;
--
Gitblit v1.9.3