| src/pages/inventoryManagement/stockManagement/Qualified.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/inventoryManagement/stockManagement/Unqualified.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/inventoryManagement/stockManagement/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/inventoryManagement/stockManagement/rawMaterialRecord.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/productionManagement/productionReport/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/works.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/pages/inventoryManagement/stockManagement/Qualified.vue
@@ -27,7 +27,7 @@ <text class="item-id">{{ item.productName }}</text> </view> <view class="item-right"> <text class="item-tag tag-type">åæ ¼åºå</text> <text class="item-tag tag-type">æååºå</text> </view> </view> @@ -35,28 +35,28 @@ <view class="item-details"> <view class="detail-row"> <text class="detail-label">è§æ ¼åå·</text> <text class="detail-value">{{ item.model }}</text> <text class="detail-label">åè´§/è§æ ¼</text> <text class="detail-value">{{item.productName || "æ " }} / {{ item.model || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">åºåæ°é</text> <text class="detail-value">{{ item.qualitity }} {{ item.unit }}</text> <text class="detail-label">主æ°é/主åä½</text> <text class="detail-value">{{ item.qualitity || "æ " }} / {{ item.unit || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">éå®/å»ç»</text> <text class="detail-value">{{ item.lockedQuantity }} {{ item.unit }}</text> <text class="detail-label">è¾ æ°é/è¾ åä½</text> <text class="detail-value">{{ item.subQualitity || "æ " }} / {{ item.subUnit || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">å¯ç¨åºå</text> <text class="detail-value" style="color: #2979ff; font-weight: bold;">{{ item.unLockedQuantity }} {{ item.unit }}</text> <text class="detail-label">ä»åºç¼ç /ä»åºåç§°</text> <text class="detail-value">{{ item.warehouseCode || "æ " }} / {{ item.warehouseName || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">åºåé¢è¦</text> <text class="detail-value">{{ item.warnNum }}</text> <text class="detail-label">åè´§ç¼ç /åºåé¢è¦</text> <text class="detail-value">{{ item.productCode || "æ " }} / {{ item.warnNum || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">æ´æ°æ¶é´</text> <text class="detail-value">{{ item.updateTime }}</text> <text class="detail-value">{{ item.updateTime || "æ " }}</text> </view> </view> </view> @@ -77,7 +77,7 @@ const loadStatus = ref('loadmore'); const page = reactive({ current: 1, size: 10 }); const total = ref(0); const searchForm = reactive({ productName: '' }); const searchForm = reactive({ productName: '', rootName: 'æå' }); const handleQuery = () => { page.current = 1; @@ -89,7 +89,7 @@ if (loading.value) return; loading.value = true; loadStatus.value = 'loading'; getStockInventoryListPage({ ...searchForm, ...page, type: 'qualified' }).then(res => { getStockInventoryListPage({ ...searchForm, ...page }).then(res => { loading.value = false; const records = res.data.records || []; tableData.value = page.current === 1 ? records : [...tableData.value, ...records]; @@ -148,4 +148,26 @@ .no-data { padding-top: 100px; } .item-actions { display: flex; justify-content: flex-end; gap: 10px; padding: 5px 0; } .fab-button { position: fixed; right: 20px; bottom: 80px; width: 50px; height: 50px; background-color: #2979ff; border-radius: 25px; display: flex; justify-content: center; align-items: center; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); z-index: 100; } </style> src/pages/inventoryManagement/stockManagement/Unqualified.vue
@@ -27,7 +27,7 @@ <text class="item-id">{{ item.productName }}</text> </view> <view class="item-right"> <text class="item-tag tag-type" style="background-color: #fde2e2; color: #f56c6c;">ä¸åæ ¼åºå</text> <text class="item-tag tag-type">è¾ æåºå</text> </view> </view> @@ -35,24 +35,28 @@ <view class="item-details"> <view class="detail-row"> <text class="detail-label">è§æ ¼åå·</text> <text class="detail-value">{{ item.model }}</text> <text class="detail-label">åè´§/è§æ ¼</text> <text class="detail-value">{{item.productName || "æ " }} / {{ item.model || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">åºåæ°é</text> <text class="detail-value">{{ item.qualitity }} {{ item.unit }}</text> <text class="detail-label">主æ°é/主åä½</text> <text class="detail-value">{{ item.qualitity || "æ " }} / {{ item.unit || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">éå®/å»ç»</text> <text class="detail-value">{{ item.lockedQuantity }} {{ item.unit }}</text> <text class="detail-label">è¾ æ°é/è¾ åä½</text> <text class="detail-value">{{ item.subQualitity || "æ " }} / {{ item.subUnit || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">å¯ç¨åºå</text> <text class="detail-value" style="color: #f56c6c; font-weight: bold;">{{ item.unLockedQuantity }} {{ item.unit }}</text> <text class="detail-label">ä»åºç¼ç /ä»åºåç§°</text> <text class="detail-value">{{ item.warehouseCode || "æ " }} / {{ item.warehouseName || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">åè´§ç¼ç /åºåé¢è¦</text> <text class="detail-value">{{ item.productCode || "æ " }} / {{ item.warnNum || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">æ´æ°æ¶é´</text> <text class="detail-value">{{ item.updateTime }}</text> <text class="detail-value">{{ item.updateTime || "æ " }}</text> </view> </view> </view> @@ -66,14 +70,14 @@ <script setup> import { ref, reactive, onMounted } from 'vue'; import { getStockUninventoryListPage } from "@/api/inventoryManagement/stockUninventory.js"; import { getStockInventoryListPage } from "@/api/inventoryManagement/stockInventory.js"; const tableData = ref([]); const loading = ref(false); const loadStatus = ref('loadmore'); const page = reactive({ current: 1, size: 10 }); const total = ref(0); const searchForm = reactive({ productName: '' }); const searchForm = reactive({ productName: '', rootName: 'è¾ æ' }); const handleQuery = () => { page.current = 1; @@ -85,7 +89,7 @@ if (loading.value) return; loading.value = true; loadStatus.value = 'loading'; getStockUninventoryListPage({ ...searchForm, ...page, type: 'unqualified' }).then(res => { getStockInventoryListPage({ ...searchForm, ...page }).then(res => { loading.value = false; const records = res.data.records || []; tableData.value = page.current === 1 ? records : [...tableData.value, ...records]; @@ -131,4 +135,34 @@ .no-data { padding-top: 100px; } .tag-type { background-color: #e8f5e9; color: #4caf50; padding: 2px 8px; border-radius: 4px; font-size: 12px; } .item-actions { display: flex; justify-content: flex-end; gap: 10px; padding: 5px 0; } .fab-button { position: fixed; right: 20px; bottom: 80px; width: 50px; height: 50px; background-color: #2979ff; border-radius: 25px; display: flex; justify-content: center; align-items: center; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); z-index: 100; } </style> src/pages/inventoryManagement/stockManagement/index.vue
@@ -9,6 +9,9 @@ <swiper-item class="swiper-item"> <unqualified-record /> </swiper-item> <swiper-item class="swiper-item"> <raw-material-record /> </swiper-item> </swiper> </view> </template> @@ -18,11 +21,13 @@ import PageHeader from "@/components/PageHeader.vue"; import QualifiedRecord from "./Qualified.vue"; import UnqualifiedRecord from "./Unqualified.vue"; import RawMaterialRecord from "./rawMaterialRecord.vue"; const activeTab = ref(0); const tabs = ref([ { name: 'åæ ¼åºå' }, { name: 'ä¸åæ ¼åºå' } { name: 'æååºå' }, { name: 'è¾ æåºå' }, { name: 'åææåºå' } ]); const handleTabClick = (item) => { src/pages/inventoryManagement/stockManagement/rawMaterialRecord.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,151 @@ <template> <view class="raw-material-record-container"> <view class="search-section"> <view class="search-bar"> <view class="search-input"> <up-input class="search-text" placeholder="请è¾å ¥äº§å大类" v-model="searchForm.productName" @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 in tableData" :key="item.id" class="ledger-item" :class="{ 'low-stock': isLowStock(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.productName }}</text> </view> <view class="item-right"> <text class="item-tag tag-type">åææåºå</text> </view> </view> <up-divider></up-divider> <view class="item-details"> <view class="detail-row"> <text class="detail-label">åè´§/è§æ ¼</text> <text class="detail-value">{{item.productName || "æ " }} / {{ item.model || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">主æ°é/主åä½</text> <text class="detail-value">{{ item.qualitity || "æ " }} / {{ item.unit || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">è¾ æ°é/è¾ åä½</text> <text class="detail-value">{{ item.subQualitity || "æ " }} / {{ item.subUnit || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">ä»åºç¼ç /ä»åºåç§°</text> <text class="detail-value">{{ item.warehouseCode || "æ " }} / {{ item.warehouseName || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">åè´§ç¼ç /åºåé¢è¦</text> <text class="detail-value">{{ item.productCode || "æ " }} / {{ item.warnNum || "æ " }}</text> </view> <view class="detail-row"> <text class="detail-label">æ´æ°æ¶é´</text> <text class="detail-value">{{ item.updateTime || "æ " }}</text> </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, onMounted } from 'vue'; import { getStockInventoryListPage } from "@/api/inventoryManagement/stockInventory.js"; const tableData = ref([]); const loading = ref(false); const loadStatus = ref('loadmore'); const page = reactive({ current: 1, size: 10 }); const total = ref(0); const searchForm = reactive({ productName: '', rootName: 'åææ' }); const handleQuery = () => { page.current = 1; tableData.value = []; getList(); }; const getList = () => { if (loading.value) return; loading.value = true; loadStatus.value = 'loading'; getStockInventoryListPage({ ...searchForm, ...page }).then(res => { loading.value = false; const records = res.data.records || []; tableData.value = page.current === 1 ? records : [...tableData.value, ...records]; total.value = res.data.total; loadStatus.value = tableData.value.length >= total.value ? 'nomore' : 'loadmore'; }).catch(() => { loading.value = false; loadStatus.value = 'loadmore'; }); }; const loadMore = () => { if (loadStatus.value === 'nomore' || loading.value) return; page.current++; getList(); }; const isLowStock = (row) => { const stock = Number(row?.unLockedQuantity ?? 0); const warn = Number(row?.warnNum ?? 0); return Number.isFinite(stock) && Number.isFinite(warn) && stock < warn; }; onMounted(() => { getList(); }); </script> <style scoped lang="scss"> @import '@/styles/sales-common.scss'; .raw-material-record-container { height: 100%; display: flex; flex-direction: column; } .tag-type { background-color: #e8f5e9; color: #4caf50; padding: 2px 8px; border-radius: 4px; font-size: 12px; } .ledger-list { flex: 1; overflow-y: auto; } .low-stock { background-color: #fde2e2; color: #c45656; } .no-data { padding-top: 100px; } </style> src/pages/productionManagement/productionReport/index.vue
@@ -11,6 +11,31 @@ error-message-align="right"> <!-- åºæ¬ä¿¡æ¯ --> <view class="form-section"> <u-form-item label="æºå°" prop="deviceName" required> <u-input v-model="form.deviceName" disabled placeholder="请è¾å ¥æºå°" /> </u-form-item> <u-form-item label="计åå¼å§æ¶é´" prop="planStartTime" required> <u-input v-model="form.planStartTime" placeholder="è¯·éæ©è®¡åå¼å§æ¶é´" readonly @click="showStartTimePicker = true" suffix-icon="calendar" /> </u-form-item> <u-form-item label="计åç»ææ¶é´" prop="planEndTime" required> <u-input v-model="form.planEndTime" placeholder="è¯·éæ©è®¡åç»ææ¶é´" readonly @click="showEndTimePicker = true" suffix-icon="calendar" /> </u-form-item> <u-form-item label="å¾ ç产æ°é" prop="planQuantity" required> @@ -57,6 +82,20 @@ title="éæ©ç产人" @select="onProducerConfirm" @close="showProducerPicker = false" /> <!-- å¼å§æ¶é´éæ©å¨ --> <up-datetime-picker :show="showStartTimePicker" v-model="startTimeValue" mode="datetime" @confirm="onStartTimeConfirm" @cancel="showStartTimePicker = false" /> <!-- ç»ææ¶é´éæ©å¨ --> <up-datetime-picker :show="showEndTimePicker" v-model="endTimeValue" mode="datetime" @confirm="onEndTimeConfirm" @cancel="showEndTimePicker = false" /> </view> </template> @@ -80,6 +119,9 @@ // è¡¨åæ°æ® const form = ref({ deviceName: "", planStartTime: "", planEndTime: "", planQuantity: "", quantity: "", scrapQty: "", @@ -97,6 +139,12 @@ // çäº§äººéæ©å¨ç¶æ const showProducerPicker = ref(false); // æ¶é´éæ©å¨ç¶æ const showStartTimePicker = ref(false); const showEndTimePicker = ref(false); const startTimeValue = ref(Number(new Date())); const endTimeValue = ref(Number(new Date())); const producerList = ref([]); const currentField = ref(""); // å½åéæ©çåæ®µ @@ -131,6 +179,30 @@ showProducerPicker.value = false; }; // æ ¼å¼åæ¥æ const formatDateTime = (timestamp) => { const date = new Date(timestamp); const y = date.getFullYear(); const m = (date.getMonth() + 1).toString().padStart(2, '0'); const d = date.getDate().toString().padStart(2, '0'); const h = date.getHours().toString().padStart(2, '0'); const min = date.getMinutes().toString().padStart(2, '0'); const s = date.getSeconds().toString().padStart(2, '0'); return `${y}-${m}-${d} ${h}:${min}:${s}`; }; // å¼å§æ¶é´ç¡®è®¤ const onStartTimeConfirm = (e) => { form.value.planStartTime = formatDateTime(e.value); showStartTimePicker.value = false; }; // ç»ææ¶é´ç¡®è®¤ const onEndTimeConfirm = (e) => { form.value.planEndTime = formatDateTime(e.value); showEndTimePicker.value = false; }; // æäº¤ç¶æ const submitting = ref(false); @@ -142,6 +214,21 @@ const submitForm = async () => { submitting.value = true; // æ ¡éªè¡¨å if (!form.value.deviceName) { submitting.value = false; showToast("请è¾å ¥æºå°"); return; } if (!form.value.planStartTime) { submitting.value = false; showToast("è¯·éæ©è®¡åå¼å§æ¶é´"); return; } if (!form.value.planEndTime) { submitting.value = false; showToast("è¯·éæ©è®¡åç»ææ¶é´"); return; } if (!form.value.quantity) { submitting.value = false; showToast("请è¾å ¥æ¬æ¬¡ç产æ°é"); @@ -202,10 +289,14 @@ onLoad(options => { try { const orderRow = JSON.parse(options.orderRow); console.log(orderRow, "orderRow"); // ç¡®ä¿ planQuantity 转æ¢ä¸ºå符串ï¼ä»¥ä¾¿å¨ u-input 䏿£ç¡®æ¾ç¤º form.value.planQuantity = orderRow.planQuantity != null ? String(orderRow.planQuantity) : ""; form.value.productProcessRouteItemId = orderRow.productProcessRouteItemId || ""; form.value.workOrderId = orderRow.id || ""; form.value.deviceName = orderRow.deviceName || ""; form.value.planStartTime = orderRow.planStartTime || ""; form.value.planEndTime = orderRow.planEndTime || ""; getInfo().then(res => { // é»è®¤ä½¿ç¨å½åç»å½ç¨æ·ï¼ä½å è®¸ç¨æ·ä¿®æ¹ form.value.userId.value = res.user.userId; src/pages/works.vue
@@ -958,13 +958,12 @@ orderRow = JSON.stringify({ id: workData.id || workOrderId, planQuantity: workData.planQuantity - workData.completeQuantity, deviceName:workData.deviceName, productProcessRouteItemId: workData.productProcessRouteItemId || workData.产åå·¥èºè·¯çº¿é¡¹ID || "", }); console.log("æé çorderRow:", orderRow); } else { modal.msgError("æªæ¾å°å¯¹åºçå·¥åä¿¡æ¯"); return;