cloud-web-corejs 1.1.0-dev.6 → 1.1.0-dev.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/bin/core-resources.js +16 -0
- package/bin/create-child-app.js +34 -0
- package/docs/child-app/README.md +95 -0
- package/docs/child-app/activiti-resources.md +63 -0
- package/docs/child-app/generate-prompt.md +55 -0
- package/docs/child-app/luckysheet-resources.md +80 -0
- package/docs/child-app/public-resources-plan.md +288 -0
- package/docs/child-app/resources-implementation.md +101 -0
- package/docs/child-app/tinymce-resources.md +88 -0
- package/docs/child-app/validation.md +34 -0
- package/docs/qiankun/346/216/245/345/205/245/345/215/217/350/256/256.md +298 -0
- package/docs/qiankun/350/257/246/346/203/205/346/211/277/350/275/275/345/255/220/345/272/224/347/224/250/345/257/271/346/216/245/346/270/205/345/215/225.md +111 -0
- package/package.json +29 -4
- package/resource-tools/index.js +126 -0
- package/src/app-bootstrap.js +531 -0
- package/src/app-bootstrap.sync.js +502 -0
- package/src/boot-assets.legacy.js +13 -0
- package/src/boot-assets.next.js +7 -0
- package/src/components/Qrcode/fileParse.vue +11 -0
- package/src/components/Tinymce/dynamicLoadScript.js +51 -59
- package/src/components/Tinymce/index.vue +382 -336
- package/src/components/Tinymce/mce-chrome.scss +150 -0
- package/src/components/VabUpload/image-viewer.vue +18 -10
- package/src/components/VabUpload/index.js +11 -4
- package/src/components/VabUpload/index.vue +1 -1
- package/src/components/VabUpload/mixins/fileLibraryDialog.js +2 -0
- package/src/components/VabUpload/mixins.js +72 -40
- package/src/components/VabUpload/partUploadConfig.js +95 -0
- package/src/components/VabUpload/privateProfileDialogMixins.js +2 -0
- package/src/components/VabUpload/style.scss +282 -0
- package/src/components/VabUpload/view.vue +19 -18
- package/src/components/baseArea/index.vue +2 -2
- package/src/components/baseInputExport/mixins.js +1 -6
- package/src/components/bizTab/BizTabListPage.vue +66 -33
- package/src/components/bizTab/README.md +3 -1
- package/src/components/bizTab/bizBillDetailMixin.js +2 -0
- package/src/components/code-editor/ace-chrome.scss +17 -0
- package/src/components/code-editor/index.vue +361 -340
- package/src/components/errorMsg/index.vue +142 -13
- package/src/components/errorMsg/mixins.js +53 -0
- package/src/components/excelExport/conditionExportConfig.js +112 -0
- package/src/components/excelExport/exportColumnMemory.js +118 -0
- package/src/components/excelExport/exportFieldDialog.vue +50 -38
- package/src/components/excelExport/exportType.js +8 -0
- package/src/components/excelExport/index.js +30 -13
- package/src/components/excelExport/index.vue +7 -1
- package/src/components/excelExport/mixins.js +782 -293
- package/src/components/excelImport/index.vue +156 -156
- package/src/components/excelImport/mixins.js +888 -834
- package/src/components/fileLibrary/mixins/indexMixins.js +2 -0
- package/src/components/fileLibrary/style.scss +579 -0
- package/src/components/formDialog/index.vue +11 -8
- package/src/components/hiprint/style.scss +188 -0
- package/src/components/hiprint/view/json-view.vue +4 -4
- package/src/components/jdPrint/mixins.js +2 -0
- package/src/components/jsonImport/index.vue +1 -1
- package/src/components/jsonImport/mixins.js +6 -10
- package/src/components/langImport/index.vue +1 -1
- package/src/components/langImport/mixins.js +6 -10
- package/src/components/luckysheet/loadResources.js +64 -0
- package/src/components/luckysheet/view.vue +239 -210
- package/src/components/mobile/buttonGroup/index.vue +1 -1
- package/src/components/mobile/wf/addTaskUserdialog.vue +100 -80
- package/src/components/mobile/wf/content.vue +1734 -1662
- package/src/components/mobile/wf/deleteTaskUserDialog.vue +73 -54
- package/src/components/mobile/wf/selectUserDialog.vue +118 -0
- package/src/components/mobile/wf/setCandidateDialog.vue +69 -48
- package/src/components/mobile/wf/urgingDialog.vue +75 -52
- package/src/components/mobile/wf/wfModifyDialog.vue +4 -0
- package/src/components/obsUpload/index.js +4 -1
- package/src/components/obsUpload/index.vue +1 -1
- package/src/components/obsUpload/mixins.js +45 -15
- package/src/components/onlineTalk/index.vue +4 -4
- package/src/components/onlineTalk/mixins.js +21 -7
- package/src/components/table/index.js +96 -81
- package/src/components/table/plugins/cell-area/index.js +10 -3
- package/src/components/table/style.scss +1399 -0
- package/src/components/table/vxeFilter/mixin.js +28 -18
- package/src/components/wf/content.vue +3 -2
- package/src/components/wf/content2.vue +1 -1
- package/src/components/wf/style.scss +265 -0
- package/src/components/wf/wf.js +7 -0
- package/src/components/wf/wfActionItems.js +3 -0
- package/src/components/wf/wfStartDialog.vue +1 -0
- package/src/components/wf/wfTransferEnabled.js +54 -0
- package/src/components/wf/wfUtil.js +47 -29
- package/src/components/wf/wfVisibility.js +6 -0
- package/src/components/xform/docs/2026-07 table/344/270/216excelExport/344/277/256/345/244/215/345/217/212/345/257/274/345/207/272/344/274/230/345/214/226.md" +64 -57
- package/src/components/xform/docs/2026-08 xform H5 P0 /345/256/236/347/216/260/350/247/204/346/240/274.md" +1 -1
- package/src/components/xform/docs/2026-08 xform /347/247/273/345/212/250/347/253/257/345/270/203/345/261/200/345/257/271/351/275/220 bill_setting /346/226/271/346/241/210.md" +1 -1
- package/src/components/xform/docs/2026-09 /345/212/250/346/200/201/345/255/227/346/256/265/350/247/204/345/210/231/344/270/216/346/265/201/347/250/213/346/216/247/345/210/266/346/211/247/350/241/214/351/241/272/345/272/217/350/220/275/345/234/260/346/226/271/346/241/210.md" +409 -0
- package/src/components/xform/docs/2026-09 /346/235/241/344/273/266/345/257/274/345/207/272/345/244/247/346/225/260/346/215/256/351/207/217/345/264/251/346/272/203/346/216/222/346/237/245.md" +389 -0
- package/src/components/xform/docs/2026-09 /346/265/217/350/247/210/345/231/250/345/264/251/346/272/203/346/262/273/347/220/206P0/344/273/243/347/240/201/350/257/204/345/256/241.md" +255 -0
- package/src/components/xform/docs/2026-09 /346/265/217/350/247/210/345/231/250/345/264/251/346/272/203/346/262/273/347/220/206P0/346/265/213/350/257/225/351/252/214/350/257/201/345/256/236/346/226/275/346/226/207/346/241/243.md" +595 -0
- package/src/components/xform/docs/2026-09 /347/274/226/350/276/221/350/241/250/350/241/214/345/206/205/344/277/235/345/255/230/346/240/241/351/252/214/350/214/203/345/233/264/344/270/216/345/210/227/345/277/205/345/241/253/350/247/243/346/236/220/344/277/256/345/244/215.md" +233 -0
- package/src/components/xform/docs/2026-09 /350/241/250/345/215/225/345/257/274/345/205/245/351/200/232/351/201/223/346/242/263/347/220/206/344/270/216/350/220/275/345/234/260/346/226/271/346/241/210.md" +745 -0
- package/src/components/xform/docs//346/265/217/350/247/210/345/231/250/345/264/251/346/272/203/346/262/273/347/220/206/344/270/216/344/277/256/345/244/215/350/220/275/345/234/260/346/226/271/346/241/210.md +324 -0
- package/src/components/xform/form-designer/designer.js +2133 -2100
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-mixin.js +7 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +4 -2
- package/src/components/xform/form-designer/form-widget/container-widget/detail-h5-widget.vue +243 -227
- package/src/components/xform/form-designer/form-widget/container-widget/h5-card-pane-widget.vue +228 -207
- package/src/components/xform/form-designer/form-widget/container-widget/h5-card-widget.vue +165 -136
- package/src/components/xform/form-designer/form-widget/dialog/formDialog.vue +30 -4
- package/src/components/xform/form-designer/form-widget/dialog/importDialog.vue +190 -185
- package/src/components/xform/form-designer/form-widget/dialog/importDialogMixin.js +2657 -1774
- package/src/components/xform/form-designer/form-widget/dialog/searchFormDialog.vue +27 -4
- package/src/components/xform/form-designer/form-widget/field-widget/a-link-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/a-text-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/area-select-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/autocomplete-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/baseAttachment-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/cascader-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/census-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/checkbox-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/color-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/copy_button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/date-range-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/date-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/descriptions-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/divider-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/download-button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/dropdown-item-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/dropdown-widget.vue +35 -4
- package/src/components/xform/form-designer/form-widget/field-widget/echart-bar-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/echart-category-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/echart-pie-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +64 -10
- package/src/components/xform/form-designer/form-widget/field-widget/file-upload-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/form-item-wrapper.vue +14 -4
- package/src/components/xform/form-designer/form-widget/field-widget/html-text-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/import-button-widget.vue +19 -6
- package/src/components/xform/form-designer/form-widget/field-widget/import2-button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/index.js +10 -1
- package/src/components/xform/form-designer/form-widget/field-widget/input-batch-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/input-widget.vue +29 -3
- package/src/components/xform/form-designer/form-widget/field-widget/multiSearch-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/news-list-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/number-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/oplog-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/picture-upload-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/print-button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/print-detail-button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/project-tag-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/radio-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/rate-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/rich-editor-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/row-col-select-widget.vue +64 -0
- package/src/components/xform/form-designer/form-widget/field-widget/save_submit_wf_button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/script-input-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/search_button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-button-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +6 -2
- package/src/components/xform/form-designer/form-widget/field-widget/select-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/singerSearch-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/singleUpload-widget.vue +145 -145
- package/src/components/xform/form-designer/form-widget/field-widget/slider-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/static-content-wrapper.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/static-text-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/status-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/switch-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue +3 -2
- package/src/components/xform/form-designer/form-widget/field-widget/tempStorage-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/text-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/textarea-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/time-range-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/time-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/title-head-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/vabSearch-widget.vue +1 -1
- package/src/components/xform/form-designer/form-widget/field-widget/vabUpload-widget.vue +3 -3
- package/src/components/xform/form-designer/form-widget/field-widget/vabUpload2-widget.vue +25 -1
- package/src/components/xform/form-designer/form-widget/field-widget/vue-page-widget.vue +1 -1
- package/src/components/xform/form-designer/indexMixin.js +27 -0
- package/src/components/xform/form-designer/setting-panel/form-dynamicField-setting.vue +687 -602
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +269 -36
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +335 -12
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +23 -7
- package/src/components/xform/form-designer/setting-panel/property-editor/container-detail/detail-temp-edito.vue +13 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/container-list-h5/list-h5-editor.vue +846 -860
- package/src/components/xform/form-designer/setting-panel/property-editor/container-tab/tab-lazyRender-editor.vue +27 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/event-handler/onTabChange-editor.vue +28 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/event-handler/onTabClick-editor.vue +28 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import-button-editor.vue +62 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import2-button-editor.vue +142 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/empty-number-input.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +27 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/table-export-button-editor.vue +33 -3
- package/src/components/xform/form-designer/setting-panel/property-editor/project-tag-editor.vue +2 -4
- package/src/components/xform/form-designer/setting-panel/property-editor/suffixIconClickable-editor.vue +23 -0
- package/src/components/xform/form-designer/setting-panel/propertyRegister.js +18 -4
- package/src/components/xform/form-designer/toolbar-panel/index.vue +884 -874
- package/src/components/xform/form-designer/toolbar-panel/indexMixin.js +13 -0
- package/src/components/xform/form-designer/widget-panel/index.vue +11 -7
- package/src/components/xform/form-designer/widget-panel/indexMixin.js +15 -2
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +152 -9
- package/src/components/xform/form-render/container-item/containerItemMixin.js +93 -8
- package/src/components/xform/form-render/container-item/data-table-item.vue +352 -347
- package/src/components/xform/form-render/container-item/data-table-mixin.js +7261 -5985
- package/src/components/xform/form-render/container-item/detail-h5-item.vue +48 -19
- package/src/components/xform/form-render/container-item/detail-item.vue +350 -446
- package/src/components/xform/form-render/container-item/dynamicFieldMixin.js +55 -1
- package/src/components/xform/form-render/container-item/list-h5-item.vue +261 -178
- package/src/components/xform/form-render/container-item/panel-item.vue +1 -1
- package/src/components/xform/form-render/container-item/tab-item.vue +177 -129
- package/src/components/xform/form-render/fieldControlEngine.js +218 -0
- package/src/components/xform/form-render/fieldControlMixin.js +536 -0
- package/src/components/xform/form-render/index.vue +164 -153
- package/src/components/xform/form-render/indexMixin.js +5443 -5311
- package/src/components/xform/form-render/pageDialogScope.js +54 -0
- package/src/components/xform/icon-picker/index.vue +1 -1
- package/src/components/xform/lang/en-US.js +8 -0
- package/src/components/xform/lang/zh-CN.js +9 -0
- package/src/components/xform/mixins/businessLock.js +59 -0
- package/src/components/xform/mixins/defaultHandle.js +713 -707
- package/src/components/xform/mixins/scriptHttp.js +42 -21
- package/src/components/xform/mixins/wfStart.js +105 -0
- package/src/components/xform/mixins/wfVisibility.js +33 -0
- package/src/components/xform/styles/census.scss +288 -0
- package/src/components/xform/styles/containers.scss +215 -0
- package/src/components/xform/styles/designer.scss +904 -0
- package/src/components/xform/styles/detail-temp.scss +71 -0
- package/src/components/xform/styles/h5-designer.scss +191 -0
- package/src/components/xform/styles/h5-runtime.scss +520 -0
- package/src/components/xform/styles/h5.scss +836 -516
- package/src/components/xform/styles/skins.scss +398 -0
- package/src/components/xform/styles/table-layout.scss +91 -0
- package/src/components/xform/styles/titles.scss +255 -0
- package/src/components/xform/utils/dynamicSchemaUtil.js +385 -361
- package/src/components/xform/utils/fixedQueryUtil.js +29 -4
- package/src/components/xform/utils/serviceNameCache.js +69 -0
- package/src/components/xform/utils/tableColumnHelper.js +46 -4
- package/src/components/xform/utils/util.js +1776 -1708
- package/src/core-resources/css/h5.scss +548 -0
- package/src/core-resources/css/iconfont.css +1447 -0
- package/src/core-resources/font/iconfont.ttf +0 -0
- package/src/core-resources/font/iconfont.woff +0 -0
- package/src/core-resources/font/iconfont.woff2 +0 -0
- package/src/core-resources/images/default-header.png +0 -0
- package/src/core-resources/images/ico-default_wenjian.svg +1 -0
- package/src/core-resources/images/ico-excel.svg +1 -0
- package/src/core-resources/images/ico-ftl.svg +7 -0
- package/src/core-resources/images/ico-html.svg +1 -0
- package/src/core-resources/images/ico-java.svg +1 -0
- package/src/core-resources/images/ico-music.svg +1 -0
- package/src/core-resources/images/ico-pdf.svg +1 -0
- package/src/core-resources/images/ico-photo.svg +1 -0
- package/src/core-resources/images/ico-ppt.svg +1 -0
- package/src/core-resources/images/ico-psd.svg +1 -0
- package/src/core-resources/images/ico-service.png +0 -0
- package/src/core-resources/images/ico-txt.svg +1 -0
- package/src/core-resources/images/ico-video.svg +1 -0
- package/src/core-resources/images/ico-vue.svg +8 -0
- package/src/core-resources/images/ico-wenjianjia.svg +1 -0
- package/src/core-resources/images/ico-wrod.svg +1 -0
- package/src/core-resources/images/ico-xml.svg +1 -0
- package/src/core-resources/images/ico-yasuobao.svg +1 -0
- package/src/core-resources/images/icon-error.png +0 -0
- package/src/core-resources/images/icon-tips.png +0 -0
- package/src/core-resources/images/nodata.png +0 -0
- package/src/core-resources/images/nodata2.png +0 -0
- package/src/directive/append-to-body/index.js +48 -0
- package/src/directive/el-dialog-center/index.js +3 -2
- package/src/directive/el-drag-dialog/drag.js +33 -4
- package/src/icons/index.js +9 -0
- package/src/icons/svg/404.svg +1 -0
- package/src/icons/svg/alert.svg +1 -0
- package/src/icons/svg/bug.svg +1 -0
- package/src/icons/svg/button.svg +1 -0
- package/src/icons/svg/card.svg +1 -0
- package/src/icons/svg/cascader-field.svg +1 -0
- package/src/icons/svg/census.svg +1 -0
- package/src/icons/svg/chart.svg +1 -0
- package/src/icons/svg/checkbox-field.svg +1 -0
- package/src/icons/svg/clipboard.svg +1 -0
- package/src/icons/svg/color-field.svg +1 -0
- package/src/icons/svg/component.svg +1 -0
- package/src/icons/svg/custom-component.svg +1 -0
- package/src/icons/svg/dashboard.svg +1 -0
- package/src/icons/svg/data-table.svg +1 -0
- package/src/icons/svg/date-field.svg +1 -0
- package/src/icons/svg/date-range-field.svg +1 -0
- package/src/icons/svg/descriptions.svg +1 -0
- package/src/icons/svg/divider.svg +1 -0
- package/src/icons/svg/document.svg +1 -0
- package/src/icons/svg/documentation.svg +1 -0
- package/src/icons/svg/drag.svg +1 -0
- package/src/icons/svg/echart-category.svg +1 -0
- package/src/icons/svg/echart-pie.svg +1 -0
- package/src/icons/svg/echart.svg +1 -0
- package/src/icons/svg/edit.svg +1 -0
- package/src/icons/svg/education.svg +1 -0
- package/src/icons/svg/email.svg +1 -0
- package/src/icons/svg/example.svg +1 -0
- package/src/icons/svg/excel.svg +1 -0
- package/src/icons/svg/exit-fullscreen.svg +1 -0
- package/src/icons/svg/eye-open.svg +1 -0
- package/src/icons/svg/eye.svg +1 -0
- package/src/icons/svg/file-upload-field.svg +1 -0
- package/src/icons/svg/form.svg +1 -0
- package/src/icons/svg/fullscreen.svg +1 -0
- package/src/icons/svg/github.svg +1 -0
- package/src/icons/svg/grid.svg +1 -0
- package/src/icons/svg/guide.svg +1 -0
- package/src/icons/svg/html-text.svg +1 -0
- package/src/icons/svg/ico-more.svg +1 -0
- package/src/icons/svg/ico-wenjianjia.svg +1 -0
- package/src/icons/svg/icon.svg +1 -0
- package/src/icons/svg/input-batch.svg +1 -0
- package/src/icons/svg/international.svg +1 -0
- package/src/icons/svg/language.svg +1 -0
- package/src/icons/svg/link.svg +1 -0
- package/src/icons/svg/list-export.svg +1 -0
- package/src/icons/svg/list.svg +1 -0
- package/src/icons/svg/lock.svg +1 -0
- package/src/icons/svg/message.svg +1 -0
- package/src/icons/svg/money.svg +1 -0
- package/src/icons/svg/nested.svg +1 -0
- package/src/icons/svg/news-list.svg +1 -0
- package/src/icons/svg/node-tree.svg +1 -0
- package/src/icons/svg/number-field.svg +1 -0
- package/src/icons/svg/password.svg +1 -0
- package/src/icons/svg/pdf.svg +1 -0
- package/src/icons/svg/people.svg +1 -0
- package/src/icons/svg/peoples.svg +1 -0
- package/src/icons/svg/picture-upload-field.svg +1 -0
- package/src/icons/svg/qq.svg +1 -0
- package/src/icons/svg/query.svg +1 -0
- package/src/icons/svg/radio-field.svg +1 -0
- package/src/icons/svg/rate-field.svg +1 -0
- package/src/icons/svg/redo.svg +1 -0
- package/src/icons/svg/rich-editor-field.svg +1 -0
- package/src/icons/svg/search.svg +1 -0
- package/src/icons/svg/searchbox.svg +1 -0
- package/src/icons/svg/section.svg +1 -0
- package/src/icons/svg/select-field.svg +1 -0
- package/src/icons/svg/shopping.svg +1 -0
- package/src/icons/svg/size.svg +1 -0
- package/src/icons/svg/skill.svg +1 -0
- package/src/icons/svg/slider-field.svg +1 -0
- package/src/icons/svg/slot-component.svg +1 -0
- package/src/icons/svg/slot-field.svg +1 -0
- package/src/icons/svg/star.svg +1 -0
- package/src/icons/svg/static-text.svg +1 -0
- package/src/icons/svg/status.svg +1 -0
- package/src/icons/svg/sub-form.svg +1 -0
- package/src/icons/svg/switch-field.svg +1 -0
- package/src/icons/svg/tab.svg +1 -0
- package/src/icons/svg/table.svg +1 -0
- package/src/icons/svg/text-field.svg +1 -0
- package/src/icons/svg/text.svg +1 -0
- package/src/icons/svg/textarea-field.svg +1 -0
- package/src/icons/svg/theme.svg +1 -0
- package/src/icons/svg/time-field.svg +1 -0
- package/src/icons/svg/time-range-field.svg +1 -0
- package/src/icons/svg/tips-text.svg +1 -0
- package/src/icons/svg/title-head.svg +1 -0
- package/src/icons/svg/tree-pane.svg +1 -0
- package/src/icons/svg/tree-table.svg +1 -0
- package/src/icons/svg/tree.svg +1 -0
- package/src/icons/svg/undo.svg +1 -0
- package/src/icons/svg/uploadbox.svg +1 -0
- package/src/icons/svg/user.svg +1 -0
- package/src/icons/svg/vf-box.svg +1 -0
- package/src/icons/svg/vf-dialog.svg +1 -0
- package/src/icons/svg/vf-drawer.svg +1 -0
- package/src/icons/svg/vue-sfc.svg +1 -0
- package/src/icons/svg/wechat.svg +1 -0
- package/src/icons/svg/zip.svg +1 -0
- package/src/index.js +2 -510
- package/src/index.next.js +5 -0
- package/src/index.sync.js +5 -0
- package/src/layout/components/Sidebar/default.vue +1656 -1655
- package/src/layout/components/TagsView/index.vue +330 -323
- package/src/layout/components/TagsView/style.scss +92 -0
- package/src/layout/defaultLayout.vue +2 -2
- package/src/router/index.js +43 -48
- package/src/router/modules/customer.js +12 -0
- package/src/store/modules/settings.js +1 -1
- package/src/store/modules/tagsView.js +241 -217
- package/src/store/modules/user.js +16 -12
- package/src/styles/btn.scss +315 -0
- package/src/styles/dialog.scss +1710 -0
- package/src/styles/element-ui.scss +1076 -0
- package/src/styles/element-variables.scss +31 -0
- package/src/styles/global.scss +115 -0
- package/src/styles/index.scss +245 -0
- package/src/styles/layout-skins.scss +840 -0
- package/src/styles/legacy-base.scss +19 -0
- package/src/styles/menu-icons.scss +75 -0
- package/src/styles/mixin.scss +80 -0
- package/src/styles/nprogress.scss +14 -0
- package/src/styles/page-shell.scss +723 -0
- package/src/styles/sidebar.scss +296 -0
- package/src/styles/split-handle.scss +52 -0
- package/src/styles/theme-variables.scss +7 -0
- package/src/styles/transition.scss +48 -0
- package/src/styles/utilities.scss +253 -0
- package/src/styles/variables.scss +72 -0
- package/src/utils/baseDictsCache.js +197 -0
- package/src/utils/chunkLoadError.js +24 -0
- package/src/utils/featureResources.js +57 -0
- package/src/utils/importLimit.js +72 -0
- package/src/utils/pdfUtil.js +6 -1
- package/src/utils/request.js +142 -7
- package/src/utils/resolveViewComponent.js +45 -90
- package/src/utils/runtimeRecovery.js +105 -0
- package/src/utils/swiperLoader.js +20 -0
- package/src/utils/vab.js +1334 -1283
- package/src/utils/xlsxLoader.js +29 -0
- package/src/views/bd/setting/formVersion/compareContMixin.scss +1 -1
- package/src/views/bd/setting/form_template/edit.vue +378 -356
- package/src/views/bd/setting/form_template/formDesignerDialog.vue +6 -0
- package/src/views/bd/setting/form_template/formTemplateType.js +43 -0
- package/src/views/bd/setting/form_template/list.vue +304 -303
- package/src/views/bd/setting/form_template/mixins/edit.js +344 -280
- package/src/views/bd/setting/form_template/mixins/list.js +749 -721
- package/src/views/bd/setting/form_template/mixins/list2.js +412 -411
- package/src/views/bd/setting/form_template/mixins/wf_list.js +431 -430
- package/src/views/mobile/user/area/dialog.vue +1 -1
- package/src/views/mobile/user/user/dialog.vue +1 -1
- package/src/views/user/bill_setting/mixins/wf.js +8 -0
- package/src/views/user/bill_setting/render.vue +1 -1
- package/src/views/user/commMenu/index.vue +3 -1
- package/src/views/user/commMenu/style.scss +123 -0
- package/src/views/user/common_attribute/edit.vue +2 -0
- package/src/views/user/common_attribute/itemEdit.vue +2 -0
- package/src/views/user/file_view_ins/list.vue +970 -970
- package/src/views/user/form/form_template/list.vue +527 -506
- package/src/views/user/form/vform/designer.vue +823 -821
- package/src/views/user/form/view/list.vue +24 -1
- package/src/views/user/home/default.vue +1124 -1117
- package/src/views/user/home/default2.vue +12 -8
- package/src/views/user/home/index.vue +102 -102
- package/src/views/user/home/wjl/content.vue +1581 -1569
- package/src/views/user/intf_permission/edit.vue +230 -0
- package/src/views/user/intf_permission/list.vue +196 -0
- package/src/views/user/menuFallback/index.vue +23 -0
- package/src/views/user/notify_message/dialog.vue +139 -139
- package/src/views/user/outLink/form_view.vue +202 -202
- package/src/views/user/outLink/index.vue +110 -110
- package/src/views/user/role/edit.vue +4 -0
- package/src/views/user/role/role-box.scss +83 -0
- package/src/views/user/role/voc_edit.vue +4 -0
- package/src/views/user/user/list.vue +28 -6
- package/src/views/user/wf/iframe/index.vue +51 -51
- package/src/views/user/wf/iframe/index2.vue +64 -64
- package/src/views/user/wf/wf_diy_attribute/edit.vue +1 -1
- package/src/views/user/wf/wf_manage/list2.vue +871 -871
- package/src/views/user/wf/wf_manage/wfContentDialog.vue +177 -126
- package/src/views/user/wf/wf_obj_config/activiti_wf.vue +134 -133
- package/src/views/user/wf/wf_obj_config/importItemDialog.vue +1 -1
- package/src/views/user/wf/wf_obj_config/list.vue +747 -746
- package/src/views/user/wf/wf_obj_config/list_form.vue +374 -373
- package/templates/child-app/.env +3 -0
- package/templates/child-app/README.md +49 -0
- package/templates/child-app/app.config.js +6 -0
- package/templates/child-app/babel.config.js +1 -0
- package/templates/child-app/core-resources.config.js +15 -0
- package/templates/child-app/gitignore +7 -0
- package/templates/child-app/package.json +34 -0
- package/templates/child-app/public/index.html +12 -0
- package/templates/child-app/src/assets/401_images/401.gif +0 -0
- package/templates/child-app/src/assets/404_images/404.png +0 -0
- package/templates/child-app/src/assets/404_images/404_cloud.png +0 -0
- package/templates/child-app/src/assets/logo.png +0 -0
- package/templates/child-app/src/corejsConfig.js +2 -0
- package/templates/child-app/src/icons/index.js +2 -0
- package/templates/child-app/src/icons/svg/child-demo.svg +1 -0
- package/templates/child-app/src/layout/index.vue +4 -0
- package/templates/child-app/src/main.js +5 -0
- package/templates/child-app/src/prefixConfig.js +13 -0
- package/templates/child-app/src/resources/css/login.scss +29 -0
- package/templates/child-app/src/resources/images/bg-login5.jpg +0 -0
- package/templates/child-app/src/resources/images/home-img.png +0 -0
- package/templates/child-app/src/router/modules/customer.js +3 -0
- package/templates/child-app/src/settings.js +24 -0
- package/templates/child-app/src/styles/app.scss +2 -0
- package/templates/child-app/src/views/demo/detail.vue +19 -0
- package/templates/child-app/src/views/demo/list.vue +38 -0
- package/templates/child-app/src/views/user/login/index.vue +18 -0
- package/templates/child-app/vue.config.js +107 -0
- package/src/components/xform/form-render/container-item/dynamicFieldEngine.js +0 -285
- package/src/components/xform/form-render/formDynamicFieldMixin.js +0 -131
- package/src/views/demo/bizTab/bill/billConfig.js +0 -41
- package/src/views/demo/bizTab/bill/detail.vue +0 -436
- package/src/views/demo/bizTab/bill/list.vue +0 -288
- package/src/views/demo/bizTab/bill/productDialog.vue +0 -176
- package/src/views/demo/bizTab/simple/billApi.js +0 -123
- package/src/views/demo/bizTab/simple/detail.vue +0 -407
- package/src/views/demo/bizTab/simple/list.vue +0 -217
- package/src/views/demo/bizTab/standalone/index.vue +0 -121
- package/src/views/demo/bizTab/wf/billConfig.js +0 -44
- package/src/views/demo/bizTab/wf/detail.vue +0 -661
- package/src/views/demo/bizTab/wf/list.vue +0 -242
- package/src/views/user/outLink/cc_form_view.vue +0 -188
- /package/src/{resources → core-resources}/js/base/common.js +0 -0
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
/**version-1.0*/
|
|
2
2
|
let tmixins = {};
|
|
3
|
+
import axios from "axios";
|
|
3
4
|
import { getToken } from "../../utils/auth";
|
|
4
5
|
import indexUtil from "../../utils/index.js";
|
|
5
6
|
import exportFieldDialog from "./exportFieldDialog.vue";
|
|
6
7
|
import { getCellValue } from "@base/components/table/util/index";
|
|
7
|
-
import {
|
|
8
|
-
|
|
8
|
+
import {
|
|
9
|
+
isConditionExport,
|
|
10
|
+
isItemExport,
|
|
11
|
+
isRowExport,
|
|
12
|
+
requiresCheckedRows,
|
|
13
|
+
} from "./exportType";
|
|
14
|
+
import { getExportItemColumns } from "./exportItemConfigUtil";
|
|
15
|
+
import { viewKey } from "@base/utils/repeatOpen";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_CONDITION_EXPORT_CONFIG,
|
|
18
|
+
loadConditionExportConfig,
|
|
19
|
+
resolveConditionExportConfig,
|
|
20
|
+
} from "./conditionExportConfig";
|
|
9
21
|
|
|
10
22
|
let configUtil = {
|
|
11
23
|
baseUrl: process.env.VUE_APP_BASE_API,
|
|
@@ -13,6 +25,45 @@ let configUtil = {
|
|
|
13
25
|
indexUtil,
|
|
14
26
|
};
|
|
15
27
|
|
|
28
|
+
/** 取值转换每处理多少行让出一次主线程,见 getExcelData。 */
|
|
29
|
+
const EXPORT_YIELD_ROWS = 200;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 让出主线程一个宏任务,给渲染与用户交互留出机会。
|
|
33
|
+
* 必须是宏任务:微任务(Promise.resolve())不会让浏览器插入渲染帧,进度条照样不动。
|
|
34
|
+
* @returns {Promise<void>}
|
|
35
|
+
*/
|
|
36
|
+
function yieldToBrowser() {
|
|
37
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 可以直接当文件存下来的响应体类型(前缀匹配)。
|
|
42
|
+
*/
|
|
43
|
+
const DOWNLOAD_BINARY_TYPES = [
|
|
44
|
+
"application/vnd.openxmlformats",
|
|
45
|
+
"application/vnd.ms-excel",
|
|
46
|
+
"application/octet-stream",
|
|
47
|
+
"application/zip",
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 这份响应体是不是真的文件流。
|
|
52
|
+
* 用白名单而不是「排除 application/json」:网关拦截、登录态失效这类失败常见的是
|
|
53
|
+
* 200 + text/html,黑名单会把一张 HTML 错误页原样存成打不开的 .xlsx,用户看到的是
|
|
54
|
+
* 一个损坏文件而不是回退后的正常下载。
|
|
55
|
+
* 后端不给 Content-Type 时 blob.type 是空串,按二进制放行 —— 旧的表单 POST 本来也是
|
|
56
|
+
* 这么下的,不能因为这次改造反而下不动。
|
|
57
|
+
* @param {Blob} res 响应体。
|
|
58
|
+
* @returns {Boolean}
|
|
59
|
+
*/
|
|
60
|
+
function isDownloadableBlob(res) {
|
|
61
|
+
if (!res) return false;
|
|
62
|
+
let type = (res.type || "").toLowerCase();
|
|
63
|
+
if (!type) return true;
|
|
64
|
+
return DOWNLOAD_BINARY_TYPES.some((item) => type.indexOf(item) === 0);
|
|
65
|
+
}
|
|
66
|
+
|
|
16
67
|
function getGrid(that, tableRef) {
|
|
17
68
|
let $grid;
|
|
18
69
|
if (Array.isArray(that.$refs[tableRef])) {
|
|
@@ -41,6 +92,8 @@ function getGrid(that, tableRef) {
|
|
|
41
92
|
CURRENT_PREFIX: "",
|
|
42
93
|
option: {},
|
|
43
94
|
uuid: "",
|
|
95
|
+
// createExcelTemplate 返回的本次导出时间快照,随每页取数请求下发(见 loopToDo)
|
|
96
|
+
nowDate: null,
|
|
44
97
|
fileRows: [],
|
|
45
98
|
title: this.$t2("导出", "components.excelExport.title"),
|
|
46
99
|
tableTarget: null,
|
|
@@ -87,23 +140,81 @@ function getGrid(that, tableRef) {
|
|
|
87
140
|
showExportFieldDialog: false,
|
|
88
141
|
leafColumns: [],
|
|
89
142
|
columns: [],
|
|
90
|
-
queryParam: {},
|
|
91
|
-
isMinimize: false,
|
|
143
|
+
queryParam: {},
|
|
144
|
+
isMinimize: false,
|
|
145
|
+
// 条件导出在本次任务内使用的配置快照。逻辑参数只在开始时读取一次,避免中途变更
|
|
146
|
+
// 导致前后页使用不同的分页/分卷口径。
|
|
147
|
+
conditionExportMode: false,
|
|
148
|
+
conditionExportConfig: { ...DEFAULT_CONDITION_EXPORT_CONFIG },
|
|
149
|
+
// 不查总数时,处理过程中分母显示「...」;文件合并成功后才回填实际完成数。
|
|
150
|
+
totalSizeKnown: true,
|
|
92
151
|
// 定时器必须放实例上:模块级共享会导致并发导出互相清除对方的定时器
|
|
93
152
|
exportTimer: null,
|
|
94
153
|
countTimer: null,
|
|
95
154
|
exportError: false,
|
|
96
|
-
|
|
97
|
-
|
|
155
|
+
// 用户点「取消」/组件被销毁的终止标记。此前取消只是停掉定时器 + 销毁组件,
|
|
156
|
+
// 已经发出去的那几页请求照样会回调下来继续上送、继续合并,甚至最后弹出一个
|
|
157
|
+
// 半截文件的下载。所有异步续点都要先问 isExportStopped()。
|
|
158
|
+
aborted: false,
|
|
159
|
+
// 本次导出全部请求共用的取消令牌源,取消时一次性掐断在途请求
|
|
160
|
+
cancelSource: null,
|
|
161
|
+
// lockMenu 实际锁上的那一个页签。必须记下来:解锁若再按「当时的
|
|
162
|
+
// $route.path」现查,用户在导出期间切了页签(弹框可最小化,切走完全合法)
|
|
163
|
+
// 解的就是另一把锁 —— 原页签会永久 affix,而 tagsView 的 delOthersViews /
|
|
164
|
+
// delAllViews 都保留 affix,「关闭其他」「全部关闭」也删不掉它,只能刷新页面。
|
|
165
|
+
lockedView: null,
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
computed: {
|
|
169
|
+
exportTotalText() {
|
|
170
|
+
return this.totalSizeKnown ? this.tTotalSize : "...";
|
|
171
|
+
},
|
|
172
|
+
},
|
|
98
173
|
created() {},
|
|
99
174
|
mounted() {
|
|
100
175
|
// this.exc();
|
|
101
176
|
},
|
|
102
177
|
beforeDestroy() {
|
|
178
|
+
this.aborted = true;
|
|
103
179
|
this.clearExportTimer();
|
|
180
|
+
this.cancelPendingRequests();
|
|
104
181
|
this.unlockMenu();
|
|
105
182
|
},
|
|
106
183
|
methods: {
|
|
184
|
+
/**
|
|
185
|
+
* 导出是否已终止:用户取消、组件销毁、或失败中止。
|
|
186
|
+
* 每一个跨越 await / .then / setTimeout 的续点都必须先问它,否则在途请求的回调
|
|
187
|
+
* 会在导出早已"取消"之后继续推进流程。
|
|
188
|
+
* @returns {Boolean}
|
|
189
|
+
*/
|
|
190
|
+
isExportStopped() {
|
|
191
|
+
if (this.aborted === true) return true;
|
|
192
|
+
if (this.exportError === true) return true;
|
|
193
|
+
return this._isDestroyed === true;
|
|
194
|
+
},
|
|
195
|
+
/**
|
|
196
|
+
* 本次导出共用的取消令牌,首次取用时创建。
|
|
197
|
+
* 每次导出都是一个全新的组件实例(index.js 的 initInstance 会先销毁旧实例),
|
|
198
|
+
* 所以一个 source 覆盖一次导出的全部请求,不存在跨导出串味。
|
|
199
|
+
* @returns {Object} axios CancelToken
|
|
200
|
+
*/
|
|
201
|
+
getCancelToken() {
|
|
202
|
+
if (!this.cancelSource) {
|
|
203
|
+
this.cancelSource = axios.CancelToken.source();
|
|
204
|
+
}
|
|
205
|
+
return this.cancelSource.token;
|
|
206
|
+
},
|
|
207
|
+
/**
|
|
208
|
+
* 掐断本次导出全部在途请求。
|
|
209
|
+
* request.js 的错误拦截器已对 axios.isCancel 短路返回,不会弹错误框;
|
|
210
|
+
* 各调用点的 .catch 也都会先问 isExportStopped() 再决定要不要提示。
|
|
211
|
+
*/
|
|
212
|
+
cancelPendingRequests() {
|
|
213
|
+
if (this.cancelSource) {
|
|
214
|
+
this.cancelSource.cancel("export-cancelled");
|
|
215
|
+
this.cancelSource = null;
|
|
216
|
+
}
|
|
217
|
+
},
|
|
107
218
|
exc() {
|
|
108
219
|
this.option = this.param;
|
|
109
220
|
let $grid = getGrid(this.option.vue, this.option.targetRef);
|
|
@@ -149,6 +260,9 @@ function getGrid(that, tableRef) {
|
|
|
149
260
|
},
|
|
150
261
|
dialogClose2() {
|
|
151
262
|
if (this.isMinimize) return;
|
|
263
|
+
// 最小化不是取消,只有真正关闭才置终止标记
|
|
264
|
+
this.aborted = true;
|
|
265
|
+
this.cancelPendingRequests();
|
|
152
266
|
let loadingObj = window.$vueRoot.$baseLoading({
|
|
153
267
|
target: document.body,
|
|
154
268
|
background: "unset",
|
|
@@ -163,13 +277,29 @@ function getGrid(that, tableRef) {
|
|
|
163
277
|
this.param.destroyComponent(loadingObj);
|
|
164
278
|
}, 0);
|
|
165
279
|
},
|
|
166
|
-
dialogPrimary2() {
|
|
280
|
+
dialogPrimary2() {
|
|
167
281
|
// this.showUserDialog=false
|
|
168
282
|
this.$emit("confirm");
|
|
169
283
|
this.$emit("close");
|
|
170
|
-
this.clearExportTimer();
|
|
171
|
-
},
|
|
172
|
-
|
|
284
|
+
this.clearExportTimer();
|
|
285
|
+
},
|
|
286
|
+
/**
|
|
287
|
+
* 读取并固化本次条件导出的全局配置。单次按钮/脚本参数已经在 option 中完成合并,
|
|
288
|
+
* resolveConditionExportConfig 会让它们覆盖同名的全局配置。
|
|
289
|
+
*/
|
|
290
|
+
prepareConditionExportConfig() {
|
|
291
|
+
this.conditionExportMode = isConditionExport(this.option.type);
|
|
292
|
+
this.totalSizeKnown = true;
|
|
293
|
+
if (!this.conditionExportMode) return Promise.resolve();
|
|
294
|
+
return loadConditionExportConfig().then((globalConfig) => {
|
|
295
|
+
this.conditionExportConfig = resolveConditionExportConfig(
|
|
296
|
+
globalConfig,
|
|
297
|
+
this.option
|
|
298
|
+
);
|
|
299
|
+
this.totalSizeKnown = this.conditionExportConfig.searchCount;
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
startProcess() {
|
|
173
303
|
this.lockMenu();
|
|
174
304
|
this.createCountTimer();
|
|
175
305
|
this.tableTarget = getGrid(this.option.vue, this.option.targetRef);
|
|
@@ -202,42 +332,63 @@ function getGrid(that, tableRef) {
|
|
|
202
332
|
this.abortExport(
|
|
203
333
|
this.$t1("无法确定导出服务前缀,请在导出配置中指定 prefix")
|
|
204
334
|
);
|
|
205
|
-
this.unlockMenu();
|
|
206
335
|
return;
|
|
207
|
-
}
|
|
208
|
-
this.CURRENT_PREFIX = options.prefix;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
that.
|
|
212
|
-
that.
|
|
213
|
-
|
|
214
|
-
.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
that.
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
336
|
+
}
|
|
337
|
+
this.CURRENT_PREFIX = options.prefix;
|
|
338
|
+
this.title = title;
|
|
339
|
+
that.tTotalPage = 0;
|
|
340
|
+
that.tTotalSize = 0;
|
|
341
|
+
that.prepareConditionExportConfig().then(() => {
|
|
342
|
+
if (that.isExportStopped()) return;
|
|
343
|
+
// 取数走 originOption.exportAjax 时请求由 xform 侧构造,前端拿不到那个 config,
|
|
344
|
+
// 只能把令牌顺着导出参数带过去(data-table-mixin 的 exportAjax 会塞进
|
|
345
|
+
// customParam.config,最终由 formHttp 的 ...opts 透传给 axios)
|
|
346
|
+
options.cancelToken = that.getCancelToken();
|
|
347
|
+
that
|
|
348
|
+
.createExcelFile()
|
|
349
|
+
.then((resultMsg) => {
|
|
350
|
+
if (that.isExportStopped()) return;
|
|
351
|
+
if (resultMsg.type === "success") {
|
|
352
|
+
let aObj = resultMsg.objx;
|
|
353
|
+
that.uuid = aObj.uuid;
|
|
354
|
+
that.nowDate = aObj.nowDate;
|
|
355
|
+
that.ippaaapp = aObj.ippaaapp;
|
|
356
|
+
setTimeout(function () {
|
|
357
|
+
if (that.isExportStopped()) return;
|
|
358
|
+
that.handleLoopToDo();
|
|
359
|
+
}, 300);
|
|
360
|
+
} else {
|
|
361
|
+
that.abortExport();
|
|
362
|
+
that.showImportDialog = false;
|
|
363
|
+
that.showImportDialog2 = false;
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
.catch((error) => {
|
|
367
|
+
if (that.isExportStopped()) return;
|
|
368
|
+
console.error(error);
|
|
369
|
+
that.abortExport(that.$t1("创建导出文件失败,导出已中止"));
|
|
370
|
+
that.showImportDialog = false;
|
|
371
|
+
that.showImportDialog2 = false;
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
},
|
|
375
|
+
getExportPageSize() {
|
|
376
|
+
let configuredPageSize = this.conditionExportMode
|
|
377
|
+
? this.conditionExportConfig.pageSize
|
|
378
|
+
: this.option.pageSize || 1000;
|
|
379
|
+
// 条件导出的按钮/脚本值已经按优先级写进配置快照,不再用全局默认值 1000
|
|
380
|
+
// 反向封顶;非条件导出保持原有最多 1000 的行为。
|
|
381
|
+
let pageSize = this.conditionExportMode
|
|
382
|
+
? configuredPageSize
|
|
383
|
+
: Math.min(configuredPageSize, 1000);
|
|
384
|
+
if (this.conditionExportMode) {
|
|
385
|
+
// 单页本身不能突破总量或单文件上限,否则无法在页级合并时兑现硬上限。
|
|
386
|
+
pageSize = Math.min(
|
|
387
|
+
pageSize,
|
|
388
|
+
this.conditionExportConfig.maxQueryTotal,
|
|
389
|
+
this.conditionExportConfig.limitFileSize
|
|
390
|
+
);
|
|
391
|
+
}
|
|
241
392
|
let showImageAtTable = this.option.showImageAtTable || false;
|
|
242
393
|
let hasExportImage = !!this.leafColumns.find((item) => {
|
|
243
394
|
let exportType = item?.params?.exportType;
|
|
@@ -250,18 +401,29 @@ function getGrid(that, tableRef) {
|
|
|
250
401
|
if (hasExportImage || (hasExportImage2 && showImageAtTable)) {
|
|
251
402
|
pageSize = Math.min(pageSize, 150);
|
|
252
403
|
}
|
|
404
|
+
// 单页压力取决于「行数 × 列数」,此前只按有无图片列降档,宽表(100+ 列)一页
|
|
405
|
+
// 的请求体与同步转换耗时是窄表的十几倍,同样的 1000 行/页天差地别。
|
|
406
|
+
let columnNum = this.leafColumns.length;
|
|
407
|
+
if (columnNum > 100) {
|
|
408
|
+
pageSize = Math.min(pageSize, 200);
|
|
409
|
+
} else if (columnNum > 50) {
|
|
410
|
+
pageSize = Math.min(pageSize, 500);
|
|
411
|
+
}
|
|
253
412
|
return pageSize;
|
|
254
413
|
},
|
|
255
|
-
hadleMergeExcel(pPageSize) {
|
|
414
|
+
hadleMergeExcel(pPageSize) {
|
|
415
|
+
if (this.isExportStopped()) return;
|
|
256
416
|
let that = this;
|
|
257
417
|
let title = this.title;
|
|
258
418
|
let options = this.option;
|
|
259
419
|
// let pPageSize = this.getExportPageSize();
|
|
260
|
-
let limitFileSize =
|
|
420
|
+
let limitFileSize = this.conditionExportMode
|
|
421
|
+
? this.conditionExportConfig.limitFileSize
|
|
422
|
+
: options.limitFileSize || 100000;
|
|
261
423
|
let limitThreadNum = options.limitThreadNum || 5;
|
|
262
424
|
let totalPages = this.tTotalPage || 1;
|
|
263
425
|
|
|
264
|
-
let kTotalPages = parseInt(limitFileSize / pPageSize);
|
|
426
|
+
let kTotalPages = Math.max(parseInt(limitFileSize / pPageSize), 1);
|
|
265
427
|
|
|
266
428
|
let fileNum = parseInt(totalPages / kTotalPages);
|
|
267
429
|
if (totalPages % kTotalPages !== 0) {
|
|
@@ -290,6 +452,9 @@ function getGrid(that, tableRef) {
|
|
|
290
452
|
that
|
|
291
453
|
.mergeExcel(startPage, endPage)
|
|
292
454
|
.then(function (resultMsg3) {
|
|
455
|
+
// 取消后组件与进度弹框都已销毁,下面 $refs["exportTable"].insertAt
|
|
456
|
+
// 会直接抛错
|
|
457
|
+
if (that.isExportStopped()) return;
|
|
293
458
|
if (resultMsg3.type === "success") {
|
|
294
459
|
mtExcedSuccessNum++;
|
|
295
460
|
let fileInfo = resultMsg3.objx;
|
|
@@ -311,89 +476,246 @@ function getGrid(that, tableRef) {
|
|
|
311
476
|
// that.fileRows.push(dataMap);
|
|
312
477
|
if (mtExcedNum < fileNum) {
|
|
313
478
|
loopDo();
|
|
314
|
-
} else if (
|
|
315
|
-
mtExcedNum >= fileNum &&
|
|
316
|
-
mtExcedSuccessNum >= fileNum
|
|
317
|
-
) {
|
|
318
|
-
setTimeout(function () {
|
|
319
|
-
that.percentageNum = parseInt(100);
|
|
320
|
-
}, 100);
|
|
321
|
-
that.clearExportTimer();
|
|
322
479
|
} else if (mtExcedSuccessNum >= fileNum) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
that.clearExportTimer();
|
|
480
|
+
// 走到 else 分支时 mtExcedNum >= fileNum 必然成立,
|
|
481
|
+
// 原先拆成的两个 else-if 条件与分支体完全相同,合并为一处
|
|
482
|
+
that.completeExport();
|
|
327
483
|
}
|
|
328
484
|
} else {
|
|
329
485
|
that.abortExport();
|
|
330
486
|
}
|
|
331
487
|
})
|
|
332
488
|
.catch(function (e) {
|
|
489
|
+
if (that.isExportStopped()) return;
|
|
333
490
|
console.error(e);
|
|
334
491
|
that.abortExport(that.$t1("文件合并异常,导出已中止"));
|
|
335
492
|
});
|
|
336
493
|
// 注意:此处不能同步 clearExportTimer,否则计时统计会在合并完成前被提前停掉
|
|
337
494
|
}
|
|
338
|
-
};
|
|
339
|
-
loopDo();
|
|
340
|
-
},
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
let
|
|
344
|
-
let
|
|
345
|
-
let
|
|
346
|
-
|
|
347
|
-
let
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
495
|
+
};
|
|
496
|
+
loopDo();
|
|
497
|
+
},
|
|
498
|
+
/** 统一组装一页条件导出的取数请求,保证两种查总数模式使用完全相同的查询条件。 */
|
|
499
|
+
async requestExportPage(pageNumber, pageSize, searchCount) {
|
|
500
|
+
let options = this.option;
|
|
501
|
+
let originOption = this.tableTarget.params.originOption;
|
|
502
|
+
let url = originOption.exportPath || originOption.path;
|
|
503
|
+
let params = this.$baseLodash.cloneDeep(this.queryParam);
|
|
504
|
+
let aParam = {
|
|
505
|
+
current: pageNumber,
|
|
506
|
+
size: pageSize,
|
|
507
|
+
nowDate: this.nowDate ?? options.nowDate,
|
|
508
|
+
searchCount,
|
|
509
|
+
};
|
|
510
|
+
let cpParam;
|
|
511
|
+
if (originOption.vform === true) {
|
|
512
|
+
params.conditions = params.conditions || {};
|
|
513
|
+
cpParam = params.conditions;
|
|
514
|
+
} else {
|
|
515
|
+
cpParam = params;
|
|
516
|
+
}
|
|
517
|
+
Object.assign(cpParam, aParam);
|
|
518
|
+
|
|
519
|
+
if (originOption.exportAjax) {
|
|
520
|
+
return originOption.exportAjax(aParam, {
|
|
521
|
+
...options,
|
|
522
|
+
exportQuerySnapshot: this.$baseLodash.cloneDeep(this.queryParam),
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
// URL 上若写死 searchCount,会与本次模式冲突;实际值统一由请求体控制。
|
|
526
|
+
let resolvedUrl = typeof url === "function" ? url() : url;
|
|
527
|
+
if (typeof resolvedUrl !== "string" || !resolvedUrl) {
|
|
528
|
+
throw new Error("无效的导出查询地址");
|
|
529
|
+
}
|
|
530
|
+
let requestUrl = resolvedUrl
|
|
531
|
+
.replace("searchCount=false", "1=1")
|
|
532
|
+
.replace("searchCount=true", "1=1");
|
|
533
|
+
let finalParams = params;
|
|
534
|
+
if (originOption.paramHandle) {
|
|
535
|
+
finalParams = originOption.paramHandle(params) || {};
|
|
536
|
+
}
|
|
537
|
+
return this.$commonHttp({
|
|
538
|
+
aes: originOption.aes || false,
|
|
539
|
+
url: requestUrl,
|
|
540
|
+
method: "post",
|
|
541
|
+
data: finalParams,
|
|
542
|
+
modal: false,
|
|
543
|
+
queryCreateInfo: originOption.queryCreateInfo,
|
|
544
|
+
addCreateInfo: originOption.addCreateInfo,
|
|
545
|
+
cancelToken: this.getCancelToken(),
|
|
546
|
+
});
|
|
547
|
+
},
|
|
548
|
+
/** 导出尚在取数/合并时最多显示 99%,100% 只由 completeExport 设置。 */
|
|
549
|
+
updateExportProgress(doneSize, progressTotal) {
|
|
550
|
+
this.doneSize = parseInt(doneSize);
|
|
551
|
+
let percentage = progressTotal > 0 ? (doneSize * 100) / progressTotal : 99;
|
|
552
|
+
if (percentage > 0 && percentage < 1) percentage = 1;
|
|
553
|
+
if (percentage >= 100) percentage = 99;
|
|
554
|
+
this.percentageNum = parseInt(percentage);
|
|
555
|
+
},
|
|
556
|
+
/**
|
|
557
|
+
* 不查询总数:每页都发 searchCount=false,以 records.length < pageSize 判定末页。
|
|
558
|
+
* 取数与写入按页串行,确保发现末页或达到最大查询总数后不会继续派发多余请求。
|
|
559
|
+
*/
|
|
560
|
+
handleLoopWithoutCount(pageSize) {
|
|
561
|
+
let that = this;
|
|
562
|
+
let maxQueryTotal = this.conditionExportConfig.maxQueryTotal;
|
|
563
|
+
let maxPages = Math.max(Math.ceil(maxQueryTotal / pageSize), 1);
|
|
564
|
+
let doneSize = 0;
|
|
565
|
+
this.tTotalPage = 0;
|
|
566
|
+
this.tTotalSize = 0;
|
|
567
|
+
this.totalSizeKnown = false;
|
|
568
|
+
|
|
569
|
+
let finish = function (lastPage) {
|
|
570
|
+
if (that.isExportStopped()) return;
|
|
571
|
+
that.tTotalPage = Math.max(lastPage, 1);
|
|
572
|
+
that.hadleMergeExcel(pageSize);
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
let fetchPage = function (pageNumber, retryCount = 0) {
|
|
576
|
+
if (that.isExportStopped()) return Promise.resolve(null);
|
|
577
|
+
return that
|
|
578
|
+
.requestExportPage(pageNumber, pageSize, false)
|
|
579
|
+
.then((resultMsg) => {
|
|
580
|
+
if (resultMsg && resultMsg.type === "success") return resultMsg;
|
|
581
|
+
if (retryCount < 1) {
|
|
582
|
+
return new Promise((resolve) => {
|
|
583
|
+
setTimeout(
|
|
584
|
+
() => resolve(fetchPage(pageNumber, retryCount + 1)),
|
|
585
|
+
500
|
|
586
|
+
);
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
that.abortExport();
|
|
590
|
+
return null;
|
|
591
|
+
})
|
|
592
|
+
.catch((error) => {
|
|
593
|
+
if (that.isExportStopped()) return null;
|
|
594
|
+
if (retryCount < 1) {
|
|
595
|
+
return new Promise((resolve) => {
|
|
596
|
+
setTimeout(
|
|
597
|
+
() => resolve(fetchPage(pageNumber, retryCount + 1)),
|
|
598
|
+
500
|
|
599
|
+
);
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
console.error(error);
|
|
603
|
+
that.abortExport(
|
|
604
|
+
that.$t1("第{n}页数据拉取失败,导出已中止", {
|
|
605
|
+
n: pageNumber,
|
|
606
|
+
})
|
|
607
|
+
);
|
|
608
|
+
return null;
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
let appendPage = function (pageNumber) {
|
|
613
|
+
fetchPage(pageNumber).then((resultMsg) => {
|
|
614
|
+
if (!resultMsg || that.isExportStopped()) return;
|
|
615
|
+
let page = resultMsg.objx || {};
|
|
616
|
+
let actualSize = Number(page.size || page.pageSize || pageSize);
|
|
617
|
+
if (!Number.isSafeInteger(actualSize) || actualSize <= 0
|
|
618
|
+
|| actualSize > pageSize || (pageNumber > 1 && actualSize !== pageSize)) {
|
|
619
|
+
that.abortExport(that.$t1("服务端分页大小发生变化,导出已中止"));
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
pageSize = actualSize;
|
|
623
|
+
maxPages = Math.max(Math.ceil(maxQueryTotal / pageSize), 1);
|
|
624
|
+
let rawRows = Array.isArray(page.records) ? page.records : [];
|
|
625
|
+
let hasNext = rawRows.length >= pageSize;
|
|
626
|
+
|
|
627
|
+
// 整页数据需要再探测一页;探测到的空页不写入,也不参与合并。
|
|
628
|
+
if (pageNumber > 1 && rawRows.length === 0) {
|
|
629
|
+
finish(pageNumber - 1);
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
let remaining = Math.max(maxQueryTotal - doneSize, 0);
|
|
634
|
+
let rows = rawRows.slice(0, remaining);
|
|
635
|
+
let reachedLimit = rows.length >= remaining;
|
|
636
|
+
page.current = pageNumber;
|
|
637
|
+
page.pageNumber = pageNumber;
|
|
638
|
+
page.size = pageSize;
|
|
639
|
+
page.pageSize = pageSize;
|
|
640
|
+
page.records = rows;
|
|
641
|
+
|
|
642
|
+
that
|
|
643
|
+
.addExcelData({ rows, pageNumber })
|
|
644
|
+
.then((appendResult) => {
|
|
645
|
+
if (that.isExportStopped()) return;
|
|
646
|
+
if (!appendResult || appendResult.type !== "success") {
|
|
647
|
+
if (appendResult && appendResult.type === "abort") return;
|
|
648
|
+
that.abortExport();
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
doneSize += rows.length;
|
|
652
|
+
that.updateExportProgress(doneSize, maxQueryTotal);
|
|
653
|
+
if (reachedLimit || !hasNext || pageNumber >= maxPages) {
|
|
654
|
+
finish(pageNumber);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
appendPage(pageNumber + 1);
|
|
658
|
+
})
|
|
659
|
+
.catch((error) => {
|
|
660
|
+
if (that.isExportStopped()) return;
|
|
661
|
+
console.error(error);
|
|
662
|
+
that.abortExport(that.$t1("导出数据写入失败,导出已中止"));
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
appendPage(1);
|
|
668
|
+
},
|
|
669
|
+
handleLoopToDo() {
|
|
670
|
+
let that = this;
|
|
671
|
+
let num = 0;
|
|
672
|
+
let options = this.option;
|
|
673
|
+
|
|
674
|
+
let pPageSize = this.getExportPageSize();
|
|
675
|
+
let limitThreadNum = options.limitThreadNum || 5;
|
|
676
|
+
|
|
677
|
+
if (
|
|
678
|
+
this.conditionExportMode
|
|
679
|
+
&& this.conditionExportConfig.searchCount === false
|
|
680
|
+
) {
|
|
681
|
+
this.handleLoopWithoutCount(pPageSize);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
352
684
|
|
|
353
685
|
/**处理返回值*/
|
|
354
686
|
this.doneSize = 0;
|
|
355
687
|
let excedNum = 0;
|
|
356
688
|
let cSize = this.doneSize;
|
|
357
689
|
|
|
358
|
-
let handleData = function (resultMsg) {
|
|
690
|
+
let handleData = function (resultMsg, flag) {
|
|
691
|
+
// 取消之后到达的在途响应直接丢弃,不再进入上送/合并流程
|
|
692
|
+
if (that.isExportStopped()) return;
|
|
359
693
|
let pageNumber = resultMsg.objx.pageNumber || 1;
|
|
694
|
+
// 并发窗口在"该页上送完成"后才释放,而不是"该页拉取完成"就释放。
|
|
695
|
+
// addExcelData 此前完全不受闸门约束:上送慢于拉取时 pending 的 POST 会无限
|
|
696
|
+
// 堆积(每个都攥着一份几 MB 的 JSON body),加上浏览器每域名 6 连接会让上送
|
|
697
|
+
// 排到拉取后面,这种反压对调度器完全不可见 —— 大数据量导出的内存曲线因此
|
|
698
|
+
// 始终只涨不落。
|
|
699
|
+
let released = flag !== 1; // 首页(flag=0)不占窗口,无需释放
|
|
700
|
+
let releaseWindow = function () {
|
|
701
|
+
if (released) return;
|
|
702
|
+
released = true;
|
|
703
|
+
if (waitReqNum > 0) waitReqNum--;
|
|
704
|
+
};
|
|
360
705
|
that
|
|
361
706
|
.addExcelData({
|
|
362
707
|
rows: resultMsg.objx.records,
|
|
363
708
|
pageNumber: pageNumber,
|
|
364
709
|
})
|
|
365
|
-
.then(function (resultMsg2) {
|
|
366
|
-
|
|
367
|
-
let
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
let k = (excedNum * 100) / totalPages;
|
|
375
|
-
if (k > 0 && k < 1) {
|
|
376
|
-
k = 1;
|
|
377
|
-
}
|
|
378
|
-
if (k > 100) k = 100;
|
|
379
|
-
let cTotal = that.tTotalSize;
|
|
380
|
-
let pageSize = data.pageSize;
|
|
381
|
-
// let datas = data.records;
|
|
382
|
-
let size = data.records.length;
|
|
383
|
-
cSize = cSize + size;
|
|
384
|
-
|
|
385
|
-
let ttNum = cSize + "/" + cTotal;
|
|
386
|
-
let percentageStr = parseInt(k) + "%";
|
|
387
|
-
|
|
388
|
-
let percentageNum = k;
|
|
389
|
-
if (percentageNum >= 100) {
|
|
390
|
-
percentageNum = 99;
|
|
391
|
-
}
|
|
392
|
-
// that.$set(that, "doneSize", parseInt(cSize));
|
|
393
|
-
// that.$set(that, "percentageNum", parseInt(percentageNum));
|
|
394
|
-
|
|
395
|
-
that.doneSize = parseInt(cSize);
|
|
396
|
-
that.percentageNum = parseInt(percentageNum);
|
|
710
|
+
.then(function (resultMsg2) {
|
|
711
|
+
releaseWindow();
|
|
712
|
+
let data = resultMsg.objx;
|
|
713
|
+
let totalPages = that.tTotalPage || 1;
|
|
714
|
+
if (resultMsg2.type === "success") {
|
|
715
|
+
excedNum++;
|
|
716
|
+
let size = data.records.length;
|
|
717
|
+
cSize = cSize + size;
|
|
718
|
+
that.updateExportProgress(cSize, that.tTotalSize);
|
|
397
719
|
|
|
398
720
|
if (totalPages === 0 || excedNum >= totalPages) {
|
|
399
721
|
that.hadleMergeExcel(data.pageSize);
|
|
@@ -481,101 +803,56 @@ function getGrid(that, tableRef) {
|
|
|
481
803
|
}
|
|
482
804
|
})
|
|
483
805
|
.catch(function (e) {
|
|
806
|
+
releaseWindow();
|
|
807
|
+
if (that.isExportStopped()) return;
|
|
484
808
|
console.error(e);
|
|
485
809
|
that.abortExport(that.$t1("导出数据写入失败,导出已中止"));
|
|
486
810
|
});
|
|
487
811
|
};
|
|
488
812
|
|
|
489
|
-
let waitReqNum = 0;
|
|
490
|
-
let
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
let
|
|
494
|
-
if (flag
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
? originOption.paramHandle(params) || {}
|
|
533
|
-
: {};
|
|
534
|
-
}
|
|
535
|
-
promise = that.$commonHttp({
|
|
536
|
-
aes: originOption.aes || false,
|
|
537
|
-
url: turl,
|
|
538
|
-
method: "post",
|
|
539
|
-
data: finaParams,
|
|
540
|
-
modal: false,
|
|
541
|
-
queryCreateInfo: originOption.queryCreateInfo,
|
|
542
|
-
addCreateInfo: originOption.addCreateInfo,
|
|
543
|
-
});
|
|
544
|
-
} else {
|
|
545
|
-
promise = originOption.exportAjax(aParam, options);
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
promise
|
|
549
|
-
.then(function (resultMsg) {
|
|
550
|
-
if (resultMsg.type === "success") {
|
|
551
|
-
let objx = resultMsg.objx;
|
|
552
|
-
objx.pageNumber = objx.current || 1;
|
|
553
|
-
objx.totalPages = objx.pages || 1;
|
|
554
|
-
objx.pageSize = objx.size;
|
|
555
|
-
let size = objx.records.length;
|
|
556
|
-
if (flag === 0) {
|
|
557
|
-
that.tTotalPage = objx.pages;
|
|
558
|
-
// that.tTotalSize = objx.total;
|
|
559
|
-
setTimeout(function () {
|
|
560
|
-
that.$set(that, "tTotalSize", objx.total);
|
|
561
|
-
}, 0);
|
|
562
|
-
let tTotalPage = objx.pages;
|
|
563
|
-
let tTotalSize = objx.total;
|
|
564
|
-
let ttNum = 0 + "/" + objx.total;
|
|
565
|
-
|
|
566
|
-
let opNum = limitFileSize;
|
|
567
|
-
let kTotalPages = parseInt(opNum / objx.size);
|
|
568
|
-
|
|
569
|
-
let fileNum = parseInt(tTotalPage / kTotalPages);
|
|
570
|
-
if (tTotalPage % kTotalPages !== 0) {
|
|
571
|
-
fileNum = fileNum + 1;
|
|
572
|
-
}
|
|
573
|
-
if (
|
|
574
|
-
size > 0 ||
|
|
575
|
-
objx.totalPages > 0 ||
|
|
576
|
-
objx.pageNumber < objx.totalPages
|
|
577
|
-
) {
|
|
578
|
-
that.exportTimer = setInterval(function () {
|
|
813
|
+
let waitReqNum = 0;
|
|
814
|
+
let loopToDo = function (flag, pageNumber, retryCount = 0) {
|
|
815
|
+
// 取消后不再发起新页,也不再重试(重试是从 .catch 里递归回来的)
|
|
816
|
+
if (that.isExportStopped()) return;
|
|
817
|
+
let maxWaitNum = limitThreadNum;
|
|
818
|
+
if (flag !== 1) waitReqNum = 0;
|
|
819
|
+
|
|
820
|
+
that
|
|
821
|
+
.requestExportPage(pageNumber, pPageSize, flag !== 1)
|
|
822
|
+
.then(function (resultMsg) {
|
|
823
|
+
if (resultMsg.type === "success") {
|
|
824
|
+
let objx = resultMsg.objx || {};
|
|
825
|
+
objx.records = Array.isArray(objx.records) ? objx.records : [];
|
|
826
|
+
objx.pageNumber = objx.current || pageNumber;
|
|
827
|
+
objx.pageSize = objx.size || pPageSize;
|
|
828
|
+
let actualSize = Number(objx.pageSize);
|
|
829
|
+
if (!Number.isSafeInteger(actualSize) || actualSize <= 0
|
|
830
|
+
|| actualSize > pPageSize || (flag !== 0 && actualSize !== pPageSize)) {
|
|
831
|
+
that.abortExport(that.$t1("服务端分页大小发生变化,导出已中止"));
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
pPageSize = actualSize;
|
|
835
|
+
objx.pageSize = actualSize;
|
|
836
|
+
let size = objx.records.length;
|
|
837
|
+
if (flag === 0) {
|
|
838
|
+
let rawTotal = Number(objx.total);
|
|
839
|
+
if (!Number.isFinite(rawTotal) || rawTotal < 0) {
|
|
840
|
+
rawTotal = size;
|
|
841
|
+
}
|
|
842
|
+
let exportTotal = that.conditionExportMode
|
|
843
|
+
? Math.min(
|
|
844
|
+
rawTotal,
|
|
845
|
+
that.conditionExportConfig.maxQueryTotal
|
|
846
|
+
)
|
|
847
|
+
: rawTotal;
|
|
848
|
+
that.tTotalPage = that.conditionExportMode
|
|
849
|
+
? Math.max(Math.ceil(exportTotal / pPageSize), 1)
|
|
850
|
+
: objx.pages;
|
|
851
|
+
objx.totalPages = that.tTotalPage || 1;
|
|
852
|
+
that.tTotalSize = exportTotal;
|
|
853
|
+
let tTotalPage = that.tTotalPage || 1;
|
|
854
|
+
if (tTotalPage > 1) {
|
|
855
|
+
that.exportTimer = setInterval(function () {
|
|
579
856
|
if (waitReqNum < maxWaitNum && num < tTotalPage) {
|
|
580
857
|
waitReqNum++;
|
|
581
858
|
num++;
|
|
@@ -590,11 +867,17 @@ function getGrid(that, tableRef) {
|
|
|
590
867
|
}, 100);
|
|
591
868
|
} else {
|
|
592
869
|
clearInterval(that.exportTimer);
|
|
593
|
-
that.exportTimer = null;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
870
|
+
that.exportTimer = null;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (that.conditionExportMode) {
|
|
874
|
+
// 总数超过有效上限时,最后一页只写允许范围内的数据。
|
|
875
|
+
let rowOffset = (pageNumber - 1) * pPageSize;
|
|
876
|
+
let allowedRows = Math.max(that.tTotalSize - rowOffset, 0);
|
|
877
|
+
objx.records = objx.records.slice(0, allowedRows);
|
|
878
|
+
}
|
|
879
|
+
// 注意:此处不再释放并发窗口。拉取完成只是这一页做完了一半,
|
|
880
|
+
// 窗口由 handleData 在上送(addExcelData)落地后释放,见那里的注释。
|
|
598
881
|
|
|
599
882
|
setTimeout(function () {
|
|
600
883
|
handleData(resultMsg, flag);
|
|
@@ -611,6 +894,8 @@ function getGrid(that, tableRef) {
|
|
|
611
894
|
}
|
|
612
895
|
})
|
|
613
896
|
.catch(function (e) {
|
|
897
|
+
// 取消导致的 reject 不是失败,也不该重试或弹提示
|
|
898
|
+
if (that.isExportStopped()) return;
|
|
614
899
|
console.error(e);
|
|
615
900
|
if (retryCount < 1) {
|
|
616
901
|
setTimeout(function () {
|
|
@@ -641,6 +926,7 @@ function getGrid(that, tableRef) {
|
|
|
641
926
|
data: datas,
|
|
642
927
|
modal: loading || false,
|
|
643
928
|
isLoading: loading,
|
|
929
|
+
cancelToken: this.getCancelToken(),
|
|
644
930
|
});
|
|
645
931
|
},
|
|
646
932
|
/*getExportTitleJson() {
|
|
@@ -742,21 +1028,31 @@ function getGrid(that, tableRef) {
|
|
|
742
1028
|
}
|
|
743
1029
|
return titleArr;
|
|
744
1030
|
},
|
|
745
|
-
addExcelData(opts, loading) {
|
|
1031
|
+
async addExcelData(opts, loading) {
|
|
746
1032
|
let target = opts.target;
|
|
747
1033
|
let pageNumber = opts.pageNumber || 1;
|
|
748
1034
|
let callback = opts.callback;
|
|
749
|
-
|
|
1035
|
+
// 已取消就不要再算、更不要再发。这里是所有上送的唯一入口,卡住它等于卡住
|
|
1036
|
+
// 取消之后的全部后续动作。
|
|
1037
|
+
if (this.isExportStopped()) {
|
|
1038
|
+
return { type: "abort" };
|
|
1039
|
+
}
|
|
1040
|
+
let datas = await this.getExcelData(opts.rows);
|
|
1041
|
+
// 取值过程中导出已被中止(getExcelData 让出主线程时会检查),不再上送这一页。
|
|
1042
|
+
// 返回非 success 让调用方走它自己的中止分支,abortExport 幂等不会重复弹窗。
|
|
1043
|
+
if (datas === null) {
|
|
1044
|
+
return { type: "abort" };
|
|
1045
|
+
}
|
|
750
1046
|
let cUUid = this.uuid;
|
|
751
1047
|
let ippaaapp = this.ippaaapp;
|
|
752
|
-
let url1
|
|
753
|
-
this.CURRENT_PREFIX
|
|
754
|
-
"/excel/appendExcelData?uuid="
|
|
755
|
-
cUUid
|
|
756
|
-
"&ippaaapp="
|
|
757
|
-
ippaaapp
|
|
758
|
-
"&pageNumber="
|
|
759
|
-
pageNumber;
|
|
1048
|
+
let url1
|
|
1049
|
+
= this.CURRENT_PREFIX
|
|
1050
|
+
+ "/excel/appendExcelData?uuid="
|
|
1051
|
+
+ cUUid
|
|
1052
|
+
+ "&ippaaapp="
|
|
1053
|
+
+ ippaaapp
|
|
1054
|
+
+ "&pageNumber="
|
|
1055
|
+
+ pageNumber;
|
|
760
1056
|
return this.$http({
|
|
761
1057
|
url: url1,
|
|
762
1058
|
method: "post",
|
|
@@ -766,20 +1062,22 @@ function getGrid(that, tableRef) {
|
|
|
766
1062
|
data: datas,
|
|
767
1063
|
modal: loading || false,
|
|
768
1064
|
isLoading: loading || false,
|
|
1065
|
+
cancelToken: this.getCancelToken(),
|
|
769
1066
|
});
|
|
770
1067
|
},
|
|
771
1068
|
mergeExcel(startPage, endPage, loading) {
|
|
772
|
-
let url1
|
|
773
|
-
this.CURRENT_PREFIX
|
|
774
|
-
"/excel/mergeExcel?uuid="
|
|
775
|
-
this.uuid
|
|
776
|
-
"&ippaaapp="
|
|
777
|
-
this.ippaaapp;
|
|
1069
|
+
let url1
|
|
1070
|
+
= this.CURRENT_PREFIX
|
|
1071
|
+
+ "/excel/mergeExcel?uuid="
|
|
1072
|
+
+ this.uuid
|
|
1073
|
+
+ "&ippaaapp="
|
|
1074
|
+
+ this.ippaaapp;
|
|
778
1075
|
return this.$http({
|
|
779
1076
|
url: url1 + "&startPage=" + startPage + "&endPage=" + endPage,
|
|
780
1077
|
method: "post",
|
|
781
1078
|
modal: loading || false,
|
|
782
1079
|
isLoading: loading || false,
|
|
1080
|
+
cancelToken: this.getCancelToken(),
|
|
783
1081
|
});
|
|
784
1082
|
},
|
|
785
1083
|
createCountTimer() {
|
|
@@ -797,13 +1095,36 @@ function getGrid(that, tableRef) {
|
|
|
797
1095
|
this.exportTimer = null;
|
|
798
1096
|
this.countTimer = null;
|
|
799
1097
|
},
|
|
1098
|
+
/**
|
|
1099
|
+
* 导出全部文件合并成功:进度置满、停掉计时,并**立刻解开页签锁**。
|
|
1100
|
+
* 锁只保护取数期间。文件已经生成之后弹框还开着(用户在看列表、点下载)是完全
|
|
1101
|
+
* 合法的状态,那时页签必须能正常关闭 —— 解锁此前只挂在 beforeDestroy 上,
|
|
1102
|
+
* 用户不点「取消/确定」就永远解不开,正是「导出完成后页签关不掉」的来源。
|
|
1103
|
+
*/
|
|
1104
|
+
completeExport() {
|
|
1105
|
+
if (!this.totalSizeKnown) {
|
|
1106
|
+
this.tTotalSize = this.doneSize;
|
|
1107
|
+
this.totalSizeKnown = true;
|
|
1108
|
+
}
|
|
1109
|
+
setTimeout(() => {
|
|
1110
|
+
if (this.isExportStopped()) return;
|
|
1111
|
+
this.percentageNum = parseInt(100);
|
|
1112
|
+
}, 100);
|
|
1113
|
+
this.clearExportTimer();
|
|
1114
|
+
this.unlockMenu();
|
|
1115
|
+
},
|
|
800
1116
|
/**
|
|
801
1117
|
* 中止导出:停止全部定时器并把进度条置为错误态。
|
|
802
1118
|
* @param {String} [msg] 需要额外弹给用户的提示;服务端已 toast 过的失败不传,避免重复提示。
|
|
803
1119
|
*/
|
|
804
1120
|
abortExport(msg) {
|
|
805
1121
|
this.clearExportTimer();
|
|
1122
|
+
// 必须先置标志再取消:取消会让其余在途请求 reject,它们的 .catch 先问
|
|
1123
|
+
// isExportStopped() 才不会重复弹提示
|
|
806
1124
|
this.exportError = true;
|
|
1125
|
+
this.cancelPendingRequests();
|
|
1126
|
+
// 中止后弹框可能还挂在那儿(错误态进度条),页签没有理由继续锁着
|
|
1127
|
+
this.unlockMenu();
|
|
807
1128
|
if (msg) this.$baseAlert(msg);
|
|
808
1129
|
},
|
|
809
1130
|
isPicture: function (suffix) {
|
|
@@ -841,10 +1162,10 @@ function getGrid(that, tableRef) {
|
|
|
841
1162
|
return column.slots.filterVal(params);
|
|
842
1163
|
}
|
|
843
1164
|
let slotDefault = column.slots && column.slots.default;
|
|
844
|
-
let hasRenderFn
|
|
845
|
-
!!column.renderCell
|
|
846
|
-
typeof slotDefault === "function"
|
|
847
|
-
typeof slotDefault === "string";
|
|
1165
|
+
let hasRenderFn
|
|
1166
|
+
= !!column.renderCell
|
|
1167
|
+
|| typeof slotDefault === "function"
|
|
1168
|
+
|| typeof slotDefault === "string";
|
|
848
1169
|
if (!hasRenderFn) {
|
|
849
1170
|
let cellValue = params.row[column.field];
|
|
850
1171
|
if (typeof column.formatter === "function") {
|
|
@@ -858,7 +1179,7 @@ function getGrid(that, tableRef) {
|
|
|
858
1179
|
}
|
|
859
1180
|
return getCellValue(params);
|
|
860
1181
|
},
|
|
861
|
-
getExcelData(rows) {
|
|
1182
|
+
async getExcelData(rows) {
|
|
862
1183
|
let that = this;
|
|
863
1184
|
|
|
864
1185
|
let showImageAtTable = this.option.showImageAtTable || false;
|
|
@@ -875,8 +1196,19 @@ function getGrid(that, tableRef) {
|
|
|
875
1196
|
let contents;
|
|
876
1197
|
let params;
|
|
877
1198
|
let resultStr;
|
|
878
|
-
|
|
879
|
-
|
|
1199
|
+
let index = -1;
|
|
1200
|
+
for (const row of rows) {
|
|
1201
|
+
index++;
|
|
1202
|
+
// 每 EXPORT_YIELD_ROWS 行让出一次主线程。取值本身是同步的双层遍历,一页
|
|
1203
|
+
// 默认 1000 行、渲染兜底列还要逐单元格挂载组件,整页跑完可达数秒;并发几页
|
|
1204
|
+
// 几乎同时到达时主线程被连续占死,进度条不动、「取消」点不动,浏览器还可能
|
|
1205
|
+
// 直接判定页面无响应而杀掉标签页。让出不减少总工作量,只保证 UI 活着。
|
|
1206
|
+
if (index > 0 && index % EXPORT_YIELD_ROWS === 0) {
|
|
1207
|
+
await yieldToBrowser();
|
|
1208
|
+
// 让出期间用户可能已取消/导出已中止,此时继续算完这一页没有意义,
|
|
1209
|
+
// 且合并根本不会发生,返回 null 让调用方跳过上送。
|
|
1210
|
+
if (that.isExportStopped()) return null;
|
|
1211
|
+
}
|
|
880
1212
|
contents = [];
|
|
881
1213
|
columns.forEach((column) => {
|
|
882
1214
|
if (column.title) {
|
|
@@ -891,27 +1223,38 @@ function getGrid(that, tableRef) {
|
|
|
891
1223
|
// _columnIndex
|
|
892
1224
|
};
|
|
893
1225
|
let exportType = column.params?.exportType;
|
|
894
|
-
let exportVal
|
|
895
|
-
column.params && column.params.exportVal
|
|
1226
|
+
let exportVal
|
|
1227
|
+
= column.params && column.params.exportVal
|
|
896
1228
|
? column.params.exportVal
|
|
897
1229
|
: null;
|
|
898
1230
|
if (exportVal) {
|
|
899
1231
|
resultStr = exportVal(params);
|
|
1232
|
+
} else if (column.params?.exportBlank && !exportType) {
|
|
1233
|
+
// 列保留、格留空:没配导出类型的附件列没有可写的内容,更不该为此
|
|
1234
|
+
// 逐单元格挂载附件组件去爬文件名。判定见 xform 的 isBlankExportColumn。
|
|
1235
|
+
// 放在 exportVal 之后:调用方显式写了取值函数就以它为准。
|
|
1236
|
+
// 必须再判一次 exportType:exportBlank 是建列时按 t.exportType 算死的,
|
|
1237
|
+
// 而 params.exportType 之后还会被 tableColumnConfig 脚本覆盖,只认
|
|
1238
|
+
// exportBlank 会把运行期才拿到导出类型的图片列错误地导成空。
|
|
1239
|
+
resultStr = null;
|
|
900
1240
|
} else if (exportType === "Number") {
|
|
901
1241
|
resultStr = that.getExportCellValue(params);
|
|
902
1242
|
if (
|
|
903
|
-
resultStr !== null
|
|
904
|
-
resultStr !== undefined
|
|
905
|
-
resultStr !== ""
|
|
906
|
-
!(resultStr + "").startsWith("[EXPNUM]")
|
|
1243
|
+
resultStr !== null
|
|
1244
|
+
&& resultStr !== undefined
|
|
1245
|
+
&& resultStr !== ""
|
|
1246
|
+
&& !(resultStr + "").startsWith("[EXPNUM]")
|
|
907
1247
|
) {
|
|
908
1248
|
resultStr = "[EXPNUM]" + resultStr;
|
|
909
1249
|
}
|
|
910
1250
|
} else if (
|
|
911
|
-
exportType === "Image"
|
|
912
|
-
(showImageAtTable && exportType === "Image2")
|
|
1251
|
+
exportType === "Image"
|
|
1252
|
+
|| (showImageAtTable && exportType === "Image2")
|
|
913
1253
|
) {
|
|
914
|
-
|
|
1254
|
+
// 取值刻意延到"确实用得上"的那条分支才做:附件的正常形态是数组,
|
|
1255
|
+
// 那条分支会用 row[column.field] 自己拼 [EXPIMG],把取值结果整个覆盖;
|
|
1256
|
+
// 空值分支同样直接给 null。而附件列没有 filterVal,取值会落到
|
|
1257
|
+
// getCellValue 的 vNode 挂载兜底——等于每个单元格白挂一次附件组件。
|
|
915
1258
|
let attachments = row[column.field];
|
|
916
1259
|
if (attachments) {
|
|
917
1260
|
if (Array.isArray(attachments)) {
|
|
@@ -919,9 +1262,9 @@ function getGrid(that, tableRef) {
|
|
|
919
1262
|
that.isPicture(item.extension)
|
|
920
1263
|
);
|
|
921
1264
|
if (items.length > 0) {
|
|
922
|
-
resultStr
|
|
923
|
-
"[EXPIMG]"
|
|
924
|
-
items
|
|
1265
|
+
resultStr
|
|
1266
|
+
= "[EXPIMG]"
|
|
1267
|
+
+ items
|
|
925
1268
|
.map((item) => {
|
|
926
1269
|
let url = item.large || item.medium;
|
|
927
1270
|
return item.domain + url;
|
|
@@ -931,16 +1274,18 @@ function getGrid(that, tableRef) {
|
|
|
931
1274
|
resultStr = null;
|
|
932
1275
|
}
|
|
933
1276
|
} else {
|
|
1277
|
+
// 单值形态(字段里直接存 URL)才需要取值来嗅后缀
|
|
1278
|
+
resultStr = that.getExportCellValue(params);
|
|
934
1279
|
if (
|
|
935
1280
|
that.isPicture(
|
|
936
1281
|
that.$commonFileUtil.getFileSuffix(resultStr)
|
|
937
1282
|
)
|
|
938
1283
|
) {
|
|
939
1284
|
if (
|
|
940
|
-
resultStr !== null
|
|
941
|
-
resultStr !== undefined
|
|
942
|
-
resultStr !== ""
|
|
943
|
-
!(resultStr + "").startsWith("[EXPIMG]")
|
|
1285
|
+
resultStr !== null
|
|
1286
|
+
&& resultStr !== undefined
|
|
1287
|
+
&& resultStr !== ""
|
|
1288
|
+
&& !(resultStr + "").startsWith("[EXPIMG]")
|
|
944
1289
|
) {
|
|
945
1290
|
resultStr = "[EXPIMG]" + resultStr;
|
|
946
1291
|
}
|
|
@@ -959,20 +1304,45 @@ function getGrid(that, tableRef) {
|
|
|
959
1304
|
}
|
|
960
1305
|
});
|
|
961
1306
|
arr.push(contents);
|
|
962
|
-
}
|
|
1307
|
+
}
|
|
963
1308
|
return arr;
|
|
964
1309
|
},
|
|
1310
|
+
/**
|
|
1311
|
+
* 从响应头解析下载文件名,取不到时用导出标题兜底。
|
|
1312
|
+
* @param {Object} response axios 原始响应。
|
|
1313
|
+
* @param {String} fallbackName 兜底文件名(不含扩展名)。
|
|
1314
|
+
* @returns {String}
|
|
1315
|
+
*/
|
|
1316
|
+
resolveDownloadFileName(response, fallbackName) {
|
|
1317
|
+
let headers = response?.headers || {};
|
|
1318
|
+
let disposition = headers["content-disposition"] || headers["Content-Disposition"];
|
|
1319
|
+
if (disposition) {
|
|
1320
|
+
// filename*=UTF-8''xxx 优先,其次 filename="xxx"
|
|
1321
|
+
let starMatch = /filename\*=(?:UTF-8'')?([^;]+)/i.exec(disposition);
|
|
1322
|
+
let plainMatch = /filename="?([^";]+)"?/i.exec(disposition);
|
|
1323
|
+
let raw = (starMatch && starMatch[1]) || (plainMatch && plainMatch[1]);
|
|
1324
|
+
if (raw) {
|
|
1325
|
+
try {
|
|
1326
|
+
return decodeURIComponent(raw.trim());
|
|
1327
|
+
} catch (e) {
|
|
1328
|
+
return raw.trim();
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
return fallbackName + ".xlsx";
|
|
1333
|
+
},
|
|
965
1334
|
exportAll(row) {
|
|
1335
|
+
let that = this;
|
|
966
1336
|
let cUUid = encodeURIComponent(row.uuid);
|
|
967
1337
|
let ippaaapp = this.ippaaapp;
|
|
968
1338
|
let fileName = row.title;
|
|
969
|
-
let fileUrl
|
|
970
|
-
configUtil.baseUrl
|
|
971
|
-
this.CURRENT_PREFIX
|
|
972
|
-
"/excel/download?uuid="
|
|
973
|
-
cUUid
|
|
974
|
-
"&ippaaapp="
|
|
975
|
-
ippaaapp;
|
|
1339
|
+
let fileUrl
|
|
1340
|
+
= configUtil.baseUrl
|
|
1341
|
+
+ this.CURRENT_PREFIX
|
|
1342
|
+
+ "/excel/download?uuid="
|
|
1343
|
+
+ cUUid
|
|
1344
|
+
+ "&ippaaapp="
|
|
1345
|
+
+ ippaaapp;
|
|
976
1346
|
|
|
977
1347
|
function downLoadFile2() {
|
|
978
1348
|
let params = {
|
|
@@ -982,8 +1352,8 @@ function getGrid(that, tableRef) {
|
|
|
982
1352
|
|
|
983
1353
|
let form = document.createElement("form");
|
|
984
1354
|
|
|
985
|
-
let randomNum
|
|
986
|
-
new Date().valueOf() + Math.floor(Math.random() * 1000000);
|
|
1355
|
+
let randomNum
|
|
1356
|
+
= new Date().valueOf() + Math.floor(Math.random() * 1000000);
|
|
987
1357
|
let formId = "formId-" + randomNum;
|
|
988
1358
|
let formName = "formName-" + randomNum;
|
|
989
1359
|
|
|
@@ -1006,14 +1376,70 @@ function getGrid(that, tableRef) {
|
|
|
1006
1376
|
document.body.removeChild(form);
|
|
1007
1377
|
}
|
|
1008
1378
|
|
|
1009
|
-
|
|
1379
|
+
/**
|
|
1380
|
+
* 优先走 axios blob 下载:token 由 request.js 的请求拦截器注入
|
|
1381
|
+
* X-Token / Authorization 头,不必再把 access_token 塞进表单字段随请求体
|
|
1382
|
+
* 明文提交;失败时也能拿到响应体做判断,而表单 POST 打开新窗口后失败只会给
|
|
1383
|
+
* 用户看一个空白页或一坨错误 JSON。
|
|
1384
|
+
*
|
|
1385
|
+
* 后端若尚未放开该接口的头鉴权(此前只认表单里的 access_token),这里会拿到
|
|
1386
|
+
* JSON 错误体或直接报错 —— 一律回退到原来的表单 POST,保证下载不会因为这次
|
|
1387
|
+
* 改造而失效。同体系的 /export_ins/download 已经是 blob + 头鉴权的用法
|
|
1388
|
+
* (见 components/baseInputExport/mixins.js),大概率是通的,但**需联调确认**。
|
|
1389
|
+
*/
|
|
1390
|
+
let fallbackToFormPost = function (reason) {
|
|
1391
|
+
console.warn("[excelExport] blob 下载不可用,回退表单 POST:", reason);
|
|
1392
|
+
downLoadFile2();
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1395
|
+
let apiUrl = `${this.CURRENT_PREFIX}/excel/download?uuid=${cUUid}&ippaaapp=${ippaaapp}&n=${encodeURIComponent(fileName)}`;
|
|
1396
|
+
|
|
1397
|
+
this.$http({
|
|
1398
|
+
url: apiUrl,
|
|
1399
|
+
method: "post",
|
|
1400
|
+
data: {},
|
|
1401
|
+
responseType: "blob",
|
|
1402
|
+
resultType: "other",
|
|
1403
|
+
modal: false,
|
|
1404
|
+
// 失败要静默回退,不能先弹一个错误框
|
|
1405
|
+
errorMsg: false,
|
|
1406
|
+
// 刻意**不带**本次导出的取消令牌。下载不是导出流水线的一环,而是用户单独
|
|
1407
|
+
// 发起的动作:分卷文件大时点完「下载」要等几秒,此时关掉进度弹框(「取消」
|
|
1408
|
+
// 和「确定」都走 dialogClose2 → cancelPendingRequests)会掐断这个请求,而
|
|
1409
|
+
// 下面的 isCancel 分支又刻意不回退表单 POST —— 结果是文件静默地下不下来,
|
|
1410
|
+
// 且没有任何提示。旧的表单 POST 脱离组件生命周期,本就不受关弹框影响。
|
|
1411
|
+
callback: (res, response) => {
|
|
1412
|
+
// 后端把错误当 200 返回时,body 是 JSON / HTML 错误页而不是 xlsx 流
|
|
1413
|
+
if (!isDownloadableBlob(res)) {
|
|
1414
|
+
fallbackToFormPost("响应不是文件流:" + (res && res.type));
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
let blobUrl = window.URL.createObjectURL(res);
|
|
1418
|
+
let a = document.createElement("a");
|
|
1419
|
+
a.href = blobUrl;
|
|
1420
|
+
a.download = that.resolveDownloadFileName(response, fileName);
|
|
1421
|
+
document.body.appendChild(a);
|
|
1422
|
+
a.click();
|
|
1423
|
+
document.body.removeChild(a);
|
|
1424
|
+
// 不释放会一直占着这份文件的内存,大导出下很可观
|
|
1425
|
+
setTimeout(() => window.URL.revokeObjectURL(blobUrl), 0);
|
|
1426
|
+
},
|
|
1427
|
+
}).catch((e) => {
|
|
1428
|
+
// 只挡真正的取消:取消后回退表单 POST 会在取消之后又弹出一次下载。
|
|
1429
|
+
// 本方法已不带取消令牌,这里是防御性保留(组件销毁等外部因素仍可能取消)。
|
|
1430
|
+
// 这里**不能**用 isExportStopped()——它含 exportError,而 exportAll 同时是
|
|
1431
|
+
// 进度弹框里的手动下载按钮:导出中途失败后用户手动下载已生成的分卷,正是最
|
|
1432
|
+
// 需要回退兜底的场景,用它拦会变成点了毫无反应。
|
|
1433
|
+
if (axios.isCancel(e)) return;
|
|
1434
|
+
fallbackToFormPost(e && e.message);
|
|
1435
|
+
});
|
|
1010
1436
|
},
|
|
1011
1437
|
startProcess2(datas) {
|
|
1012
1438
|
this.tableTarget = getGrid(this.option.vue, this.option.targetRef);
|
|
1013
1439
|
let that = this;
|
|
1014
1440
|
let options = this.option;
|
|
1015
|
-
let title
|
|
1016
|
-
options.title || this.$t2("导出", "components.excelExport.title");
|
|
1441
|
+
let title
|
|
1442
|
+
= options.title || this.$t2("导出", "components.excelExport.title");
|
|
1017
1443
|
if (!options.prefix && options.prefix !== "") {
|
|
1018
1444
|
let originOption = this.tableTarget.params.originOption;
|
|
1019
1445
|
let path = originOption.exportPath || originOption.path;
|
|
@@ -1035,20 +1461,49 @@ function getGrid(that, tableRef) {
|
|
|
1035
1461
|
}
|
|
1036
1462
|
this.CURRENT_PREFIX = options.prefix;
|
|
1037
1463
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1464
|
+
// 勾选/当前页导出此前把全部行塞进**一个**请求上送。`getCheckboxRecords(true)`
|
|
1465
|
+
// 是跨页全量勾选,选得多时请求体轻易超限(后端/网关直接拒),而且整批取值转换
|
|
1466
|
+
// 与 JSON 序列化一次性压在主线程上。改为复用条件导出那套「分页 append + 一次
|
|
1467
|
+
// merge」:按 getExportPageSize() 切片顺序上送。
|
|
1468
|
+
// 注意页数 ≤ 1 时(勾选量不超过一页,即绝大多数场景)请求序列与旧实现完全一致,
|
|
1469
|
+
// 不引入任何行为变化;这里刻意保持**串行**,避免把条件导出那边"上送无并发闸门"
|
|
1470
|
+
// 的老问题原样复制过来。
|
|
1471
|
+
let pageSize = this.getExportPageSize();
|
|
1472
|
+
let totalPages = Math.max(Math.ceil(datas.length / pageSize), 1);
|
|
1473
|
+
|
|
1474
|
+
let appendPage = function (pageNumber) {
|
|
1475
|
+
let start = (pageNumber - 1) * pageSize;
|
|
1476
|
+
return that
|
|
1041
1477
|
.addExcelData(
|
|
1042
1478
|
{
|
|
1043
|
-
rows: datas,
|
|
1044
|
-
pageNumber:
|
|
1479
|
+
rows: datas.slice(start, start + pageSize),
|
|
1480
|
+
pageNumber: pageNumber,
|
|
1045
1481
|
},
|
|
1046
1482
|
true
|
|
1047
1483
|
)
|
|
1048
1484
|
.then((resultMsg2) => {
|
|
1049
|
-
if (resultMsg2.type
|
|
1050
|
-
|
|
1051
|
-
|
|
1485
|
+
if (resultMsg2.type !== "success") {
|
|
1486
|
+
// "abort" 是取值过程中组件已销毁/已中止,无需再提示;
|
|
1487
|
+
// 其余失败服务端已 toast 过,abortExport 不带 msg 避免重复弹
|
|
1488
|
+
if (resultMsg2.type !== "abort") that.abortExport();
|
|
1489
|
+
return false;
|
|
1490
|
+
}
|
|
1491
|
+
if (pageNumber >= totalPages) return true;
|
|
1492
|
+
return appendPage(pageNumber + 1);
|
|
1493
|
+
});
|
|
1494
|
+
};
|
|
1495
|
+
|
|
1496
|
+
let handleData = function () {
|
|
1497
|
+
appendPage(1)
|
|
1498
|
+
.then((completed) => {
|
|
1499
|
+
// 缺页合并会静默丢行,任一页失败都必须停在这里
|
|
1500
|
+
if (!completed) return;
|
|
1501
|
+
setTimeout(() => {
|
|
1502
|
+
that
|
|
1503
|
+
.mergeExcel(1, totalPages, true)
|
|
1504
|
+
.then((resultMsg3) => {
|
|
1505
|
+
// 取消后不能再自动弹下载:那会是一个半截文件
|
|
1506
|
+
if (that.isExportStopped()) return;
|
|
1052
1507
|
if (resultMsg3.type === "success") {
|
|
1053
1508
|
let fileInfo = resultMsg3.objx;
|
|
1054
1509
|
let fileName = fileInfo.fileName;
|
|
@@ -1056,28 +1511,49 @@ function getGrid(that, tableRef) {
|
|
|
1056
1511
|
|
|
1057
1512
|
let dataMap = {};
|
|
1058
1513
|
dataMap["startPage"] = 1;
|
|
1059
|
-
dataMap["endPage"] =
|
|
1514
|
+
dataMap["endPage"] = totalPages;
|
|
1060
1515
|
dataMap["title"] = title;
|
|
1061
1516
|
dataMap["uuid"] = fileName;
|
|
1062
1517
|
dataMap["fileSize"] = fileSize;
|
|
1063
1518
|
that.exportAll(dataMap);
|
|
1519
|
+
} else {
|
|
1520
|
+
that.abortExport();
|
|
1064
1521
|
}
|
|
1522
|
+
})
|
|
1523
|
+
.catch((e) => {
|
|
1524
|
+
if (that.isExportStopped()) return;
|
|
1525
|
+
console.error(e);
|
|
1526
|
+
that.abortExport(that.$t1("文件合并异常,导出已中止"));
|
|
1065
1527
|
});
|
|
1066
|
-
|
|
1067
|
-
|
|
1528
|
+
}, 0);
|
|
1529
|
+
})
|
|
1530
|
+
.catch((e) => {
|
|
1531
|
+
if (that.isExportStopped()) return;
|
|
1532
|
+
console.error(e);
|
|
1533
|
+
that.abortExport(that.$t1("导出数据写入失败,导出已中止"));
|
|
1068
1534
|
});
|
|
1069
1535
|
};
|
|
1070
|
-
that
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
that.
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1536
|
+
that
|
|
1537
|
+
.createExcelFile(true)
|
|
1538
|
+
.then((resultMsg) => {
|
|
1539
|
+
if (that.isExportStopped()) return;
|
|
1540
|
+
if (resultMsg.type === "success") {
|
|
1541
|
+
let aObj = resultMsg.objx;
|
|
1542
|
+
that.uuid = aObj.uuid;
|
|
1543
|
+
that.nowDate = aObj.nowDate;
|
|
1544
|
+
that.ippaaapp = aObj.ippaaapp;
|
|
1545
|
+
setTimeout(() => {
|
|
1546
|
+
handleData();
|
|
1547
|
+
}, 0);
|
|
1548
|
+
} else {
|
|
1549
|
+
that.abortExport();
|
|
1550
|
+
}
|
|
1551
|
+
})
|
|
1552
|
+
.catch((error) => {
|
|
1553
|
+
if (that.isExportStopped()) return;
|
|
1554
|
+
console.error(error);
|
|
1555
|
+
that.abortExport(that.$t1("创建导出文件失败,导出已中止"));
|
|
1556
|
+
});
|
|
1081
1557
|
},
|
|
1082
1558
|
closeExportFieldDialog() {
|
|
1083
1559
|
this.dialogClose2();
|
|
@@ -1122,29 +1598,42 @@ function getGrid(that, tableRef) {
|
|
|
1122
1598
|
}
|
|
1123
1599
|
});
|
|
1124
1600
|
},
|
|
1601
|
+
/**
|
|
1602
|
+
* 导出期间锁住当前页签(不让关),并记下锁的是哪一个,见 lockedView。
|
|
1603
|
+
* 本就是固定页签(affix)的不接管 —— 那不是我们加的锁,解的时候也不能动它。
|
|
1604
|
+
*
|
|
1605
|
+
* 只写 user_affix,**绝不能再写 meta.affix**:isRepeatable() 见到 affix 就返回
|
|
1606
|
+
* false,可重复打开的页签的 viewKey 会从 fullPath 塌成 path,于是 AppMain 的
|
|
1607
|
+
* router-view key 与 BaseKeepAlive 的缓存名同时错位 —— 切走再切回整页重建。
|
|
1608
|
+
* 「不让批量关闭」的语义由 tagsView 的 isPinned 认 user_affix 兜住。
|
|
1609
|
+
*
|
|
1610
|
+
* 定位页签用 viewKey 而不是 path:可重复打开时同一 path 会有多个页签,
|
|
1611
|
+
* 按 path 找到的可能是另一个实例。
|
|
1612
|
+
*/
|
|
1125
1613
|
lockMenu() {
|
|
1126
1614
|
let vueTarget = window.$vueRoot;
|
|
1127
|
-
let
|
|
1615
|
+
let key = viewKey(vueTarget.$route);
|
|
1128
1616
|
let visitedViews = vueTarget.$store.state.tagsView.visitedViews;
|
|
1129
|
-
if (visitedViews)
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
}
|
|
1617
|
+
if (!visitedViews) return;
|
|
1618
|
+
let currentItem = visitedViews.find((item) => viewKey(item) === key);
|
|
1619
|
+
if (currentItem && !currentItem.meta.affix) {
|
|
1620
|
+
this.$set(currentItem.meta, "user_affix", true);
|
|
1621
|
+
this.lockedView = currentItem;
|
|
1135
1622
|
}
|
|
1136
1623
|
},
|
|
1624
|
+
/**
|
|
1625
|
+
* 解开自己锁的那一个页签。
|
|
1626
|
+
* **不能**再按当前路由去查:解锁的时机是组件销毁(取消、或下一次导出把上一个
|
|
1627
|
+
* 实例顶掉),那时的当前路由未必还是上锁时那一个。典型漏锁路径:A 页开始条件
|
|
1628
|
+
* 导出 → 切到 B 页 → 在 B 页再点一次导出,initInstance 先销毁旧实例,旧实例按
|
|
1629
|
+
* $route.path 查到的是 B(B 还没锁,什么也没做),于是 A 永久锁死。
|
|
1630
|
+
* 页签可能已被别处删掉,此时改的是一个游离对象,无副作用。
|
|
1631
|
+
*/
|
|
1137
1632
|
unlockMenu() {
|
|
1138
|
-
let
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
let currentItem = visitedViews.find((item) => item.path === path);
|
|
1143
|
-
if (currentItem && currentItem.meta.user_affix) {
|
|
1144
|
-
currentItem.meta.affix = false;
|
|
1145
|
-
currentItem.meta.user_affix = false;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1633
|
+
let view = this.lockedView;
|
|
1634
|
+
this.lockedView = null;
|
|
1635
|
+
if (!view || !view.meta.user_affix) return;
|
|
1636
|
+
view.meta.user_affix = false;
|
|
1148
1637
|
},
|
|
1149
1638
|
},
|
|
1150
1639
|
};
|