| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |