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