From 5b3d68b45ced3d09078e77658641b3f6c7537338 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期三, 06 五月 2026 11:51:27 +0800
Subject: [PATCH] 报工台账模块开发

---
 src/pages.json                                                |    7 
 src/pages/works.vue                                           |    9 +
 src/api/productionManagement/productionProductMain.js         |   29 +++
 src/pages/productionManagement/productionReporting/ledger.vue |  412 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 457 insertions(+), 0 deletions(-)

diff --git a/src/api/productionManagement/productionProductMain.js b/src/api/productionManagement/productionProductMain.js
new file mode 100644
index 0000000..4242e1b
--- /dev/null
+++ b/src/api/productionManagement/productionProductMain.js
@@ -0,0 +1,29 @@
+// 鐢熶骇鎶ュ伐椤甸潰鎺ュ彛
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ鐢熶骇鎶ュ伐涓昏〃
+export function productionProductMainListPage(query) {
+    return request({
+        url: "/productionProductMain/listPage",
+        method: "get",
+        params: query,
+    });
+}
+
+// 鍒犻櫎鎶ュ伐
+export function productionReportDelete(query) {
+    return request({
+        url: "/productionProductMain/delete",
+        method: "get",
+        params: query,
+    });
+}
+
+// 鏌ヨ鎶曞叆鍒楄〃
+export function productionProductInputListPage(query) {
+    return request({
+        url: "/productionProductInput/listPage",
+        method: "get",
+        params: query,
+    });
+}
diff --git a/src/pages.json b/src/pages.json
index 2677dc6..ee0b3e0 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -824,6 +824,13 @@
       }
     },
     {
+      "path": "pages/productionManagement/productionReporting/ledger",
+      "style": {
+        "navigationBarTitleText": "鎶ュ伐鍙拌处",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/productionManagement/workOrder/index",
       "style": {
         "navigationBarTitleText": "鐢熶骇宸ュ崟",
diff --git a/src/pages/productionManagement/productionReporting/ledger.vue b/src/pages/productionManagement/productionReporting/ledger.vue
new file mode 100644
index 0000000..b71a9a3
--- /dev/null
+++ b/src/pages/productionManagement/productionReporting/ledger.vue
@@ -0,0 +1,412 @@
+<template>
+  <view class="reporting-ledger">
+    <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.keyword"
+                    @change="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="list-container"
+                 v-if="tableData.length > 0"
+                 @scrolltolower="loadMore">
+      <view class="ledger-list">
+        <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.productNo || '-' }}</text>
+              </view>
+              <view class="item-tag">
+                <text class="create-time">{{ formatDate(item.createTime) }}</text>
+              </view>
+            </view>
+            <up-divider></up-divider>
+            <view class="item-details">
+              <view class="detail-row">
+                <text class="detail-label">鎶ュ伐浜哄憳</text>
+                <text class="detail-value highlight">{{ item.nickName || '-' }}</text>
+              </view>
+              <view class="detail-row">
+                <text class="detail-label">鎵�灞炲伐搴�</text>
+                <view class="detail-value">
+                  <up-tag :text="item.process || '-'"
+                          type="primary"
+                          size="mini"
+                          plain />
+                </view>
+              </view>
+              <view class="detail-row">
+                <text class="detail-label">宸ュ崟缂栧彿</text>
+                <text class="detail-value">{{ item.workOrderNo || '-' }}</text>
+              </view>
+              <view class="detail-row">
+                <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.productModelName || '-' }}</text>
+              </view>
+              <view class="quantity-section">
+                <view class="qty-item">
+                  <text class="qty-label">浜у嚭鏁伴噺</text>
+                  <text class="qty-value success">{{ item.quantity || 0 }} {{ item.unit || '' }}</text>
+                </view>
+                <view class="qty-item">
+                  <text class="qty-label">鎶ュ簾鏁伴噺</text>
+                  <text class="qty-value error">{{ item.scrapQty || 0 }}</text>
+                </view>
+              </view>
+              <view class="item-footer">
+                <view class="action-buttons">
+                  <up-button type="primary"
+                             size="small"
+                             plain
+                             text="鏌ョ湅鎶曞叆"
+                             @click="handleShowInput(item)"></up-button>
+                  <up-button type="info"
+                             size="small"
+                             plain
+                             text="鍙傛暟璇︽儏"
+                             @click="handleShowParams(item)"></up-button>
+                  <up-button type="error"
+                             size="small"
+                             plain
+                             text="鍒犻櫎"
+                             @click="handleDelete(item)"></up-button>
+                </view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <up-loadmore :status="loadStatus"
+                   v-if="tableData.length >= page.size" />
+    </scroll-view>
+    <view v-else
+          class="empty-state">
+      <up-empty mode="data"
+                text="鏆傛棤鎶ュ伐鍙拌处鏁版嵁"></up-empty>
+    </view>
+    <!-- 鎶曞叆璇︽儏寮圭獥 -->
+    <up-modal :show="inputVisible"
+              title="鎶曞叆璇︽儏"
+              @confirm="inputVisible = false">
+      <view class="modal-content scroll-view">
+        <view v-if="inputList.length > 0">
+          <view v-for="(input, idx) in inputList"
+                :key="idx"
+                class="detail-item">
+            <view class="detail-row">
+              <text class="detail-label">鎶曞叆浜у搧</text>
+              <text class="detail-value font-bold">{{ input.productName }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">瑙勬牸鍨嬪彿</text>
+              <text class="detail-value">{{ input.model }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">鎶曞叆鏁伴噺</text>
+              <text class="detail-value highlight">{{ input.quantity }} {{ input.unit }}</text>
+            </view>
+            <up-divider></up-divider>
+          </view>
+        </view>
+        <up-empty v-else
+                  mode="data"
+                  text="鏆傛棤鎶曞叆鏁版嵁" />
+      </view>
+    </up-modal>
+    <!-- 鍙傛暟璇︽儏寮圭獥 -->
+    <up-modal :show="paramsVisible"
+              title="鍙傛暟璇︽儏"
+              @confirm="paramsVisible = false">
+      <view class="modal-content">
+        <view v-if="currentParams.length > 0">
+          <view v-for="(param, idx) in currentParams"
+                :key="idx"
+                class="detail-row">
+            <text class="detail-label">{{ param.paramName }}</text>
+            <text class="detail-value">{{ param.inputValue }} {{ param.unit && param.unit !== '/' ? '(' + param.unit + ')' : '' }}</text>
+          </view>
+        </view>
+        <up-empty v-else
+                  mode="data"
+                  text="鏆傛棤鍙傛暟鏁版嵁" />
+      </view>
+    </up-modal>
+  </view>
+</template>
+
+<script setup>
+  import { ref, reactive, onMounted } from "vue";
+  import dayjs from "dayjs";
+  import {
+    productionProductMainListPage,
+    productionReportDelete,
+    productionProductInputListPage,
+  } from "@/api/productionManagement/productionProductMain.js";
+  import PageHeader from "@/components/PageHeader.vue";
+  import modal from "@/plugins/modal";
+
+  const tableData = ref([]);
+  const loading = ref(false);
+  const loadStatus = ref("loadmore");
+
+  const page = reactive({
+    current: 1,
+    size: 10,
+    total: 0,
+  });
+
+  const searchForm = reactive({
+    keyword: "",
+  });
+
+  // 鎶曞叆璇︽儏鐩稿叧
+  const inputVisible = ref(false);
+  const inputList = ref([]);
+
+  // 鍙傛暟璇︽儏鐩稿叧
+  const paramsVisible = ref(false);
+  const currentParams = ref([]);
+
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  const formatDate = date => {
+    return date ? dayjs(date).format("YYYY-MM-DD HH:mm") : "-";
+  };
+
+  const handleQuery = () => {
+    page.current = 1;
+    tableData.value = [];
+    getList();
+  };
+
+  const loadMore = () => {
+    if (loadStatus.value === "nomore" || loading.value) return;
+    page.current++;
+    getList();
+  };
+
+  const getList = () => {
+    loading.value = true;
+    loadStatus.value = "loading";
+
+    const params = {
+      current: page.current,
+      size: page.size,
+      workOrderNo: searchForm.keyword,
+    };
+
+    productionProductMainListPage(params)
+      .then(res => {
+        loading.value = false;
+        const records = res.data.records || [];
+        if (page.current === 1) {
+          tableData.value = records;
+        } else {
+          tableData.value = [...tableData.value, ...records];
+        }
+
+        if (records.length < page.size) {
+          loadStatus.value = "nomore";
+        } else {
+          loadStatus.value = "loadmore";
+        }
+        page.total = res.data.total || 0;
+      })
+      .catch(() => {
+        loading.value = false;
+        loadStatus.value = "loadmore";
+        modal.msgError("鍔犺浇澶辫触");
+      });
+  };
+
+  const handleShowInput = item => {
+    modal.loading("鍔犺浇涓�...");
+    productionProductInputListPage({
+      productMainId: item.id,
+      current: 1,
+      size: 100,
+    })
+      .then(res => {
+        modal.closeLoading();
+        inputList.value = res.data.records || [];
+        inputVisible.value = true;
+      })
+      .catch(() => {
+        modal.closeLoading();
+        modal.msgError("鍔犺浇鎶曞叆鏁版嵁澶辫触");
+      });
+  };
+
+  const handleShowParams = item => {
+    currentParams.value = item.productionOperationParamList || [];
+    paramsVisible.value = true;
+  };
+
+  const handleDelete = item => {
+    uni.showModal({
+      title: "鎻愮ず",
+      content: "纭畾瑕佸垹闄よ鎶ュ伐璁板綍鍚楋紵",
+      success: res => {
+        if (res.confirm) {
+          productionReportDelete({ id: item.id }).then(res => {
+            if (res.code === 200) {
+              modal.msgSuccess("鍒犻櫎鎴愬姛");
+              handleQuery();
+            } else {
+              modal.msgError(res.msg || "鍒犻櫎澶辫触");
+            }
+          });
+        }
+      },
+    });
+  };
+
+  onMounted(() => {
+    getList();
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "@/styles/procurement-common.scss";
+
+  .reporting-ledger {
+    min-height: 100vh;
+    background-color: #f8f9fa;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .list-container {
+    flex: 1;
+    height: 0;
+  }
+
+  .ledger-item {
+    .item-header {
+      .item-tag {
+        .create-time {
+          font-size: 24rpx;
+          color: #999;
+        }
+      }
+    }
+
+    .item-details {
+      .quantity-section {
+        display: flex;
+        background-color: #f9f9f9;
+        border-radius: 8rpx;
+        padding: 20rpx;
+        margin: 20rpx 0;
+
+        .qty-item {
+          flex: 1;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+
+          &:first-child {
+            border-right: 1rpx solid #eee;
+          }
+
+          .qty-label {
+            font-size: 24rpx;
+            color: #999;
+            margin-bottom: 8rpx;
+          }
+
+          .qty-value {
+            font-size: 32rpx;
+            font-weight: bold;
+
+            &.success {
+              color: #52c41a;
+            }
+
+            &.error {
+              color: #f56c6c;
+            }
+          }
+        }
+      }
+
+      .item-footer {
+        padding-top: 20rpx;
+        border-top: 1rpx solid #f0f0f0;
+
+        .action-buttons {
+          display: flex;
+          justify-content: flex-end;
+          gap: 20rpx;
+        }
+      }
+    }
+  }
+
+  .modal-content {
+    width: 100%;
+    padding: 20rpx 0;
+    max-height: 60vh;
+    overflow-y: auto;
+
+    .detail-item {
+      padding-bottom: 20rpx;
+    }
+
+    .detail-row {
+      display: flex;
+      justify-content: space-between;
+      margin-bottom: 16rpx;
+
+      .detail-label {
+        font-size: 26rpx;
+        color: #999;
+      }
+
+      .detail-value {
+        font-size: 26rpx;
+        color: #333;
+
+        &.font-bold {
+          font-weight: bold;
+        }
+
+        &.highlight {
+          color: #3c9cff;
+        }
+      }
+    }
+  }
+
+  .empty-state {
+    padding-top: 200rpx;
+  }
+</style>
diff --git a/src/pages/works.vue b/src/pages/works.vue
index 71bcd99..a647ada 100644
--- a/src/pages/works.vue
+++ b/src/pages/works.vue
@@ -589,6 +589,10 @@
       icon: "/static/images/icon/shengchanbaogong.svg",
       label: "鐢熶骇鎶ュ伐",
     },
+    {
+      icon: "/static/images/icon/xiaoshoutaizhang.svg",
+      label: "鎶ュ伐鍙拌处",
+    },
     // {
     //   icon: "/static/images/icon/shengchanbaogong.svg",
     //   label: "鐢熶骇宸ュ崟",
@@ -860,6 +864,11 @@
       case "鐢熶骇鎶ュ伐":
         getcode();
         break;
+      case "鎶ュ伐鍙拌处":
+        uni.navigateTo({
+          url: "/pages/productionManagement/productionReporting/ledger",
+        });
+        break;
       case "鐢熶骇鏍哥畻":
         uni.navigateTo({
           url: "/pages/productionManagement/productionAccounting/index",

--
Gitblit v1.9.3