zhangwencui
2026-04-30 fa403c58d2bea76a7131ea9dbb1d60247ea9ca77
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>