| | |
| | | return requestClient.post<number>('/crm/sale-quotation/convert-contract', null, { |
| | | params: { id }, |
| | | }); |
| | | } |
| | | /** ä¸è½½æ¥ä»·æç»å¯¼å
¥æ¨¡æ¿ */ |
| | | export function importSaleQuotationTemplate() { |
| | | return requestClient.download('/crm/sale-quotation/get-import-template'); |
| | | } |
| | | |
| | | /** 导å
¥æ¥ä»·ï¼ä»
æ°å¢ï¼ */ |
| | | export function importSaleQuotation(file: File, updateSupport: boolean) { |
| | | return requestClient.upload('/crm/sale-quotation/import', { file, updateSupport }); |
| | | } |
| | |
| | | /** ç©æä¿¡æ¯ */ |
| | | export interface Item { |
| | | id?: number; |
| | | sort?: number; |
| | | code: string; |
| | | name: string; |
| | | barCode?: string; |
| | |
| | | workOrderCode?: string; // 订åç¼ç |
| | | workOrderName?: string; // 订ååç§° |
| | | taskId?: number; // ç产任å¡ç¼å· |
| | | paramValues?: ParamValue[]; |
| | | paramSnapshot?: string; |
| | | taskCode?: string; // ä»»å¡ç¼ç |
| | | itemId?: number; // 产åç©æç¼å· |
| | | itemCode?: string; // ç©æç¼ç |
| | |
| | | createTime?: number; // å建æ¶é´ |
| | | } |
| | | |
| | | export interface ParamValue { detailId: number; value?: string } |
| | | export interface ParamDetail { id: number; paramCode?: string; paramName: string; paramType?: number; required?: boolean; unitMeasureId?: number; unitMeasureName?: string } |
| | | export interface ParamTemplate { templateId: number; templateCode?: string; templateName?: string; details: ParamDetail[] } |
| | | export interface ParamSnapshot { template: ParamTemplate; values: ParamValue[] } |
| | | export interface ParamConfig { mode: number; template?: ParamTemplate; shared?: ParamSnapshot } |
| | | |
| | | /** MES ç产æ¥å·¥å页æ¥è¯¢åæ° */ |
| | | export interface PageParams extends PageParam { |
| | | code?: string; |
| | |
| | | status?: number; |
| | | feedbackTime?: string[]; |
| | | } |
| | | } |
| | | |
| | | /** è·å¾ä»»å¡ä¸è¾¾æ¶å»ç»çåæ°é
ç½® */ |
| | | export function getFeedbackParamConfig(taskId: number) { |
| | | return requestClient.get<MesProFeedbackApi.ParamConfig>('/mes/pro/feedback/param-config', { params: { taskId } }); |
| | | } |
| | | |
| | | /** æ¥è¯¢ç产æ¥å·¥å页 */ |
| | |
| | | /** å¿«éæ¥å·¥è¯·æ± */ |
| | | export interface QuickCreateReq { |
| | | taskId: number; |
| | | paramValues?: MesProFeedbackApi.ParamValue[]; |
| | | feedbackQuantity: number; |
| | | qualifiedQuantity?: number; |
| | | unqualifiedQuantity?: number; |
| | |
| | | name?: string; |
| | | type?: number; // çµåå·¥èºåç±» |
| | | attention?: string; |
| | | paramCollectMode?: number; // 0 ä¸ééï¼1 æ¯æ¬¡æ¥å·¥ï¼2 ä»»å¡å
±ç¨ |
| | | paramTemplateId?: number; |
| | | status?: number; |
| | | remark?: string; |
| | | createTime?: Date; |
| | |
| | | id?: number; |
| | | code?: string; |
| | | name?: string; |
| | | referenceProductCode?: string; |
| | | referenceProductName?: string; |
| | | description?: string; |
| | | status?: number; |
| | | remark?: string; |
| | |
| | | return requestClient.download('/mes/pro/route/export-excel', { params }); |
| | | } |
| | | |
| | | /** ä¸è½½å
å«å¯ç¨è·¯çº¿åè产ååå·¥åºã产åºãææç宿´æ¨¡æ¿ */ |
| | | export function downloadFullRouteTemplate(routeId: number) { |
| | | return requestClient.download('/mes/pro/route/get-full-import-template', { params: { routeId } }); |
| | | } |
| | | |
| | | /** æè·¯çº¿å¯¼å
¥å®æ´å·¥èºæµç¨ */ |
| | | export function importFullRoute(file: File, updateSupport: boolean) { |
| | | return requestClient.upload(`/mes/pro/route/import-full?updateSupport=${updateSupport}`, { file }); |
| | | } |
| | | |
| | | /** ä¸è½½å·¥èºè·¯çº¿å¯¼å
¥æ¨¡æ¿ */ |
| | | export function importRouteTemplate() { |
| | | return requestClient.download('/mes/pro/route/get-import-template'); |
| | |
| | | id?: number; |
| | | routeId?: number; |
| | | itemId?: number; |
| | | templateReference?: boolean; |
| | | itemCode?: string; |
| | | itemName?: string; |
| | | warehouseId?: number; |
| | |
| | | ); |
| | | } |
| | | |
| | | /** è®¾ç½®è·¯çº¿çæ¨¡æ¿åè产å */ |
| | | export function setRouteProductTemplateReference(id: number) { |
| | | return requestClient.put('/mes/pro/route-product/set-template-reference', null, { params: { id } }); |
| | | } |
| | | |
| | | /** æ¥è¯¢å·¥èºè·¯çº¿äº§å详æ
*/ |
| | | export function getRouteProduct(id: number) { |
| | | return requestClient.get<MesProRouteProductApi.RouteProduct>( |
| | |
| | | ); |
| | | } |
| | | |
| | | /** ä¸è½½åºåå¢é导å
¥æ¨¡æ¿ */ |
| | | export function importMaterialStockTemplate() { |
| | | return requestClient.download('/mes/wm/material-stock/get-import-template'); |
| | | } |
| | | |
| | | /** 导å
¥åºåå¢é */ |
| | | export function importMaterialStock(file: File, updateSupport: boolean) { |
| | | return requestClient.upload('/mes/wm/material-stock/import', { file, updateSupport }); |
| | | } |
| | | /** æ´æ°åºåå»ç»ç¶æ */ |
| | | export function updateMaterialStockFrozen(data: { |
| | | frozen: boolean; |
| | |
| | | fileName: string; |
| | | /** æ§è¡å¯¼å
¥çæ¥å£å½æ° (file, updateSupport) => Promise */ |
| | | importFn: (file: File, updateSupport: boolean) => Promise<unknown>; |
| | | /** æ¯å¦å
许è¦çå·²ææ°æ® */ |
| | | allowUpdate?: boolean; |
| | | uploadHint?: string; |
| | | /** 䏿便¨¡æ¿ä¸è½½æ¶éèå¼¹çªå
çä¸è½½æé®ã */ |
| | | showTemplateDownload?: boolean; |
| | | /** ä¸è½½æ¨¡æ¿çæ¥å£å½æ° () => Promise(blob) */ |
| | | templateFn: () => Promise<BlobPart>; |
| | | templateFn?: () => Promise<BlobPart>; |
| | | } |
| | | |
| | | const emit = defineEmits(['success']); |
| | |
| | | label: 'æ°æ®æä»¶', |
| | | component: 'Upload', |
| | | rules: 'required', |
| | | help: 'ä»
å
许导å
¥ xlsãxlsx æ ¼å¼æä»¶', |
| | | help: () => config.value.uploadHint || 'ä»
å
许导å
¥ xlsãxlsx æ ¼å¼æä»¶', |
| | | }, |
| | | { |
| | | fieldName: 'updateSupport', |
| | | dependencies: { triggerFields: ['file'], show: () => config.value.allowUpdate !== false }, |
| | | label: 'æ¯å¦è¦ç', |
| | | component: 'Switch', |
| | | componentProps: { |
| | |
| | | |
| | | /** ä¸è½½æ¨¡ç */ |
| | | async function handleDownload() { |
| | | if (!config.value.templateFn) return; |
| | | const data = await config.value.templateFn(); |
| | | downloadFileFromBlobPart({ fileName: config.value.fileName, source: data }); |
| | | } |
| | |
| | | </template> |
| | | </Form> |
| | | <template #prepend-footer> |
| | | <div class="flex flex-auto items-center"> |
| | | <div v-if="config.showTemplateDownload !== false" class="flex flex-auto items-center"> |
| | | <Button @click="handleDownload"> ä¸è½½å¯¼å
¥æ¨¡æ¿ </Button> |
| | | </div> |
| | | </template> |
| | |
| | | }, |
| | | }, |
| | | { |
| | | component: 'InputNumber', |
| | | fieldName: 'sort', |
| | | label: 'æåº', |
| | | defaultValue: 0, |
| | | componentProps: { min: 0, max: 2147483647, precision: 0, placeholder: 'æ°å¼è¶å°è¶é å' }, |
| | | }, |
| | | { |
| | | component: "Input", |
| | | fieldName: "code", |
| | | label: "ç©æç¼ç ", |
| | |
| | | export function useGridColumns(): VxeTableGridOptions["columns"] { |
| | | return [ |
| | | { type: "checkbox", width: 40 }, |
| | | { field: 'sort', title: 'æåº', width: 80 }, |
| | | { |
| | | field: "code", |
| | | title: "ç©æç¼ç ", |
| | |
| | | fileName: 'ç©æå¯¼å
¥æ¨¡æ¿.xls', |
| | | importFn: importItem, |
| | | templateFn: importItemTemplate, |
| | | uploadHint: '红è²è¡¨å¤´ä¸ºå¿
å¡«ãåç±»ååä½é¡»å·²åå¨ï¼æ°å¢ç©æåæ¥ MESï¼è¦çæ¶ä¿çååæ¥ç¶æã', |
| | | }) |
| | | .open(); |
| | | } |
| | |
| | | convertSaleQuotationToContract, |
| | | deleteSaleQuotation, |
| | | getSaleQuotationPage, |
| | | importSaleQuotation, |
| | | importSaleQuotationTemplate, |
| | | } from '#/api/crm/saleQuotation'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { QUOTATION_STATUS, useGridColumns, useGridFormSchema } from './data'; |
| | | import Form from './modules/form.vue'; |
| | | import ImportModalComponent from '#/components/import-modal'; |
| | | |
| | | const { push } = useRouter(); |
| | | |
| | |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const [ImportModal, importModalApi] = useVbenModal({ connectedComponent: ImportModalComponent, destroyOnClose: true }); |
| | | |
| | | function handleImport() { |
| | | importModalApi.setData({ title: '导å
¥æ¥ä»·å', fileName: 'é宿¥ä»·å¯¼å
¥æ¨¡æ¿.xls', importFn: importSaleQuotation, templateFn: importSaleQuotationTemplate, allowUpdate: false, uploadHint: '请ä¸è½½æ¨¡æ¿ï¼åä¸å®¢æ·åæ¥ä»·åç§°çå¤è¡ä¼å并为ä¸å¼ æ¥ä»·åï¼ä»
æ¯ææ°å¢ã' }).open(); |
| | | } |
| | | |
| | | /** å·æ°è¡¨æ ¼ */ |
| | | function handleRefresh() { |
| | |
| | | } |
| | | |
| | | const toolbarActions: ActionItem[] = [ |
| | | { label: '导å
¥æ¥ä»·å', icon: ACTION_ICON.UPLOAD, auth: ['crm:sale-quotation:create'], onClick: handleImport }, |
| | | { |
| | | label: $t('ui.actionTitle.create', ['æ¥ä»·å']), |
| | | type: 'primary', |
| | |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <ImportModal @success="handleRefresh" /> |
| | | <Grid> |
| | | <template #toolbar-tools> |
| | | <TableAction :actions="toolbarActions" /> |
| | |
| | | fileName: 'éè´è®¢å导å
¥æ¨¡æ¿.xls', |
| | | importFn: importPurchaseOrder, |
| | | templateFn: importPurchaseOrderTemplate, |
| | | allowUpdate: false, |
| | | uploadHint: '红è²è¡¨å¤´ä¸ºå¿
å¡«ãåä¸åå·çå¤è¡å并为ä¸å¼ 订åï¼æ£å¼åå·ç±ç³»ç»çæï¼ä»
æ¯ææ°å¢ï¼è¯·å¿éå¤å¯¼å
¥ãéå
³èéè´ç³è¯·æ¶ï¼è¯·å¨å·²å®¡æ¹ç³è¯·ä¸çæéè´è®¢åã', |
| | | }) |
| | | .open(); |
| | | } |
| | |
| | | fileName: 'éè´ç³è¯·å¯¼å
¥æ¨¡æ¿.xls', |
| | | importFn: importPurchaseRequest, |
| | | templateFn: importPurchaseRequestTemplate, |
| | | allowUpdate: false, |
| | | uploadHint: '红è²è¡¨å¤´ä¸ºå¿
å¡«ãåä¸åå·çå¤è¡å并为ä¸å¼ ç³è¯·ï¼æ£å¼åå·ç±ç³»ç»çæï¼ä»
æ¯ææ°å¢ï¼è¯·å¿éå¤å¯¼å
¥ã', |
| | | }) |
| | | .open(); |
| | | } |
| | |
| | | fileName: 'éå®è®¢å导å
¥æ¨¡æ¿.xls', |
| | | importFn: importSaleOrder, |
| | | templateFn: importSaleOrderTemplate, |
| | | allowUpdate: false, |
| | | uploadHint: 'åä¸åå·çå¤è¡å并为ä¸å¼ 订åï¼ç³»ç»çææ£å¼åå·ãåååå·å¯éï¼å¡«åæ¶é¡»ä¸ºå·²å®¡æ¹åå䏿ç»ä¸è´ãä»
æ¯ææ°å¢ï¼è¯·å¿éå¤å¯¼å
¥ã', |
| | | }) |
| | | .open(); |
| | | } |
| | |
| | | stopMockProgress(); |
| | | progressPercent.value = 100; |
| | | await delay(500); |
| | | message.success('导å
¥å®æ'); |
| | | if (Object.keys(importResult.value?.failureNames ?? {}).length > 0) { |
| | | message.warning('导å
¥å®æï¼é¨ååå·¥æªå¯¼å
¥ï¼è¯·æ¥ç失败åå '); |
| | | } else { |
| | | message.success('导å
¥å®æ'); |
| | | } |
| | | emit('success'); |
| | | } finally { |
| | | stopMockProgress(); |
| | |
| | | <Switch v-model:checked="updateSupport" /> |
| | | </div> |
| | | <div class="mt-2 text-gray-500"> |
| | | ä»
å
许导å
¥ xlsãxlsx æ ¼å¼æä»¶ï¼æ¨¡æ¿ä¸"é¨é¨åç§°/å²ä½åç§°/ç¨æ·è§è²"å¡«ååç§°ï¼è§è²å¤ä¸ªç¨éå·åé |
| | | ä»
æ¯æ xlsãxlsxï¼çº¢è²è¡¨å¤´ä¸ºå¿
å¡«ãé¨é¨ãå²ä½åè§è²åç§°é¡»å¯ä¸ï¼è§è²å¤ä¸ªç¨éå·åéãæ°å¢æ¶éå¡«åæ§å«ï¼è¦çå·²æåå·¥æ¶è¯·å°åå§å¯ç åè§è²ç空ï¼å²ä½é¡»ä¸åæ¡£æ¡ä¸è´ã |
| | | </div> |
| | | <!-- 导å
¥è¿åº¦æ¡ --> |
| | | <div v-if="importing" class="mt-4"> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { MesProFeedbackApi } from '#/api/mes/pro/feedback'; |
| | | import { computed, ref, watch } from 'vue'; |
| | | import { message } from 'ant-design-vue'; |
| | | import { getFeedbackParamConfig } from '#/api/mes/pro/feedback'; |
| | | |
| | | const props = defineProps<{ taskId?: number; snapshot?: string; readonly?: boolean }>(); |
| | | const config = ref<MesProFeedbackApi.ParamConfig>(); |
| | | const values = ref<Record<number, string>>({}); |
| | | const loading = ref(false); |
| | | const error = ref(''); |
| | | let loadVersion = 0; |
| | | const shared = computed(() => config.value?.mode === 2 && !!config.value?.shared); |
| | | const details = computed(() => config.value?.template?.details ?? []); |
| | | |
| | | watch(() => [props.taskId, props.snapshot] as const, async ([taskId, raw]) => { |
| | | const version = ++loadVersion; |
| | | config.value = undefined; |
| | | values.value = {}; |
| | | error.value = ''; |
| | | if (!taskId) return; |
| | | loading.value = true; |
| | | try { |
| | | const result = await getFeedbackParamConfig(taskId); |
| | | if (version !== loadVersion) return; |
| | | config.value = result; |
| | | let previous: MesProFeedbackApi.ParamSnapshot | undefined; |
| | | if (raw) previous = JSON.parse(raw) as MesProFeedbackApi.ParamSnapshot; |
| | | const existing = props.readonly ? (previous ?? result.shared) : (result.shared ?? previous); |
| | | for (const entry of existing?.values ?? []) values.value[entry.detailId] = entry.value ?? ''; |
| | | } catch { |
| | | if (version === loadVersion) error.value = 'åæ°é
ç½®å 载失败ï¼è¯·éæ°éæ©ä»»å¡'; |
| | | } finally { |
| | | if (version === loadVersion) loading.value = false; |
| | | } |
| | | }, { immediate: true }); |
| | | |
| | | function getValues() { |
| | | if (loading.value || error.value || (props.taskId && !config.value)) { |
| | | message.error(error.value || 'åæ°é
ç½®æ£å¨å è½½ï¼è¯·ç¨ååè¯'); |
| | | throw new Error('åæ°é
ç½®æªå°±ç»ª'); |
| | | } |
| | | if (!config.value?.mode || shared.value || props.readonly) return undefined; |
| | | return details.value.map((d) => ({ detailId: d.id, value: values.value[d.id] ?? '' })); |
| | | } |
| | | defineExpose({ getValues }); |
| | | </script> |
| | | |
| | | <template> |
| | | <section v-if="taskId && (loading || error || config?.mode)" class="param-fields"> |
| | | <h4>å·¥èºåæ°</h4> |
| | | <p v-if="loading">æ£å¨å è½½åæ°é
ç½®â¦</p> |
| | | <p v-else-if="error" role="alert">{{ error }}</p> |
| | | <template v-else-if="config?.mode"> |
| | | <p>{{ config.template?.templateName }} · {{ config.mode === 1 ? 'æ¯æ¬¡æ¥å·¥å¡«å' : 'æ¯ä¸ªä»»å¡å¡«å䏿¬¡' }}</p> |
| | | <p v-if="shared">æ¤ä»»å¡å·²å¡«ååæ°ï¼æ¥å·¥å°æ²¿ç¨å·²ä¿åçå¼ã</p> |
| | | <div v-for="detail in details" :key="detail.id" class="param-fields__item"> |
| | | <label :for="`feedback-param-${detail.id}`">{{ detail.paramName }}<span v-if="detail.unitMeasureName">ï¼{{ detail.unitMeasureName }}ï¼</span><span v-if="detail.required">ï¼å¿
å¡«ï¼</span></label> |
| | | <a-input :id="`feedback-param-${detail.id}`" v-model:value="values[detail.id]" |
| | | :disabled="readonly || shared" :maxlength="100" |
| | | :type="detail.paramType === 4 ? 'time' : detail.paramType === 5 ? 'date' : 'text'" |
| | | :placeholder="`请è¾å
¥${detail.paramName}`" /> |
| | | </div> |
| | | </template> |
| | | </section> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .param-fields { margin: 16px; padding: 16px; border: 1px solid var(--ant-color-border, #d9d9d9); border-radius: 6px; } |
| | | .param-fields h4 { margin: 0 0 8px; font-weight: 600; } |
| | | .param-fields p { margin: 0 0 12px; } |
| | | .param-fields__item { display: grid; grid-template-columns: minmax(120px, 1fr) 2fr; align-items: center; gap: 12px; margin-top: 10px; } |
| | | @media (max-width: 600px) { .param-fields__item { grid-template-columns: 1fr; gap: 4px; } } |
| | | </style> |
| | |
| | | export function useFormSchema( |
| | | formType: FormType, |
| | | formApi?: VbenFormApi, |
| | | onTaskChange?: (taskId?: number) => void, |
| | | ): VbenFormSchema[] { |
| | | const isHeaderReadonly = ['approve', 'detail', 'submit'].includes(formType); |
| | | return [ |
| | |
| | | status: MesProWorkOrderStatusEnum.CONFIRMED, |
| | | // 订ååæ´ï¼æ¸
空任å¡åä»»å¡å¸¦åºç产åä¿¡æ¯ãæ°éåºåæ§å¶ä½ |
| | | onChange: async () => { |
| | | onTaskChange?.(undefined); |
| | | await formApi?.setValues({ |
| | | checkFlag: true, |
| | | itemCode: undefined, |
| | |
| | | // ä»»å¡åæ´ï¼èªå¨å¡«å
å
³èåæ®µã产åä¿¡æ¯ãcheckFlag |
| | | componentProps: { |
| | | onChange: async (task?: MesProTaskApi.Task) => { |
| | | onTaskChange?.(task?.id); |
| | | if (!task) { |
| | | return; |
| | | } |
| | |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { Button, message, Tag } from 'ant-design-vue'; |
| | | import { Button, message, Modal as AntModal, Tag } from 'ant-design-vue'; |
| | | |
| | | import { batchCreateFeedback } from '#/api/mes/pro/feedback'; |
| | | import ProTaskSelectDialog from '#/views/mes/pro/task/components/select-dialog.vue'; |
| | |
| | | remark: formData.value.remark || undefined, |
| | | }); |
| | | if (result.failCount) { |
| | | message.warning( |
| | | `æ¹éæ¥å·¥å®æï¼æå ${result.successCount} 个ï¼å¤±è´¥ ${result.failCount} 个`, |
| | | ); |
| | | } else { |
| | | message.success(`æ¹éæ¥å·¥æåï¼å
± ${result.successCount} 个`); |
| | | const failures = (result.results ?? []).filter((row) => !row.success); |
| | | const names = new Map(selectedTasks.value.map((task) => [task.id, task.code])); |
| | | AntModal.warning({ |
| | | title: `æå ${result.successCount} 个ï¼å¤±è´¥ ${result.failCount} 个`, |
| | | content: failures.map((row) => `${names.get(row.taskId) ?? row.taskId}ï¼${row.errorMsg ?? 'æ¥å·¥å¤±è´¥'}`).join('ï¼'), |
| | | }); |
| | | const failedIds = new Set(failures.map((row) => row.taskId)); |
| | | selectedTasks.value = selectedTasks.value.filter((task) => failedIds.has(task.id!)); |
| | | emit('success'); |
| | | return; |
| | | } |
| | | message.success(`æ¹éæ¥å·¥æåï¼å
± ${result.successCount} 个`); |
| | | modalApi.close(); |
| | | emit('success'); |
| | | } finally { |
| | |
| | | import BatchInputDialog from './batch-input-dialog.vue'; |
| | | import ItemConsumeList from './item-consume-list.vue'; |
| | | import ProductProduceList from './product-produce-list.vue'; |
| | | import FeedbackParamFields from '../components/FeedbackParamFields.vue'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formType = ref<FormType>('create'); |
| | |
| | | const userStore = useUserStore(); |
| | | const subTabsName = ref('itemConsume'); |
| | | const originalSnapshot = ref(''); // 表ååå§æ°æ®å¿«ç
§ï¼ç¨äº submit æ¶è·³è¿æªåæ´çä¿åè¯·æ± |
| | | const paramTaskId = ref<number>(); |
| | | const paramSnapshot = ref<string>(); |
| | | const paramFields = ref<InstanceType<typeof FeedbackParamFields>>(); |
| | | function onParamTaskChange(taskId?: number) { paramTaskId.value = taskId; paramSnapshot.value = undefined; } |
| | | |
| | | const isEditable = computed(() => |
| | | ['create', 'submit', 'update'].includes(formType.value), |
| | |
| | | } |
| | | |
| | | /** 读åå¹¶ææäº¤è§å对é½åçè¡¨åæ°æ®ï¼ç¨äºå¿«ç
§åä¿å */ |
| | | async function getAlignedData(): Promise<MesProFeedbackApi.Feedback> { |
| | | async function getAlignedData(includeParams = true): Promise<MesProFeedbackApi.Feedback> { |
| | | const data = (await formApi.getValues()) as MesProFeedbackApi.Feedback; |
| | | alignQuantity(data); |
| | | if (includeParams) data.paramValues = paramFields.value?.getValues(); |
| | | return data; |
| | | } |
| | | |
| | |
| | | status: MesProFeedbackStatusEnum.PREPARE, |
| | | }; |
| | | formType.value = 'update'; |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi) }); |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi, onParamTaskChange) }); |
| | | await formApi.setFieldValue('id', id); |
| | | message.success($t('common.createSuccess')); |
| | | } else { |
| | |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = undefined; |
| | | paramTaskId.value = undefined; |
| | | paramSnapshot.value = undefined; |
| | | subTabsName.value = 'itemConsume'; |
| | | originalSnapshot.value = ''; |
| | | return; |
| | |
| | | const data = modalApi.getData<{ formType: FormType; id?: number; showSubmitButton?: boolean }>(); |
| | | formType.value = data.formType; |
| | | showSubmitButton.value = data.showSubmitButton !== false; |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi) }); |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi, onParamTaskChange) }); |
| | | // 审æ¹/详æ
æ´è¡¨ç¦ç¨ï¼é¿å
å®¡æ ¸äººè¯¯æ¹æªæäº¤çåæ®µ |
| | | formApi.setDisabled( |
| | | formType.value === 'approve' || formType.value === 'detail', |
| | |
| | | feedbackUserId: userStore.userInfo?.id, |
| | | }); |
| | | // è®°å½åå§å¿«ç
§ï¼å«æ°é对é½ç»æï¼ï¼submit æ¶ç¨äºè·³è¿æ åæ´çä¿åè¯·æ± |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData()); |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData(false)); |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getFeedback(data.id); |
| | | paramTaskId.value = formData.value.taskId; |
| | | paramSnapshot.value = formData.value.paramSnapshot; |
| | | const checkFlag = await resolveCheckFlag( |
| | | formData.value.routeId, |
| | | formData.value.processId, |
| | |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues({ ...formData.value, checkFlag }); |
| | | // è®°å½åå§å¿«ç
§ï¼å«æ°é对é½ç»æï¼ï¼submit æ¶ç¨äºè·³è¿æ åæ´çä¿åè¯·æ± |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData()); |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData(false)); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | <template> |
| | | <Modal :title="getTitle" class="w-3/5"> |
| | | <Form class="mx-4" /> |
| | | <FeedbackParamFields ref="paramFields" :task-id="paramTaskId" :snapshot="paramSnapshot" :readonly="!isEditable" /> |
| | | <Tabs |
| | | v-if="showSubTabs" |
| | | v-model:active-key="subTabsName" |
| | |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getTemplatePage } from '#/api/mes/pro/processdesign/template'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'update'; |
| | |
| | | rules: z.number().default(CommonStatusEnum.ENABLE), |
| | | }, |
| | | { |
| | | fieldName: 'paramCollectMode', |
| | | label: 'åæ°ééæ¹å¼', |
| | | component: 'Select', |
| | | defaultValue: 0, |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'ä¸éé', value: 0 }, |
| | | { label: 'æ¯æ¬¡æ¥å·¥å¡«å', value: 1 }, |
| | | { label: 'æ¯ä¸ªä»»å¡å¡«å䏿¬¡', value: 2 }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'paramTemplateId', |
| | | label: 'åæ°æ¨¡æ¿', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | api: getTemplatePage, |
| | | params: { pageNo: 1, pageSize: 100 }, |
| | | resultField: 'list', labelField: 'templateName', valueField: 'id', |
| | | showSearch: true, optionFilterProp: 'label', allowClear: true, |
| | | placeholder: 'å¯ç¨åæ°ééæ¶è¯·éæ©æ¨¡æ¿', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'attention', |
| | | label: 'å·¥åºè¯´æ', |
| | | component: 'Textarea', |
| | |
| | | return [ |
| | | { field: 'itemCode', title: '产åºç¼ç ', width: 150 }, |
| | | { field: 'itemName', title: '产åºåç§°', width: 150 }, |
| | | { field: 'templateReference', title: '模æ¿å¼ç¨', width: 100, slots: { default: 'templateReference' } }, |
| | | { field: 'specification', title: 'è§æ ¼åå·', width: 150 }, |
| | | { field: 'unitName', title: 'åä½', width: 80 }, |
| | | { field: 'quantity', title: 'ç产æ°é', width: 100 }, |
| | |
| | | import { computed, ref, watch } from 'vue'; |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | import { useAccess } from '@vben/access'; |
| | | import { DICT_TYPE } from '@vben/constants'; |
| | | import { getDictLabel } from '@vben/hooks'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | import { message, Radio } from 'ant-design-vue'; |
| | | |
| | | import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | deleteRouteProduct, |
| | | getRouteProductListByRoute, |
| | | setRouteProductTemplateReference, |
| | | } from '#/api/mes/pro/route/product'; |
| | | import { $t } from '#/locales'; |
| | | |
| | |
| | | |
| | | const emit = defineEmits<{ |
| | | change: [list: MesProRouteProductApi.RouteProduct[]]; |
| | | referenceChange: []; |
| | | }>(); |
| | | |
| | | const { hasAccessByCodes } = useAccess(); |
| | | const canSetTemplateReference = hasAccessByCodes(['mes:pro-route:update']); |
| | | const isEditable = computed(() => props.formType !== 'detail'); // æ¯å¦å¯ç¼è¾ |
| | | const list = ref<MesProRouteProductApi.RouteProduct[]>([]); // å·¥èºè·¯çº¿äº§åå表 |
| | | |
| | |
| | | productFormModalApi.setData({ id: row.id, routeId: props.routeId }).open(); |
| | | } |
| | | |
| | | /** æ¯æ¡è·¯çº¿ä½¿ç¨ä¸ä¸ªäº§åºäº§åä½ä¸ºå¯¼å
¥æ¨¡æ¿åèã */ |
| | | async function handleTemplateReference(row: MesProRouteProductApi.RouteProduct) { |
| | | if (!canSetTemplateReference || !row.id || row.templateReference) return; |
| | | await setRouteProductTemplateReference(row.id); |
| | | message.success('已设置模æ¿å¼ç¨äº§å'); |
| | | await getList(); |
| | | emit('referenceChange'); |
| | | } |
| | | |
| | | /** å é¤å·¥èºè·¯çº¿äº§å */ |
| | | async function handleDelete(row: MesProRouteProductApi.RouteProduct) { |
| | | await deleteRouteProduct(row.id!); |
| | |
| | | /> |
| | | </div> |
| | | <Grid class="w-full" table-title="产åºäº§å忥工å
¥åºä½ç½®"> |
| | | <template #templateReference="{ row }"> |
| | | <Radio :checked="!!row.templateReference" :disabled="!canSetTemplateReference" @change="handleTemplateReference(row)"> |
| | | {{ row.templateReference ? 'å·²é' : 'éæ©' }} |
| | | </Radio> |
| | | </template> |
| | | <template #productionTime="{ row }"> |
| | | <span v-if="row.productionTime"> |
| | | {{ row.productionTime }} |
| | |
| | | <Alert |
| | | class="mb-4" |
| | | message="å
ç»´æ¤ææå¯è½çå·¥åºäº§åº" |
| | | description="å®é
å½¢æçä¸é´åæååæ«éå·¥åºçæåé½è¦å å
¥ï¼å¹¶å嫿宿¥å·¥åè¿å
¥çä»åºãåºåºååºä½ã" |
| | | description="å®é
å½¢æçä¸é´åæååæ«éå·¥åºçæåé½è¦å å
¥ï¼å¹¶æå®å
¥åºä»ä½ï¼éæ©ä¸ä¸ªæåä½ä¸ºæ¨¡æ¿å¼ç¨ï¼ä¾å·¥èºæµç¨æ¨¡æ¿ä¸è½½ä½¿ç¨ã" |
| | | show-icon |
| | | type="info" |
| | | /> |
| | |
| | | :form-type="formType" |
| | | :route-id="routeId" |
| | | @change="productList = $event" |
| | | @reference-change="emit('success')" |
| | | /> |
| | | </section> |
| | | |
| | |
| | | |
| | | import { quickCreateFeedback } from '#/api/mes/pro/feedback'; |
| | | import ProTaskSelect from '#/views/mes/pro/task/components/select.vue'; |
| | | import FeedbackParamFields from '#/views/mes/pro/feedback/components/FeedbackParamFields.vue'; |
| | | |
| | | defineOptions({ name: 'QuickFeedbackForm' }); |
| | | |
| | |
| | | }); |
| | | |
| | | const formRef = ref<FormInstance>(); |
| | | const paramFields = ref<InstanceType<typeof FeedbackParamFields>>(); |
| | | const selectedTaskId = ref<number | undefined>(props.taskId); |
| | | const selectedTask = ref<MesProTaskApi.Task>(); |
| | | const formData = ref({ |
| | |
| | | try { |
| | | await quickCreateFeedback({ |
| | | taskId, |
| | | paramValues: paramFields.value?.getValues(), |
| | | feedbackQuantity: formData.value.feedbackQuantity, |
| | | qualifiedQuantity: formData.value.qualifiedQuantity, |
| | | unqualifiedQuantity: formData.value.unqualifiedQuantity, |
| | |
| | | class="!w-full" |
| | | /> |
| | | </a-form-item> |
| | | <FeedbackParamFields ref="paramFields" :task-id="selectedTaskId" /> |
| | | <a-form-item label="夿³¨"> |
| | | <a-textarea |
| | | v-model:value="formData.remark" |
| | |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getTemplatePage } from '#/api/mes/pro/processdesign/template'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'update'; |
| | |
| | | options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), |
| | | }, |
| | | rules: z.number().default(CommonStatusEnum.ENABLE), |
| | | }, |
| | | { |
| | | fieldName: 'paramCollectMode', |
| | | label: 'åæ°ééæ¹å¼', |
| | | component: 'Select', |
| | | defaultValue: 0, |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'ä¸éé', value: 0 }, |
| | | { label: 'æ¯æ¬¡æ¥å·¥å¡«å', value: 1 }, |
| | | { label: 'æ¯ä¸ªä»»å¡å¡«å䏿¬¡', value: 2 }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'paramTemplateId', |
| | | label: 'åæ°æ¨¡æ¿', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | api: getTemplatePage, |
| | | params: { pageNo: 1, pageSize: 100 }, |
| | | resultField: 'list', |
| | | labelField: 'templateName', |
| | | valueField: 'id', |
| | | showSearch: true, |
| | | optionFilterProp: 'label', |
| | | allowClear: true, |
| | | placeholder: 'å¯ç¨åæ°ééæ¶è¯·éæ©æ¨¡æ¿', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'attention', |
| | |
| | | props: { type: DICT_TYPE.COMMON_STATUS }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'paramCollectMode', |
| | | title: 'åæ°ééæ¹å¼', |
| | | minWidth: 150, |
| | | formatter: ({ cellValue }) => |
| | | (['ä¸éé', 'æ¯æ¬¡æ¥å·¥å¡«å', 'æ¯ä¸ªä»»å¡å¡«å䏿¬¡'])[Number(cellValue ?? 0)] ?? 'æªç¥', |
| | | }, |
| | | { field: 'remark', title: '夿³¨', minWidth: 180 }, |
| | | { |
| | | field: 'createTime', |
| | |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = (await formApi.getValues()) as MesProProcessApi.Process; |
| | | if ((data.paramCollectMode ?? 0) !== 0 && !data.paramTemplateId) { |
| | | message.warning('å¯ç¨åæ°ééæ¶ï¼è¯·éæ©åæ°æ¨¡æ¿'); |
| | | modalApi.unlock(); |
| | | return; |
| | | } |
| | | try { |
| | | await (formData.value?.id ? updateProcess(data) : createProcess(data)); |
| | | // å
³éå¹¶æç¤º |
| | |
| | | slots: { default: "code" }, |
| | | }, |
| | | { field: "name", title: "路线åç§°", minWidth: 180 }, |
| | | { field: "referenceProductName", title: "å¯ç¨äº§å", minWidth: 160 }, |
| | | { field: "description", title: "路线说æ", minWidth: 200 }, |
| | | { |
| | | field: "status", |
| | |
| | | }, |
| | | { |
| | | title: "æä½", |
| | | width: 160, |
| | | width: 260, |
| | | fixed: "right", |
| | | slots: { default: "actions" }, |
| | | }, |
| | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | deleteRoute, |
| | | downloadFullRouteTemplate, |
| | | importFullRoute, |
| | | exportRoute, |
| | | getRoutePage, |
| | | importRoute, |
| | | importRouteTemplate, |
| | | updateRouteStatus, |
| | | } from '#/api/mes/pro/route'; |
| | | import { $t } from '#/locales'; |
| | |
| | | importModalApi |
| | | .setData({ |
| | | title: $t('ui.actionTitle.import', ['å·¥èºè·¯çº¿']), |
| | | fileName: 'å·¥èºè·¯çº¿å¯¼å
¥æ¨¡æ¿.xls', |
| | | importFn: importRoute, |
| | | templateFn: importRouteTemplate, |
| | | fileName: 'å·¥èºæµç¨å®æ´å¯¼å
¥æ¨¡æ¿.xlsx', |
| | | importFn: importFullRoute, |
| | | showTemplateDownload: false, |
| | | uploadHint: '请å
ä»è·¯çº¿æä½åä¸è½½æ¨¡æ¿ãè¡¨æ ¼åä¸ºåºæ¬ä¿¡æ¯ã产åä¸ä»ä½ãå·¥åºãå·¥åºäº§åºãå·¥åºææï¼å¤å¶äº§åæ¶åªéä¿®æ¹æ¨¡æ¿äº§åè¡ç产åç¼ç ï¼âæ¬äº§åâä¼èªå¨å
³èï¼åç§°ä»
ä¾åèï¼å¯¼å
¥ä»¥ç¼ç 为åãæ´æ°è·¯çº¿è¯·å
åç¨å¹¶å¾éè¦çï¼æªååºçæ°æ®ä¸ä¼å é¤ã', |
| | | }) |
| | | .open(); |
| | | } |
| | | |
| | | /** ä¸è½½æå®è·¯çº¿ç模æ¿å¼ç¨äº§åå宿´å·¥èºæµç¨ã */ |
| | | async function handleDownloadTemplate(row: MesProRouteApi.Route) { |
| | | if (!row.id) return; |
| | | if (!row.referenceProductCode) { |
| | | message.warning('请å
å¨è·¯çº¿ç产åºäº§åä¸éæ©æ¨¡æ¿å¼ç¨'); |
| | | return; |
| | | } |
| | | const data = await downloadFullRouteTemplate(row.id); |
| | | downloadFileFromBlobPart({ fileName: `å·¥èºæµç¨æ¨¡æ¿-${row.code || row.id}.xlsx`, source: data }); |
| | | } |
| | | |
| | | /** å建工èºè·¯çº¿ */ |
| | |
| | | <Alert |
| | | class="mb-3" |
| | | message="路线é
置顺åº" |
| | | description="åºæ¬ä¿¡æ¯ â 产åºäº§ååå
¥åºä» â å·¥åºååå·¥åºäº§åº â å·¥åºææ â æ ¡éªå¯ç¨" |
| | | description="å
å¨äº§åºäº§åä¸éæ©æ¨¡æ¿å¼ç¨ï¼å¨ç®æ 路线çæä½åä¸è½½è¯¥äº§åçå·¥åºã产åºåææï¼è·¯çº¿å¯ç¨æåç¨åå¯ä¸è½½ã" |
| | | show-icon |
| | | type="info" |
| | | /> |
| | |
| | | <Button type="link" @click="handleDetail(row)">{{ row.code }}</Button> |
| | | </template> |
| | | <template #actions="{ row }"> |
| | | <Button |
| | | v-if="row.referenceProductCode && hasAccessByCodes(['mes:pro-route:import'])" |
| | | type="link" |
| | | @click="handleDownloadTemplate(row)" |
| | | >ä¸è½½æ¨¡æ¿</Button> |
| | | <Tooltip |
| | | :open="row.status === CommonStatusEnum.DISABLE ? false : undefined" |
| | | title="ä»
åç¨ç¶æï¼æå¯ä»¥æä½" |
| | |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../../../pro/feedback/data'; |
| | | import FeedbackParamFields from '../../../pro/feedback/components/FeedbackParamFields.vue'; |
| | | |
| | | defineOptions({ name: 'WorkbenchFeedbackTab' }); |
| | | |
| | |
| | | const feedbackId = ref<number>(); |
| | | const feedbackStatus = ref<number>(); |
| | | const originalSnapshot = ref(''); |
| | | const paramFields = ref<InstanceType<typeof FeedbackParamFields>>(); |
| | | const paramSnapshot = ref<string>(); |
| | | const paramRenderKey = ref(0); |
| | | |
| | | const isEditable = computed(() => |
| | | ['create', 'submit', 'update'].includes(formType.value), |
| | |
| | | } |
| | | } |
| | | |
| | | async function getAlignedData() { |
| | | async function getAlignedData(includeParams = true) { |
| | | const data = (await formApi.getValues()) as any; |
| | | // æ°å»ºæ¶ä¸è½æºå¸¦ä¸ä¸å¼ æ¥å·¥åæ®çç idï¼å¦åå端æä¸»é®æå
¥ä¼å²çª |
| | | if (formType.value === 'create') { |
| | | delete data.id; |
| | | } |
| | | alignQuantity(data); |
| | | if (includeParams) data.paramValues = paramFields.value?.getValues(); |
| | | return data; |
| | | } |
| | | |
| | |
| | | feedbackId.value = undefined; |
| | | feedbackStatus.value = undefined; |
| | | originalSnapshot.value = ''; |
| | | paramSnapshot.value = undefined; |
| | | paramRenderKey.value++; |
| | | |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi) }); |
| | | |
| | |
| | | checkFlag, |
| | | }); |
| | | |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData()); |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData(false)); |
| | | } |
| | | |
| | | /** ä¿å */ |
| | |
| | | async function loadFeedback(id: number) { |
| | | const data = await getFeedback(id); |
| | | feedbackId.value = data.id; |
| | | paramSnapshot.value = data.paramSnapshot; |
| | | feedbackStatus.value = data.status; |
| | | formType.value = 'update'; |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi) }); |
| | | const checkFlag = await resolveCheckFlag(data.routeId, data.processId); |
| | | await formApi.setValues({ ...data, checkFlag }); |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData()); |
| | | originalSnapshot.value = JSON.stringify(await getAlignedData(false)); |
| | | } |
| | | |
| | | // çå¬ä»»å¡åæ´ï¼ä»
å½ä»»å¡ ID çæ£ååæ¶æé置表åï¼ |
| | |
| | | </div> |
| | | |
| | | <Form class="feedback-tab__form" /> |
| | | <FeedbackParamFields :key="paramRenderKey" ref="paramFields" :task-id="task.id" :snapshot="paramSnapshot" :readonly="!isEditable" /> |
| | | |
| | | <div class="feedback-tab__actions"> |
| | | <Button |
| | |
| | | import { |
| | | exportMaterialStock, |
| | | getMaterialStockPage, |
| | | importMaterialStock, |
| | | importMaterialStockTemplate, |
| | | updateMaterialStockFrozen, |
| | | } from '#/api/mes/wm/materialstock'; |
| | | import { $t } from '#/locales'; |
| | |
| | | import { WmBatchDetail } from '#/views/wls/batch/components'; |
| | | import AreaForm from '#/views/wls/warehouse/area/modules/form.vue'; |
| | | import { WmStockAdjustModal, WmStockMoveModal } from './components'; |
| | | import ImportModalComponent from '#/components/import-modal'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | | |
| | |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const [StockImportModal, stockImportModalApi] = useVbenModal({ |
| | | connectedComponent: ImportModalComponent, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | function handleImportStock() { |
| | | stockImportModalApi.setData({ |
| | | title: '导å
¥åºåå¢é', |
| | | fileName: 'åºå导å
¥æ¨¡æ¿.xls', |
| | | importFn: importMaterialStock, |
| | | templateFn: importMaterialStockTemplate, |
| | | allowUpdate: false, |
| | | uploadHint: 'æ°éæç©æä¸»åä½ç´¯å ï¼æ¯è¡ä½¿ç¨å¯ä¸å¯¼å
¥æç»ç¼å·ï¼éå¤ç¼å·ä¸ä¼å次å
¥è´¦ãæ¹æ¬¡é¡»é¢å
建ç«ä¸åæ ¼ï¼ç¸ååºå维度åå¨å¤ä¸ªä¾åºåæ¶é¡»å¡«åä¾åºåç¼ç ãåºåå·ç©æä¸å¯æ¹é导å
¥ã', |
| | | }).open(); |
| | | } |
| | | const batchDetailRef = ref<InstanceType<typeof WmBatchDetail>>(); |
| | | |
| | | /** å·æ°è¡¨æ ¼ */ |
| | |
| | | <Page auto-content-height><AreaModal /> |
| | | <WmBatchDetail ref="batchDetailRef" /> |
| | | <StockAdjustModal @success="handleStockAdjustSuccess" /> |
| | | <StockImportModal @success="handleRefresh" /> |
| | | <StockMoveModal @success="handleStockMoveSuccess" /> |
| | | |
| | | <div class="flex h-full w-full"> |
| | |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: '导å
¥åºå', |
| | | type: 'default', |
| | | icon: ACTION_ICON.UPLOAD, |
| | | auth: ['mes:wm-material-stock:adjust'], |
| | | onClick: handleImportStock, |
| | | }, |
| | | { |
| | | label: 'åºåè°æ´', |
| | | type: 'default', |
| | | icon: ACTION_ICON.EDIT, |
| | |
| | | |
| | | /** ä¸å¡ç±»åé项 */ |
| | | const bizTypeOptions = [ |
| | | { label: 'åºå导å
¥å
¥åº', value: 128 }, |
| | | { label: 'èªå®ä¹å
¥åº', value: 126 }, |
| | | { label: 'èªå®ä¹åºåº', value: 127 }, |
| | | { label: 'éè´å
¥åº', value: 110 }, |