feat(wls): 更新销售退货功能支持关联销售出库单
- 移除产品销售、退货销售、发货通知单中的质检相关字段
- 重构退货销售单,新增关联销售出库单选择功能
- 新增退货销售单行表单,支持通过出库单行自动带入物料和批次信息
- 添加退货销售单行列表组件,支持添加和编辑退货行
- 实现销售出库单和出库行选择对话框组件
- 更新退货销售单API接口,添加可退销售出库单查询功能
- 修改退货销售单表格列,增加销售出库单号显示
- 调整物料规格型号和单位字段命名规范
- 移除退货销售单的质检执行按钮和相关逻辑
| | |
| | | clientId?: number; // 客æ·ç¼å· |
| | | clientCode?: string; // 客æ·ç¼ç |
| | | clientName?: string; // 客æ·åç§° |
| | | productSalesId?: number; // éå®åºåºåç¼å· |
| | | productSalesCode?: string; // éå®åºåºåå· |
| | | returnDate?: number; // éè´§æ¥æ |
| | | returnReason?: string; // éè´§åå |
| | | status?: number; // åæ®ç¶æ |
| | | remark?: string; // 夿³¨ |
| | | createTime?: Date; // å建æ¶é´ |
| | | } |
| | | |
| | | /** å¯ééå®åºåºå */ |
| | | export interface ReturnableProductSales { |
| | | id?: number; // éå®åºåºåç¼å· |
| | | code?: string; // åºåºåå· |
| | | name?: string; // åºåºååç§° |
| | | clientId?: number; // 客æ·ç¼å· |
| | | clientName?: string; // 客æ·åç§° |
| | | salesDate?: number; // åºåºæ¥æ |
| | | outboundTime?: number; // å®é
åºåºæ¶é´ |
| | | } |
| | | |
| | | /** å¯ééå®åºåºåè¡ */ |
| | | export interface ReturnableProductSalesLine { |
| | | productSalesLineId?: number; // éå®åºåºåè¡ç¼å· |
| | | salesId?: number; // éå®åºåºåç¼å· |
| | | itemId?: number; // ç©æç¼å· |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | itemSpecification?: string; // è§æ ¼åå· |
| | | itemUnit?: string; // 计éåä½ |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡å· |
| | | outboundQuantity?: number; // åºåºæ°é |
| | | returnedQuantity?: number; // 已鿰é |
| | | returnableQuantity?: number; // å¯éæ°é |
| | | } |
| | | } |
| | | |
| | |
| | | ); |
| | | } |
| | | |
| | | /** æ¥è¯¢å¯ééå®åºåºåå页ï¼ä»
已宿ä¸åå¨å¯éè¡ï¼ */ |
| | | export function getReturnableProductSalesPage(params: PageParam) { |
| | | return requestClient.get< |
| | | PageResult<MesWmReturnSalesApi.ReturnableProductSales> |
| | | >('/mes/wm/return-sales/returnable-product-sales-page', { params }); |
| | | } |
| | | |
| | | /** æ¥è¯¢éå®åºåºåå¯éè¡å表 */ |
| | | export function getReturnableProductSalesLineList(productSalesId: number) { |
| | | return requestClient.get<MesWmReturnSalesApi.ReturnableProductSalesLine[]>( |
| | | '/mes/wm/return-sales/returnable-product-sales-line-list', |
| | | { params: { productSalesId } }, |
| | | ); |
| | | } |
| | | |
| | | /** æ¥è¯¢éå®éè´§å详æ
*/ |
| | | export function getReturnSales(id: number) { |
| | | return requestClient.get<MesWmReturnSalesApi.ReturnSales>( |
| | |
| | | export interface ReturnSalesLine { |
| | | id?: number; // è¡ç¼å· |
| | | returnId?: number; // éè´§åç¼å· |
| | | productSalesLineId?: number; // éå®åºåºåè¡ç¼å· |
| | | itemId?: number; // ç©æç¼å· |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureName?: string; // åä½ |
| | | itemSpecification?: string; // è§æ ¼åå· |
| | | itemUnit?: string; // åä½ |
| | | quantity?: number; // éè´§æ°é |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡å· |
| | |
| | | |
| | | import { Button } from 'ant-design-vue'; |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import CrmCustomerSelect from '#/components/crm-customer-select.vue'; |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'oqcCheckFlag', |
| | | title: 'æ¯å¦æ ¡éª', |
| | | width: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'remark', |
| | | title: '夿³¨', |
| | | minWidth: 150, |
| | |
| | | label: 'åè´§éç¥åè¡', |
| | | component: markRaw(WmSalesNoticeLineSelect), |
| | | componentProps: { |
| | | // éæ©åè´§éç¥åè¡åï¼èªå¨åå¡«ç©æãæ°éãæ¹æ¬¡ãæ¯å¦æ£éª |
| | | // éæ©åè´§éç¥åè¡åï¼èªå¨åå¡«ç©æãæ°éãæ¹æ¬¡ |
| | | onChange: async (line?: MesWmSalesNoticeLineApi.SalesNoticeLine) => { |
| | | await formApi?.setValues({ |
| | | batchCode: line?.batchCode, |
| | | itemId: line?.itemId, |
| | | oqcCheckFlag: line?.oqcCheckFlag ?? false, |
| | | quantity: line?.quantity, |
| | | }); |
| | | }, |
| | |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'oqcCheckFlag', |
| | | label: 'æ¯å¦æ ¡éª', |
| | | component: 'RadioGroup', |
| | | componentProps: { |
| | | buttonStyle: 'solid', |
| | | optionType: 'button', |
| | | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| | | }, |
| | | rules: z.boolean().default(false), |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export { default as WmReturnSalesProductSalesLineSelect } from './line-select.vue'; |
| | | export { default as WmReturnSalesProductSalesSelect } from './select.vue'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesWmReturnSalesApi } from '#/api/mes/wm/returnsales'; |
| | | |
| | | import { nextTick, ref } from 'vue'; |
| | | |
| | | import { message, Modal } from 'ant-design-vue'; |
| | | |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { getReturnableProductSalesLineList } from '#/api/mes/wm/returnsales'; |
| | | |
| | | const emit = defineEmits<{ |
| | | selected: [rows: MesWmReturnSalesApi.ReturnableProductSalesLine[]]; |
| | | }>(); |
| | | |
| | | const open = ref(false); // å¼¹çªæ¯å¦æå¼ |
| | | const productSalesId = ref<number>(); // æå±éå®åºåºåç¼å· |
| | | const selectedRows = ref<MesWmReturnSalesApi.ReturnableProductSalesLine[]>([]); // å·²éè¡ |
| | | const preSelectedId = ref<number>(); // é¢éè¡ç¼å· |
| | | |
| | | /** è¡¨æ ¼åæ®µ */ |
| | | function useGridColumns(): VxeTableGridOptions<MesWmReturnSalesApi.ReturnableProductSalesLine>['columns'] { |
| | | return [ |
| | | { |
| | | type: 'radio', |
| | | width: 50, |
| | | }, |
| | | { |
| | | field: 'itemCode', |
| | | title: 'ç©æç¼ç ', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemName', |
| | | title: 'ç©æåç§°', |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | field: 'itemSpecification', |
| | | title: 'è§æ ¼åå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemUnit', |
| | | title: 'åä½', |
| | | width: 80, |
| | | }, |
| | | { |
| | | field: 'batchCode', |
| | | title: 'æ¹æ¬¡å·', |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | field: 'outboundQuantity', |
| | | title: 'åºåºæ°é', |
| | | width: 110, |
| | | }, |
| | | { |
| | | field: 'returnedQuantity', |
| | | title: '已鿰é', |
| | | width: 110, |
| | | }, |
| | | { |
| | | field: 'returnableQuantity', |
| | | title: 'å¯éæ°é', |
| | | width: 110, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** å¤çåé忢 */ |
| | | function handleRadioChange(row: MesWmReturnSalesApi.ReturnableProductSalesLine) { |
| | | selectedRows.value = [row]; |
| | | } |
| | | |
| | | /** å¤çè¡åå»ï¼éä¸å¹¶ç¡®è®¤ */ |
| | | async function handleCellDblclick({ |
| | | row, |
| | | }: { |
| | | row: MesWmReturnSalesApi.ReturnableProductSalesLine; |
| | | }) { |
| | | selectedRows.value = [row]; |
| | | await gridApi.grid.setRadioRow(row); |
| | | handleConfirm(); |
| | | } |
| | | |
| | | /** åæ¾é¢éè¡ */ |
| | | async function applyPreSelection() { |
| | | if (!preSelectedId.value) { |
| | | return; |
| | | } |
| | | const rows = |
| | | gridApi.grid.getData() as MesWmReturnSalesApi.ReturnableProductSalesLine[]; |
| | | for (const row of rows) { |
| | | if (row.productSalesLineId === preSelectedId.value) { |
| | | await gridApi.grid.setRadioRow(row); |
| | | selectedRows.value = [row]; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | | gridOptions: { |
| | | columns: useGridColumns(), |
| | | height: 460, |
| | | keepSource: true, |
| | | pagerConfig: { |
| | | enabled: false, |
| | | }, |
| | | radioConfig: { |
| | | highlight: true, |
| | | trigger: 'row', |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async () => { |
| | | if (!productSalesId.value) { |
| | | return { list: [], total: 0 }; |
| | | } |
| | | const list = await getReturnableProductSalesLineList( |
| | | productSalesId.value, |
| | | ); |
| | | return { list, total: list.length }; |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'productSalesLineId', |
| | | isHover: true, |
| | | }, |
| | | toolbarConfig: { |
| | | refresh: true, |
| | | }, |
| | | } as VxeTableGridOptions<MesWmReturnSalesApi.ReturnableProductSalesLine>, |
| | | gridEvents: { |
| | | cellDblclick: handleCellDblclick, |
| | | radioChange: ({ |
| | | row, |
| | | }: { |
| | | row: MesWmReturnSalesApi.ReturnableProductSalesLine; |
| | | }) => { |
| | | handleRadioChange(row); |
| | | }, |
| | | }, |
| | | }); |
| | | |
| | | /** æå¼è¡éæ©å¼¹çª */ |
| | | async function openModal(id: number | undefined, selectedId?: number) { |
| | | open.value = true; |
| | | productSalesId.value = id; |
| | | preSelectedId.value = selectedId; |
| | | selectedRows.value = []; |
| | | await nextTick(); |
| | | await gridApi.grid.clearRadioRow(); |
| | | await gridApi.query(); |
| | | await nextTick(); |
| | | await applyPreSelection(); |
| | | } |
| | | |
| | | /** å
³éå¼¹çª */ |
| | | async function closeModal() { |
| | | open.value = false; |
| | | selectedRows.value = []; |
| | | await gridApi.grid.clearRadioRow(); |
| | | } |
| | | |
| | | /** ç¡®è®¤éæ©è¡ */ |
| | | function handleConfirm() { |
| | | if (selectedRows.value.length === 0) { |
| | | message.warning('è¯·éæ©ä¸æ¡æ°æ®'); |
| | | return; |
| | | } |
| | | emit('selected', [selectedRows.value[0]!]); |
| | | open.value = false; |
| | | } |
| | | |
| | | defineExpose({ open: openModal }); |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal |
| | | v-model:open="open" |
| | | title="å¯éåºåºè¡éæ©" |
| | | width="70%" |
| | | :destroy-on-close="true" |
| | | @cancel="closeModal" |
| | | @ok="handleConfirm" |
| | | > |
| | | <Grid table-title="å¯éåºåºè¡å表" /> |
| | | </Modal> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { MesWmReturnSalesApi } from '#/api/mes/wm/returnsales'; |
| | | |
| | | import { computed, ref, useAttrs, watch } from 'vue'; |
| | | |
| | | import { IconifyIcon } from '@vben/icons'; |
| | | |
| | | import { Input, Tooltip } from 'ant-design-vue'; |
| | | |
| | | import { getProductSalesLine } from '#/api/mes/wm/productsales/line'; |
| | | |
| | | import WmReturnSalesProductSalesLineSelectDialog from './line-select-dialog.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'WmReturnSalesProductSalesLineSelect', |
| | | inheritAttrs: false, |
| | | }); |
| | | |
| | | const props = withDefaults( |
| | | defineProps<{ |
| | | allowClear?: boolean; |
| | | disabled?: boolean; |
| | | modelValue?: number; |
| | | placeholder?: string; |
| | | productSalesId?: number; // æå±éå®åºåºåç¼å· |
| | | }>(), |
| | | { |
| | | allowClear: true, |
| | | disabled: false, |
| | | modelValue: undefined, |
| | | placeholder: 'è¯·éæ©åºåºè¡', |
| | | productSalesId: undefined, |
| | | }, |
| | | ); |
| | | |
| | | const emit = defineEmits<{ |
| | | change: [item: MesWmReturnSalesApi.ReturnableProductSalesLine | undefined]; |
| | | 'update:modelValue': [value: number | undefined]; |
| | | }>(); |
| | | |
| | | const attrs = useAttrs(); |
| | | const dialogRef = ref< |
| | | InstanceType<typeof WmReturnSalesProductSalesLineSelectDialog> |
| | | >(); |
| | | const hovering = ref(false); |
| | | const selectedItem = ref<MesWmReturnSalesApi.ReturnableProductSalesLine>(); |
| | | |
| | | const displayLabel = computed(() => { |
| | | const item = selectedItem.value; |
| | | if (!item) { |
| | | return ''; |
| | | } |
| | | return `${item.itemCode ?? ''} - ${item.itemName ?? ''}`; |
| | | }); |
| | | |
| | | const showClear = computed( |
| | | () => |
| | | props.allowClear && |
| | | !props.disabled && |
| | | hovering.value && |
| | | props.modelValue !== undefined && |
| | | props.modelValue !== null, |
| | | ); |
| | | |
| | | /** æ ¹æ®ç¼å·åæ¡æ¥è¯¢åºåºè¡ä¿¡æ¯ï¼ç¨äºç¼è¾åæ¾ï¼ */ |
| | | async function resolveItemById(id: number | undefined) { |
| | | if (!id) { |
| | | selectedItem.value = undefined; |
| | | return; |
| | | } |
| | | if (selectedItem.value?.productSalesLineId === id) { |
| | | return; |
| | | } |
| | | try { |
| | | const line = await getProductSalesLine(id); |
| | | selectedItem.value = line |
| | | ? { |
| | | batchCode: line.batchCode, |
| | | batchId: line.batchId, |
| | | itemCode: line.itemCode, |
| | | itemId: line.itemId, |
| | | itemName: line.itemName, |
| | | itemSpecification: line.specification, |
| | | itemUnit: line.unitMeasureName, |
| | | outboundQuantity: line.quantity, |
| | | productSalesLineId: line.id, |
| | | salesId: line.salesId, |
| | | } |
| | | : undefined; |
| | | } catch { |
| | | selectedItem.value = undefined; |
| | | } |
| | | } |
| | | |
| | | watch(() => props.modelValue, resolveItemById, { immediate: true }); |
| | | |
| | | /** productSalesId ååæ¶æ¸
空éä¸ï¼å
³èçåºåºè¡å·²å¤±æï¼ */ |
| | | watch( |
| | | () => props.productSalesId, |
| | | () => { |
| | | selectedItem.value = undefined; |
| | | emit('update:modelValue', undefined); |
| | | emit('change', undefined); |
| | | }, |
| | | ); |
| | | |
| | | /** æ¸
空已éè¡ */ |
| | | function clearSelected() { |
| | | selectedItem.value = undefined; |
| | | emit('update:modelValue', undefined); |
| | | emit('change', undefined); |
| | | } |
| | | |
| | | /** æå¼è¡éæ©å¼¹çª */ |
| | | function handleClick(event: MouseEvent) { |
| | | if (props.disabled || !props.productSalesId) { |
| | | return; |
| | | } |
| | | const target = event.target as HTMLElement; |
| | | if (showClear.value && target.closest('.ant-input-suffix')) { |
| | | event.stopPropagation(); |
| | | clearSelected(); |
| | | return; |
| | | } |
| | | dialogRef.value?.open(props.productSalesId, props.modelValue ?? undefined); |
| | | } |
| | | |
| | | /** å¼¹çªéä¸åè° */ |
| | | function handleSelected( |
| | | rows: MesWmReturnSalesApi.ReturnableProductSalesLine[], |
| | | ) { |
| | | const item = rows[0]; |
| | | if (!item) { |
| | | return; |
| | | } |
| | | selectedItem.value = item; |
| | | emit('update:modelValue', item.productSalesLineId); |
| | | emit('change', item); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div |
| | | v-bind="attrs" |
| | | class="w-full" |
| | | :class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'" |
| | | @click="handleClick" |
| | | @mouseenter="hovering = true" |
| | | @mouseleave="hovering = false" |
| | | > |
| | | <Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false"> |
| | | <template #title> |
| | | <div v-if="selectedItem" class="leading-6"> |
| | | <div>ç©æç¼ç ï¼{{ selectedItem.itemCode || '-' }}</div> |
| | | <div>ç©æåç§°ï¼{{ selectedItem.itemName || '-' }}</div> |
| | | <div>è§æ ¼åå·ï¼{{ selectedItem.itemSpecification || '-' }}</div> |
| | | <div>æ¹æ¬¡å·ï¼{{ selectedItem.batchCode || '-' }}</div> |
| | | <div>åºåºæ°éï¼{{ selectedItem.outboundQuantity ?? '-' }}</div> |
| | | </div> |
| | | </template> |
| | | <Input |
| | | :disabled="disabled" |
| | | :placeholder="placeholder" |
| | | :value="displayLabel" |
| | | readonly |
| | | > |
| | | <template #suffix> |
| | | <IconifyIcon |
| | | class="size-4" |
| | | :icon="showClear ? 'lucide:circle-x' : 'lucide:search'" |
| | | /> |
| | | </template> |
| | | </Input> |
| | | </Tooltip> |
| | | </div> |
| | | <WmReturnSalesProductSalesLineSelectDialog |
| | | ref="dialogRef" |
| | | @selected="handleSelected" |
| | | /> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesWmReturnSalesApi } from '#/api/mes/wm/returnsales'; |
| | | |
| | | import { markRaw, nextTick, ref } from 'vue'; |
| | | |
| | | import { message, Modal } from 'ant-design-vue'; |
| | | |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { getReturnableProductSalesPage } from '#/api/mes/wm/returnsales'; |
| | | import CrmCustomerSelect from '#/components/crm-customer-select.vue'; |
| | | |
| | | const emit = defineEmits<{ |
| | | selected: [rows: MesWmReturnSalesApi.ReturnableProductSales[]]; |
| | | }>(); |
| | | |
| | | const open = ref(false); // å¼¹çªæ¯å¦æå¼ |
| | | const selectedRows = ref<MesWmReturnSalesApi.ReturnableProductSales[]>([]); // å·²éåºåºå |
| | | const preSelectedId = ref<number>(); // é¢éåºåºåç¼å· |
| | | |
| | | /** æç´¢è¡¨å */ |
| | | function useSearchSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'code', |
| | | label: 'åºåºåå·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥åºåºåå·', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'name', |
| | | label: 'åºåºååç§°', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥åºåºååç§°', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'clientId', |
| | | label: '客æ·', |
| | | component: markRaw(CrmCustomerSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©å®¢æ·', |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** è¡¨æ ¼åæ®µ */ |
| | | function useGridColumns(): VxeTableGridOptions<MesWmReturnSalesApi.ReturnableProductSales>['columns'] { |
| | | return [ |
| | | { |
| | | type: 'radio', |
| | | width: 50, |
| | | }, |
| | | { |
| | | field: 'code', |
| | | title: 'åºåºåå·', |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | field: 'name', |
| | | title: 'åºåºååç§°', |
| | | minWidth: 150, |
| | | }, |
| | | { |
| | | field: 'clientName', |
| | | title: '客æ·åç§°', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'salesDate', |
| | | title: 'åºåºæ¥æ', |
| | | width: 120, |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'outboundTime', |
| | | title: 'å®é
åºåºæ¶é´', |
| | | minWidth: 160, |
| | | formatter: 'formatDateTime', |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** å¤çåé忢 */ |
| | | function handleRadioChange(row: MesWmReturnSalesApi.ReturnableProductSales) { |
| | | selectedRows.value = [row]; |
| | | } |
| | | |
| | | /** å¤çè¡åå»ï¼éä¸å¹¶ç¡®è®¤ */ |
| | | async function handleCellDblclick({ |
| | | row, |
| | | }: { |
| | | row: MesWmReturnSalesApi.ReturnableProductSales; |
| | | }) { |
| | | selectedRows.value = [row]; |
| | | await gridApi.grid.setRadioRow(row); |
| | | handleConfirm(); |
| | | } |
| | | |
| | | /** åæ¾é¢éåºåºå */ |
| | | async function applyPreSelection() { |
| | | if (!preSelectedId.value) { |
| | | return; |
| | | } |
| | | const rows = gridApi.grid.getData() as MesWmReturnSalesApi.ReturnableProductSales[]; |
| | | for (const row of rows) { |
| | | if (row.id === preSelectedId.value) { |
| | | await gridApi.grid.setRadioRow(row); |
| | | selectedRows.value = [row]; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | | formOptions: { |
| | | schema: useSearchSchema(), |
| | | }, |
| | | gridOptions: { |
| | | columns: useGridColumns(), |
| | | height: 520, |
| | | keepSource: true, |
| | | radioConfig: { |
| | | highlight: true, |
| | | trigger: 'row', |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues) => { |
| | | return await getReturnableProductSalesPage({ |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | isHover: true, |
| | | }, |
| | | toolbarConfig: { |
| | | refresh: true, |
| | | search: true, |
| | | }, |
| | | } as VxeTableGridOptions<MesWmReturnSalesApi.ReturnableProductSales>, |
| | | gridEvents: { |
| | | cellDblclick: handleCellDblclick, |
| | | radioChange: ({ row }: { row: MesWmReturnSalesApi.ReturnableProductSales }) => { |
| | | handleRadioChange(row); |
| | | }, |
| | | }, |
| | | }); |
| | | |
| | | /** éç½®æ¥è¯¢åéæ©ç¶æ */ |
| | | async function resetQueryState() { |
| | | selectedRows.value = []; |
| | | await gridApi.grid.clearRadioRow(); |
| | | await gridApi.formApi.resetForm(); |
| | | } |
| | | |
| | | /** æå¼åºåºåéæ©å¼¹çª */ |
| | | async function openModal(selectedId?: number) { |
| | | open.value = true; |
| | | preSelectedId.value = selectedId; |
| | | await resetQueryState(); |
| | | await gridApi.query(); |
| | | await nextTick(); |
| | | await applyPreSelection(); |
| | | } |
| | | |
| | | /** å
³éåºåºåéæ©å¼¹çª */ |
| | | async function closeModal() { |
| | | open.value = false; |
| | | await resetQueryState(); |
| | | } |
| | | |
| | | /** ç¡®è®¤éæ©åºåºå */ |
| | | function handleConfirm() { |
| | | if (selectedRows.value.length === 0) { |
| | | message.warning('è¯·éæ©ä¸æ¡æ°æ®'); |
| | | return; |
| | | } |
| | | emit('selected', [selectedRows.value[0]!]); |
| | | open.value = false; |
| | | } |
| | | |
| | | defineExpose({ open: openModal }); |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal |
| | | v-model:open="open" |
| | | title="éå®åºåºåéæ©" |
| | | width="70%" |
| | | :destroy-on-close="true" |
| | | @cancel="closeModal" |
| | | @ok="handleConfirm" |
| | | > |
| | | <Grid table-title="å¯ééå®åºåºåå表" /> |
| | | </Modal> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { MesWmReturnSalesApi } from '#/api/mes/wm/returnsales'; |
| | | |
| | | import { computed, ref, useAttrs, watch } from 'vue'; |
| | | |
| | | import { IconifyIcon } from '@vben/icons'; |
| | | |
| | | import { Input, Tooltip } from 'ant-design-vue'; |
| | | |
| | | import { getProductSales } from '#/api/mes/wm/productsales'; |
| | | |
| | | import WmReturnSalesProductSalesSelectDialog from './select-dialog.vue'; |
| | | |
| | | defineOptions({ name: 'WmReturnSalesProductSalesSelect', inheritAttrs: false }); |
| | | |
| | | const props = withDefaults( |
| | | defineProps<{ |
| | | allowClear?: boolean; |
| | | disabled?: boolean; |
| | | modelValue?: number; |
| | | placeholder?: string; |
| | | }>(), |
| | | { |
| | | allowClear: true, |
| | | disabled: false, |
| | | modelValue: undefined, |
| | | placeholder: 'è¯·éæ©éå®åºåºå', |
| | | }, |
| | | ); |
| | | |
| | | const emit = defineEmits<{ |
| | | change: [item: MesWmReturnSalesApi.ReturnableProductSales | undefined]; |
| | | 'update:modelValue': [value: number | undefined]; |
| | | }>(); |
| | | |
| | | const attrs = useAttrs(); |
| | | const dialogRef = ref< |
| | | InstanceType<typeof WmReturnSalesProductSalesSelectDialog> |
| | | >(); |
| | | const hovering = ref(false); |
| | | const selectedItem = ref<MesWmReturnSalesApi.ReturnableProductSales>(); |
| | | |
| | | const displayLabel = computed(() => selectedItem.value?.code ?? ''); |
| | | |
| | | const showClear = computed( |
| | | () => |
| | | props.allowClear && |
| | | !props.disabled && |
| | | hovering.value && |
| | | props.modelValue !== undefined && |
| | | props.modelValue !== null, |
| | | ); |
| | | |
| | | /** æ ¹æ®ç¼å·åæ¡æ¥è¯¢åºåºåä¿¡æ¯ï¼ç¨äºç¼è¾åæ¾ï¼ */ |
| | | async function resolveItemById(id: number | undefined) { |
| | | if (!id) { |
| | | selectedItem.value = undefined; |
| | | return; |
| | | } |
| | | if (selectedItem.value?.id === id) { |
| | | return; |
| | | } |
| | | // å·²éå®çåºåºåä¸å¨ãå¯éãå表ä¸ï¼è¿éç´æ¥æç¼å·åæ¾ |
| | | try { |
| | | const productSales = await getProductSales(id); |
| | | selectedItem.value = productSales |
| | | ? { |
| | | clientId: productSales.clientId, |
| | | clientName: productSales.clientName, |
| | | code: productSales.code, |
| | | id: productSales.id, |
| | | name: productSales.name, |
| | | salesDate: productSales.salesDate, |
| | | } |
| | | : undefined; |
| | | } catch { |
| | | selectedItem.value = undefined; |
| | | } |
| | | } |
| | | |
| | | watch(() => props.modelValue, resolveItemById, { immediate: true }); |
| | | |
| | | /** æ¸
空已éåºåºå */ |
| | | function clearSelected() { |
| | | selectedItem.value = undefined; |
| | | emit('update:modelValue', undefined); |
| | | emit('change', undefined); |
| | | } |
| | | |
| | | /** æå¼åºåºåéæ©å¼¹çª */ |
| | | function handleClick(event: MouseEvent) { |
| | | if (props.disabled) { |
| | | return; |
| | | } |
| | | const target = event.target as HTMLElement; |
| | | if (showClear.value && target.closest('.ant-input-suffix')) { |
| | | event.stopPropagation(); |
| | | clearSelected(); |
| | | return; |
| | | } |
| | | dialogRef.value?.open(props.modelValue ?? undefined); |
| | | } |
| | | |
| | | /** å¼¹çªéä¸åè° */ |
| | | function handleSelected(rows: MesWmReturnSalesApi.ReturnableProductSales[]) { |
| | | const item = rows[0]; |
| | | if (!item) { |
| | | return; |
| | | } |
| | | selectedItem.value = item; |
| | | emit('update:modelValue', item.id); |
| | | emit('change', item); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div |
| | | v-bind="attrs" |
| | | class="w-full" |
| | | :class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'" |
| | | @click="handleClick" |
| | | @mouseenter="hovering = true" |
| | | @mouseleave="hovering = false" |
| | | > |
| | | <Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false"> |
| | | <template #title> |
| | | <div v-if="selectedItem" class="leading-6"> |
| | | <div>åºåºåå·ï¼{{ selectedItem.code || '-' }}</div> |
| | | <div>åºåºååç§°ï¼{{ selectedItem.name || '-' }}</div> |
| | | <div>客æ·ï¼{{ selectedItem.clientName || '-' }}</div> |
| | | </div> |
| | | </template> |
| | | <Input |
| | | :disabled="disabled" |
| | | :placeholder="placeholder" |
| | | :value="displayLabel" |
| | | readonly |
| | | > |
| | | <template #suffix> |
| | | <IconifyIcon |
| | | class="size-4" |
| | | :icon="showClear ? 'lucide:circle-x' : 'lucide:search'" |
| | | /> |
| | | </template> |
| | | </Input> |
| | | </Tooltip> |
| | | </div> |
| | | <WmReturnSalesProductSalesSelectDialog |
| | | ref="dialogRef" |
| | | @selected="handleSelected" |
| | | /> |
| | | </template> |
| | |
| | | |
| | | import { Button } from 'ant-design-vue'; |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import CrmCustomerSelect from '#/components/crm-customer-select.vue'; |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | import { WmBatchSelect } from '#/views/wls/batch/components'; |
| | | import { |
| | | WmWarehouseAreaSelect, |
| | | WmWarehouseLocationSelect, |
| | | WmWarehouseSelect, |
| | | } from '#/views/wls/warehouse/components'; |
| | | |
| | | import { |
| | | WmReturnSalesProductSalesLineSelect, |
| | | WmReturnSalesProductSalesSelect, |
| | | } from './components'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'finish' | 'stock' | 'update'; |
| | |
| | | placeholder: '请è¾å
¥éè´§ååç§°', |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'productSalesId', |
| | | label: 'éå®åºåºå', |
| | | component: markRaw(WmReturnSalesProductSalesSelect), |
| | | componentProps: { |
| | | disabled: isHeaderReadonly(formType), |
| | | // éæ©åºåºååèªå¨å¸¦åºå®¢æ· |
| | | onChange: async ( |
| | | productSales?: MesWmReturnSalesApi.ReturnableProductSales, |
| | | ) => { |
| | | await formApi?.setFieldValue('clientId', productSales?.clientId); |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'clientId', |
| | |
| | | minWidth: 150, |
| | | }, |
| | | { |
| | | field: 'productSalesCode', |
| | | title: 'éå®åºåºåå·', |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | field: 'clientCode', |
| | | title: '客æ·ç¼ç ', |
| | | minWidth: 120, |
| | |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | field: 'specification', |
| | | field: 'itemSpecification', |
| | | title: 'è§æ ¼åå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | field: 'itemUnit', |
| | | title: 'åä½', |
| | | width: 80, |
| | | }, |
| | |
| | | field: 'batchCode', |
| | | title: 'æ¹æ¬¡å·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'rqcCheckFlag', |
| | | title: 'æ¯å¦éè¦è´¨æ£', |
| | | width: 120, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'qualityStatus', |
| | | title: 'è´¨éç¶æ', |
| | | width: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_WM_QUALITY_STATUS }, |
| | | }, |
| | | }, |
| | | ...(editable || stockable |
| | | ? [ |
| | |
| | | } |
| | | |
| | | /** éè´§åè¡æ°å¢/ä¿®æ¹ç表å */ |
| | | export function useLineFormSchema(clientId?: number): VbenFormSchema[] { |
| | | export function useLineFormSchema( |
| | | options: { clientId?: number; productSalesId?: number } = {}, |
| | | formApi?: VbenFormApi, |
| | | ): VbenFormSchema[] { |
| | | const { clientId, productSalesId } = options; |
| | | const hasProductSales = !!productSalesId; // å
³èäºéå®åºåºåæ¶ï¼ç©æ/æ¹æ¬¡ç±åºåºè¡å¸¦å
¥ |
| | | return [ |
| | | { |
| | | fieldName: 'productSalesLineId', |
| | | label: 'åºåºè¡', |
| | | component: markRaw(WmReturnSalesProductSalesLineSelect), |
| | | componentProps: { |
| | | // éæ©åºåºè¡åèªå¨å¸¦å
¥ç©æãæ¹æ¬¡ä¸å¯éæ°é |
| | | onChange: async ( |
| | | line?: MesWmReturnSalesApi.ReturnableProductSalesLine, |
| | | ) => { |
| | | await formApi?.setValues({ |
| | | batchCode: line?.batchCode, |
| | | itemId: line?.itemId, |
| | | quantity: line?.returnableQuantity, |
| | | returnableQuantity: line?.returnableQuantity, |
| | | }); |
| | | }, |
| | | productSalesId, |
| | | }, |
| | | rules: hasProductSales ? 'selectRequired' : undefined, |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | if: () => hasProductSales, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'itemId', |
| | | label: 'ç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ç©æ', |
| | | }, |
| | | rules: 'selectRequired', |
| | | dependencies: { |
| | | triggerFields: ['productSalesLineId'], |
| | | componentProps: (values) => ({ |
| | | disabled: hasProductSales || !!values.productSalesLineId, |
| | | placeholder: 'è¯·éæ©ç©æ', |
| | | }), |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: 'éè´§æ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥éè´§æ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'batchId', |
| | |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['itemId'], |
| | | if: () => !hasProductSales, |
| | | componentProps: (values) => ({ |
| | | clientId, |
| | | disabled: true, |
| | |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'rqcCheckFlag', |
| | | label: 'éè¦è´¨æ£', |
| | | component: 'Switch', |
| | | rules: z.boolean().default(false), |
| | | fieldName: 'batchCode', |
| | | label: 'æ¹æ¬¡å·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | disabled: true, |
| | | placeholder: 'ç±åºåºè¡å¸¦å
¥', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | if: () => hasProductSales, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'returnableQuantity', |
| | | label: 'å¯éæ°é', |
| | | component: 'Input', |
| | | componentProps: { |
| | | disabled: true, |
| | | placeholder: 'éæ©åºåºè¡åèªå¨å¸¦åº', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | if: () => hasProductSales, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: 'éè´§æ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥éè´§æ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | dependencies: { |
| | | triggerFields: ['returnableQuantity'], |
| | | componentProps: (values) => ({ |
| | | max: hasProductSales |
| | | ? (values.returnableQuantity as number | undefined) |
| | | : undefined, |
| | | }), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: 'ç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | disabled: true, |
| | | }, |
| | |
| | | label: 'æ¹æ¬¡å·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥æ¹æ¬¡å·', |
| | | disabled: true, |
| | | placeholder: 'ç±éè´§è¡å¸¦å
¥', |
| | | }, |
| | | }, |
| | | { |
| | |
| | | formModalApi.setData({ formType: 'finish', id: row.id }).open(); |
| | | } |
| | | |
| | | /** æç¤ºåå¾è´¨æ£æ¨¡å */ |
| | | function handleQc() { |
| | | message.info('请åå¾ãè´¨é管ç - éè´§æ£éªï¼RQCï¼ãä¸è¿è¡éè´§æ£éªæä½'); |
| | | } |
| | | |
| | | /** å é¤éå®éè´§å */ |
| | | async function handleDelete(row: MesWmReturnSalesApi.ReturnSales) { |
| | | const hideLoading = message.loading({ |
| | |
| | | }, |
| | | }, |
| | | { |
| | | label: 'æ§è¡è´¨æ£', |
| | | type: 'link', |
| | | ifShow: row.status === MesWmReturnSalesStatusEnum.CONFIRMED, |
| | | onClick: handleQc, |
| | | }, |
| | | { |
| | | label: 'æ§è¡éè´§', |
| | | type: 'link', |
| | | auth: ['mes:wm-return-sales:finish'], |
| | |
| | | danger: true, |
| | | auth: ['mes:wm-return-sales:cancel'], |
| | | ifShow: |
| | | row.status === MesWmReturnSalesStatusEnum.CONFIRMED || |
| | | row.status === MesWmReturnSalesStatusEnum.APPROVING || |
| | | row.status === MesWmReturnSalesStatusEnum.APPROVED, |
| | | popConfirm: { |
| | |
| | | formApi.setState({ schema: useDetailFormSchema(formApi) }); |
| | | // å è½½æ°æ® |
| | | const data = modalApi.getData<{ |
| | | batchCode?: string; |
| | | detailId?: number; |
| | | itemId?: number; |
| | | lineId: number; |
| | |
| | | modalApi.unlock(); |
| | | } |
| | | } else if (data.itemId) { |
| | | await formApi.setFieldValue('itemId', data.itemId); |
| | | await formApi.setValues({ |
| | | batchCode: data.batchCode, |
| | | itemId: data.itemId, |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | |
| | | <LineList |
| | | :client-id="formData.clientId" |
| | | :form-type="formType" |
| | | :product-sales-id="formData.productSalesId" |
| | | :return-id="formData.id" |
| | | /> |
| | | </div> |
| | |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { getReturnableProductSalesLineList } from '#/api/mes/wm/returnsales'; |
| | | import { |
| | | createReturnSalesLine, |
| | | getReturnSalesLine, |
| | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref<MesWmReturnSalesLineApi.ReturnSalesLine>(); |
| | | const returnId = ref<number>(); // æå±éè´§åç¼å· |
| | | const productSalesId = ref<number>(); // å
³èçéå®åºåºåç¼å· |
| | | |
| | | const getTitle = computed(() => { |
| | | return formData.value?.id |
| | |
| | | showDefaultActions: false, |
| | | wrapperClass: 'grid-cols-3', |
| | | }); |
| | | |
| | | /** |
| | | * 计ç®å½åè¡å¯å¡«åçæå¤§æ°éï¼ |
| | | * å¯éè¡å表ä¸çå¯éæ°éä¸å«æ¬åå ç¨ï¼éå 䏿¬è¡å·²ææ°é |
| | | */ |
| | | async function loadReturnableQuantity( |
| | | line: MesWmReturnSalesLineApi.ReturnSalesLine, |
| | | ) { |
| | | if (!productSalesId.value) { |
| | | return; |
| | | } |
| | | const current = Number(line.quantity ?? 0); |
| | | await formApi.setFieldValue('returnableQuantity', current); |
| | | if (!line.productSalesLineId) { |
| | | return; |
| | | } |
| | | try { |
| | | const lines = await getReturnableProductSalesLineList( |
| | | productSalesId.value, |
| | | ); |
| | | const matched = lines.find( |
| | | (item) => item.productSalesLineId === line.productSalesLineId, |
| | | ); |
| | | if (matched) { |
| | | await formApi.setFieldValue( |
| | | 'returnableQuantity', |
| | | Number(matched.returnableQuantity ?? 0) + current, |
| | | ); |
| | | } |
| | | } catch { |
| | | // åºåºåå·²ä¸å¯éæ¶ä¿ææ¬è¡æ°éä½ä¸ºä¸é |
| | | } |
| | | } |
| | | |
| | | const [Modal, modalApi] = useVbenModal({ |
| | | async onConfirm() { |
| | |
| | | const data = modalApi.getData<{ |
| | | clientId?: number; |
| | | id?: number; |
| | | productSalesId?: number; |
| | | returnId: number; |
| | | }>(); |
| | | returnId.value = data.returnId; |
| | | formApi.setState({ schema: useLineFormSchema(data.clientId) }); |
| | | productSalesId.value = data.productSalesId; |
| | | formApi.setState({ |
| | | schema: useLineFormSchema( |
| | | { clientId: data.clientId, productSalesId: data.productSalesId }, |
| | | formApi, |
| | | ), |
| | | }); |
| | | if (!data.id) { |
| | | return; |
| | | } |
| | |
| | | formData.value = await getReturnSalesLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues(formData.value); |
| | | await loadReturnableQuantity(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | const props = defineProps<{ |
| | | clientId?: number; |
| | | formType: FormType; |
| | | productSalesId?: number; |
| | | returnId: number; |
| | | }>(); |
| | | |
| | |
| | | lineFormModalApi |
| | | .setData({ |
| | | clientId: props.clientId, |
| | | productSalesId: props.productSalesId, |
| | | returnId: props.returnId, |
| | | }) |
| | | .open(); |
| | |
| | | .setData({ |
| | | clientId: props.clientId, |
| | | id: row.id, |
| | | productSalesId: props.productSalesId, |
| | | returnId: props.returnId, |
| | | }) |
| | | .open(); |
| | |
| | | |
| | | /** 䏿¶ï¼ç´æ¥æå¼æç»å建表å */ |
| | | function handleStock(row: MesWmReturnSalesLineApi.ReturnSalesLine) { |
| | | openDetailForm(row.id!, row.itemId); |
| | | openDetailForm(row.id!, row.itemId, row.batchCode); |
| | | } |
| | | |
| | | /** æå¼ä¸æ¶æç»è¡¨å */ |
| | | function openDetailForm(lineId: number, itemId?: number, detailId?: number) { |
| | | function openDetailForm( |
| | | lineId: number, |
| | | itemId?: number, |
| | | batchCode?: string, |
| | | detailId?: number, |
| | | ) { |
| | | detailFormModalApi |
| | | .setData({ detailId, itemId, lineId, returnId: props.returnId }) |
| | | .setData({ batchCode, detailId, itemId, lineId, returnId: props.returnId }) |
| | | .open(); |
| | | } |
| | | |
| | |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: 'æ·»å ç©æ', |
| | | label: 'æ·»å éè´§è¡', |
| | | type: 'primary', |
| | | icon: ACTION_ICON.ADD, |
| | | onClick: handleCreate, |
| | |
| | | <DetailList |
| | | :details="getExpandedDetails(row)" |
| | | :form-type="formType" |
| | | @edit="(detailId) => openDetailForm(row.id!, row.itemId, detailId)" |
| | | @edit=" |
| | | (detailId) => openDetailForm(row.id!, row.itemId, row.batchCode, detailId) |
| | | " |
| | | @refresh="loadLineDetails(row.id!)" |
| | | /> |
| | | </template> |
| | |
| | | |
| | | import { nextTick, ref } from 'vue'; |
| | | |
| | | import { DICT_TYPE } from '@vben/constants'; |
| | | |
| | | import { message, Modal } from 'ant-design-vue'; |
| | | |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | |
| | | field: 'batchCode', |
| | | title: 'æ¹æ¬¡å·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'oqcCheckFlag', |
| | | title: 'æ¯å¦æ£éª', |
| | | width: 90, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | |
| | | |
| | | import { Button } from 'ant-design-vue'; |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import CrmCustomerSelect from '#/components/crm-customer-select.vue'; |
| | | import { |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'oqcCheckFlag', |
| | | title: 'æ¯å¦æ£éª', |
| | | width: 90, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'remark', |
| | | title: '夿³¨', |
| | | minWidth: 120, |
| | |
| | | disabled: true, |
| | | placeholder: 'éæ©ç©æ/æ¹æ¬¡åèªå¨å¸¦åº', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'oqcCheckFlag', |
| | | label: 'æ¯å¦æ£éª', |
| | | component: 'Switch', |
| | | rules: z.boolean().default(true), |
| | | }, |
| | | { |
| | | fieldName: 'remark', |