| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index9", |
| | | "style": { |
| | | "navigationBarTitleText": "åæç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetingSettings/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®è®¾ç½®", |
| | |
| | | <view class="form-section"> |
| | | <view class="section-title">è¿ç£
ä¿¡æ¯</view> |
| | | <view class="form-row"> |
| | | <text class="form-label">车çå·</text> |
| | | <text class="form-label required">车çå·</text> |
| | | <up-input v-model="form.licensePlateNo" placeholder="请è¾å
¥è½¦çå·" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">æ¯é(å¨)</text> |
| | | <up-input v-model="form.grossWeight" type="number" placeholder="请è¾å
¥æ¯é" /> |
| | | <text class="form-label required">æ¯é(å¨)</text> |
| | | <up-input v-model="form.grossWeight" type="digit" placeholder="请è¾å
¥æ¯é" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">ç®é(å¨)</text> |
| | | <up-input v-model="form.tareWeight" type="number" placeholder="请è¾å
¥ç®é" /> |
| | | <text class="form-label required">ç®é(å¨)</text> |
| | | <up-input v-model="form.tareWeight" type="digit" placeholder="请è¾å
¥ç®é" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">åé(å¨)</text> |
| | | <up-input v-model="form.netWeight" type="number" disabled placeholder="èªå¨è®¡ç®" /> |
| | | <up-input v-model="form.netWeight" type="digit" disabled placeholder="èªå¨è®¡ç®" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">è¿ç£
æ¥æ</text> |
| | | <text class="form-label required">è¿ç£
æ¥æ</text> |
| | | <view class="selector-trigger" @click="openWeighingDatePicker"> |
| | | <text class="selector-text" :class="{ placeholder: !form.weighingDate }"> |
| | | {{ form.weighingDate || "è¯·éæ©è¿ç£
æ¥æ" }} |
| | |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">è¿ç£
å</text> |
| | | <text class="form-label required">è¿ç£
å</text> |
| | | <up-input v-model="form.weighingOperator" placeholder="请è¾å
¥è¿ç£
å" /> |
| | | </view> |
| | | </view> |
| | |
| | | uni.showToast({ title: "è¯·éæ©äº§å", icon: "none" }); |
| | | return; |
| | | } |
| | | if (!form.licensePlateNo) { |
| | | uni.showToast({ title: "请è¾å
¥è½¦çå·", icon: "none" }); |
| | | return; |
| | | } |
| | | if (!form.grossWeight || Number(form.grossWeight) <= 0) { |
| | | uni.showToast({ title: "请è¾å
¥æ¯é", icon: "none" }); |
| | | return; |
| | | } |
| | | if (!form.tareWeight || Number(form.tareWeight) <= 0) { |
| | | uni.showToast({ title: "请è¾å
¥ç®é", icon: "none" }); |
| | | return; |
| | | } |
| | | if (!form.weighingDate) { |
| | | uni.showToast({ title: "è¯·éæ©è¿ç£
æ¥æ", icon: "none" }); |
| | | return; |
| | | } |
| | | if (!form.weighingOperator) { |
| | | uni.showToast({ title: "请è¾å
¥è¿ç£
å", icon: "none" }); |
| | | return; |
| | | } |
| | | const payload = { |
| | | productId: form.productId, |
| | | productModelId: form.productModelId, |
| | |
| | | const goDetail = (item) => { |
| | | if (!item) return; |
| | | try { |
| | | uni.setStorageSync( |
| | | "stockDetailItem", |
| | | JSON.stringify({ |
| | | item, |
| | | type: isQualified() ? "0" : "1", |
| | | }) |
| | | ); |
| | | uni.setStorageSync('stockDetailItem', JSON.stringify({ |
| | | item, |
| | | type: '0' |
| | | })) |
| | | } catch (e) {} |
| | | if (!item.id) { |
| | | uni.navigateTo({ url: "/pages/consumablesLogistics/stockManagement/view" }); |
| | |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">æ¯é(å¨)</text> |
| | | <up-input v-model="form.grossWeight" type="number" placeholder="请è¾å
¥æ¯é" /> |
| | | <up-input v-model="form.grossWeight" type="digit" placeholder="请è¾å
¥æ¯é" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">ç®é(å¨)</text> |
| | | <up-input v-model="form.tareWeight" type="number" placeholder="请è¾å
¥ç®é" /> |
| | | <up-input v-model="form.tareWeight" type="digit" placeholder="请è¾å
¥ç®é" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">åé(å¨)</text> |
| | | <up-input v-model="form.netWeight" type="number" disabled placeholder="èªå¨è®¡ç®" /> |
| | | <up-input v-model="form.netWeight" type="digit" disabled placeholder="èªå¨è®¡ç®" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">è¿ç£
æ¥æ</text> |
| | |
| | | if (!outNum || outNum <= 0 || outNum > Number(stockRecord.unLockedQuantity)) { |
| | | uni.showToast({ title: `请è¾å
¥ 1~${stockRecord.unLockedQuantity} ä¹é´çæ°é`, icon: "none" }); |
| | | return; |
| | | } |
| | | const net = Number(form.netWeight); |
| | | if (!isNaN(net) && net > 0) { |
| | | const max = Number(stockRecord.unLockedQuantity) || 0; |
| | | if (max > 0 && net > max) { |
| | | uni.showToast({ title: `åéä¸è½å¤§äºå¯ç¨åºå ${max}`, icon: "none" }); |
| | | return; |
| | | } |
| | | if (net > outNum) { |
| | | uni.showToast({ title: `åéä¸è½å¤§äºåºåºæ°é ${outNum}`, icon: "none" }); |
| | | return; |
| | | } |
| | | } |
| | | subtractConsumablesIn({ |
| | | id: stockRecord.id, |
| | |
| | | </view> |
| | | <view class="section-body"> |
| | | <view class="detail-row"> |
| | | <text class="label">åºå·</text> |
| | | <text class="value">{{ detail.index ?? '-' }}</text> |
| | | <text class="label">产åç±»å</text> |
| | | <text class="value">{{ detail.parentName ?? '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="label">产å大类</text> |
| | |
| | | <text class="label">æè¿æ´æ°æ¶é´</text> |
| | | <text class="value">{{ detail.updateTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="label">夿³¨</text> |
| | | <text class="value">{{ detail.remark || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | const d = typeof raw === "object" ? raw : {}; |
| | | return { |
| | | index: d.index ?? 1, |
| | | parentName: d.parentName, |
| | | productName: d.productName, |
| | | model: d.model, |
| | | unit: d.unit, |
| | |
| | | unLockedQuantity: d.unLockedQuantity ?? (d.qualitity - (d.lockedQuantity || 0)), |
| | | updateTime: d.updateTime, |
| | | typeLabel: "åæ ¼åºå", |
| | | remark: d.remark, |
| | | }; |
| | | } |
| | | |
| | |
| | | <view class="row" v-if="searchForm.reportType === 'inout'"><text class="l">åºåºæ°é</text><text class="r">{{ item.totalStockOut }}</text></view> |
| | | <view class="row"><text class="l">ç°å¨åºå</text><text class="r highlight">{{ item.currentStock }}</text></view> |
| | | <view class="row" v-if="item.createBy"><text class="l">å
¥åºäºº</text><text class="r">{{ item.createBy }}</text></view> |
| | | <view class="row" v-if="item.currentWeight"><text class="l">ç°åé(å¨)</text><text class="r">{{ item.currentWeight }}</text></view> |
| | | <view class="row" v-if="item.recordType"><text class="l">æ¥æº</text><text class="r">{{ getRecordType(item.recordType) }}</text></view> |
| | | </view> |
| | | </view> |
| | | <view class="load-more-wrap"> |
| | |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | import { onShow, onReachBottom } from "@dcloudio/uni-app"; |
| | | import { getConsumablesInReportList, getConsumablesInInAndOutReportList } from "@/api/consumablesLogistics/consumablesIn.js"; |
| | | |
| | | import { |
| | | findAllQualifiedStockInRecordTypeOptions, |
| | | } from "@/api/basicData/enum.js"; |
| | | const reportTypes = [ |
| | | { label: "æ¥æ¥", value: "daily" }, |
| | | { label: "ææ¥", value: "monthly" }, |
| | |
| | | } |
| | | return p; |
| | | }; |
| | | |
| | | const stockRecordTypeOptions = ref([]) |
| | | |
| | | const getRecordType = (recordType) => { |
| | | return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || '' |
| | | } |
| | | |
| | | // è·åæ¥æºç±»åé项 |
| | | const fetchStockRecordTypeOptions = () => { |
| | | findAllQualifiedStockInRecordTypeOptions() |
| | | .then(res => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }) |
| | | } |
| | | |
| | | const getList = () => { |
| | | const isFirstPage = page.current === 1; |
| | |
| | | onShow(() => { |
| | | initDefaultDates(); |
| | | handleQuery(); |
| | | fetchStockRecordTypeOptions(); |
| | | }); |
| | | |
| | | onReachBottom(() => loadMore()); |
| | |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn edit" |
| | | :disabled="item.approveStatus == 2 || item.approveStatus == 1 || item.approveStatus == 4 || item.approveStatus == 8" |
| | | :disabled="item.approveStatus == 2 || item.approveStatus == 1 || item.approveStatus == 4 || item.approveStatus == 8 || approveType == 9" |
| | | @click="handleItemClick(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | |
| | | </view> |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" |
| | | v-if="props.approveType != 5 && props.approveType != 6 && props.approveType != 7" |
| | | v-if="props.approveType != 5 && props.approveType != 6 && props.approveType != 7 && props.approveType != 9" |
| | | @click="handleAdd"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | |
| | | 6: "æ¥ä»·ç®¡ç", |
| | | 7: "å货审æ¹", |
| | | 8: "å±é©ä½ä¸å®¡æ¹", |
| | | 9: "åæç®¡ç", |
| | | }; |
| | | return titleMap[type] || "审æ¹ç®¡ç"; |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="9" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| | |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index7", |
| | | }); |
| | | break; |
| | | case "åæç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index9", |
| | | }); |
| | | break; |
| | | case "ä¼è®®è®¾ç½®": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingSettings/index", |
| | |
| | | |
| | | // è´¨é管çèåï¼åºå®åªå±ç¤º 3 个å
¥å£ |
| | | const originalQuality = [ |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "æ£æµé¡¹ç»´æ¤" }, |
| | | { icon: "/static/images/icon/shengchanhesuan@2x.png", label: "æ£æµé¡¹ç»´æ¤" }, |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "åææ£" }, |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "ä¸åæ ¼å管ç" }, |
| | | { icon: "/static/images/icon/shengchandingdan@2x.png", label: "ä¸åæ ¼å管ç" }, |
| | | ]; |
| | | qualityItems.splice(0, qualityItems.length, ...originalQuality); |
| | | |
| | |
| | | icon: "/static/images/icon/baoxiaoguanli.png", |
| | | label: "æ¥é管ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/yuanliaoguanli@2x.png", |
| | | label: "åæç®¡ç", |
| | | }, |
| | | // { |
| | | // icon: "/static/images/icon/caigouguanli.png", |
| | | // label: "éè´å®¡æ¹", |
| | |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index7", |
| | | }); |
| | | break; |
| | | case "åæç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index9", |
| | | }); |
| | | break; |
| | | case "ä¼è®®è®¾ç½®": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingSettings/index", |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- è¿ç£
ç¸å
³å段 --> |
| | | <view class="form-section"> |
| | | <!-- æåï¼åªéè¦æ°é --> |
| | | <view v-if="isFinishedProduct" class="form-section"> |
| | | <view class="form-row"> |
| | | <text class="form-label required">æ°é</text> |
| | | <up-input v-model="form.qualitity" type="number" placeholder="请è¾å
¥æ°é" /> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- åææï¼è¿ç£
ç¸å
³å段 --> |
| | | <view v-else class="form-section"> |
| | | <view class="section-title">è¿ç£
ä¿¡æ¯</view> |
| | | <view class="form-row"> |
| | | <text class="form-label">车çå·</text> |
| | | <text class="form-label required">车çå·</text> |
| | | <up-input v-model="form.licensePlateNo" placeholder="请è¾å
¥è½¦çå·" /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">æ¯é(å¨)</text> |
| | | <text class="form-label required">æ¯é(å¨)</text> |
| | | <up-input |
| | | v-model="form.grossWeight" |
| | | type="number" |
| | | type="digit" |
| | | placeholder="请è¾å
¥æ¯é" |
| | | /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">ç®é(å¨)</text> |
| | | <text class="form-label required">ç®é(å¨)</text> |
| | | <up-input |
| | | v-model="form.tareWeight" |
| | | type="number" |
| | | type="digit" |
| | | placeholder="请è¾å
¥ç®é" |
| | | /> |
| | | </view> |
| | |
| | | <text class="form-label">åé(å¨)</text> |
| | | <up-input |
| | | v-model="form.netWeight" |
| | | type="number" |
| | | type="digit" |
| | | disabled |
| | | placeholder="èªå¨è®¡ç®" |
| | | /> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">è¿ç£
æ¥æ</text> |
| | | <text class="form-label required">è¿ç£
æ¥æ</text> |
| | | <view class="selector-trigger" @click="openWeighingDatePicker"> |
| | | <text class="selector-text" :class="{ placeholder: !form.weighingDate }"> |
| | | {{ form.weighingDate || 'è¯·éæ©è¿ç£
æ¥æ' }} |
| | |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <text class="form-label">è¿ç£
å</text> |
| | | <text class="form-label required">è¿ç£
å</text> |
| | | <up-input v-model="form.weighingOperator" placeholder="请è¾å
¥è¿ç£
å" /> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-section"> |
| | | <!-- <view class="form-row"> |
| | | <text class="form-label required">æ°é</text> |
| | | <up-input v-model="form.qualitity" type="number" placeholder="请è¾å
¥æ°é" /> |
| | | </view> --> |
| | | <view class="form-row"> |
| | | <text class="form-label">夿³¨</text> |
| | | <up-input v-model="form.remark" type="textarea" placeholder="éå¡«" /> |
| | |
| | | productModelName: '', |
| | | unit: '', |
| | | productType: undefined, |
| | | parentName: '', |
| | | licensePlateNo: '', |
| | | grossWeight: '', |
| | | tareWeight: '', |
| | |
| | | |
| | | const type = ref('0') // åºå®åæ ¼åºå |
| | | const isQualified = computed(() => true) |
| | | const isFinishedProduct = computed(() => form.parentName === 'æå') |
| | | |
| | | const showProductPopup = ref(false) |
| | | const productQuery = reactive({ |
| | |
| | | form.productModelName = item.model |
| | | form.unit = item.unit |
| | | form.productType = item.productType |
| | | form.parentName = parentName |
| | | |
| | | // åæ¢äº§ååï¼æç±»åæ¸
çæ å
³å段 |
| | | if (parentName === 'æå') { |
| | | form.licensePlateNo = '' |
| | | form.grossWeight = '' |
| | | form.tareWeight = '' |
| | | form.netWeight = '' |
| | | form.weighingDate = '' |
| | | form.weighingOperator = '' |
| | | } else { |
| | | form.qualitity = '' |
| | | } |
| | | showProductPopup.value = false |
| | | } |
| | | |
| | |
| | | uni.showToast({ title: 'è¯·éæ©äº§å', icon: 'none' }) |
| | | return |
| | | } |
| | | // if (!form.qualitity || Number(form.qualitity) <= 0) { |
| | | // uni.showToast({ title: '请è¾å
¥æ°é', icon: 'none' }) |
| | | // return |
| | | // } |
| | | const payload = { |
| | | if (isFinishedProduct.value) { |
| | | if (!form.qualitity || Number(form.qualitity) <= 0) { |
| | | uni.showToast({ title: '请è¾å
¥æ°é', icon: 'none' }) |
| | | return |
| | | } |
| | | } else { |
| | | if (!form.licensePlateNo) { |
| | | uni.showToast({ title: '请è¾å
¥è½¦çå·', icon: 'none' }) |
| | | return |
| | | } |
| | | if (!form.grossWeight || Number(form.grossWeight) <= 0) { |
| | | uni.showToast({ title: '请è¾å
¥æ¯é', icon: 'none' }) |
| | | return |
| | | } |
| | | if (!form.tareWeight || Number(form.tareWeight) <= 0) { |
| | | uni.showToast({ title: '请è¾å
¥ç®é', icon: 'none' }) |
| | | return |
| | | } |
| | | if (!form.weighingDate) { |
| | | uni.showToast({ title: 'è¯·éæ©è¿ç£
æ¥æ', icon: 'none' }) |
| | | return |
| | | } |
| | | if (!form.weighingOperator) { |
| | | uni.showToast({ title: '请è¾å
¥è¿ç£
å', icon: 'none' }) |
| | | return |
| | | } |
| | | } |
| | | |
| | | const base = { |
| | | productId: form.productId, |
| | | productModelId: form.productModelId, |
| | | productName: form.productName, |
| | | productModelName: form.productModelName, |
| | | unit: form.unit, |
| | | productType: form.productType, |
| | | licensePlateNo: form.licensePlateNo, |
| | | grossWeight: form.grossWeight, |
| | | tareWeight: form.tareWeight, |
| | | netWeight: form.netWeight, |
| | | weighingDate: form.weighingDate, |
| | | weighingOperator: form.weighingOperator, |
| | | remark: form.remark |
| | | } |
| | | const payload = isFinishedProduct.value |
| | | ? { ...base, qualitity: Number(form.qualitity) } |
| | | : { |
| | | ...base, |
| | | licensePlateNo: form.licensePlateNo, |
| | | grossWeight: form.grossWeight, |
| | | tareWeight: form.tareWeight, |
| | | netWeight: form.netWeight, |
| | | weighingDate: form.weighingDate, |
| | | weighingOperator: form.weighingOperator |
| | | } |
| | | createStockInventory(payload) |
| | | .then(() => { |
| | | uni.showToast({ title: 'æ°å¢æå', icon: 'success' }) |
| | |
| | | <text class="form-label">æ¯é(å¨)</text> |
| | | <up-input |
| | | v-model="form.grossWeight" |
| | | type="number" |
| | | type="digit" |
| | | placeholder="请è¾å
¥æ¯é" |
| | | /> |
| | | </view> |
| | |
| | | <text class="form-label">ç®é(å¨)</text> |
| | | <up-input |
| | | v-model="form.tareWeight" |
| | | type="number" |
| | | type="digit" |
| | | placeholder="请è¾å
¥ç®é" |
| | | /> |
| | | </view> |
| | |
| | | <text class="form-label">åé(å¨)</text> |
| | | <up-input |
| | | v-model="form.netWeight" |
| | | type="number" |
| | | type="digit" |
| | | disabled |
| | | placeholder="èªå¨è®¡ç®" |
| | | /> |
| | |
| | | const showWeighingDatePicker = ref(false) |
| | | const weighingDateValue = ref(Date.now()) |
| | | |
| | | const maxAllowedNetWeight = computed(() => { |
| | | const v = form.unLockedQuantity ?? form.qualitity |
| | | const n = Number(v) |
| | | return !isNaN(n) ? n : 0 |
| | | }) |
| | | |
| | | onLoad((options) => { |
| | | type.value = '0' |
| | | const cached = uni.getStorageSync('stockSubtractRecord') |
| | |
| | | const handleSubmit = () => { |
| | | if (!form.id) { |
| | | uni.showToast({ title: 'è®°å½ä¿¡æ¯ç¼ºå¤±ï¼æ æ³åºåº', icon: 'none' }) |
| | | return |
| | | } |
| | | const net = Number(form.netWeight) |
| | | if (!isNaN(net) && net > 0 && maxAllowedNetWeight.value > 0 && net > maxAllowedNetWeight.value) { |
| | | uni.showToast({ title: `åéä¸è½å¤§äºå¯ç¨åºå ${maxAllowedNetWeight.value}`, icon: 'none' }) |
| | | return |
| | | } |
| | | const payload = { ...form } |
| | |
| | | </view> |
| | | <view class="section-body"> |
| | | <view class="detail-row"> |
| | | <text class="label">åºå·</text> |
| | | <text class="value">{{ detail.index ?? '-' }}</text> |
| | | <text class="label">产åç±»å</text> |
| | | <text class="value">{{ detail.parentName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="label">产å大类</text> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="section-card"> |
| | | <view class="section-head"> |
| | | <view class="section-dot"></view> |
| | | <text class="section-title">å
¶ä»ä¿¡æ¯</text> |
| | | </view> |
| | | <view class="section-body"> |
| | | <view class="detail-row"> |
| | | <text class="label">夿³¨</text> |
| | | <text class="value value-num">{{ detail.remark ?? '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="empty"> |
| | | <text class="empty-text">ææ è¯¦æ
æ°æ®</text> |
| | |
| | | const d = typeof raw === 'object' ? raw : {} |
| | | return { |
| | | index: d.index ?? 1, |
| | | parentName: d.parentName, |
| | | productName: d.productName, |
| | | model: d.model, |
| | | unit: d.unit, |
| | | qualitity: d.qualitity, |
| | | lockedQuantity: d.lockedQuantity, |
| | | unLockedQuantity: d.unLockedQuantity, |
| | | updateTime: d.updateTime |
| | | updateTime: d.updateTime, |
| | | remark: d.remark, |
| | | } |
| | | } |
| | | |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ¶é´éæ©åºåå·²å»é¤ï¼ä½¿ç¨é»è®¤æ¥æé»è¾ --> |
| | | <!-- æ¶é´éæ©åºå --> |
| | | <view class="search-section"> |
| | | <!-- æ¥æ¥ï¼éæ©å¹´ææ¥ --> |
| | | <view v-if="searchForm.reportType === 'daily'" class="search-row"> |
| | | <view class="date-picker" @click="openDatePicker('single')"> |
| | | <text>{{ searchForm.singleDate || 'è¯·éæ©æ¥æ' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- ææ¥ï¼éæ©å¹´æ --> |
| | | <view v-else-if="searchForm.reportType === 'monthly'" class="search-row"> |
| | | <view class="date-picker" @click="openDatePicker('startMonth')"> |
| | | <text>{{ searchForm.startMonth || 'è¯·éæ©å¼å§æä»½' }}</text> |
| | | </view> |
| | | ~ |
| | | <view class="date-picker" @click="openDatePicker('endMonth')"> |
| | | <text>{{ searchForm.endMonth || 'è¯·éæ©ç»ææä»½' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- è¿åºåï¼éæ©å¹´ææ¥æ¶é´èå´ --> |
| | | <view v-else-if="searchForm.reportType === 'inout'" class="search-row"> |
| | | <view class="date-picker" @click="openDatePicker('startDate')"> |
| | | <text>{{ searchForm.startDate || 'è¯·éæ©å¼å§æ¥æ' }}</text> |
| | | </view> |
| | | ~ |
| | | <view class="date-picker" @click="openDatePicker('endDate')"> |
| | | <text>{{ searchForm.endDate || 'è¯·éæ©ç»ææ¥æ' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å表 + æ»å¨å页 --> |
| | | <view class="list-section"> |
| | |
| | | <view class="row" v-if="searchForm.reportType === 'inout'"><text class="l">åºåºæ°é</text><text class="r">{{ item.totalStockOut }}</text></view> |
| | | <view class="row"><text class="l">ç°å¨åºå</text><text class="r highlight">{{ item.currentStock }}</text></view> |
| | | <view class="row" v-if="item.createBy"><text class="l">å
¥åºäºº</text><text class="r">{{ item.createBy }}</text></view> |
| | | <view class="row" v-if="item.currentWeight"><text class="l">ç°åé(å¨)</text><text class="r">{{ item.currentWeight }}</text></view> |
| | | <view class="row" v-if="item.recordType"><text class="l">æ¥æº</text><text class="r">{{ getRecordType(item.recordType) }}</text></view> |
| | | </view> |
| | | </view> |
| | | <view class="load-more-wrap"> |
| | |
| | | <up-datetime-picker |
| | | v-model="dateValue" |
| | | :mode="datePickerMode" |
| | | :show="showDatePicker" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | /> |
| | |
| | | import dayjs from 'dayjs' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { onShow, onReachBottom } from '@dcloudio/uni-app' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import { |
| | | getStockInventoryReportList, |
| | | getStockInventoryInAndOutReportList |
| | | } from '@/api/inventoryManagement/stockInventory.js' |
| | | import {findAllQualifiedStockInRecordTypeOptions} from "@/api/basicData/enum"; |
| | | |
| | | const reportTypes = [ |
| | | { label: 'æ¥æ¥', value: 'daily' }, |
| | |
| | | startMonth: '', |
| | | endMonth: '', |
| | | startDate: '', |
| | | endDate: '' |
| | | endDate: '', |
| | | } |
| | | }) |
| | | |
| | | const { searchForm } = toRefs(data) |
| | | |
| | | const datePickerMode = computed(() => { |
| | | if (datePickerTarget.value === 'startMonth' || datePickerTarget.value === 'endMonth') return 'month' |
| | | if (datePickerTarget.value === 'startMonth' || datePickerTarget.value === 'endMonth') return 'year-month' |
| | | return 'date' |
| | | }) |
| | | |
| | |
| | | if (searchForm.value.reportType === 'daily') { |
| | | p.reportDate = searchForm.value.singleDate |
| | | } else if (searchForm.value.reportType === 'monthly') { |
| | | p.startMonth = searchForm.value.startMonth |
| | | p.endMonth = searchForm.value.endMonth |
| | | } else if (searchForm.value.reportType === 'monthly') { |
| | | p.startMonth = searchForm.value.startMonth |
| | | p.endMonth = searchForm.value.endMonth |
| | | p.startMonth = searchForm.value.startMonth + '-01' |
| | | p.endMonth = searchForm.value.endMonth + '-01' |
| | | } else { |
| | | p.startDate = searchForm.value.startDate |
| | | p.endDate = searchForm.value.endDate |
| | | p.startMonth = searchForm.value.startDate |
| | | p.endMonth = searchForm.value.endDate |
| | | } |
| | | return p |
| | | } |
| | | |
| | | const stockRecordTypeOptions = ref([]) |
| | | |
| | | const getRecordType = (recordType) => { |
| | | return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || '' |
| | | } |
| | | |
| | | // è·åæ¥æºç±»åé项 |
| | | const fetchStockRecordTypeOptions = () => { |
| | | findAllQualifiedStockInRecordTypeOptions() |
| | | .then(res => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }) |
| | | } |
| | | |
| | | const getList = () => { |
| | |
| | | } |
| | | |
| | | const openDatePicker = (target) => { |
| | | datePickerTarget.value = target |
| | | let val = '' |
| | | if (target === 'single') val = searchForm.value.singleDate |
| | | else if (target === 'startMonth') val = searchForm.value.startMonth |
| | | else if (target === 'endMonth') val = searchForm.value.endMonth |
| | | datePickerTarget.value = target |
| | | switch (target) { |
| | | case 'single': |
| | | val = searchForm.value.singleDate |
| | | break |
| | | case 'startMonth': |
| | | val = searchForm.value.startMonth |
| | | break |
| | | case 'endMonth': |
| | | val = searchForm.value.endMonth |
| | | break |
| | | case 'startDate': |
| | | val = searchForm.value.startDate |
| | | break |
| | | case 'endDate': |
| | | val = searchForm.value.endDate |
| | | break |
| | | } |
| | | dateValue.value = val ? new Date(val).getTime() : Date.now() |
| | | showDatePicker.value = true |
| | | } |
| | |
| | | const onDateConfirm = (e) => { |
| | | const isMonth = datePickerTarget.value === 'startMonth' || datePickerTarget.value === 'endMonth' |
| | | const str = isMonth ? dayjs(e.value).format('YYYY-MM') : formatDateToYMD(e.value) |
| | | if (datePickerTarget.value === 'single') searchForm.value.singleDate = str |
| | | else if (datePickerTarget.value === 'startMonth') searchForm.value.startMonth = str |
| | | else if (datePickerTarget.value === 'endMonth') searchForm.value.endMonth = str |
| | | showDatePicker.value = false |
| | | handleQuery() |
| | | |
| | | if (datePickerTarget.value === 'single') { |
| | | searchForm.value.singleDate = str |
| | | showDatePicker.value = false |
| | | handleQuery() |
| | | } else if (datePickerTarget.value === 'startMonth') { |
| | | searchForm.value.startMonth = str |
| | | showDatePicker.value = false |
| | | setTimeout(() => { |
| | | openDatePicker('endMonth') |
| | | }, 300) |
| | | } else if (datePickerTarget.value === 'endMonth') { |
| | | searchForm.value.endMonth = str |
| | | showDatePicker.value = false |
| | | handleQuery() |
| | | } else if (datePickerTarget.value === 'startDate') { |
| | | searchForm.value.startDate = str |
| | | showDatePicker.value = false |
| | | // 确认å¼å§æ¥æåï¼æå¼ç»ææ¥æéæ©æ¡ |
| | | setTimeout(() => { |
| | | openDatePicker('endDate') |
| | | }, 300) |
| | | } else if (datePickerTarget.value === 'endDate') { |
| | | searchForm.value.endDate = str |
| | | showDatePicker.value = false |
| | | handleQuery() |
| | | } |
| | | } |
| | | |
| | | // åå§åï¼æ¥æ¥é»è®¤ä»å¤©ï¼ææ¥é»è®¤æ¬æï¼è¿åºåé»è®¤æè¿7天 |
| | |
| | | searchForm.value.singleDate = today.format('YYYY-MM-DD') |
| | | } |
| | | if (!searchForm.value.startMonth || !searchForm.value.endMonth) { |
| | | const startOfMonth = today.startOf('month').format('YYYY-MM-DD') |
| | | const endOfMonth = today.endOf('month').format('YYYY-MM-DD') |
| | | searchForm.value.startMonth = startOfMonth |
| | | searchForm.value.endMonth = endOfMonth |
| | | searchForm.value.startMonth = today.format('YYYY-MM') |
| | | searchForm.value.endMonth = today.add(1, 'month').format('YYYY-MM') |
| | | } |
| | | if (!searchForm.value.startDate || !searchForm.value.endDate) { |
| | | searchForm.value.endDate = today.format('YYYY-MM-DD') |
| | |
| | | onShow(() => { |
| | | initDefaultDates() |
| | | handleQuery() |
| | | fetchStockRecordTypeOptions() |
| | | }) |
| | | |
| | | const goBack = () => uni.navigateBack() |
| | |
| | | .card-body .l { color: #666; } .card-body .r { color: #333; } .card-body .r.highlight { color: #2979ff; font-weight: 500; } |
| | | .no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; } |
| | | .load-more-wrap { padding: 24rpx 0 8rpx; } |
| | | </style> |
| | | </style> |
| | |
| | | <view class="card-actions"> |
| | | <view class="btn-link btn-link-primary" v-if="item.inspectState == 0" @click.stop="openDealDialog(item)">å¤ç</view> |
| | | <view class="btn-link btn-link-plain" v-if="item.inspectState == 0" @click.stop="openForm('edit', item)">ç¼è¾</view> |
| | | <view class="btn-link btn-link-warn" @click.stop="handleDelete(item)">å é¤</view> |
| | | <view class="btn-link btn-link-warn" v-if="item.inspectState == 0" @click.stop="handleDelete(item)">å é¤</view> |
| | | </view> |
| | | </view> |
| | | <view class="load-more-wrap"> |
| | |
| | | return types[String(type ?? '')] || '-'; |
| | | }; |
| | | |
| | | const getList = () => { |
| | | const getList = (force = false) => { |
| | | const isFirstPage = page.current === 1 |
| | | if (loadStatus.value === 'loading' || (!isFirstPage && page.total > 0 && tableData.value.length >= page.total)) return |
| | | if ( |
| | | !force && |
| | | (loadStatus.value === 'loading' || |
| | | (!isFirstPage && page.total > 0 && tableData.value.length >= page.total)) |
| | | ) |
| | | return |
| | | |
| | | loadStatus.value = 'loading' |
| | | const params = { |
| | |
| | | page.total = 0; |
| | | tableData.value = []; |
| | | loadStatus.value = 'loadmore'; |
| | | getList(); |
| | | getList(true); |
| | | }; |
| | | |
| | | const selectType = (e) => { |
| | |
| | | }; |
| | | |
| | | const handleDelete = (row) => { |
| | | showConfirm('确认å é¤è¯¥ä¸åæ ¼è®°å½åï¼').then(res => { |
| | | if (res.confirm) { |
| | | qualityUnqualifiedDel([row.id]).then(() => { |
| | | toast('å 餿å'); |
| | | handleQuery(); |
| | | }); |
| | | } |
| | | }); |
| | | showConfirm('确认å é¤è¯¥ä¸åæ ¼è®°å½åï¼').then(async res => { |
| | | if (!res.confirm) return |
| | | await qualityUnqualifiedDel([row.id]) |
| | | toast('å 餿å') |
| | | handleQuery() |
| | | }) |
| | | }; |
| | | |
| | | const confirmDate = (e) => { |
| | |
| | | </view> |
| | | |
| | | <view class="upload-bar"> |
| | | <view class="btn-upload" @click="chooseFile">ä¸ä¼ éä»¶</view> |
| | | <view class="btn-upload" @tap="chooseFile">ä¸ä¼ éä»¶</view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | |
| | | uni.showToast({ title: 'ç¼ºå°æ£éªè®°å½ID', icon: 'none' }) |
| | | return |
| | | } |
| | | uni.chooseFile({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const path = res?.tempFiles?.[0]?.path |
| | | const name = res?.tempFiles?.[0]?.name |
| | | if (!path) return |
| | | uploadOne(path, name) |
| | | const pickByChooseFile = () => { |
| | | if (typeof uni.chooseFile !== 'function') return false |
| | | uni.chooseFile({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const file = res?.tempFiles?.[0] |
| | | const path = file?.path |
| | | const name = file?.name |
| | | if (!path) return |
| | | uploadOne(path, name) |
| | | }, |
| | | fail: () => { |
| | | // chooseFile å¨é¨å App æºå/åºåº§å¯è½ä¼å¤±è´¥ï¼åé级 |
| | | pickByChooseImage() |
| | | } |
| | | }) |
| | | return true |
| | | } |
| | | |
| | | const pickByChooseImage = () => { |
| | | if (typeof uni.chooseImage !== 'function') { |
| | | uni.showToast({ title: 'å½åçæ¬ä¸æ¯æéæ©æä»¶', icon: 'none' }) |
| | | return |
| | | } |
| | | }) |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const path = res?.tempFilePaths?.[0] |
| | | if (!path) return |
| | | uploadOne(path, 'å¾çéä»¶') |
| | | }, |
| | | fail: () => { |
| | | uni.showToast({ title: 'éæ©å¤±è´¥', icon: 'none' }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // App/H5 ç»ä¸èµ° chooseFileï¼å¤±è´¥æ¶é级 chooseImage |
| | | const ok = pickByChooseFile() |
| | | if (!ok) pickByChooseImage() |
| | | } |
| | | |
| | | const uploadOne = (filePath, originalName) => { |
| | |
| | | } |
| | | |
| | | const previewFile = (f) => { |
| | | const url = f?.url |
| | | const rawUrl = f?.url |
| | | if (!rawUrl) return |
| | | |
| | | const url = normalizeUrl(rawUrl) |
| | | const name = f?.name || 'éä»¶' |
| | | if (!url) return |
| | | // H5/APP ç»ä¸ç¨å¤é¨æå¼ |
| | | uni.navigateTo({ |
| | | url: `/pages/inspectionUpload/filePreview?url=${encodeURIComponent(url)}` |
| | | |
| | | // å¾çä¼å
ç¨åçé¢è§ |
| | | if (isImageUrl(url) || isImageName(name)) { |
| | | uni.previewImage({ urls: [url] }) |
| | | return |
| | | } |
| | | |
| | | // éå¾çï¼ä¸è½½åæå¼ |
| | | const token = getToken() |
| | | uni.showLoading({ title: 'æå¼ä¸...', mask: true }) |
| | | uni.downloadFile({ |
| | | url, |
| | | header: token ? { Authorization: 'Bearer ' + token } : undefined, |
| | | success: (res) => { |
| | | const filePath = res?.tempFilePath |
| | | if (!filePath) { |
| | | uni.hideLoading() |
| | | uni.showToast({ title: 'æå¼å¤±è´¥', icon: 'none' }) |
| | | return |
| | | } |
| | | uni.openDocument({ |
| | | filePath, |
| | | showMenu: true, |
| | | success: () => { |
| | | uni.hideLoading() |
| | | }, |
| | | fail: () => { |
| | | uni.hideLoading() |
| | | uni.showToast({ title: 'æå¼å¤±è´¥', icon: 'none' }) |
| | | } |
| | | }) |
| | | }, |
| | | fail: () => { |
| | | uni.hideLoading() |
| | | uni.showToast({ title: 'ä¸è½½å¤±è´¥', icon: 'none' }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const normalizeUrl = (u) => { |
| | | const s = String(u || '').trim() |
| | | if (!s) return '' |
| | | if (s.startsWith('http://') || s.startsWith('https://')) return s |
| | | if (s.startsWith('//')) return 'https:' + s |
| | | // ç³»ç»ééä»¶é¢è§/ä¸è½½ä¸è¬èµ° fileUrl |
| | | if (s.startsWith('/')) return `${config.fileUrl}${s}` |
| | | return `${config.fileUrl}/${s.replace(/^\//, '')}` |
| | | } |
| | | |
| | | const isImageName = (name) => { |
| | | const n = String(name || '').toLowerCase() |
| | | return /\.(png|jpe?g|gif|bmp|webp|heic)$/.test(n) |
| | | } |
| | | |
| | | const isImageUrl = (url) => { |
| | | const u = String(url || '').toLowerCase() |
| | | return /\.(png|jpe?g|gif|bmp|webp|heic)(\?|#|$)/.test(u) |
| | | } |
| | | |
| | | const confirmDelete = (f) => { |
| | |
| | | .file-list { margin: 24rpx; background: #fff; border-radius: 16rpx; padding: 12rpx 24rpx; } |
| | | .file-item { padding: 20rpx 0; border-bottom: 1rpx solid #eee; display: flex; justify-content: space-between; align-items: center; gap: 16rpx; } |
| | | .file-item:last-child { border-bottom: 0; } |
| | | .file-name { font-size: 28rpx; color: #333; } |
| | | .file-actions { display: flex; gap: 20rpx; } |
| | | .file-info { flex: 1; min-width: 0; } |
| | | .file-name { |
| | | display: block; |
| | | width: 420rpx; |
| | | max-width: 100%; |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | .file-actions { display: flex; gap: 20rpx; flex-shrink: 0; } |
| | | .btn-link { color: #2979ff; font-size: 26rpx; } |
| | | .btn-link.danger { color: #f56c6c; } |
| | | .empty { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; } |
| | | .upload-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); } |
| | | .upload-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); z-index: 20; } |
| | | .btn-upload { height: 88rpx; border-radius: 999rpx; background: #2979ff; color: #fff; font-size: 30rpx; display: flex; align-items: center; justify-content: center; } |
| | | </style> |
| | | |