银川
1.采购申请页面修改
2.添加在线查看附件预览功能
3.修改我的流程页面展示样式流程状态点击报错问题
| | |
| | | "@vben/types": "workspace:*", |
| | | "@vben/utils": "workspace:*", |
| | | "@videojs-player/vue": "catalog:", |
| | | "@vue-office/docx": "^1.6.3", |
| | | "@vue-office/excel": "^1.7.14", |
| | | "@vue-office/pdf": "^2.0.10", |
| | | "@vue-office/pptx": "^1.0.1", |
| | | "@vueuse/core": "catalog:", |
| | | "@vueuse/integrations": "catalog:", |
| | | "ant-design-vue": "catalog:", |
| | |
| | | '@videojs-player/vue': |
| | | specifier: 'catalog:' |
| | | version: 1.0.0(@types/video.js@7.3.58)(video.js@7.21.7)(vue@3.5.38(typescript@6.0.3)) |
| | | '@vue-office/docx': |
| | | specifier: ^1.6.3 |
| | | version: 1.6.3(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3)) |
| | | '@vue-office/excel': |
| | | specifier: ^1.7.14 |
| | | version: 1.7.14(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3)) |
| | | '@vue-office/pdf': |
| | | specifier: ^2.0.10 |
| | | version: 2.0.10(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3)) |
| | | '@vue-office/pptx': |
| | | specifier: ^1.0.1 |
| | | version: 1.0.1(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3)) |
| | | '@vueuse/core': |
| | | specifier: 'catalog:' |
| | | version: 14.3.0(vue@3.5.38(typescript@6.0.3)) |
| | |
| | | vue: |
| | | optional: true |
| | | |
| | | '@vue-office/docx@1.6.3': |
| | | resolution: {integrity: sha512-Cs+3CAaRBOWOiW4XAhTwwxJ0dy8cPIf6DqfNvYcD3YACiLwO4kuawLF2IAXxyijhbuOeoFsfvoVbOc16A/4bZA==} |
| | | peerDependencies: |
| | | '@vue/composition-api': ^1.7.1 |
| | | vue: ^2.0.0 || >=3.0.0 |
| | | vue-demi: ^0.14.6 |
| | | peerDependenciesMeta: |
| | | '@vue/composition-api': |
| | | optional: true |
| | | |
| | | '@vue-office/excel@1.7.14': |
| | | resolution: {integrity: sha512-pVUgt+emDQUnW7q22CfnQ+jl43mM/7IFwYzOg7lwOwPEbiVB4K4qEQf+y/bc4xGXz75w1/e3Kz3G6wAafmFBFg==} |
| | | peerDependencies: |
| | | '@vue/composition-api': ^1.7.1 |
| | | vue: ^2.0.0 || >=3.0.0 |
| | | vue-demi: ^0.14.6 |
| | | peerDependenciesMeta: |
| | | '@vue/composition-api': |
| | | optional: true |
| | | |
| | | '@vue-office/pdf@2.0.10': |
| | | resolution: {integrity: sha512-yHVLrMAKpMPBkhBwofFyGEtEeJF0Zd7oGmf56Pe5aj/xObdRq3E1CIZqTqhWJNgHV8oLQqaX0vs4p5T1zq+GIA==} |
| | | peerDependencies: |
| | | '@vue/composition-api': ^1.7.1 |
| | | vue: ^2.0.0 || >=3.0.0 |
| | | vue-demi: ^0.14.6 |
| | | peerDependenciesMeta: |
| | | '@vue/composition-api': |
| | | optional: true |
| | | |
| | | '@vue-office/pptx@1.0.1': |
| | | resolution: {integrity: sha512-+V7Kctzl6f6+Yk4NaD/wQGRIkqLWcowe0jEhPexWQb8Oilbzt1OyhWRWcMsxNDTdrgm6aMLP+0/tmw27cxddMg==} |
| | | peerDependencies: |
| | | '@vue/composition-api': ^1.7.1 |
| | | vue: ^2.0.0 || >=3.0.0 |
| | | vue-demi: ^0.14.6 |
| | | peerDependenciesMeta: |
| | | '@vue/composition-api': |
| | | optional: true |
| | | |
| | | '@vue/babel-helper-vue-transform-on@1.1.5': |
| | | resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==} |
| | | |
| | |
| | | |
| | | ignore@7.0.5: |
| | | resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} |
| | | engines: {node: '>= 4'} |
| | | |
| | | ignore@7.0.6: |
| | | resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} |
| | | engines: {node: '>= 4'} |
| | | |
| | | immutable@5.1.7: |
| | |
| | | destr: 2.0.5 |
| | | errx: 0.1.0 |
| | | exsolve: 1.1.0 |
| | | ignore: 7.0.5 |
| | | ignore: 7.0.6 |
| | | jiti: 2.7.0 |
| | | klona: 2.0.6 |
| | | knitwork: 1.3.0 |
| | |
| | | unplugin-utils: 0.3.1 |
| | | optionalDependencies: |
| | | vue: 3.5.38(typescript@6.0.3) |
| | | |
| | | '@vue-office/docx@1.6.3(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3))': |
| | | dependencies: |
| | | vue: 3.5.38(typescript@6.0.3) |
| | | vue-demi: 0.14.10(vue@3.5.38(typescript@6.0.3)) |
| | | |
| | | '@vue-office/excel@1.7.14(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3))': |
| | | dependencies: |
| | | vue: 3.5.38(typescript@6.0.3) |
| | | vue-demi: 0.14.10(vue@3.5.38(typescript@6.0.3)) |
| | | |
| | | '@vue-office/pdf@2.0.10(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3))': |
| | | dependencies: |
| | | vue: 3.5.38(typescript@6.0.3) |
| | | vue-demi: 0.14.10(vue@3.5.38(typescript@6.0.3)) |
| | | |
| | | '@vue-office/pptx@1.0.1(vue-demi@0.14.10(vue@3.5.38(typescript@6.0.3)))(vue@3.5.38(typescript@6.0.3))': |
| | | dependencies: |
| | | vue: 3.5.38(typescript@6.0.3) |
| | | vue-demi: 0.14.10(vue@3.5.38(typescript@6.0.3)) |
| | | |
| | | '@vue/babel-helper-vue-transform-on@1.1.5': {} |
| | | |
| | |
| | | |
| | | ignore@7.0.5: {} |
| | | |
| | | ignore@7.0.6: |
| | | optional: true |
| | | |
| | | immutable@5.1.7: {} |
| | | |
| | | import-fresh@3.3.0: |
| | |
| | | allowBuilds: |
| | | '@carbon/icons': true |
| | | '@parcel/watcher': true |
| | | '@vue-office/docx': set this to true or false |
| | | '@vue-office/excel': set this to true or false |
| | | '@vue-office/pdf': set this to true or false |
| | | '@vue-office/pptx': set this to true or false |
| | | core-js: true |
| | | core-js-pure: true |
| | | esbuild: true |
| | |
| | | totalTaxPrice?: number; // å«ç¨æ»ä»·ï¼åä½ï¼å
|
| | | remark?: string; // 夿³¨ |
| | | stockCount?: number; // åºåæ°éï¼æ¾ç¤ºåæ®µï¼ |
| | | qcCheckFlag?: boolean; // æ¯å¦éè¦æ¥ææ£éª |
| | | } |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { PreviewFileType } from '@vben/utils'; |
| | | |
| | | import { computed, defineAsyncComponent, ref, watch } from 'vue'; |
| | | |
| | | import { getFileIcon } from '@vben/utils'; |
| | | |
| | | import { Button, Modal, Spin } from 'ant-design-vue'; |
| | | |
| | | import { IconifyIcon } from '@vben/icons'; |
| | | |
| | | const VueOfficePdf = defineAsyncComponent(() => import('@vue-office/pdf')); |
| | | const VueOfficeDocx = defineAsyncComponent(() => import('@vue-office/docx')); |
| | | const VueOfficeExcel = defineAsyncComponent(() => import('@vue-office/excel')); |
| | | const VueOfficePptx = defineAsyncComponent(() => import('@vue-office/pptx')); |
| | | |
| | | // @vue-office/excel éè¦é¢å¤å¯¼å
¥ CSS |
| | | // @vue-office/excel éè¦é¢å¤å¯¼å
¥ CSS |
| | | // @vue-office/excel éè¦é¢å¤å¯¼å
¥ CSS |
| | | import '@vue-office/excel-css'; |
| | | |
| | | const props = withDefaults( |
| | | defineProps<{ |
| | | fileUrl?: string; |
| | | fileName?: string; |
| | | visible?: boolean; |
| | | width?: number | string; |
| | | }>(), |
| | | { |
| | | fileUrl: '', |
| | | fileName: '', |
| | | visible: false, |
| | | width: '90vw', |
| | | }, |
| | | ); |
| | | |
| | | const emit = defineEmits<{ |
| | | 'update:visible': [value: boolean]; |
| | | }>(); |
| | | |
| | | const loading = ref(false); |
| | | const hasError = ref(false); |
| | | |
| | | const open = computed({ |
| | | get: () => props.visible, |
| | | set: (val) => emit('update:visible', val), |
| | | }); |
| | | |
| | | const displayName = computed(() => props.fileName || 'æä»¶é¢è§'); |
| | | |
| | | // æ ¹æ® fileName æ fileUrl 夿æä»¶ç±»å |
| | | const fileType = computed<PreviewFileType>(() => { |
| | | const name = props.fileName || props.fileUrl; |
| | | if (!name) return 'unknown'; |
| | | const ext = name.split('.').pop()?.toLowerCase() || ''; |
| | | if (ext === 'pdf') return 'pdf'; |
| | | if (['doc', 'docx'].includes(ext)) return 'docx'; |
| | | if (['xls', 'xlsx'].includes(ext)) return 'excel'; |
| | | if (['ppt', 'pptx'].includes(ext)) return 'pptx'; |
| | | return 'unknown'; |
| | | }); |
| | | |
| | | const canPreview = computed( |
| | | () => ['pdf', 'docx', 'excel', 'pptx'].includes(fileType.value), |
| | | ); |
| | | |
| | | watch(open, (val) => { |
| | | if (val) { |
| | | hasError.value = false; |
| | | loading.value = canPreview.value; |
| | | } |
| | | }); |
| | | |
| | | function onRendered() { |
| | | loading.value = false; |
| | | } |
| | | |
| | | function onError() { |
| | | loading.value = false; |
| | | hasError.value = true; |
| | | } |
| | | |
| | | function openInNewTab() { |
| | | if (props.fileUrl) { |
| | | window.open(props.fileUrl, '_blank'); |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal |
| | | v-model:open="open" |
| | | :title="displayName" |
| | | :width="width" |
| | | :footer="null" |
| | | destroy-on-close |
| | | centered |
| | | :style="{ top: '20px' }" |
| | | :body-style="{ height: '80vh', overflow: 'auto' }" |
| | | > |
| | | <!-- Loading --> |
| | | <div |
| | | v-if="loading" |
| | | class="flex h-full items-center justify-center" |
| | | > |
| | | <Spin size="large" tip="å è½½ä¸..." /> |
| | | </div> |
| | | |
| | | <!-- Error --> |
| | | <div |
| | | v-else-if="hasError" |
| | | class="flex h-full flex-col items-center justify-center" |
| | | > |
| | | <IconifyIcon icon="lucide:file-x" :size="64" class="text-red-400" /> |
| | | <p class="mt-4 text-gray-500">æä»¶é¢è§å¤±è´¥</p> |
| | | <Button type="primary" class="mt-4" @click="openInNewTab"> |
| | | 卿°æ ç¾é¡µæå¼ |
| | | </Button> |
| | | </div> |
| | | |
| | | <!-- Unsupported --> |
| | | <div |
| | | v-else-if="!canPreview" |
| | | class="flex h-full flex-col items-center justify-center" |
| | | > |
| | | <IconifyIcon |
| | | :icon="getFileIcon(fileName || fileUrl)" |
| | | :size="64" |
| | | class="text-gray-400" |
| | | /> |
| | | <p class="mt-4 text-gray-500">䏿¯æé¢è§æ¤æä»¶ç±»å</p> |
| | | <Button type="primary" class="mt-4" @click="openInNewTab"> |
| | | ä¸è½½æä»¶ |
| | | </Button> |
| | | </div> |
| | | |
| | | <!-- PDF --> |
| | | <VueOfficePdf |
| | | v-else-if="fileType === 'pdf'" |
| | | :src="fileUrl" |
| | | @rendered="onRendered" |
| | | @error="onError" |
| | | /> |
| | | |
| | | <!-- Word --> |
| | | <VueOfficeDocx |
| | | v-else-if="fileType === 'docx'" |
| | | :src="fileUrl" |
| | | @rendered="onRendered" |
| | | @error="onError" |
| | | /> |
| | | |
| | | <!-- Excel --> |
| | | <VueOfficeExcel |
| | | v-else-if="fileType === 'excel'" |
| | | :src="fileUrl" |
| | | @rendered="onRendered" |
| | | @error="onError" |
| | | /> |
| | | |
| | | <!-- PowerPoint --> |
| | | <VueOfficePptx |
| | | v-else-if="fileType === 'pptx'" |
| | | :src="fileUrl" |
| | | @rendered="onRendered" |
| | | @error="onError" |
| | | /> |
| | | </Modal> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export { default as FilePreviewModal } from './file-preview-modal.vue'; |
| | | export { useFilePreview } from './use-file-preview'; |
| | | export type { FilePreviewModalProps, PreviewFileType } from './typing'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { PreviewFileType } from '@vben/utils'; |
| | | |
| | | export type { PreviewFileType }; |
| | | |
| | | export interface FilePreviewModalProps { |
| | | fileUrl?: string; |
| | | fileName?: string; |
| | | visible?: boolean; |
| | | width?: number | string; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { Ref } from 'vue'; |
| | | |
| | | import { computed, ref } from 'vue'; |
| | | |
| | | import { getFileNameFromUrl, getFileType } from '@vben/utils'; |
| | | |
| | | export function useFilePreview() { |
| | | const visible = ref(false); |
| | | const fileUrl = ref(''); |
| | | const fileName = ref(''); |
| | | |
| | | const fileType = computed(() => getFileType(fileName.value || fileUrl.value)); |
| | | |
| | | function openPreview(url: string, name?: string) { |
| | | fileUrl.value = url; |
| | | fileName.value = name || getFileNameFromUrl(url); |
| | | visible.value = true; |
| | | } |
| | | |
| | | function closePreview() { |
| | | visible.value = false; |
| | | } |
| | | |
| | | return { |
| | | closePreview, |
| | | openPreview, |
| | | previewState: { |
| | | fileUrl: fileUrl as Ref<string>, |
| | | fileName: fileName as Ref<string>, |
| | | fileType, |
| | | visible: visible as Ref<boolean>, |
| | | }, |
| | | }; |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * é¢è§æä»¶ç±»å |
| | | */ |
| | | export type PreviewFileType = |
| | | | 'docx' |
| | | | 'excel' |
| | | | 'image' |
| | | | 'pdf' |
| | | | 'pptx' |
| | | | 'unknown'; |
| | | |
| | | /** |
| | | * æ ¹æ®æä»¶å夿é¢è§æä»¶ç±»å |
| | | * |
| | | * @param filename æä»¶åæ URL |
| | | * @returns é¢è§æä»¶ç±»å |
| | | */ |
| | | export function getFileType(filename: null | string | undefined): PreviewFileType { |
| | | if (!filename) return 'unknown'; |
| | | const ext = filename.split('.').pop()?.toLowerCase() || ''; |
| | | if (isImage(ext)) return 'image'; |
| | | if (ext === 'pdf') return 'pdf'; |
| | | if (['doc', 'docx'].includes(ext)) return 'docx'; |
| | | if (['xls', 'xlsx'].includes(ext)) return 'excel'; |
| | | if (['ppt', 'pptx'].includes(ext)) return 'pptx'; |
| | | return 'unknown'; |
| | | } |
| | | |
| | | /** |
| | | * è·åæä»¶å¾æ ï¼Lucide Iconsï¼ |
| | | * |
| | | * @param filename æä»¶å |
| | |
| | | |
| | | const routes: RouteRecordRaw[] = [ |
| | | { |
| | | path: '/bpm', |
| | | name: 'bpm', |
| | | meta: { |
| | | title: '工使µ', |
| | | hideInMenu: true, |
| | | }, |
| | | children: [ |
| | | { |
| | | path: 'process-instance/detail', |
| | | path: '/bpm/process-instance/detail', |
| | | component: () => import('#/views/bpm/processInstance/detail/index.vue'), |
| | | name: 'BpmProcessInstanceDetail', |
| | | meta: { |
| | |
| | | icon: 'ant-design:history-outlined', |
| | | keepAlive: false, |
| | | hideInMenu: true, |
| | | noBasicLayout: false, |
| | | }, |
| | | props: (route) => { |
| | | return { |
| | |
| | | }, |
| | | }, |
| | | { |
| | | path: '/bpm', |
| | | name: 'bpm', |
| | | meta: { |
| | | title: '工使µ', |
| | | hideInMenu: true, |
| | | }, |
| | | children: [ |
| | | { |
| | | path: '/bpm/manager/form/edit', |
| | | name: 'BpmFormEditor', |
| | | component: () => import('#/views/bpm/form/designer/index.vue'), |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | declare module '@vue-office/pdf' { |
| | | import type { DefineComponent } from 'vue'; |
| | | const VueOfficePdf: DefineComponent<{ |
| | | src: string; |
| | | }>; |
| | | export default VueOfficePdf; |
| | | } |
| | | |
| | | declare module '@vue-office/docx' { |
| | | import type { DefineComponent } from 'vue'; |
| | | const VueOfficeDocx: DefineComponent<{ |
| | | src: string; |
| | | }>; |
| | | export default VueOfficeDocx; |
| | | } |
| | | |
| | | declare module '@vue-office/excel' { |
| | | import type { DefineComponent } from 'vue'; |
| | | const VueOfficeExcel: DefineComponent<{ |
| | | src: string; |
| | | }>; |
| | | export default VueOfficeExcel; |
| | | } |
| | | |
| | | declare module '@vue-office/pptx' { |
| | | import type { DefineComponent } from 'vue'; |
| | | const VueOfficePptx: DefineComponent<{ |
| | | src: string; |
| | | }>; |
| | | export default VueOfficePptx; |
| | | } |
| | | |
| | | declare module '@vue-office/excel/lib/index.css'; |
| | |
| | | import { computed } from 'vue'; |
| | | |
| | | import { IconifyIcon } from '@vben/icons'; |
| | | import { getFileIcon, getFileNameFromUrl, getFileTypeClass } from '@vben/utils'; |
| | | import { getFileIcon, getFileNameFromUrl, getFileTypeClass, isImage } from '@vben/utils'; |
| | | |
| | | import { FilePreviewModal, useFilePreview } from '#/components/file-preview'; |
| | | |
| | | const props = defineProps<{ |
| | | attachmentUrls?: string[]; |
| | | }>(); |
| | | |
| | | const { openPreview, previewState } = useFilePreview(); |
| | | |
| | | /** è¿æ»¤æç©ºå¼çéä»¶å表 */ |
| | | const validAttachmentUrls = computed(() => { |
| | |
| | | |
| | | /** ç¹å»æä»¶ */ |
| | | function handleFileClick(url: string) { |
| | | if (isImage(url)) { |
| | | window.open(url, '_blank'); |
| | | } else { |
| | | openPreview(url); |
| | | } |
| | | } |
| | | </script> |
| | | |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <FilePreviewModal |
| | | v-model:visible="previewState.visible.value" |
| | | :file-url="previewState.fileUrl.value" |
| | | :file-name="previewState.fileName.value" |
| | | /> |
| | | </template> |
| | |
| | | import { useUserStore } from '@vben/stores'; |
| | | import { isEmpty } from '@vben/utils'; |
| | | |
| | | import { FilePreviewModal, useFilePreview } from '#/components/file-preview'; |
| | | |
| | | import FormCreate from '@form-create/ant-design-vue'; |
| | | import { until, useDebounceFn } from '@vueuse/core'; |
| | | import { |
| | |
| | | const imagePreviewVisible = ref(false); |
| | | const imagePreviewUrl = ref(''); |
| | | |
| | | const { openPreview: openFilePreview, previewState: filePreviewState } = useFilePreview(); |
| | | |
| | | /** 夿æä»¶æ¯å¦ä¸ºå¾çç±»å */ |
| | | function isImageUrl(url: string) { |
| | | return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test( |
| | |
| | | imagePreviewUrl.value = url; |
| | | imagePreviewVisible.value = true; |
| | | } else { |
| | | window.open(url, '_blank'); |
| | | openFilePreview(url, file?.name); |
| | | } |
| | | } |
| | | |
| | |
| | | :src="imagePreviewUrl" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- æä»¶é¢è§ï¼PDF/Word/Excel/PPTï¼ --> |
| | | <FilePreviewModal |
| | | v-model:visible="filePreviewState.visible.value" |
| | | :file-url="filePreviewState.fileUrl.value" |
| | | :file-name="filePreviewState.fileName.value" |
| | | /> |
| | | </template> |
| | |
| | | DICT_TYPE, |
| | | } from '@vben/constants'; |
| | | |
| | | import { Button, message, Textarea } from 'ant-design-vue'; |
| | | import { Button, message, Textarea, Tooltip } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { getProcessDefinition } from '#/api/bpm/definition'; |
| | |
| | | <template> |
| | | <Page auto-content-height><Grid table-title="æµç¨ç¶æ"> |
| | | <template #slot-summary="{ row }"> |
| | | <div |
| | | class="flex flex-col py-2" |
| | | <Tooltip |
| | | v-if="row.summary && row.summary.length > 0" |
| | | placement="topLeft" |
| | | > |
| | | <template #title> |
| | | <div v-for="(item, index) in row.summary" :key="index"> |
| | | {{ item.key }} : {{ item.value }} |
| | | </div> |
| | | </template> |
| | | <div class="truncate max-w-[200px] cursor-pointer"> |
| | | <span |
| | | v-for="(item, index) in row.summary" |
| | | :key="index" |
| | | > |
| | | <span class="text-gray-500"> |
| | | {{ item.key }} : {{ item.value }} |
| | | </span> |
| | | <span v-if="index < row.summary.length - 1" class="mx-1 text-gray-300">|</span> |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </Tooltip> |
| | | <div v-else>-</div> |
| | | </template> |
| | | <template #slot-status="{ row }"> |
| | |
| | | import type { VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | |
| | | import { markRaw } from 'vue'; |
| | | |
| | | import { DICT_TYPE } from '@vben/constants'; |
| | | import { getDictOptions } from '@vben/hooks'; |
| | | import { erpPriceInputFormatter } from '@vben/utils'; |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import { getAccountSimpleList } from '#/api/erp/finance/account'; |
| | | import { getProductSimpleList } from '#/api/erp/product/product'; |
| | | import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | | |
| | | /** 表åç±»å */ |
| | |
| | | slots: { default: 'remark' }, |
| | | }, |
| | | { |
| | | field: 'qcCheckFlag', |
| | | title: 'æ¯å¦è´¨æ£', |
| | | minWidth: 80, |
| | | fixed: 'right', |
| | | slots: { default: 'qcCheckFlag' }, |
| | | }, |
| | | { |
| | | field: 'count', |
| | | title: 'æ°é', |
| | | minWidth: 120, |
| | |
| | | { |
| | | fieldName: 'productId', |
| | | label: '产å', |
| | | component: 'ApiSelect', |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§å', |
| | | allowClear: true, |
| | | showSearch: true, |
| | | api: getProductSimpleList, |
| | | labelField: 'name', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | |
| | | erpPriceMultiply, |
| | | } from '@vben/utils'; |
| | | |
| | | import { Input, InputNumber, Select } from 'ant-design-vue'; |
| | | import { Input, InputNumber, Select, Switch } from 'ant-design-vue'; |
| | | |
| | | import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { getItemPage } from '#/api/mdm/item'; |
| | |
| | | taxPrice: undefined, |
| | | totalPrice: undefined, |
| | | remark: undefined, |
| | | qcCheckFlag: false, |
| | | }; |
| | | tableData.value.push(newRow); |
| | | // éç¥ç¶ç»ä»¶æ´æ° |
| | |
| | | <Input v-if="!disabled" v-model:value="row.remark" class="w-full" /> |
| | | <span v-else>{{ row.remark || '-' }}</span> |
| | | </template> |
| | | <template #qcCheckFlag="{ row }"> |
| | | <Switch |
| | | v-if="!disabled" |
| | | v-model:checked="row.qcCheckFlag" |
| | | checked-children="æ¯" |
| | | un-checked-children="å¦" |
| | | @change="handleRowChange(row)" |
| | | /> |
| | | <span v-else>{{ row.qcCheckFlag ? 'æ¯' : 'å¦' }}</span> |
| | | </template> |
| | | <template #taxPercent="{ row }"> |
| | | <InputNumber |
| | | v-if="!disabled" |
| | |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | import { MdVendorSelect } from '#/views/mes/md/vendor/components'; |
| | | |
| | | /** 表åç±»å */ |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '产åç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | }, |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '产åç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | }, |
| | |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { MdClientSelect } from '#/views/mes/md/client/components'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'update'; |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '产åç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | }, |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '产åç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | }, |
| | |
| | | |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'update'; |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '产åç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | }, |
| | |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '产åç©æ', |
| | | component: markRaw(MdItemSelect), |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | }, |
| | |
| | | field: 'iqcCode', |
| | | title: 'æ£éªåå·', |
| | | minWidth: 140, |
| | | slots: { default: 'iqcCode' }, |
| | | }, |
| | | { |
| | | field: 'remark', |
| | |
| | | |
| | | import { computed } from 'vue'; |
| | | |
| | | import { useRouter } from 'vue-router'; |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | import { Button, message } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | |
| | | formType: FormType; |
| | | noticeId: number; |
| | | }>(); |
| | | |
| | | const router = useRouter(); |
| | | |
| | | const isEditable = computed(() => |
| | | // æ¯å¦å¯ç¼è¾æç»è¡ |
| | |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | | } |
| | | } |
| | | |
| | | /** 跳转 IQC æ£éªå详æ
*/ |
| | | function handleOpenIqc(row: MesWmArrivalNoticeLineApi.ArrivalNoticeLine) { |
| | | if (row.iqcId) { |
| | | router.push({ path: '/mes/qc/iqc', query: { id: row.iqcId } }); |
| | | } |
| | | } |
| | | |
| | |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #iqcCode="{ row }"> |
| | | <Button |
| | | v-if="row.iqcCode" |
| | | size="small" |
| | | type="link" |
| | | @click="handleOpenIqc(row)" |
| | | > |
| | | {{ row.iqcCode }} |
| | | </Button> |
| | | <span v-else>-</span> |
| | | </template> |
| | | <template #actions="{ row }"> |
| | | <TableAction |
| | | :actions="[ |