| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import { onMounted, reactive, ref } from 'vue'; |
| | | import { Page } from '@vben/common-ui'; |
| | | import { Button, Card, DatePicker, Form, FormItem, Input, InputNumber, Modal, Space, Table, Tabs, TabPane, message } from 'ant-design-vue'; |
| | | import dayjs from 'dayjs'; |
| | | import { requestClient } from '#/api/request'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components'; |
| | | import { WmMaterialStockSelect } from '#/views/wls/materialstock/components'; |
| | | import { WmWarehouseAreaSelect, WmWarehouseLocationSelect, WmWarehouseSelect } from '#/views/wls/warehouse/components'; |
| | | |
| | | defineOptions({ name: 'WlsScrap' }); |
| | | const receiptOpen = ref(false); const saleOpen = ref(false); const detailsOpen = ref(false); const saleLines = ref<any[]>([]); const busy = ref(false); |
| | | const receiptRows = ref<any[]>([]); const saleRows = ref<any[]>([]); const summaryRows = ref<any[]>([]); |
| | | const month = ref(dayjs()); |
| | | const receiptPage = reactive({ current: 1, pageSize: 20, total: 0 }); |
| | | const salePage = reactive({ current: 1, pageSize: 20, total: 0 }); |
| | | const receipt = reactive<any>({}); const sale = reactive<any>({}); |
| | | const receiptColumns = [{title:'å
¥åºåå·',dataIndex:'code'}, {title:'ç产订åå·',dataIndex:'workOrderCode'}, {title:'ç©æç¼å·',dataIndex:'itemId'}, {title:'æ°é',dataIndex:'quantity'}, {title:'åºä½ç¼å·',dataIndex:'areaId'}, {title:'å
¥åºæ¶é´',dataIndex:'receiptTime'}]; |
| | | const saleColumns = [{title:'åºå®åå·',dataIndex:'code'}, {title:'è´ä¹°æ¹',dataIndex:'buyer'}, {title:'ç¶æ',dataIndex:'status'}, {title:'å建æ¶é´',dataIndex:'createTime'}, {title:'æä½',key:'actions'}]; |
| | | const summaryColumns = [{title:'ç产订åå·',dataIndex:'workOrderCode'}, {title:'ç©æç¼å·',dataIndex:'itemId'}, {title:'åºææ°é',dataIndex:'quantity'}]; |
| | | const statusText: Record<number,string> = {0:'è稿',1:'审æ¹ä¸',2:'å·²åºåº',3:'已驳å',4:'已忶'}; |
| | | async function loadReceipts() { const r: any = await requestClient.get('/mes/wm/scrap-receipt/page', {params:{pageNo:receiptPage.current,pageSize:receiptPage.pageSize}}); receiptRows.value = r.list; receiptPage.total = r.total; } |
| | | async function loadSales() { const r: any = await requestClient.get('/mes/wm/scrap-sale/page', {params:{pageNo:salePage.current,pageSize:salePage.pageSize}}); saleRows.value = r.list; salePage.total = r.total; } |
| | | async function loadSummary() { if (month.value) summaryRows.value = await requestClient.get('/mes/wm/scrap-receipt/monthly-summary', {params:{month:month.value.format('YYYY-MM')}}); } |
| | | function newRequestId() { return globalThis.crypto?.randomUUID?.() ?? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replaceAll(/[xy]/g, c => { const n = Math.trunc(Math.random() * 16); return (c === 'x' ? n : (n & 3) | 8).toString(16); }); } |
| | | async function showDetails(row:any) { saleLines.value = await requestClient.get('/mes/wm/scrap-sale/lines', {params:{id:row.id}}); detailsOpen.value = true; } |
| | | function openReceipt() { Object.keys(receipt).forEach(k=>delete receipt[k]); Object.assign(receipt,{requestId:newRequestId(),quantity:1}); receiptOpen.value=true; } |
| | | function openSale() { Object.keys(sale).forEach(k=>delete sale[k]); Object.assign(sale,{requestId:newRequestId(),quantity:1,unitPrice:0}); saleOpen.value=true; } |
| | | async function saveReceipt() { |
| | | if (!receipt.workOrderId || !receipt.itemId || !receipt.warehouseId || !receipt.locationId || !receipt.areaId || !(receipt.quantity > 0)) { message.warning('请填åç产订åãç©æãåºä½åæ°é'); return; } |
| | | busy.value=true; try { await requestClient.post('/mes/wm/scrap-receipt/create',receipt); receiptOpen.value=false; message.success('å
¥åºæå'); await loadReceipts(); } finally {busy.value=false;} |
| | | } |
| | | async function saveSale() { |
| | | if (!sale.buyer?.trim() || !sale.materialStockId || !(sale.quantity > 0) || sale.unitPrice == null || sale.unitPrice < 0) { message.warning('请填åè´ä¹°æ¹ãåºåãæ°éååä»·'); return; } |
| | | busy.value=true; try { await requestClient.post('/mes/wm/scrap-sale/create',{requestId:sale.requestId,buyer:sale.buyer,remark:sale.remark,lines:[{materialStockId:sale.materialStockId,quantity:sale.quantity,unitPrice:sale.unitPrice}]}); saleOpen.value=false; message.success('åºå®åå·²å建'); await loadSales(); } finally {busy.value=false;} |
| | | } |
| | | async function submitSale(row:any) { await requestClient.put('/mes/wm/scrap-sale/submit',null,{params:{id:row.id}}); message.success('å·²æäº¤è´¢å¡å®¡æ¹'); await loadSales(); } |
| | | onMounted(async()=>{ await Promise.all([loadReceipts(),loadSales(),loadSummary()]); }); |
| | | </script> |
| | | <template> |
| | | <Page auto-content-height> |
| | | <Card title="åºæç®¡ç"> |
| | | <Tabs> |
| | | <TabPane key="receipts" tab="åºæå
¥åº"> |
| | | <Space style="margin-bottom: 16px"><Button type="primary" @click="openReceipt">ç»è®°å
¥åº</Button><Button @click="loadReceipts">å·æ°</Button></Space> |
| | | <Table :data-source="receiptRows" :columns="receiptColumns" row-key="id" :pagination="receiptPage" :scroll="{x:900}" @change="(p:any)=>{receiptPage.current=p.current;receiptPage.pageSize=p.pageSize;loadReceipts()}" /> |
| | | </TabPane> |
| | | <TabPane key="sales" tab="åºæåºå®"> |
| | | <Space style="margin-bottom: 16px"><Button type="primary" @click="openSale">æ°å»ºåºå®å</Button><Button @click="loadSales">å·æ°</Button></Space> |
| | | <Table :data-source="saleRows" :columns="saleColumns" row-key="id" :pagination="salePage" :scroll="{x:800}" @change="(p:any)=>{salePage.current=p.current;salePage.pageSize=p.pageSize;loadSales()}"> |
| | | <template #bodyCell="{column,record}"><template v-if="column.dataIndex === 'status'">{{ statusText[record.status] || record.status }}</template><template v-else-if="column.key === 'actions'"><Button type="link" @click="showDetails(record)">æç»</Button><Button v-if="record.status === 0" type="link" @click="submitSale(record)">æäº¤è´¢å¡å®¡æ¹</Button></template></template> |
| | | </Table> |
| | | </TabPane> |
| | | <TabPane key="summary" tab="æè®¢åç»è®¡"> |
| | | <Space style="margin-bottom: 16px"><DatePicker v-model:value="month" picker="month" :allow-clear="false" /><Button @click="loadSummary">æ¥è¯¢</Button></Space> |
| | | <Table :data-source="summaryRows" :columns="summaryColumns" :pagination="false" :row-key="(r:any)=>`${r.workOrderId}-${r.itemId}`" /> |
| | | </TabPane> |
| | | </Tabs> |
| | | </Card> |
| | | <Modal v-model:open="receiptOpen" title="ç»è®°åºæå
¥åº" :confirm-loading="busy" @ok="saveReceipt"> |
| | | <Form layout="vertical"> |
| | | <FormItem label="ç产订å" required><ProWorkOrderSelect v-model="receipt.workOrderId" /></FormItem> |
| | | <FormItem label="åºæç©æ" required><MdItemSelect v-model="receipt.itemId" /></FormItem> |
| | | <FormItem label="ä»åº" required><WmWarehouseSelect v-model="receipt.warehouseId" @change="receipt.locationId=undefined;receipt.areaId=undefined" /></FormItem> |
| | | <FormItem label="åºåº" required><WmWarehouseLocationSelect v-model="receipt.locationId" :warehouse-id="receipt.warehouseId" @change="receipt.areaId=undefined" /></FormItem> |
| | | <FormItem label="åºæåºä½" required><WmWarehouseAreaSelect v-model="receipt.areaId" :location-id="receipt.locationId" /></FormItem> |
| | | <FormItem label="æ°é" required><InputNumber v-model:value="receipt.quantity" :min="0.0001" :precision="4" style="width:100%" /></FormItem> |
| | | <FormItem label="æ¹æ¬¡å·"><Input v-model:value="receipt.batchCode" :maxlength="100" /></FormItem> |
| | | <FormItem label="夿³¨"><Input.TextArea v-model:value="receipt.remark" :maxlength="500" /></FormItem> |
| | | </Form> |
| | | </Modal> |
| | | <Modal v-model:open="detailsOpen" title="åºå®æç»" :footer="null"><Table :data-source="saleLines" row-key="id" :pagination="false" :columns="[{title:'åºåç¼å·',dataIndex:'materialStockId'},{title:'æ°é',dataIndex:'quantity'},{title:'åä»·',dataIndex:'unitPrice'},{title:'åºåºæµæ°´ç¼å·',dataIndex:'transactionId'}]" /></Modal> |
| | | <Modal v-model:open="saleOpen" title="æ°å»ºåºæåºå®å" :confirm-loading="busy" @ok="saveSale"> |
| | | <Form layout="vertical"> |
| | | <FormItem label="è´ä¹°æ¹" required><Input v-model:value="sale.buyer" :maxlength="200" /></FormItem> |
| | | <FormItem label="åºæåºå" required><WmMaterialStockSelect v-model="sale.materialStockId" /></FormItem> |
| | | <FormItem label="æ°é" required><InputNumber v-model:value="sale.quantity" :min="0.0001" :precision="4" style="width:100%" /></FormItem> |
| | | <FormItem label="åä»·" required><InputNumber v-model:value="sale.unitPrice" :min="0" :precision="4" style="width:100%" /></FormItem> |
| | | <FormItem label="夿³¨"><Input.TextArea v-model:value="sale.remark" :maxlength="500" /></FormItem> |
| | | </Form> |
| | | </Modal> |
| | | </Page> |
| | | </template> |