cloud-web-corejs 1.0.54-dev.76 → 1.0.54-dev.761
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/package.json +196 -183
- package/src/App.vue +73 -75
- package/src/api/user.js +85 -40
- package/src/components/Qrcode/fileParse.vue +0 -1
- package/src/components/Tinymce/index.vue +112 -71
- package/src/components/VabUpload/fileLibraryDialog.vue +296 -0
- package/src/components/VabUpload/image-viewer.vue +2 -2
- package/src/components/VabUpload/index.js +69 -1
- package/src/components/VabUpload/index.vue +9 -1
- package/src/components/VabUpload/mixins/fileLibraryDialog.js +1112 -0
- package/src/components/VabUpload/mixins.js +1881 -2
- package/src/components/VabUpload/propertiesDialog.vue +1 -1
- package/src/components/VabUpload/view.vue +209 -120
- package/src/components/advancedSearchDialog/mixins.js +28 -1
- package/src/components/base-textarea/index.vue +104 -0
- package/src/components/baseAlert/index.js +44 -1
- package/src/components/baseAlert/index.vue +24 -20
- package/src/components/baseAlert/mixins.js +61 -1
- package/src/components/baseArea/index.vue +1628 -0
- package/src/components/baseAttachment/index.vue +49 -40
- package/src/components/baseAttachment/install.js +21 -5
- package/src/components/baseAttachment/mixins.js +310 -1
- package/src/components/baseInputBatch/mixins.js +58 -1
- package/src/components/baseInputExport/index.vue +21 -14
- package/src/components/baseInputExport/mixins.js +391 -1
- package/src/components/baseInputNumber/index.vue +9 -9
- package/src/components/baseTabs/index.vue +16 -8
- package/src/components/baseTabs/mixins.js +177 -1
- package/src/components/cnPrint/index.js +44 -1
- package/src/components/cnPrint/mixins.js +189 -1
- package/src/components/code-editor/index.vue +131 -62
- package/src/components/confirmDialog/index.js +41 -1
- package/src/components/confirmDialog/index.vue +24 -17
- package/src/components/confirmDialog/mixins.js +31 -1
- package/src/components/errorMsg/index.js +47 -3
- package/src/components/errorMsg/index.vue +78 -70
- package/src/components/errorMsg/mixins.js +103 -5
- package/src/components/excelExport/button.vue +86 -24
- package/src/components/excelExport/exportFieldDialog.vue +246 -90
- package/src/components/excelExport/index.js +65 -6
- package/src/components/excelExport/index.vue +109 -26
- package/src/components/excelExport/mixins.js +1132 -8
- package/src/components/excelImport/index.js +13 -13
- package/src/components/excelImport/mixins.js +2 -1
- package/src/components/fileLibrary/categoryMoveDialog.vue +109 -109
- package/src/components/fileLibrary/fileObjAuthDialog.vue +297 -208
- package/src/components/fileLibrary/fileObjAuthEditDialog.vue +6 -0
- package/src/components/fileLibrary/filterDialog.vue +454 -0
- package/src/components/fileLibrary/index.vue +1109 -687
- package/src/components/fileLibrary/mixins/categoryMoveDialogMixins.js +1 -1
- package/src/components/fileLibrary/mixins/fileCategoryDialogMixins.js +1 -1
- package/src/components/fileLibrary/mixins/fileHistoryDialogMixins.js +2 -2
- package/src/components/fileLibrary/mixins/fileObjAuthDialogMixin.js +339 -211
- package/src/components/fileLibrary/mixins/fileObjAuthEditDialogMixin.js +31 -27
- package/src/components/fileLibrary/mixins/fileObjAuthEditMixin.js +4 -4
- package/src/components/fileLibrary/mixins/indexMixins.js +230 -101
- package/src/components/fileLibrary/mixins/propertiesDialogMixins.js +62 -3
- package/src/components/fileLibrary/mixins/recycleBinDialogMixins.js +3 -3
- package/src/components/fileLibrary/propertiesDialog.vue +190 -145
- package/src/components/fileLibrary/recycleBinDialog.vue +237 -236
- package/src/components/fileLibrary/shareDialog.vue +1 -1
- package/src/components/formDialog/README.md +239 -0
- package/src/components/formDialog/index.js +35 -0
- package/src/components/formDialog/index.vue +724 -0
- package/src/components/formOplog/mixins.js +85 -4
- package/src/components/hiprint/css/bootstrap.min.css +6 -0
- package/src/components/hiprint/fonts/glyphicons-halflings-regular.eot +0 -0
- package/src/components/hiprint/fonts/glyphicons-halflings-regular.svg +288 -0
- package/src/components/hiprint/fonts/glyphicons-halflings-regular.ttf +0 -0
- package/src/components/hiprint/fonts/glyphicons-halflings-regular.woff +0 -0
- package/src/components/hiprint/fonts/glyphicons-halflings-regular.woff2 +0 -0
- package/src/components/hiprint/hiprint.bundle.js +15 -3
- package/src/components/hiprint/view/design/index.vue +140 -47
- package/src/components/hiprint/view/design/mixins.js +611 -1
- package/src/components/hiprint/view/design/preview.vue +75 -52
- package/src/components/hiprint/view/json-view.vue +31 -31
- package/src/components/jdPrint/index.js +44 -1
- package/src/components/jdPrint/mixins.js +208 -1
- package/src/components/jsonImport/exportUtil.js +106 -0
- package/src/components/jsonImport/index.js +212 -17
- package/src/components/jsonImport/mixins.js +350 -16
- package/src/components/langImport/index.js +80 -1
- package/src/components/langImport/mixins.js +487 -1
- package/src/components/langTag/mixins/addButton.js +51 -5
- package/src/components/langTag/mixins/deleteButton.js +55 -5
- package/src/components/langTag/mixins/view.js +47 -5
- package/src/components/luckysheet/dialog.vue +159 -0
- package/src/components/luckysheet/export.js +595 -0
- package/src/components/luckysheet/fileUtils.js +147 -0
- package/src/components/luckysheet/index.js +72 -0
- package/src/components/luckysheet/templateJson.js +12078 -0
- package/src/components/luckysheet/view.vue +210 -0
- package/src/components/mobile/file/index.vue +10 -0
- package/src/components/obsUpload/index.js +34 -0
- package/src/components/obsUpload/index.vue +231 -0
- package/src/components/obsUpload/mixins.js +1476 -0
- package/src/components/onlineTalk/index.vue +1 -1
- package/src/components/onlineTalk/mixins.js +852 -1
- package/src/components/onlineTalk/talkUserDialog.vue +280 -0
- package/src/components/oplogTable/mixins.js +83 -4
- package/src/components/pddPrint/index.js +44 -1
- package/src/components/pddPrint/mixins.js +252 -1
- package/src/components/projectTag/mixins/addButton.js +52 -1
- package/src/components/projectTag/mixins/deleteButton.js +52 -1
- package/src/components/projectTag/mixins/view.js +43 -1
- package/src/components/scriptDescription/button.vue +12 -4
- package/src/components/scriptDescription/mixins.js +30 -1
- package/src/components/scriptTest/mixins.js +90 -1
- package/src/components/statusTag/mixins.js +66 -1
- package/src/components/table/CellSlot.vue +12 -9
- package/src/components/table/config.js +74 -1
- package/src/components/table/index.js +1215 -11
- package/src/components/table/plugins/extend-cell-area/vxe-table-extend-cell-area.es6.min.js +11028 -0
- package/src/components/table/plugins/extend-cell-area/vxe-table-extend-cell-area.min.css +200 -0
- package/src/components/table/tableForm.vue +99 -63
- package/src/components/table/tableFormMixin.js +285 -1
- package/src/components/table/util/index.js +337 -0
- package/src/components/table/vxeFilter/index.js +153 -1
- package/src/components/table/vxeFilter/mixin.js +310 -6
- package/src/components/tempStorage/index.vue +76 -55
- package/src/components/tempStorage/tempStorageDialog.vue +179 -54
- package/src/components/vb-tabs/x-tabs.vue +57 -30
- package/src/components/vipPrint/index.js +44 -1
- package/src/components/vipPrint/mixins.js +268 -1
- package/src/components/wf/addOpinionButton.vue +57 -0
- package/src/components/wf/content.vue +834 -362
- package/src/components/wf/mixins/addOpinionButton.js +53 -0
- package/src/components/wf/mixins/setCandidateButton.js +161 -0
- package/src/components/wf/mixins/setCandidateDialog.js +217 -5
- package/src/components/wf/mixins/setCandidateDialog2.js +252 -0
- package/src/components/wf/mixins/wfFlowEleScriptDialog.js +131 -0
- package/src/components/wf/mixins/wfTaskUserRangeDialog.js +69 -0
- package/src/components/wf/setCandidateButton.vue +40 -0
- package/src/components/wf/setCandidateDialog.vue +10 -0
- package/src/components/wf/setCandidateDialog2.vue +105 -0
- package/src/components/wf/wf.js +2221 -30
- package/src/components/wf/wfFlowEleScriptDialog.vue +89 -0
- package/src/components/wf/wfStartDialog.vue +66 -42
- package/src/components/wf/wfTaskUserRangeDialog.vue +65 -0
- package/src/components/wf/wfUtil.js +280 -1
- package/src/components/xform/XFormTabContainer//346/226/260/345/242/236/351/241/265/347/255/276/346/250/241/345/274/217-/346/234/200/347/273/210/345/256/236/347/216/260.md +195 -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" +57 -0
- package/src/components/xform/docs/2026-07 /346/216/222/346/237/245/344/277/256/345/244/215/350/256/260/345/275/225.md" +73 -0
- package/src/components/xform/docs/autocomplete /350/207/252/345/212/250/345/256/214/346/210/220/347/273/204/344/273/266/350/257/264/346/230/216.md" +126 -0
- package/src/components/xform/docs//345/220/216/345/217/260/345/255/227/346/256/265/357/274/210/345/212/250/346/200/201/347/224/237/346/210/220/357/274/211JSON /350/257/264/346/230/216.md" +1286 -0
- package/src/components/xform/docs//345/257/271/346/257/224/345/212/237/350/203/275/350/220/275/345/234/260/346/226/271/346/241/210.md +986 -0
- package/src/components/xform/docs//346/225/260/346/215/256/350/241/250/346/240/274/345/212/250/346/200/201/345/210/227 JSON /350/257/264/346/230/216.md" +657 -0
- package/src/components/xform/form-designer/designer.js +2027 -29
- package/src/components/xform/form-designer/form-widget/components/gantt/index.vue +434 -0
- package/src/components/xform/form-designer/form-widget/container-widget/containerMixin.js +108 -1
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-mixin.js +291 -8
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +14 -1
- package/src/components/xform/form-designer/form-widget/container-widget/detail-pane-widget.vue +3 -2
- package/src/components/xform/form-designer/form-widget/container-widget/detail-widget.vue +3 -3
- package/src/components/xform/form-designer/form-widget/dialog/baseFormulaDialog copy.vue +971 -0
- package/src/components/xform/form-designer/form-widget/dialog/baseFormulaDialog.vue +971 -0
- package/src/components/xform/form-designer/form-widget/dialog/exportDialog.vue +13 -0
- package/src/components/xform/form-designer/form-widget/dialog/fileReferenceDialog.vue +300 -0
- package/src/components/xform/form-designer/form-widget/dialog/formDialog.vue +85 -49
- package/src/components/xform/form-designer/form-widget/dialog/formDrawer.vue +6 -3
- package/src/components/xform/form-designer/form-widget/dialog/formulaDialog.vue +799 -0
- package/src/components/xform/form-designer/form-widget/dialog/importDialog.vue +30 -8
- package/src/components/xform/form-designer/form-widget/dialog/importDialogMixin.js +1774 -19
- package/src/components/xform/form-designer/form-widget/dialog/searchFormDialog.vue +222 -76
- package/src/components/xform/form-designer/form-widget/field-widget/a-link-widget.vue +67 -54
- 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 +272 -0
- package/src/components/xform/form-designer/form-widget/field-widget/autocomplete-widget.vue +119 -0
- package/src/components/xform/form-designer/form-widget/field-widget/baseAttachment-widget.vue +216 -184
- package/src/components/xform/form-designer/form-widget/field-widget/button-widget.vue +76 -66
- package/src/components/xform/form-designer/form-widget/field-widget/cascader-widget.vue +209 -90
- package/src/components/xform/form-designer/form-widget/field-widget/census-widget.vue +41 -35
- package/src/components/xform/form-designer/form-widget/field-widget/checkbox-widget.vue +18 -7
- package/src/components/xform/form-designer/form-widget/field-widget/color-widget.vue +4 -1
- package/src/components/xform/form-designer/form-widget/field-widget/copy_button-widget.vue +95 -0
- package/src/components/xform/form-designer/form-widget/field-widget/date-range-widget.vue +14 -3
- package/src/components/xform/form-designer/form-widget/field-widget/date-widget.vue +48 -5
- package/src/components/xform/form-designer/form-widget/field-widget/download-button-widget.vue +133 -0
- package/src/components/xform/form-designer/form-widget/field-widget/dropdown-item-widget.vue +86 -0
- package/src/components/xform/form-designer/form-widget/field-widget/dropdown-widget.vue +170 -0
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +1939 -16
- package/src/components/xform/form-designer/form-widget/field-widget/form-item-wrapper.vue +657 -108
- package/src/components/xform/form-designer/form-widget/field-widget/gantt-widget.vue +964 -0
- package/src/components/xform/form-designer/form-widget/field-widget/html-text-widget.vue +6 -2
- package/src/components/xform/form-designer/form-widget/field-widget/import-button-widget.vue +22 -11
- package/src/components/xform/form-designer/form-widget/field-widget/import2-button-widget.vue +90 -0
- package/src/components/xform/form-designer/form-widget/field-widget/input-widget.vue +7 -2
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/autocomplete-mixin.js +451 -0
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/date-limit-mixin.js +157 -0
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/echart-bar-mixin.js +3 -9
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/echart-category-mixin.js +3 -9
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/echart-pie-mixin.js +3 -9
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/utc-transform-mixin.js +75 -0
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/vabsearch-mixin.js +192 -0
- package/src/components/xform/form-designer/form-widget/field-widget/multiSearch-widget.vue +53 -0
- package/src/components/xform/form-designer/form-widget/field-widget/number-widget.vue +117 -81
- package/src/components/xform/form-designer/form-widget/field-widget/oplog-widget.vue +186 -0
- package/src/components/xform/form-designer/form-widget/field-widget/print-button-widget.vue +55 -28
- package/src/components/xform/form-designer/form-widget/field-widget/print-detail-button-widget.vue +119 -0
- package/src/components/xform/form-designer/form-widget/field-widget/project-tag-widget.vue +156 -54
- package/src/components/xform/form-designer/form-widget/field-widget/radio-widget.vue +26 -6
- package/src/components/xform/form-designer/form-widget/field-widget/save_submit_wf_button-widget.vue +112 -0
- package/src/components/xform/form-designer/form-widget/field-widget/script-input-widget.vue +146 -0
- package/src/components/xform/form-designer/form-widget/field-widget/search_button-widget.vue +2 -2
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-button-widget.vue +86 -0
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +92 -0
- package/src/components/xform/form-designer/form-widget/field-widget/select-widget.vue +24 -9
- package/src/components/xform/form-designer/form-widget/field-widget/singerSearch-widget.vue +53 -0
- package/src/components/xform/form-designer/form-widget/field-widget/singleUpload-widget.vue +145 -0
- package/src/components/xform/form-designer/form-widget/field-widget/static-content-wrapper.vue +16 -1
- package/src/components/xform/form-designer/form-widget/field-widget/static-text-widget.vue +8 -3
- package/src/components/xform/form-designer/form-widget/field-widget/status-widget.vue +93 -49
- package/src/components/xform/form-designer/form-widget/field-widget/switch-widget.vue +9 -1
- package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue +38 -38
- package/src/components/xform/form-designer/form-widget/field-widget/tempStorage-widget.vue +147 -0
- package/src/components/xform/form-designer/form-widget/field-widget/text-widget.vue +111 -34
- package/src/components/xform/form-designer/form-widget/field-widget/time-range-widget.vue +4 -3
- package/src/components/xform/form-designer/form-widget/field-widget/time-widget.vue +2 -1
- package/src/components/xform/form-designer/form-widget/field-widget/vabSearch-widget.vue +3 -171
- package/src/components/xform/form-designer/form-widget/field-widget/vabUpload-widget.vue +187 -70
- package/src/components/xform/form-designer/form-widget/field-widget/vabUpload2-widget.vue +753 -0
- package/src/components/xform/form-designer/form-widget/field-widget/vue-page-widget.vue +231 -0
- package/src/components/xform/form-designer/form-widget/index.vue +6 -1
- package/src/components/xform/form-designer/form-widget/indexMixin.js +184 -2
- package/src/components/xform/form-designer/index.vue +195 -191
- package/src/components/xform/form-designer/indexMixin.js +855 -24
- package/src/components/xform/form-designer/refMixinDesign.js +27 -28
- package/src/components/xform/form-designer/setting-panel/form-dynamicField-setting.vue +601 -0
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +1553 -629
- package/src/components/xform/form-designer/setting-panel/index.vue +313 -305
- package/src/components/xform/form-designer/setting-panel/indexMixin.js +370 -12
- package/src/components/xform/form-designer/setting-panel/option-items-setting.vue +585 -302
- package/src/components/xform/form-designer/setting-panel/property-editor/a-link-editor.vue +4 -4
- package/src/components/xform/form-designer/setting-panel/property-editor/a-text-editor.vue +3 -3
- package/src/components/xform/form-designer/setting-panel/property-editor/autoValueEnabled-editor.vue +38 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/buttonIcon-editor.vue +14 -15
- package/src/components/xform/form-designer/setting-panel/property-editor/censusClass-editor.vue +6 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/colorClass-editor.vue +28 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/commonAttributeEnabled-editor.vue +41 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/columnRenderDialog.vue +124 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +1154 -1048
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/edit-tree-button-group-config-dialog.vue +281 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/exportItemColumns-dialog.vue +432 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/onCheckboxChange-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +1632 -592
- package/src/components/xform/form-designer/setting-panel/property-editor/container-detail/detail-editor.vue +3 -3
- package/src/components/xform/form-designer/setting-panel/property-editor/container-detail-pane/detail-pane-editor.vue +3 -3
- package/src/components/xform/form-designer/setting-panel/property-editor/container-grid-col/grid-col-offset-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/container-grid-col/grid-col-pull-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/container-grid-col/grid-col-push-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/container-list-h5/list-h5-editor.vue +34 -46
- package/src/components/xform/form-designer/setting-panel/property-editor/container-table/table-dynamicField-editor.vue +344 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-tree/tree-customClass-editor.vue +31 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/copyButton-editor.vue +36 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/downloadButtonFlag-editor.vue +32 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/dropdownFlag-editor.vue +133 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/event-handler/eventMixin.js +2 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/event-handler/onClick-editor.vue +23 -8
- package/src/components/xform/form-designer/setting-panel/property-editor/field-area-select/areaDataType-editor.vue +25 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-area-select/areaMinLevel-editor.vue +50 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-area-select/areaName-editor.vue +20 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-autocomplete/autocomplete-vabSearchName-editor.vue +199 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/clickBindEvent-editor.vue +35 -20
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/icon-editor.vue +14 -15
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/search-dialog-event-editor.vue +64 -5
- package/src/components/xform/form-designer/setting-panel/property-editor/field-cascader/cascader-multiple-editor.vue +8 -3
- package/src/components/xform/form-designer/setting-panel/property-editor/field-cascader/checkStrictly-editor.vue +11 -13
- package/src/components/xform/form-designer/setting-panel/property-editor/field-cascader/showAllLevels-editor.vue +21 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-date/date-dateLimit-editor.vue +157 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-dropdown-menu/dropdown-item-editor.vue +21 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-dropdown-menu/dropdown-menu-editor.vue +59 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-gantt/gantt-editor.vue +36 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import-button-editor.vue +75 -21
- package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import2-button-editor.vue +96 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-print-button/print-button-editor.vue +44 -15
- package/src/components/xform/form-designer/setting-panel/property-editor/field-print-button/print-detail-button-editor.vue +115 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-rate/rate-defaultValue-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-script-input/script-input-editor.vue +55 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-static-text/preWrap-editor.vue +23 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-static-text/textContent-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-status/field-status-editor.vue +67 -41
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-button-editor.vue +56 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +71 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-vabSearch/vabSearchName-editor.vue +13 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-vabUpload/field-vabUpload-editor.vue +33 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-vabUpload2/field-vabUpload2-editor.vue +66 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-vue-page/vue-page-editor.vue +48 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/formScriptEnabled-editor.vue +107 -19
- package/src/components/xform/form-designer/setting-panel/property-editor/formatType-editor.vue +137 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/formula-editor.vue +721 -466
- package/src/components/xform/form-designer/setting-panel/property-editor/labelColor-editor.vue +20 -11
- package/src/components/xform/form-designer/setting-panel/property-editor/labelIconClass-editor.vue +17 -16
- package/src/components/xform/form-designer/setting-panel/property-editor/labelIconPosition-editor.vue +25 -25
- package/src/components/xform/form-designer/setting-panel/property-editor/labelTooltip-editor.vue +67 -13
- package/src/components/xform/form-designer/setting-panel/property-editor/limit-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/multiple-editor.vue +19 -14
- package/src/components/xform/form-designer/setting-panel/property-editor/multipleLimit-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/name-editor.vue +127 -50
- package/src/components/xform/form-designer/setting-panel/property-editor/oplog-editor.vue +31 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/precision-editor.vue +1 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/prefixIcon-editor.vue +14 -15
- package/src/components/xform/form-designer/setting-panel/property-editor/project-tag-editor.vue +349 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/required-editor.vue +10 -6
- package/src/components/xform/form-designer/setting-panel/property-editor/requiredHint-editor.vue +3 -3
- package/src/components/xform/form-designer/setting-panel/property-editor/showViewButton-editor.vue +29 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/suffixIcon-editor.vue +14 -15
- package/src/components/xform/form-designer/setting-panel/property-editor/tempStorage-editor.vue +42 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/textFlag-editor.vue +304 -19
- package/src/components/xform/form-designer/setting-panel/property-editor/utcTransformEnabled-editor.vue +19 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/validation-editor.vue +2 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/validationHint-editor.vue +2 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/wfFlag-editor.vue +372 -50
- package/src/components/xform/form-designer/setting-panel/property-editor/widgetShowRuleFlag-editor.vue +263 -0
- package/src/components/xform/form-designer/setting-panel/propertyRegister.js +369 -324
- package/src/components/xform/form-designer/setting-panel/widgetPropertyDialogMixin.js +186 -0
- package/src/components/xform/form-designer/toolbar-panel/index.vue +267 -103
- package/src/components/xform/form-designer/toolbar-panel/indexMixin.js +655 -24
- package/src/components/xform/form-designer/widget-panel/index.vue +389 -321
- package/src/components/xform/form-designer/widget-panel/indexMixin.js +334 -2
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +4531 -3141
- package/src/components/xform/form-render/compareDelList.vue +83 -0
- package/src/components/xform/form-render/compareView.vue +76 -0
- package/src/components/xform/form-render/container-item/containerItemMixin.js +404 -11
- package/src/components/xform/form-render/container-item/data-table-item.vue +221 -203
- package/src/components/xform/form-render/container-item/data-table-mixin.js +3716 -858
- package/src/components/xform/form-render/container-item/detail-h5-item.vue +173 -172
- package/src/components/xform/form-render/container-item/detail-item.vue +287 -158
- package/src/components/xform/form-render/container-item/detail-pane-item.vue +17 -3
- package/src/components/xform/form-render/container-item/dynamicFieldEngine.js +285 -0
- package/src/components/xform/form-render/container-item/dynamicFieldMixin.js +416 -0
- package/src/components/xform/form-render/container-item/grid-col-item.vue +10 -3
- package/src/components/xform/form-render/container-item/grid-item.vue +1 -1
- package/src/components/xform/form-render/container-item/list-h5-item.vue +1184 -419
- package/src/components/xform/form-render/container-item/sub-form-item.vue +10 -2
- package/src/components/xform/form-render/container-item/tab-item.vue +125 -88
- package/src/components/xform/form-render/container-item/table-cell-item.vue +38 -32
- package/src/components/xform/form-render/container-item/table-item.vue +7 -7
- package/src/components/xform/form-render/container-item/table2-cell-item.vue +53 -34
- package/src/components/xform/form-render/container-item/table2-item.vue +198 -99
- package/src/components/xform/form-render/container-item/tree-item.vue +32 -11
- package/src/components/xform/form-render/dynamicDialogRender.js +238 -3
- package/src/components/xform/form-render/dynamicDrawerRender.js +229 -0
- package/src/components/xform/form-render/formDynamicFieldMixin.js +131 -0
- package/src/components/xform/form-render/index.vue +86 -21
- package/src/components/xform/form-render/indexMixin.js +5070 -37
- package/src/components/xform/form-render/refMixin.js +34 -3
- package/src/components/xform/icon-picker/icons.json +284 -0
- package/src/components/xform/icon-picker/index.vue +145 -0
- package/src/components/xform/lang/en-US.js +457 -438
- package/src/components/xform/lang/en-US_extension.js +4 -0
- package/src/components/xform/lang/zh-CN.js +628 -593
- package/src/components/xform/mixins/defaultHandle.js +474 -2
- package/src/components/xform/mixins/scriptHttp.js +179 -3
- package/src/components/xform/utils/dynamicSchemaUtil.js +361 -0
- package/src/components/xform/utils/emitter.js +4 -4
- package/src/components/xform/utils/formHttp.js +162 -0
- package/src/components/xform/utils/format.js +205 -172
- package/src/components/xform/utils/formula-util.js +969 -0
- package/src/components/xform/utils/sfc-generator.js +2 -2
- package/src/components/xform/utils/smart-vue-i18n/index.js +2 -1
- package/src/components/xform/utils/tableCellValidateUtil.js +148 -0
- package/src/components/xform/utils/tableColumnHelper.js +155 -0
- package/src/components/xform/utils/util.js +1591 -1
- package/src/components/xform/utils/validators.js +185 -4
- package/src/components/xform/utils/vue2js-generator.js +2 -2
- package/src/components/xhsPrint/index.js +44 -1
- package/src/components/xhsPrint/mixins.js +269 -1
- package/src/directive/LimitNumber/index.js +144 -1
- package/src/directive/el-dialog-center/index.js +34 -1
- package/src/directive/el-drag-dialog/drag.js +86 -1
- package/src/directive/el-readonly/index.js +15 -1
- package/src/directive/permission/hasPermi.js +34 -1
- package/src/index.js +240 -63
- package/src/lang/index.js +56 -51
- package/src/lang/locale/en/login.js +27 -0
- package/src/lang/locale/zh/login.js +26 -0
- package/src/layout/components/AppMain.vue +148 -111
- package/src/layout/components/Sidebar/default.vue +1655 -1223
- package/src/layout/components/Sidebar/index.vue +6 -1
- package/src/layout/components/TagsView/index.vue +57 -15
- package/src/layout/components/createCompany/createCompanyDialog.vue +157 -0
- package/src/layout/components/extractedCode/createDialog.vue +92 -0
- package/src/layout/components/extractedCode/queryDialog.vue +103 -0
- package/src/layout/components/extractedCode/viewDialog.vue +207 -0
- package/src/layout/components/langTool.vue +128 -120
- package/src/layout/components/watermark/index.vue +83 -0
- package/src/layout/defaultLayout.vue +170 -150
- package/src/microRouter/index.js +521 -0
- package/src/mixins/selectDialog/index.js +266 -1
- package/src/mixins/tableTree/index.js +199 -4
- package/src/mixins/wf/index.js +33 -1
- package/src/permission.js +168 -1
- package/src/public-path.js +8 -0
- package/src/resources/js/base/common.js +109 -109
- package/src/router/index.js +4 -7
- package/src/router/modules/customer.js +21 -18
- package/src/router/modules/system.js +4 -0
- package/src/store/config/index.js +667 -600
- package/src/store/getters.js +4 -1
- package/src/store/modules/micro.js +56 -0
- package/src/store/modules/permission.js +495 -23
- package/src/store/modules/settings.js +26 -1
- package/src/store/modules/tagsView.js +206 -5
- package/src/store/modules/user.js +419 -29
- package/src/utils/aes.js +21 -1
- package/src/utils/auth.js +27 -1
- package/src/utils/componentDialog.js +322 -0
- package/src/utils/global.js +370 -8
- package/src/utils/index.js +579 -7
- package/src/utils/keepAlive.js +189 -1
- package/src/utils/menuAdapter.js +183 -0
- package/src/utils/pddLog.js +92 -0
- package/src/utils/pdfUtil.js +71 -0
- package/src/utils/repeatOpen.js +48 -0
- package/src/utils/request.js +417 -28
- package/src/utils/vab.js +1275 -27
- package/src/utils/validate.js +104 -1
- package/src/utils/wf.js +4 -4
- package/src/views/bd/setting/bd_attach_setting/edit.vue +5 -5
- package/src/views/bd/setting/bd_attach_setting/list.vue +28 -55
- package/src/views/bd/setting/bd_attach_setting/mixins/dialog.js +84 -1
- package/src/views/bd/setting/bd_attach_setting/mixins/edit.js +116 -5
- package/src/views/bd/setting/bd_attach_setting/mixins/list.js +239 -1
- package/src/views/bd/setting/bd_company_env/dialog.vue +174 -0
- package/src/views/bd/setting/bd_company_env/edit.vue +193 -0
- package/src/views/bd/setting/bd_company_env/list.vue +175 -0
- package/src/views/bd/setting/config_manage/list.vue +83 -0
- package/src/views/bd/setting/formVersion/button.vue +55 -0
- package/src/views/bd/setting/formVersion/compareBasicSection.vue +125 -0
- package/src/views/bd/setting/formVersion/compareCodeSection.vue +539 -0
- package/src/views/bd/setting/formVersion/compareContMixin.scss +65 -0
- package/src/views/bd/setting/formVersion/compareContent.vue +63 -0
- package/src/views/bd/setting/formVersion/compareDialog.vue +88 -0
- package/src/views/bd/setting/formVersion/compareMixin.js +93 -0
- package/src/views/bd/setting/formVersion/fieldCompare.vue +54 -0
- package/src/views/bd/setting/formVersion/formScriptCompareView.vue +94 -0
- package/src/views/bd/setting/formVersion/formTemplateCompareView.vue +74 -0
- package/src/views/bd/setting/formVersion/ftHistoryDialog.vue +483 -0
- package/src/views/bd/setting/formVersion/link.vue +58 -0
- package/src/views/bd/setting/formVersion/preformDialog.vue +87 -0
- package/src/views/bd/setting/formVersion/reverButton.vue +82 -0
- package/src/views/bd/setting/formVersion/tableDetailDiff.js +99 -0
- package/src/views/bd/setting/formVersion/tableModelCompareView.vue +514 -0
- package/src/views/bd/setting/formVersion/textDiff.js +102 -0
- package/src/views/bd/setting/form_import_log/edit.vue +130 -0
- package/src/views/bd/setting/form_import_log/list.vue +211 -0
- package/src/views/bd/setting/form_script/edit.vue +196 -74
- package/src/views/bd/setting/form_script/edit1.vue +410 -187
- package/src/views/bd/setting/form_script/form_list.vue +174 -85
- package/src/views/bd/setting/form_script/list.vue +95 -21
- package/src/views/bd/setting/form_script/list1.vue +205 -118
- package/src/views/bd/setting/form_script/mixins/dialog.js +130 -1
- package/src/views/bd/setting/form_script/mixins/edit.js +265 -7
- package/src/views/bd/setting/form_script/mixins/edit1.js +259 -9
- package/src/views/bd/setting/form_script/mixins/form_list.js +320 -4
- package/src/views/bd/setting/form_script/mixins/list.js +307 -4
- package/src/views/bd/setting/form_script/mixins/list1.js +512 -14
- package/src/views/bd/setting/form_script/mixins/list2.js +10 -1
- package/src/views/bd/setting/form_script/mixins/otherAuthDialog.js +194 -0
- package/src/views/bd/setting/form_script/mixins/preformDialog.js +34 -1
- package/src/views/bd/setting/form_script/otherAuthDialog.vue +83 -0
- package/src/views/bd/setting/form_template/batchWfObjConfigDialog.vue +3 -3
- package/src/views/bd/setting/form_template/edit.vue +355 -184
- package/src/views/bd/setting/form_template/formDesignerDialog.vue +171 -0
- package/src/views/bd/setting/form_template/list.vue +301 -214
- package/src/views/bd/setting/form_template/mixins/batchWfObjConfigDialog.js +279 -1
- package/src/views/bd/setting/form_template/mixins/dialog.js +103 -1
- package/src/views/bd/setting/form_template/mixins/edit.js +277 -9
- package/src/views/bd/setting/form_template/mixins/editWfObjConfigDialog.js +92 -1
- package/src/views/bd/setting/form_template/mixins/ftHistoryDialog.js +91 -1
- package/src/views/bd/setting/form_template/mixins/itemEdit.js +104 -1
- package/src/views/bd/setting/form_template/mixins/itemList.js +234 -1
- package/src/views/bd/setting/form_template/mixins/list.js +721 -22
- package/src/views/bd/setting/form_template/mixins/list2.js +411 -0
- package/src/views/bd/setting/form_template/mixins/otherAuthDialog.js +193 -0
- package/src/views/bd/setting/form_template/mixins/preformDialog.js +28 -3
- package/src/views/bd/setting/form_template/mixins/wf_list.js +421 -3
- package/src/views/bd/setting/form_template/otherAuthDialog.vue +83 -0
- package/src/views/bd/setting/form_template/wfObjConfigDialog.vue +253 -254
- package/src/views/bd/setting/form_template/wf_list.vue +161 -127
- package/src/views/bd/setting/logic_param/edit.vue +146 -0
- package/src/views/bd/setting/logic_param/edit1.vue +106 -0
- package/src/views/bd/setting/logic_param/edit2.vue +139 -0
- package/src/views/bd/setting/logic_param/list.vue +74 -0
- package/src/views/bd/setting/logic_param/list1.vue +12 -0
- package/src/views/bd/setting/logic_param/list2.vue +12 -0
- package/src/views/bd/setting/logic_param/mixins/edit.js +93 -0
- package/src/views/bd/setting/logic_param/mixins/list.js +376 -0
- package/src/views/bd/setting/menu_kind/list.vue +172 -83
- package/src/views/bd/setting/menu_kind/mixins/authDialog.js +300 -7
- package/src/views/bd/setting/menu_kind/mixins/dialog.js +139 -1
- package/src/views/bd/setting/menu_kind/mixins/list.js +201 -1
- package/src/views/bd/setting/push_data/edit.vue +139 -0
- package/src/views/bd/setting/push_data/list.vue +283 -0
- package/src/views/bd/setting/push_data_h/edit.vue +153 -0
- package/src/views/bd/setting/push_data_h/list.vue +293 -0
- package/src/views/bd/setting/request_async_setting/edit.vue +320 -0
- package/src/views/bd/setting/request_async_setting/list.vue +372 -0
- package/src/views/bd/setting/request_setting/edit.vue +300 -0
- package/src/views/bd/setting/request_setting/list.vue +301 -0
- package/src/views/bd/setting/table_model/edit.vue +1079 -426
- package/src/views/bd/setting/table_model/list.vue +218 -128
- package/src/views/bd/setting/table_model/mixins/dialog.js +71 -1
- package/src/views/bd/setting/table_model/mixins/edit.js +1309 -13
- package/src/views/bd/setting/table_model/mixins/list.js +463 -2
- package/src/views/bd/setting/table_model/mixins/otherAuthDialog.js +201 -0
- package/src/views/bd/setting/table_model/mixins/zdDialog.js +114 -3
- package/src/views/bd/setting/table_model/otherAuthDialog.vue +83 -0
- package/src/views/bd/setting/utils/index.js +75 -1
- package/src/views/support/form-dialog-demo/demoPickerDialog.vue +72 -0
- package/src/views/support/form-dialog-demo/index.vue +537 -0
- package/src/views/user/access_log/list.vue +418 -349
- package/src/views/user/area/dialog.vue +223 -117
- package/src/views/user/area/list.vue +318 -0
- package/src/views/user/commMenu/index.vue +2 -2
- package/src/views/user/common_attribute/list.vue +4 -1
- package/src/views/user/company_info/dialog.vue +195 -163
- package/src/views/user/extend_datasource/dialog.vue +3 -0
- package/src/views/user/extend_datasource/edit.vue +2 -1
- package/src/views/user/extend_datasource/list.vue +3 -0
- package/src/views/user/fieldTranslation/editDialog.vue +8 -8
- package/src/views/user/fieldTranslation/list.vue +33 -33
- package/src/views/user/form/vform/designer.vue +792 -749
- package/src/views/user/form/vform/formFieldMapping.js +2 -3
- package/src/views/user/form/vform/out_render.vue +1 -1
- package/src/views/user/form/vform/render.vue +65 -52
- package/src/views/user/form/view/edit.vue +56 -37
- package/src/views/user/form/view/list.vue +474 -54
- package/src/views/user/home/default.vue +1117 -979
- package/src/views/user/home/default2.vue +1158 -0
- package/src/views/user/home/dev.vue +29 -0
- package/src/views/user/home/index.vue +18 -7
- package/src/views/user/login/default.vue +165 -44
- package/src/views/user/login/index.vue +4 -6
- package/src/views/user/login/indexMixin.js +661 -425
- package/src/views/user/menu/list.vue +50 -1
- package/src/views/user/menuFallback/index.vue +123 -0
- package/src/views/user/notify_message/dialog.vue +44 -22
- package/src/views/user/notify_template/edit.vue +188 -187
- package/src/views/user/notify_template/edit2.vue +176 -0
- package/src/views/user/notify_template/list.vue +4 -1
- package/src/views/user/notify_template/list2.vue +190 -0
- package/src/views/user/outLink/form_view.vue +211 -211
- package/src/views/user/outLink/index.vue +64 -15
- package/src/views/user/position/list.vue +4 -4
- package/src/views/user/project_tag/dialog.vue +9 -4
- package/src/views/user/project_tag/edit.vue +2 -2
- package/src/views/user/project_tag/list.vue +9 -4
- package/src/views/user/request_setting/edit.vue +258 -0
- package/src/views/user/request_setting/list.vue +248 -0
- package/src/views/user/role/authConfig.vue +89 -0
- package/src/views/user/role/dialog.vue +70 -48
- package/src/views/user/role/edit.vue +609 -429
- package/src/views/user/role/list.vue +4 -4
- package/src/views/user/sale_org/dialog.vue +1 -1
- package/src/views/user/sale_org/list.vue +4 -1
- package/src/views/user/system_notice/infoDialog.vue +61 -1
- package/src/views/user/user/dialog.vue +46 -23
- package/src/views/user/user/edit.vue +1391 -1021
- package/src/views/user/user/form_dialog.vue +158 -0
- package/src/views/user/user/form_info.vue +210 -0
- package/src/views/user/user/info.vue +253 -140
- package/src/views/user/user/list.vue +652 -563
- package/src/views/user/user/modifyPasswordDialog.vue +64 -53
- package/src/views/user/wf/wfReport/index.vue +625 -0
- package/src/views/user/wf/wf_auto_submit_data/list.vue +2 -0
- package/src/views/user/wf/wf_manage/list.vue +640 -256
- package/src/views/user/wf/wf_manage/list2.vue +854 -0
- package/src/views/user/wf/wf_manage/wfContentDialog.vue +25 -22
- package/src/views/user/wf/wf_obj_config/importItemDialog.vue +109 -0
- package/src/views/user/wf/wf_obj_config/itemEdit.vue +25 -1
- package/src/views/user/wf/wf_obj_config/list.vue +114 -9
- package/src/views/user/wf/wf_transfer_setting/edit.vue +282 -0
- package/src/views/user/wf/wf_transfer_setting/list.vue +319 -0
- package/src/views/user/workbench_menu/list.vue +555 -0
- package/src/components/xform/form-render/container-item/list-h5-item2.vue +0 -1347
|
@@ -0,0 +1,986 @@
|
|
|
1
|
+
# xform 表单对比(变更前/变更后)功能落地方案
|
|
2
|
+
|
|
3
|
+
> **实现状态:已落地。** 涉及文件:
|
|
4
|
+
>
|
|
5
|
+
> - 新增 `form-render/compareView.vue`(对比提示组件;感叹号固定在字段前、flex 布局不失焦不顶起输入框,文案 `$t1` 国际化)
|
|
6
|
+
> - 新增 `form-render/compareDelList.vue`(查看删除数据弹窗;vxe-grid、列取当前数据表格字段/标题/宽度、固定高度铺满、系统弹框样式、`$t1` 国际化)
|
|
7
|
+
> - `form-render/indexMixin.js`:状态 `isCompare/oldFormData/compareRowKey/compareExcludeTypes/compareExcludeFields`;provide 下发(含 `isCompareExcludeField`);公开方法 `enableCompare/disableCompare/setOldSubData/getDelData/openCompareDelList`;取数 `loadOldData`(主表 getOne + 表头附件各自 getList + data-table 子表 getList,均带 `attachmentType/thirdtabm`);一行接入 `initChangeFromSource`(模式 A)/`enableCompareBySource`(模式 B);订单 → 变更单整套编排工厂 `setupChangeCompare(cfg)`(返回按钮联动/加载/清洗一体的控制器,业务只给 cfg);清洗 `sanitizeChangeData`(系统字段清理、树表 id/parent_id 重生成 `regenerateTreeIds`、附件白名单 `attachmentKeepFields`、`defaultFields/subDefaultFields` 不覆盖取默认、`subSourceFields` 原单字段/表头回填);行级样式 `getCompareRowClass`(变更行/新增行)、字段级排除 `isCompareExcludeField`(`create_by/create_date/modify_by/modify_date` 等系统字段默认排除)
|
|
8
|
+
> - `form-render/index.vue`:注册并挂载 compareDelList
|
|
9
|
+
> - `field-widget/fieldMixin.js`:`compareEquals`(原始值判定)、`resolveDisplayValue`(值 →label)、`resolveCompareOldDisplay`(关联类从原单行取伴随 label);各映射组件 override(select/radio/checkbox/status/switch/cascader/vabSearch/autocomplete)
|
|
10
|
+
> - `field-widget/form-item-wrapper.vue`:inject 对比接口、`isCompareOn/compareOldRow/compareIsDiff/compareOldDisplay/compareRowIsNew`(新增行不逐格显示感叹号)、按类型+字段名排除
|
|
11
|
+
> - `container-item/data-table-mixin.js` + `data-table-item.vue`:`rowClassName` 注入变更行/新增行整行高亮;`getSubTableCurrentRows` 读实时表格数据
|
|
12
|
+
> - `mixins/defaultHandle.js`:`getReqFormData` 提交前递归剥除对比快照字段 `hData`
|
|
13
|
+
> - `widget-panel/widgetsConfig.js` + `widget-panel/index.vue`:业务组件标签页下新增「对比组件」分组(对比 / 关闭对比 / 查看删除明细 3 个按钮,默认展开)
|
|
14
|
+
|
|
15
|
+
> 参考实现:`2023/yx2-vue/sf-cloud-web-vue-tw@std/src/views/yx/certificate/agreementChange/edit.vue`
|
|
16
|
+
> 目标组件:`src/components/xform/`(form-render + field-widget)
|
|
17
|
+
|
|
18
|
+
## 〇、接入指南(配置流程)
|
|
19
|
+
|
|
20
|
+
> 面向业务配置人员:如何给一张「变更单」接上对比。form-render 已内置能力,业务侧只需配置按钮 onClick 脚本、表单 onMounted 脚本,以及列表页一段 autoAdd。
|
|
21
|
+
|
|
22
|
+
### 前置:后端接口
|
|
23
|
+
|
|
24
|
+
推荐用内置的**通用多包加载 `loadOldData`**,它直接复用原单模板的标准读脚本(主表 `getOne`、data-table 子表 `getList`),**无需为对比新增后端接口** —— 只要原单本身的表单读脚本可按 id 查询即可。
|
|
25
|
+
|
|
26
|
+
仅当需要自定义取数时,才手动取数 + `enableCompare`。**取原单数据统一走 `loadOldData`(内部用 `formHttp` 按模板脚本发包),不要用 `formRef.$http` 直接打 url。** 需要额外定制请求时用 `formRef.formHttp({ scriptCode, data, success })`。
|
|
27
|
+
|
|
28
|
+
### 相关入口(本项目现有机制)
|
|
29
|
+
|
|
30
|
+
- 列表打开详情:`openEditDialog(row, param, option)` —— `row=null` 走新增(无 dataId);`param` 为业务参数,详情用 `getFormParam()` 读取。列表 xform 宿主:`src/views/user/form/view/list.vue`。
|
|
31
|
+
- 详情表单读打开参数:`this.getFormParam()`(`defaultHandle.js`,返回 `formRef.param`)。
|
|
32
|
+
- 按钮/表单脚本上下文:`this` 为组件,`this.getFormRef()` 拿 form-render 实例;注入参数含 `dataId`。
|
|
33
|
+
|
|
34
|
+
### 数据流(三跳)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
原单详情「变更」按钮
|
|
38
|
+
└─ router.push 到「变更单列表路由」,query 带 sourceId + autoAdd
|
|
39
|
+
↓
|
|
40
|
+
变更单列表页 (list.vue 宿主)
|
|
41
|
+
└─ mounted 读 $route.query,autoAdd 时调
|
|
42
|
+
openEditDialog(null, { sourceId }, { formCode: addFormCode })
|
|
43
|
+
↓
|
|
44
|
+
变更单详情表单 onMounted
|
|
45
|
+
└─ 无 dataId:sourceId = getFormParam().sourceId
|
|
46
|
+
→ getOld(sourceId) → setFormData + enableCompare (模式A 自动对比)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 第 1 跳:原单「变更」按钮 onClick
|
|
50
|
+
|
|
51
|
+
从「对比组件」拖入**变更**按钮(`compare-change-button`),预置 onClick 直接调内置方法(`dataId` 为注入参数):
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
this.getFormRef().goChangeBill(dataId, "变更单formCode"); // 把 '变更单formCode' 改成实际编号
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> **`goChangeBill(sourceId, formCode, options)`(form-render 内置)**:跳到变更单列表并携带 sourceId 打开新增。
|
|
58
|
+
>
|
|
59
|
+
> - 目标列表路径:默认复用当前路由、把**最后一段替换为 `formCode`**(同基兄弟列表约定);不符合时用 `options.listPath` 指定完整路径。
|
|
60
|
+
> - 打开参数走 `query.param`(JSON):`{ sourceId, autoAdd:1 }`(可用 `options.param` 追加)。
|
|
61
|
+
> - 跳转方式:先 `store.dispatch('tagsView/delCachedView', view)` 清缓存视图,再 `router.replace(view)`,确保列表按新参数重载。
|
|
62
|
+
|
|
63
|
+
### 第 2 跳:变更单列表页自动打开新增详情
|
|
64
|
+
|
|
65
|
+
变更单列表页(xform 宿主 `list.vue` 或其业务包装)`mounted`/`activated` 里加(`param` 由 `query.param` 解析到 `this.param`):
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
let p = this.param || {};
|
|
69
|
+
if (p.autoAdd) {
|
|
70
|
+
// row=null → 新增;param 带 sourceId,详情用 getFormParam() 取
|
|
71
|
+
this.openEditDialog(
|
|
72
|
+
null,
|
|
73
|
+
{ sourceId: p.sourceId },
|
|
74
|
+
{ formCode: this.addFormCode }
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> 唯一需在列表页新增的一小段(读 param → 调现有 `openEditDialog`)。
|
|
80
|
+
|
|
81
|
+
### 第 3 跳:变更单详情表单 onMounted(模式 A 自动对比)
|
|
82
|
+
|
|
83
|
+
**推荐:一行接入 `initChangeFromSource`** —— 内部自动按原单模板多包拉取(主表 + 所有 data-table 子表)→ 清洗 → 填充新单 → 开启对比。无需逐个子表写发包。
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
if (!dataId) {
|
|
87
|
+
// dataId 注入参数,无=新建
|
|
88
|
+
let f = this.getFormRef();
|
|
89
|
+
let sourceId = f.getFormParam() && f.getFormParam().sourceId;
|
|
90
|
+
f.initChangeFromSource(sourceId, {
|
|
91
|
+
// 单层扁平配置,取数/对比/清洗参数同层
|
|
92
|
+
sourceFormCode: "原单formCode", // 用原单模板拉原单数据(原单≠变更单模板时)
|
|
93
|
+
compareRowKey: "uuid", // 对比参数
|
|
94
|
+
excludeFields: ["f_type"], // 对比参数:主表不对比字段
|
|
95
|
+
defaultFields: ["billType"], // 清洗参数:主表字段不吃原单值、保留变更单默认值
|
|
96
|
+
subDefaultFields: { 明细A: ["status"] }, // 清洗参数:明细列不吃原单值
|
|
97
|
+
subSourceFields: { 明细A: "f_source_id" }, // 清洗参数:原明细 id 回填
|
|
98
|
+
treeSubTables: ["分类明细"], // 清洗参数
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> `initChangeFromSource` = `loadOldData`(自动多包) + `sanitizeChangeData`(清洗) + `setFormData`(新单) + `enableCompare`(原始旧数据为基准)。
|
|
104
|
+
>
|
|
105
|
+
> **模板解析**:传 `sourceFormCode` 时,内部按 `/formTemplate/getByFormCode` 拉**原单模板**,用其 widgetList 枚举原单子表、entity、formCode 来发包(原单与变更单模板不同时用这个);不传则复用当前变更单模板(结构一致时)。也可用 `reportTemplate/formCode/formVersion/entity` 精确覆盖。
|
|
106
|
+
|
|
107
|
+
**手动版(需自定义拆解逻辑时)**:仍用 `loadOldData` 取数(内部 formHttp),只是手动清洗/填充/对比。`setFormData` 用清洗后数据,`enableCompare` 用原始旧数据;`uuid` 不被清理,新旧行仍匹配。
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
f.loadOldData(sourceId, { sourceFormCode: "原单formCode" }).then((oldData) => {
|
|
111
|
+
let newData = f.sanitizeChangeData(oldData, { defaultFields: ["billType"] });
|
|
112
|
+
f.setFormData(newData);
|
|
113
|
+
f.enableCompare(oldData, { compareRowKey: "uuid" });
|
|
114
|
+
// 子表多包补充:f.setOldSubData('子表字段名', 子表旧行);
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`sanitizeChangeData(oldData, options)` 选项:
|
|
119
|
+
|
|
120
|
+
- `masterClearFields`:覆盖主表默认清理字段(默认含 id/createBy/createDate/modifyBy/modifyDate/\_createBy/\_modifyBy 及其 snake_case 形式);
|
|
121
|
+
- `subExtraClearFields`:仅子表额外清理的外键字段,默认 `head_table_id/headTableId/alias_id/object_foreign_id`;
|
|
122
|
+
- `defaultFields`(主表)/ `subDefaultFields`(明细 `{keyName:[列prop]}`):这些字段**不吃原单值**,保留变更单自身值/默认值;
|
|
123
|
+
- `subSourceFields`:`{ 明细keyName: 配置 }`,原明细行/原单表头字段回填到明细(字符串/`{from,to}`/`{fromHeader,to}`/数组/`(row,header)=>{}`;早于清 id/树表重生成执行);
|
|
124
|
+
- `attachmentKeepFields`:附件文件对象保留字段白名单(默认 `name/thumbnail/extension/large/fileSize/domain/source/medium/url`);`cleanAttachment:false` 关闭精简;
|
|
125
|
+
- `treeSubTables`:**树结构子表**配置,其 `id/parent_id` 需重新生成并把 parent_id 按旧 → 新映射重指向以保留层级。格式 `[{ name, idField='id', parentField='parent_id' }]`,也可简写字符串数组 `['子表名']`。外部父级的 parent_id 置空作根。**新生成 id 形如 `_row{随机数}`,本表内保证唯一。**
|
|
126
|
+
|
|
127
|
+
示例(含树表):
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
let newData = f.sanitizeChangeData(oldData, {
|
|
131
|
+
defaultFields: ["billType"],
|
|
132
|
+
subDefaultFields: { 明细A: ["status"] },
|
|
133
|
+
subSourceFields: {
|
|
134
|
+
明细A: (row, header) => {
|
|
135
|
+
row.f_source_id = row.id;
|
|
136
|
+
row.f_head_no = header.f_no;
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
treeSubTables: [
|
|
140
|
+
{ name: "分类明细", idField: "id", parentField: "parent_id" },
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 模式 B:已保存变更单「对比」按钮 onClick
|
|
146
|
+
|
|
147
|
+
**推荐:一行接入 `enableCompareBySource`** —— 自动按模板多包拉取原单并开启对比:
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
let f = this.getFormRef();
|
|
151
|
+
let sourceId = f.getFormData().sourceId; // 变更单里存的原单引用
|
|
152
|
+
f.enableCompareBySource(sourceId, { compareRowKey: "uuid" });
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
> 手动版:`f.loadOldData(sourceId).then(old => f.enableCompare(old, { compareRowKey:'uuid' }))`。
|
|
156
|
+
|
|
157
|
+
### 模式 B 变体:搜索框选原单 → 点「对比」
|
|
158
|
+
|
|
159
|
+
支持,**无需额外开发**。本质仍是模式 B,只是 `sourceId` 的来源从「变更单里存的原单引用」换成「搜索框(关联组件)当前选中的值」。
|
|
160
|
+
|
|
161
|
+
关联组件(vabSearch / autocomplete 等)选中后,**原单 id 就存在它绑定的字段**(`formModel[该字段keyName]`,label 存在伴随字段)。只要「搜索框绑定字段名」= `cfg.sourceIdField`(如都用 `f_source_id`),用 `setupChangeCompare(cfg)` 工厂即可,无需手写逻辑(完整接入见下方「完整接入示例」):
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
// 搜索框 onChange:选中即加载原单(compare:false,只填充)
|
|
165
|
+
this.getFormRef().loadSourceOnPick(this.formModel.f_source_id);
|
|
166
|
+
// 搜索框 onClear:清空即关闭对比(若还要清掉已填数据,改用 clearCompareSource() + onClearSource 钩子)
|
|
167
|
+
if (!this.formModel.f_source_id) this.getFormRef().disableCompare();
|
|
168
|
+
// 「对比」按钮:点击才开启对比(重拉基准)
|
|
169
|
+
this.getFormRef().enableCompareBySource();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
注意事项:
|
|
173
|
+
|
|
174
|
+
1. **切换原单**:重选一张再点「对比」,`enableCompareBySource` 会重新拉数并覆盖 `oldFormData`、重做行快照——控制器内部已处理,无需手动先 `disableCompare`。
|
|
175
|
+
2. **模板不同必须传 `cfg.sourceFormCode`**:否则会用变更单模板去枚举子表发包,取不到原单数据。
|
|
176
|
+
3. **搜索框字段本身要排除对比**:框架已自动把 `cfg.sourceIdField` 纳入 `excludeFields`,无需手写;否则它自己会被判为「变更」。
|
|
177
|
+
4. 与模式 A 不冲突:新增走 `loadSourceFromParam()`(路由参数)、手选走 `loadSourceOnPick()`,两条路落到同一个 `cfg.sourceIdField`。
|
|
178
|
+
|
|
179
|
+
### 其它按钮
|
|
180
|
+
|
|
181
|
+
- 关闭对比:`this.getFormRef().disableCompare();`
|
|
182
|
+
- 查看删除数据:`this.getFormRef().openCompareDelList('子表字段名');`(要中文列头传第二参 `[{field,title},...]`)
|
|
183
|
+
|
|
184
|
+
### 全局配置项(可选)
|
|
185
|
+
|
|
186
|
+
- `formConfig.compareRowKey`:子表行匹配键,默认 `uuid`;也可 `enableCompare(old,{compareRowKey})` 覆盖。值支持 `'字段'`(两边同名)/ `{from,to}`(跨字段名:原单[from]===变更[to])/ 数组(联合键);按明细不同用 `subRowKeys:{明细keyName:键}`。
|
|
187
|
+
- `formConfig.compareExcludeTypes` / `enableCompare(old,{excludeTypes})`:不参与对比的字段类型(附件/上传类已默认排除)。
|
|
188
|
+
- **对比字段名单(主表 / 明细分开配置)**:
|
|
189
|
+
|
|
190
|
+
| | 黑名单(不对比) | 白名单(只对比) |
|
|
191
|
+
| ---- | ------------------------------------------------- | --------------------------------------------------- |
|
|
192
|
+
| 主表 | `excludeFields: ['f_type', ...]` | `includeFields: ['f_qty', ...]` |
|
|
193
|
+
| 明细 | `subExcludeFields: { 明细keyName: ['f_x', ...] }` | `subIncludeFields: { 明细keyName: ['f_qty', ...] }` |
|
|
194
|
+
|
|
195
|
+
- 都通过 `initChangeFromSource / enableCompareBySource / enableCompare` 的 options 传;兜底位 `formConfig.compareExcludeFields / compareSubExcludeFields / compareIncludeFields / compareSubIncludeFields`。
|
|
196
|
+
- **主表名单与明细名单互不干涉**:主表字段只看 `excludeFields/includeFields`,明细字段只看 `subExcludeFields[表]/subIncludeFields[表]`。主表名单**不会下渗到明细**(两者字段空间不同,同名字段语义也可能不同);明细字段要排除,就必须写进该表的 `subExcludeFields`。
|
|
197
|
+
- **白名单优先于黑名单**:某张表一旦配了白名单,该表的黑名单整体失效,别同时配。这个优先关系按表独立生效——主表用白名单、明细用黑名单是允许的。
|
|
198
|
+
- 系统字段(`id/create_by/create_date/modify_by/modify_date/head_table_id/alias_id/object_foreign_id` 等)、附件字段(`attachments_` 前缀)、`subSourceFields` 回填字段,**已默认排除**,不用写。
|
|
199
|
+
- 跨表场景(compareMapping)下白名单**自动推导**:主表白名单来自 `mapping.master[].to`,每张明细的白名单来自该表 `fields[].to` —— 主表与各明细互不串味,无需手写。
|
|
200
|
+
> **配置是单层扁平的**:`initChangeFromSource` 的 options 同时供取数、对比、清洗三类参数,**平铺在同一层**,无 `sanitize` 子对象。三组键互不相交(对比 `excludeFields/includeFields/compareRowKey/compareMapping…`、清洗 `defaultFields/subDefaultFields/subSourceFields/treeSubTables…`、取数 `sourceFormCode/subParams…`),各方法各取所需。直接单独调用 `sanitizeChangeData(oldData, options)` 时,它只挑自己认得的清洗键,其余忽略。
|
|
201
|
+
|
|
202
|
+
- `defaultFields`(主表)/ `subDefaultFields`(明细表 `{keyName:[列prop]}`):这些字段**不吃原单值**,保留变更单自身值/默认值。
|
|
203
|
+
- `subExtraClearFields`:子表额外清空的外键字段,默认 `head_table_id/headTableId/alias_id/object_foreign_id`。
|
|
204
|
+
- `attachmentKeepFields`:附件文件对象保留字段白名单,默认 `name/thumbnail/extension/large/fileSize/domain/source/medium/url`(表头附件、data-table 单元格附件都按此精简;`cleanAttachment:false` 可整体关闭)。
|
|
205
|
+
- `subSourceFields`:`{ 明细keyName: 配置 }`,把原明细行/原单表头字段回填到明细业务字段。配置支持:
|
|
206
|
+
|
|
207
|
+
- `'目标字段'` → 原明细 `id` → 目标字段
|
|
208
|
+
- `{ from:'明细字段', to:'目标字段' }`(from 默认 `id`)
|
|
209
|
+
- `{ fromHeader:'表头字段', to:'目标字段' }` → 原单表头字段回填
|
|
210
|
+
- `[ {..}, {..} ]` → 多字段
|
|
211
|
+
- `(row, header) => {...}` → 自定义函数(row 原明细行、header 原单表头;均为原始值,早于清 id/树表重生成执行)
|
|
212
|
+
|
|
213
|
+
> **回填字段自动排除对比**:回填出的字段(如 `f_source_item_id`)只存在于新单行,原单行没有 → 逐字段比较时是「空 → 有值」,会把整表行判成**变更行(黄)**。`sanitizeChangeData` 已自动把回填目标字段登记进 `compareAutoExcludeFields`(函数式配置也支持:通过比对函数执行前后新增的 key 捕获),无需手工配置。
|
|
214
|
+
> **但模式 A(打开已保存的变更单点「对比」)不会走 sanitize**,此时请把这些字段一并写进 `excludeFields`,例如 `excludeFields: ['f_type', 'f_source_id', 'f_source_item_id']`。
|
|
215
|
+
|
|
216
|
+
- `treeSubTables`:树表配置 `[{ name, idField, parentField }]`,id/parent_id 会重新生成并保留层级。
|
|
217
|
+
- **保存**:提交时 `getReqFormData` 自动剥除对比快照字段 `hData`,无需业务处理。
|
|
218
|
+
- **行级高亮**:变更行橙色、新增行绿色(各带左侧色条),新增行不逐格显示感叹号。
|
|
219
|
+
> **行变黄只校验「数据表格列」对应的字段**(取自设计器 `tableColumns` 的叶子列 `prop`,含运行时动态列,排除附件列)。后台多返回的非列字段、`subSourceFields` 回填字段等**天然不参与**行级判定——这是正向定义,比黑名单更可靠。白/黑名单(`subExcludeFields/subIncludeFields`)在列集之上做进一步收窄。取不到列(实例未就绪)时退回「两行键并集」旧口径。
|
|
220
|
+
> 附件恒不对比:新单附件已按 `attachmentKeepFields` 白名单精简(9 个字段),原单快照里是完整对象(含 id/createDate/sn…),直接比必然不等。故按 `attachments_` 前缀(设计器 `keyNamePrefixMap` 固定前缀)在行级判定里整体跳过。
|
|
221
|
+
|
|
222
|
+
### 全字段参考配置(options 全集)
|
|
223
|
+
|
|
224
|
+
`initChangeFromSource(sourceId, options)` 的 options 是**单层扁平**对象。`enableCompareBySource` 接收其中的**取数 + 对比**字段(不含清洗,模式 B 不填充新单);`sanitizeChangeData(oldData, options)` 只取其中的**清洗**字段。
|
|
225
|
+
|
|
226
|
+
#### A. 常用字段(按业务需要填)
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
formRef.initChangeFromSource(sourceId, {
|
|
230
|
+
// ── 取数 ──
|
|
231
|
+
sourceFormCode: "订单formCode", // 原单≠变更单模板时必填(枚举原单子表/entity/formCode);结构一致可省略
|
|
232
|
+
sourceKeyField: "f_no", // 原单存的是编码而非 id 时,指定主表用哪个字段查
|
|
233
|
+
subParams: {
|
|
234
|
+
// 明细需要额外查询参数时;值可为对象或 (ctx)=>对象,ctx={masterData,masterId}
|
|
235
|
+
订单明细: { f_status: 1 },
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
// ── 对比 ──
|
|
239
|
+
compareRowKey: "f_uuid", // 子表行匹配主键(务必是明细里稳定唯一的业务键)
|
|
240
|
+
excludeFields: ["f_type"], // 主表不对比字段
|
|
241
|
+
subExcludeFields: {
|
|
242
|
+
// 明细不对比字段:{ 明细keyName: [字段名] }
|
|
243
|
+
test_source_bill_item: ["f_source_item_id"],
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
// ── 清洗 ──
|
|
247
|
+
defaultFields: ["f_no"], // 主表:不吃原单值、保留变更单自身默认值的字段
|
|
248
|
+
subDefaultFields: {
|
|
249
|
+
// 明细:{ 明细keyName: ['列prop'] },取该列设计器默认值
|
|
250
|
+
test_source_bill_item: ["f_state"],
|
|
251
|
+
},
|
|
252
|
+
subSourceFields: {
|
|
253
|
+
// 原明细行/原单表头字段回填到明细
|
|
254
|
+
test_source_bill_item: (row, header) => {
|
|
255
|
+
row.f_source_item_id = row.id;
|
|
256
|
+
},
|
|
257
|
+
// 也支持:'目标字段' | { from, to } | { fromHeader, to } | [ ...多个 ]
|
|
258
|
+
},
|
|
259
|
+
treeSubTables: ["分类明细"], // 有树表时才填:重生成 id/parent_id 并保层级
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
跨表场景(B)另加 `compareMapping`(白名单、行主键由它自动推导,此时 `subRowKeys/includeFields` 不用手写):
|
|
264
|
+
|
|
265
|
+
```js
|
|
266
|
+
compareMapping: {
|
|
267
|
+
master: [{ from: 'o_cust', to: 'f_cust' }],
|
|
268
|
+
subs: [{
|
|
269
|
+
from: 'order_item', to: 'test_source_bill_item',
|
|
270
|
+
rowKey: { from: 'o_line_no', to: 'f_line_no' },
|
|
271
|
+
fields: [{ from: 'o_qty', to: 'f_qty' }],
|
|
272
|
+
}],
|
|
273
|
+
},
|
|
274
|
+
transformOldData: null, // 可选:映射之外的值转换兜底钩子 (oldData, srcData) => oldData
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### B. 其余选项(均有默认值,一般省略)
|
|
278
|
+
|
|
279
|
+
| 字段 | 默认 | 说明 |
|
|
280
|
+
| -------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
281
|
+
| `compare` | `true` | `false`=只填充新单、不开启对比(可稍后手动 `enableCompare`) |
|
|
282
|
+
| `includeFields` | `null` | 主表白名单:设置后主表只比这些字段、主表黑名单失效 |
|
|
283
|
+
| `subIncludeFields` | `{}` | 明细白名单:`{ 明细keyName: [字段] }`,设置后该表只比这些、该表黑名单失效 |
|
|
284
|
+
| `subRowKeys` | `{}` | 按明细覆盖行匹配键 `{ 明细keyName: 键 }`,键支持 `'字段'` / `{from,to}`(跨字段名:原单[from]===变更[to])/ 数组(联合);跨表由 `compareMapping` 自动推导。`setupChangeCompare` 里可直接用 `compareRowKey` 传按明细 map,不必用这个底层名 |
|
|
285
|
+
| `excludeTypes` | 附件/上传类 | 覆盖不参与对比的字段「类型」 |
|
|
286
|
+
| `commonParams` | `{}` | 追加到「所有」明细/附件包的公共查询参数 |
|
|
287
|
+
| `sourceIdField` | `'id'` | 从主表响应取「真实主键」的字段名(用于发明细/附件包) |
|
|
288
|
+
| `sourceIdIsKey` | `false` | `true`=传的就是 id → 主表/明细并行查(快路径) |
|
|
289
|
+
| `isLoading` | `true` | 取数是否显示 loading |
|
|
290
|
+
| `masterScriptCode` | `'getOne'` | 主表读取脚本 |
|
|
291
|
+
| `reportTemplate`/`formCode`/`formVersion`/`entity` | 取自模板 | 覆盖取数用的模板/编号/版本/主表 entity |
|
|
292
|
+
| `masterClearFields` | 系统字段集 | 覆盖主表默认清理字段(id/createBy/createDate/modifyBy/modifyDate/…) |
|
|
293
|
+
| `subExtraClearFields` | 外键集 | 覆盖子表额外清空字段(head_table_id/alias_id/object_foreign_id/…) |
|
|
294
|
+
| `attachmentKeepFields` | 9 字段白名单 | 覆盖附件保留字段(name/thumbnail/extension/large/fileSize/domain/source/medium/url) |
|
|
295
|
+
| `cleanAttachment` | `true` | `false`=不精简附件字段 |
|
|
296
|
+
|
|
297
|
+
### 完整接入示例(GlobalConfig)
|
|
298
|
+
|
|
299
|
+
把对比相关逻辑收敛到 `getGlobalConfig()` 返回对象里,详情页脚本按需调用。
|
|
300
|
+
|
|
301
|
+
#### 步骤 1:从「对比组件」拖入 3 个按钮
|
|
302
|
+
|
|
303
|
+
设计器 → **业务组件**标签页 → **对比组件**分组(默认展开),拖入按钮。分组含 4 个按钮,已预置好 `label`、默认显隐、`onClick` 脚本,拖进去基本即用。
|
|
304
|
+
|
|
305
|
+
| 按钮 | 面板 type | 放在 | 唯一名称(示例) | 默认显隐 | 预置 onClick |
|
|
306
|
+
| ------------ | ----------------------- | -------- | -------------- | -------- | ---------------------------------------------------------- |
|
|
307
|
+
| 变更 | `compare-change-button` | **原单** | — | 显示 | `this.getFormRef().goChangeBill(dataId, '变更单formCode')` |
|
|
308
|
+
| 对比 | `compare-button` | 变更单 | `button52848` | 显示 | `this.getFormRef().enableCompareBySource()` |
|
|
309
|
+
| 关闭对比 | `compare-close-button` | 变更单 | `button56167` | **隐藏** | `this.getFormRef().disableCompare()` |
|
|
310
|
+
| 查看删除明细 | `compare-del-button` | 变更单 | `button67652` | **隐藏** | `this.getFormRef().openCompareDelList()` |
|
|
311
|
+
|
|
312
|
+
拖入后仅需:① **变更**按钮把 `'变更单formCode'` 改成实际变更单编号(放在原单表单);② 变更单上 3 个按钮设「唯一名称」,与 cfg 的 `compareBtnName/closeBtnName/delBtnNames` 对应;③ 明细表名收在 `cfg.detailName`,onClick 全部无参。
|
|
313
|
+
|
|
314
|
+
> 「关闭对比」「查看删除明细」已预置默认隐藏;开启对比后由框架 `setupChangeCompare` 统一放出、隐藏「对比」。
|
|
315
|
+
|
|
316
|
+
#### 步骤 2:`getGlobalConfig` 里配置一次 `setupChangeCompare`
|
|
317
|
+
|
|
318
|
+
编排逻辑已沉到框架 `setupChangeCompare(cfg)`(form-render 内置):按钮显隐联动、原单加载、预置字段、名单派生、提示语全在里面。业务侧 **只给一份 cfg**。`setupChangeCompare` 执行时会把控制器缓存到 form-render,并让 form-render 的同名方法「控制器感知」,所以 onClick / 脚本**直接** `this.getFormRef().enableCompareBySource()` 即可,无需经 `getGlobalConfig`。**换表单只改 cfg**。
|
|
319
|
+
|
|
320
|
+
> 配置在哪都行:放在 `getGlobalConfig`(`return this.getFormRef().setupChangeCompare({...})`,随表单初始化执行一次);或表单 `onMounted`/入口脚本里 `this.getFormRef().setupChangeCompare({...})`(此时 `getGlobalConfig` 可另放别的配置)。两种都会缓存,onClick 调用方式一致。
|
|
321
|
+
>
|
|
322
|
+
> **合二为一**:在 `onMounted`/入口脚本里配置时,可传 `autoLoadFromParam: true`,`setupChangeCompare` 配置后顺带执行 `loadSourceFromParam()`(模式 A 自动加载,编辑态自守卫跳过),省掉单独那一行。⚠️ 放 `getGlobalConfig` 里**不要**开——那时 `formModel`/路由参数可能未就绪,加载时机过早。
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
return this.getFormRef().setupChangeCompare({
|
|
326
|
+
sourceIdField: "f_source_id", // 变更单里存「原单ID」的字段(自动纳入不对比+不覆盖)
|
|
327
|
+
presetFields: { f_type: 1 }, // 新建时预置的固定字段(可多个,自动纳入不对比+不覆盖)
|
|
328
|
+
compareRowKey: "f_uuid", // 明细行匹配键(原单行 vs 变更单行按它配对,形态见下)
|
|
329
|
+
detailName: "test_source_bill_item", // 明细表属性名(keyName)
|
|
330
|
+
sourceItemIdField: "f_source_item_id", // 明细「回填原单明细ID」的字段
|
|
331
|
+
|
|
332
|
+
// ── 不对比字段 / 不覆盖字段(都在 sourceIdField+presetFields 之外“额外”追加)──
|
|
333
|
+
excludeFields: ["f_status"], // 表头【不对比】的额外字段
|
|
334
|
+
defaultFields: ["f_no"], // 表头【不覆盖】的额外字段(保住新单自身值/默认值)
|
|
335
|
+
subExcludeFields: {
|
|
336
|
+
// 明细【不对比】:{ 明细keyName: [字段] }
|
|
337
|
+
test_source_bill_item: ["f_line_state"],
|
|
338
|
+
},
|
|
339
|
+
subDefaultFields: {
|
|
340
|
+
// 明细【不覆盖,取该列设计器默认值】:{ 明细keyName: [列prop] }
|
|
341
|
+
test_source_bill_item: ["f_state"],
|
|
342
|
+
},
|
|
343
|
+
compareBtnName: "button52848", // 对比按钮唯一名
|
|
344
|
+
closeBtnName: "button56167", // 关闭对比按钮唯一名
|
|
345
|
+
delBtnNames: ["button67652"], // 查看删除明细按钮唯一名(可多个)
|
|
346
|
+
sourceFormCode: "", // 原单≠变更单模板时填原单formCode,否则留空
|
|
347
|
+
sourceLabel: "原单", // 原单业务称呼,用于提示语
|
|
348
|
+
// extraOptions: {}, // 高级:透传给 initChangeFromSource/enableCompareBySource
|
|
349
|
+
|
|
350
|
+
// ── 业务钩子(可选,this = form-render,可直接用 form 能力)──
|
|
351
|
+
onLoaded(oldData, ctx) {}, // 原单加载完成 ctx={mode:'param'|'pick'|'compare', sourceId}
|
|
352
|
+
onCompareToggle(isCompare) {}, // 对比开/关后(同步别的 UI)
|
|
353
|
+
onClearSource() {
|
|
354
|
+
// 搜索框清空时——在此清掉已填数据(框架只关对比、不清数据)
|
|
355
|
+
this.formModel.f_cust = null;
|
|
356
|
+
this.formModel.test_source_bill_item = [];
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
> 框架内部自动:`sourceIdField` + `presetFields` 的键并入「不覆盖(defaultFields) + 不对比(excludeFields)」;`detailName`+`sourceItemIdField` 组成 `subSourceFields` 回填;三个入口共用一份 options。业务无需再写这些派生。
|
|
362
|
+
|
|
363
|
+
##### `compareRowKey` 的形态(原单行 vs 变更行怎么配对)
|
|
364
|
+
|
|
365
|
+
匹配方向固定:`a`=原单行、`b`=变更行。一个字段两用:
|
|
366
|
+
|
|
367
|
+
| 写法 | 含义 |
|
|
368
|
+
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
369
|
+
| `'f_uuid'` | 全局、两边同名:`原单.f_uuid === 变更.f_uuid` |
|
|
370
|
+
| `{ from:'id', to:'f_source_item_id' }` | 全局、**两边字段名不同**:`原单.id === 变更.f_source_item_id`(正好对上 `subSourceFields` 回填的 `f_source_item_id`) |
|
|
371
|
+
| `['f_a','f_b']` 或 `[{from,to},...]` | 全局、多字段联合,全部满足才算同一行 |
|
|
372
|
+
| `{ 明细A: {from,to}, 明细B: 'f_uuid' }` | **按明细** map:每张明细各用各的键(键为明细 keyName、无 `from`/`to` 键时判定为此形态) |
|
|
373
|
+
|
|
374
|
+
- 原单侧字段取值必须非空,否则该行找不到配对 → 判为「新增」。
|
|
375
|
+
- 判定「按明细 map」vs「单个 `{from,to}`」:对象含 `from`/`to` 键 = 单键;否则键是明细名 = 按明细 map。(明细表极少会叫 `from`/`to`;真撞上用 `extraOptions.subRowKeys` 显式指定。)
|
|
376
|
+
|
|
377
|
+
控制器方法(onClick / 入口脚本直接调,均无参):
|
|
378
|
+
|
|
379
|
+
| 方法 | 用途 | 触发 |
|
|
380
|
+
| ---------------------------- | ------------------------------------------------------------------------------ | -------------------- |
|
|
381
|
+
| `loadSourceFromParam()` | 模式 A:路由参数带 sourceId,新建页自动加载 + 开启对比 | 入口脚本 / onMounted |
|
|
382
|
+
| `loadSourceOnPick(sourceId)` | 模式 B 变体:搜索框选原单,只加载不对比 | 搜索框 onChange |
|
|
383
|
+
| `enableCompareBySource()` | 点「对比」:重拉原单作基准并开启对比 | 对比按钮 |
|
|
384
|
+
| `disableCompare()` | 关闭对比 | 关闭对比按钮 |
|
|
385
|
+
| `clearCompareSource()` | = `disableCompare()` **+ 触发 `onClearSource` 钩子**(需连带清已填数据时才用) | 搜索框 onClear |
|
|
386
|
+
| `openCompareDelList()` | 打开「查看删除明细」(表名取 `cfg.detailName`) | 查看删除明细按钮 |
|
|
387
|
+
|
|
388
|
+
> `loadSourceFromParam`(原单 ID 来自路由参数)与 `loadSourceOnPick`(来自搜索框手选)都走框架 `initChangeFromSource`,仅 `compare` 与触发时机不同:前者自动开启对比,后者只填充、把「对比」留给用户手动点。
|
|
389
|
+
|
|
390
|
+
#### 步骤 3:详情页入口脚本 / 按钮 onClick 调用
|
|
391
|
+
|
|
392
|
+
控制器方法内部操作 form-render 自身,**onClick / 入口脚本直接调、不用传 `this`**:
|
|
393
|
+
|
|
394
|
+
```js
|
|
395
|
+
// ① 新建页入口脚本 / onMounted(模式A:变更跳转,原单ID 来自路由参数)
|
|
396
|
+
this.getFormRef().loadSourceFromParam();
|
|
397
|
+
|
|
398
|
+
// ② 搜索框「选中」原单 onChange(this = 搜索框组件,取其绑定字段的当前值)
|
|
399
|
+
this.getFormRef().loadSourceOnPick(this.formModel.f_source_id);
|
|
400
|
+
|
|
401
|
+
// ③ 搜索框「清空」onClear(或 onChange 里判空)→ 关闭对比
|
|
402
|
+
// 一般用 disableCompare() 即可;若清搜索框还要连带清掉已填数据,改用 clearCompareSource() 并实现 onClearSource 钩子
|
|
403
|
+
if (!this.formModel.f_source_id) this.getFormRef().disableCompare();
|
|
404
|
+
|
|
405
|
+
// 「对比」按钮 onClick
|
|
406
|
+
this.getFormRef().enableCompareBySource();
|
|
407
|
+
|
|
408
|
+
// 「关闭对比」按钮 onClick
|
|
409
|
+
this.getFormRef().disableCompare();
|
|
410
|
+
|
|
411
|
+
// 「查看删除明细」按钮 onClick(表名收在 cfg.detailName)
|
|
412
|
+
this.getFormRef().openCompareDelList();
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
> **易错点**:
|
|
416
|
+
>
|
|
417
|
+
> 1. 三个按钮在设计器里设好唯一名,与 cfg 的 `compareBtnName/closeBtnName/delBtnNames` 对应;「关闭对比」「查看删除明细」默认隐藏,避免非对比态先闪出(对比中由框架自动放出)。
|
|
418
|
+
> 2. 模式 B 靠 `cfg.sourceIdField` 拿原单,确认搜索框绑定字段/保存回显链路带上了该字段。它已被框架自动纳入 `excludeFields`(否则搜索框字段本身会被判为「变更」),无需手写。
|
|
419
|
+
> 3. 搜索框 onClear 一般直接 `disableCompare()`(只关对比、保留已填数据)。`disableCompare` 被「关闭对比」按钮和搜索框清空共用——若想让**搜索框清空时连带清掉已填数据、而「关闭对比」按钮保留数据**,则搜索框走 `clearCompareSource()` 并实现 `onClearSource` 钩子(在钩子里重置字段与明细数组)。这也是 `clearCompareSource` 与 `disableCompare` 的唯一区别。
|
|
420
|
+
> 4. **多张明细**:`cfg.detailName`/`sourceItemIdField` 只是**单明细便捷写法**(回填 + `openCompareDelList()` 默认弹它)。多明细时:
|
|
421
|
+
> - 回填改用 `cfg.subSourceFields`(完整 `{ 明细keyName: 配置 }`,见上方「全字段参考配置」的 `subSourceFields`),与 `detailName` 派生的自动合并;
|
|
422
|
+
> - 查看删除明细给每张明细各放一个按钮,onClick 传各自表名:`this.getFormRef().openCompareDelList('another_detail')`。
|
|
423
|
+
> 5. `loadSourceFromParam` 不对 sourceId 做 `Number()` 转换(兼容编码/ID);若后端主键必须是数字,在 cfg 之外自行转或用 `sourceKeyField`。
|
|
424
|
+
|
|
425
|
+
## 一、背景与目标
|
|
426
|
+
|
|
427
|
+
外部业务页把「变更前的旧整单数据」传入 form-render,开启对比模式后:
|
|
428
|
+
|
|
429
|
+
- **主表字段**:值发生变化时,字段旁展示"变更前"提示(hover 弹出旧值)。
|
|
430
|
+
- **子表格单元格**:同上,逐行逐列对比。
|
|
431
|
+
- **被删除的子表行**:可通过"查看删除数据"弹窗查看。
|
|
432
|
+
|
|
433
|
+
对比逻辑完全参照 agreementChange:`isCompare` 开关 + 旧数据对象 + `compareView` 提示组件 + 子表逐行 `hData` 快照(按主键匹配)+ `getDelData` 删除行比对。
|
|
434
|
+
|
|
435
|
+
## 二、参考实现的对比机制(梳理)
|
|
436
|
+
|
|
437
|
+
1. **双份数据**:`agreement`(当前)与 `oldAgreement`(变更前)并存。
|
|
438
|
+
2. **主表字段**:`compareView` 直接吃 `oldAgreement.xxx` 与 `agreement.xxx`。
|
|
439
|
+
3. **子表**:每行携带 `hData` 快照(`item.hData = cloneDeep(旧行)`),按 `uuid` 匹配新旧行;`getHValue(row, column)` 返回 `row.hData[column.property]`。
|
|
440
|
+
4. **compareView 组件**:props `isCompare / oldVal / newVal`;`isCompare && oldVal != newVal` → 显示 `el-icon-warning` + popover「变更前:xxx」,否则原样渲染 slot。
|
|
441
|
+
5. **删除行**:`getDelData(key)` 用 uuid 比对新旧明细数组,找出"旧有但新无"的行,配合 `compareDelList` 弹窗展示。
|
|
442
|
+
|
|
443
|
+
## 二·五、业务场景与触发时机(重要)
|
|
444
|
+
|
|
445
|
+
整个对比发生在「变更单」表单上,分两种模式:
|
|
446
|
+
|
|
447
|
+
### 模式 A:新建变更单(默认开启对比)
|
|
448
|
+
|
|
449
|
+
1. 在原单据详情页点击「变更」按钮。
|
|
450
|
+
2. 跳转到变更单列表页,并自动打开对应的变更单**新增**详情页(此时无变更单 id)。
|
|
451
|
+
3. 页面加载时拿到**原单据数据**作为旧数据,`enableCompare(原单据数据)` 自动执行,默认进入对比态。
|
|
452
|
+
|
|
453
|
+
> 对应参考实现:`created()` 中 `if (!this._dataId) this.isCompare = true;`,旧数据来自 `getOld`。
|
|
454
|
+
|
|
455
|
+
### 模式 B:已保存的变更单(手动点「对比」触发)
|
|
456
|
+
|
|
457
|
+
1. 变更单保存成功后,页面已带变更单 id,**默认不开启对比**。
|
|
458
|
+
2. 用户点击「对比」按钮 → 此时才去拉取原单据数据 → `enableCompare(原单据数据)` 进入对比态。
|
|
459
|
+
|
|
460
|
+
> 对应参考实现:保存后 `isCompare=false`,点 `compare()` → `getDataH` 拉原单 → `isCompare=true`。
|
|
461
|
+
|
|
462
|
+
### 职责划分(按钮为 xform 内部 button-widget)
|
|
463
|
+
|
|
464
|
+
「变更 / 对比 / 保存」按钮都是**表单内部的 button-widget**,通过配置在 `field.options.onClick` 的自定义脚本触发。脚本运行时:
|
|
465
|
+
|
|
466
|
+
- `this` = 按钮组件实例,`this.getFormRef()` 返回 form-render 实例。
|
|
467
|
+
- 注入参数含 `dataId`(当前单据 id)、`formCode`、`event`(表格内按钮另有 `row/rowIndex`)。
|
|
468
|
+
- 可用 `this.getFormRef().$http(...)` 发请求、`this.getFormRef().enableCompare(...)` 开启对比。
|
|
469
|
+
|
|
470
|
+
因此:
|
|
471
|
+
|
|
472
|
+
- **form-render 只负责**:提供 `enableCompare(oldData) / disableCompare() / getDelData() / openCompareDelList()` 与对比渲染;**不主动发请求、不做路由**。
|
|
473
|
+
- **onClick 脚本负责**:拉原单据数据、判断新建/已存、调 `enableCompare`。
|
|
474
|
+
- **无需给 button-widget 新增"对比"动作类型** —— 完全靠 onClick 脚本调用 form-render 的公开方法即可。这一点使内部按钮方案对 xform 核心的改动与外层按钮方案一致。
|
|
475
|
+
|
|
476
|
+
### 与 form-render 的衔接点
|
|
477
|
+
|
|
478
|
+
- 模式 A(新建自动开):可写在表单的 `onMounted` 脚本或"变更/新增"入口脚本里,判断无 dataId 时 `getFormRef().enableCompare(oldData)`。
|
|
479
|
+
- 模式 B(点对比开):「对比」按钮 onClick 脚本里拉原单 → `getFormRef().enableCompare(oldData)`。
|
|
480
|
+
|
|
481
|
+
## 二·六、旧数据的传递与获取(数据流)
|
|
482
|
+
|
|
483
|
+
> **已封装为通用方法,日常接入看第〇章一行式 `initChangeFromSource`/`enableCompareBySource` 即可。** 本节保留底层原理与手动版,供理解与特殊定制。
|
|
484
|
+
|
|
485
|
+
xform 的 form-render 通过 `loadFormData` 用 `dataId` + `reportTemplate.formCode` 调后端脚本(`getOne` 或自定义 `formScriptCode`)拉取自己的数据(额外参数来自 `formScriptParam` 脚本),结果经 `setFormData` 注入。`loadOldData` 即复用这套机制,按原单模板对原单 id 自动多包取数。
|
|
486
|
+
|
|
487
|
+
**核心原则:跨页面传的是「原单 id」,旧数据一律在目标页用 id 向后端拉取,不搬运数据 blob。**(整单+子表数据量大、跨路由易丢失/失真,后端才是快照权威来源。)
|
|
488
|
+
|
|
489
|
+
### 点「变更」时——传 id,不传数据
|
|
490
|
+
|
|
491
|
+
`变更` 打开一张新的变更单(无 dataId),旧数据 = 原单据快照:
|
|
492
|
+
|
|
493
|
+
1. `变更` 按钮 onClick:跳转变更单详情页,URL/打开参数带上**原单 id**(如 `?sourceId=xxx`)。
|
|
494
|
+
2. 变更详情页无 dataId,在 `onMounted` / 入口脚本读到 `sourceId`,用 `initChangeFromSource` 一步完成(内部 `loadOldData`→formHttp 取数,一份两用):
|
|
495
|
+
|
|
496
|
+
```js
|
|
497
|
+
if (!dataId) {
|
|
498
|
+
// 新建变更单
|
|
499
|
+
let formRef = this.getFormRef();
|
|
500
|
+
let sourceId = formRef.getFormParam() && formRef.getFormParam().sourceId;
|
|
501
|
+
formRef.initChangeFromSource(sourceId, {
|
|
502
|
+
sourceFormCode: "原单formCode",
|
|
503
|
+
compareRowKey: "uuid",
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
> 对应参考:`getOld(原单id)` 既 clone 出新单,又作为 `oldAgreement`。**取数统一走 `loadOldData`(formHttp 按模板脚本发包),不要用 `formRef.$http` 直接打 url。**
|
|
509
|
+
|
|
510
|
+
### 详情页点「对比」时——用当前单关联 id 反查
|
|
511
|
+
|
|
512
|
+
已保存变更单(带 dataId)数据里存有指向原单的引用(如 `sourceId`/`sourceSn`,保存时落库)。`对比` 按钮 onClick:
|
|
513
|
+
|
|
514
|
+
```js
|
|
515
|
+
let formRef = this.getFormRef();
|
|
516
|
+
let sourceId = formRef.getFormData().sourceId; // 当前变更单里存的原单引用
|
|
517
|
+
formRef.enableCompareBySource(sourceId, {
|
|
518
|
+
sourceFormCode: "原单formCode",
|
|
519
|
+
compareRowKey: "uuid",
|
|
520
|
+
});
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### 主从表旧数据的获取粒度(多包 vs 单包)
|
|
524
|
+
|
|
525
|
+
xform 现状:加载现单时主表 `getOne` 一个包,**每个 data-table 子表各自 `getList`(`taBm=fieldKeyName`)独立发包**(见 `data-table-mixin.loadDefaultViewList`),子表本就是异步/懒加载。旧数据获取与之对称,有两套落地:
|
|
526
|
+
|
|
527
|
+
**方案一:分表增量(推荐,贴合 xform 异步加载)**
|
|
528
|
+
`loadOldData` 内部即按此思路自动多包(主表 `getOne` + 各 data-table `getList`,均走 `formHttp`)并组装。若要手动控制各包时序,用 `enableCompare(oldMasterData)` 先设主表 + `setOldSubData(name, oldRows)` 增量补子表;子表旧数据同样通过 `formHttp`(按模板脚本)而非 `formRef.$http` 打 url 获取:
|
|
529
|
+
|
|
530
|
+
```js
|
|
531
|
+
formRef.enableCompare(master, { compareRowKey: "uuid" }); // 主表旧数据
|
|
532
|
+
formRef.formHttp({
|
|
533
|
+
vue: formRef,
|
|
534
|
+
scriptCode: "getList",
|
|
535
|
+
data: { formCode, formVersion, taBm: "子表A", data: { id } },
|
|
536
|
+
success: (r) =>
|
|
537
|
+
formRef.setOldSubData("子表A", (r.objx && r.objx.records) || r.objx || []),
|
|
538
|
+
});
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
优点:与子表懒加载/分 tab 加载天然契合;某子表未加载不阻塞主表对比。
|
|
542
|
+
|
|
543
|
+
**方案二:一个大包**
|
|
544
|
+
后端提供 `getOldFull(id)` 一次返回主表+所有子表数组,前端 `enableCompare(fullOldData)` 内部遍历所有子表做快照(即"设主表 + 循环 setOldSubData")。
|
|
545
|
+
|
|
546
|
+
- 优点:前端简单、时序可控;缺点:需后端聚合接口,大单据传输量大,且若新子表懒加载未就绪,`getDelData` 需等新子表加载完再算。
|
|
547
|
+
|
|
548
|
+
> **两种方式都要支持,且共用同一套底层 API,无需两套实现。** 由调用方(按钮 onClick 脚本)自行选择:
|
|
549
|
+
>
|
|
550
|
+
> - 走**多包**就多次调用 `setOldSubData`;
|
|
551
|
+
> - 走**单包**就用聚合数据调一次 `enableCompare(fullOldData)`(其内部即"设主表 + 循环 setOldSubData")。
|
|
552
|
+
> - 甚至可混用:主表 + 部分子表随主包一次给(`enableCompare` 内处理已带的子表数组),其余子表后续 `setOldSubData` 增量补入。
|
|
553
|
+
>
|
|
554
|
+
> 因此 form-render 的实现要点是:`enableCompare` 能吃"仅主表"或"主表+任意数量子表数组"的 oldData,`setOldSubData` 可被任意次增量调用,两者对同一子表重复设置时以最后一次为准(幂等)。
|
|
555
|
+
|
|
556
|
+
### 取旧数据的后端约定(二选一)
|
|
557
|
+
|
|
558
|
+
- **A(推荐)**:后端提供 `getOld(变更单 dataId)`,直接返回该变更单对应的"变更前快照"(参考实现即此,`agreementChange/getOld`)。前端不必关心原单 id。
|
|
559
|
+
- **B**:变更单里存 `sourceId`,前端读出后调通用 `get(原单id)`。
|
|
560
|
+
|
|
561
|
+
### 依赖前提
|
|
562
|
+
|
|
563
|
+
两种模式都需**后端提供返回"变更前快照"的接口**。这是外部依赖,不在 xform 前端范围内。
|
|
564
|
+
|
|
565
|
+
## 三、xform 现有架构关键点
|
|
566
|
+
|
|
567
|
+
- **form-render**(`form-render/indexMixin.js`)持有 `formDataModel`(当前整单数据),暴露 `getFormData/setFormData`,通过 `provide()` 的 `globalModel.formModel` 下发给所有字段。
|
|
568
|
+
- **字段**(`field-widget/fieldMixin.js`)从 `formModel[fieldKeyName]`(或表格内 `tableParam.row[fieldKeyName]`)计算 `fieldModel`。
|
|
569
|
+
- **form-item-wrapper.vue**:渲染字段编辑控件 slot 与只读文本(`getShowValue`),是注入对比图标的统一入口。
|
|
570
|
+
- **三类表格容器**:`sub-form-item`、`table2-item`、`data-table-item`(vxe),单元格都经 `field-widget + tableParam.row` 渲染,旧行快照挂 `tableParam.row.hData`。
|
|
571
|
+
- 现状:xform 中**无任何** `isCompare / hData / compareView` 基础设施,需从零搭建。
|
|
572
|
+
|
|
573
|
+
## 四、主键约定
|
|
574
|
+
|
|
575
|
+
- 子表行匹配默认字段 `uuid`,可通过 `enableCompare` 的 options 或 `formConfig.compareRowKey` 覆盖(如 `id`)。
|
|
576
|
+
- 统一匹配 helper:`matchRowKey(rowA, rowB, key = 'uuid')`。
|
|
577
|
+
|
|
578
|
+
## 五、新增文件
|
|
579
|
+
|
|
580
|
+
### 1. `form-render/compareView.vue`
|
|
581
|
+
|
|
582
|
+
基于参考实现,接口调整以支持字段差异化(见 七·五):
|
|
583
|
+
|
|
584
|
+
- props:`isCompare` / `isDiff` / `oldVal`(展示文本)/ `newVal`(展示文本)。
|
|
585
|
+
- `isCompare && isDiff` → 渲染 `<slot>` + hover popover「变更前:{{ oldVal }}」的 `el-icon-warning` 图标;否则仅渲染 `<slot>`。
|
|
586
|
+
- 差异判定由字段侧(wrapper + fieldMixin.compareEquals)算好通过 `isDiff` 传入,组件本身不再做 `oldVal!=newVal` 裸比。
|
|
587
|
+
- 注册进 form-render 的 components,供 form-item-wrapper 使用。
|
|
588
|
+
|
|
589
|
+
### 2. `form-render/compareDelList.vue`
|
|
590
|
+
|
|
591
|
+
- `el-dialog` + `vxe-grid`,props:`visiable` / `option`(`{ columns, data }`)。
|
|
592
|
+
- 展示某子表被删除的行;列配置由 form-render 依据子表 widget 列自动生成。
|
|
593
|
+
|
|
594
|
+
## 六、form-render 改造(`indexMixin.js`)
|
|
595
|
+
|
|
596
|
+
### data 新增(实际实现)
|
|
597
|
+
|
|
598
|
+
```js
|
|
599
|
+
isCompare: false, // 对比开关
|
|
600
|
+
oldFormData: {}, // 旧整单数据(主表字段 + 各子表数组)
|
|
601
|
+
compareRowKey: 'uuid', // 子表行匹配主键,可被 enableCompare(options)/formConfig 覆盖
|
|
602
|
+
compareExcludeTypes: [ // 不参与对比的字段类型(附件/上传类)
|
|
603
|
+
'file-upload','picture-upload','baseAttachment','vabUpload','vabUpload2','singleUpload',
|
|
604
|
+
],
|
|
605
|
+
showCompareDelList: false,
|
|
606
|
+
compareDelListOption: {},
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
### 公开方法(实际实现)
|
|
610
|
+
|
|
611
|
+
**对比开关**
|
|
612
|
+
|
|
613
|
+
- **`enableCompare(oldData, options)`**:`oldFormData=deepClone(oldData)` → 解析 `compareRowKey`(options / formConfig / 默认)→ `isCompare=true` → 对 `oldData` 中已带的数组子表逐个 `applyCompareSubSnapshot`。
|
|
614
|
+
- **`setOldSubData(subFormName, oldRows)`**:多包/增量设置某子表旧数据(幂等),写 `oldFormData[name]` 并 `applyCompareSubSnapshot(name)`。
|
|
615
|
+
- **`applyCompareSubSnapshot(subFormName)`**(内部):按 `compareRowKey` 把旧行匹配到当前行,写每行 `hData`;当前子表未加载时仅保留旧数据,加载后可再次调用补做。
|
|
616
|
+
- **`matchCompareRowKey(a, b, rowKey)`**(内部):按主键匹配两行。
|
|
617
|
+
- **`disableCompare()`**:复位状态、移除各行 `hData`。
|
|
618
|
+
|
|
619
|
+
**删除行 / 弹窗**
|
|
620
|
+
|
|
621
|
+
- **`getDelData(subFormName)`**:**实时计算**(旧数组中当前按主键找不到的行),不缓存。
|
|
622
|
+
- **`openCompareDelList(subFormName, columns)`**:组装 `compareDelListOption` 并弹窗。
|
|
623
|
+
|
|
624
|
+
**变更跳转(原单侧)**
|
|
625
|
+
|
|
626
|
+
- **`goChangeBill(sourceId, formCode, options)`**:跳变更单列表并携带 `sourceId` 打开新增。默认把当前路由最后一段替换为 `formCode`(`options.listPath` 可覆盖),`query.param`=JSON`{sourceId,autoAdd:1}`;先 `tagsView/delCachedView` 清缓存视图再 `router.replace`。
|
|
627
|
+
|
|
628
|
+
**通用取数(自动多包)**
|
|
629
|
+
|
|
630
|
+
- **`loadOldData(sourceId, options)`** → `Promise<oldData>`:先解析模板(`sourceFormCode` 拉原单模板 / 否则复用当前模板)→ 主表 `getOne` 包 + 各 data-table 子表 `getList` 包 → 组装整单返回。
|
|
631
|
+
- **`getCompareSubTables()` / `getCompareSubTablesFrom(widgetList)`**:枚举需独立发包的 data-table 子表。
|
|
632
|
+
- **`fetchTemplateByFormCode(formCode)`** → `Promise<{reportTemplate, formConfig, widgetList}>`:按 formCode 拉模板(`/formTemplate/getByFormCode`)。
|
|
633
|
+
- **`enableCompareBySource(sourceId, options)`**(模式 B 一行):`loadOldData` → `enableCompare`。
|
|
634
|
+
- **`initChangeFromSource(sourceId, options)`**(模式 A 一行,options 单层扁平):`loadOldData` → `applyCompareSourceTransform` → `sanitizeChangeData(old, options)` → `setFormData(新单)` → `enableCompare(原始旧数据)`。
|
|
635
|
+
- **`setupChangeCompare(cfg)`**(订单 → 变更单编排工厂):把按钮显隐联动、原单加载、预置字段、名单派生(`sourceIdField`+`presetFields`键 → defaultFields/excludeFields)、`subSourceFields` 回填、提示语全收进框架;业务只给一份 cfg。执行后**缓存控制器到 form-render**,并让 form-render 同名方法「控制器感知」,于是这些方法**直接**在 form-render 上无参调用:
|
|
636
|
+
- `loadSourceFromParam()`(模式 A)/ `loadSourceOnPick(id)`(模式 B 变体)/ `clearCompareSource()`(代理到控制器)
|
|
637
|
+
- `enableCompareBySource()` / `disableCompare()` / `openCompareDelList([明细keyName])`(与底层同名方法合并:无参走控制器、带参走底层)
|
|
638
|
+
- 业务钩子:`onBeforeLoadFromParam / onBeforeLoadOnPick / onLoaded / onCompareToggle / onClearSource`
|
|
639
|
+
- `cfg.autoLoadFromParam:true`:配置后顺带执行 `loadSourceFromParam()`(onMounted 里用;勿在 getGlobalConfig 里开)
|
|
640
|
+
- 也可 `getChangeCompare()` 取控制器对象,或从 `getGlobalConfig()` 返回它。
|
|
641
|
+
|
|
642
|
+
**数据清洗(变更初始化)**
|
|
643
|
+
|
|
644
|
+
- **`sanitizeChangeData(oldData, options)`** → 清洗后克隆:清主/子表系统字段(id/createBy/createDate/modifyBy/modifyDate/\_createBy/\_modifyBy + snake_case)、子表外键(head_table_id/alias_id/object_foreign_id)、附件白名单精简(attachmentKeepFields)、不覆盖取默认(defaultFields/subDefaultFields)、原单字段回填(subSourceFields)、树表 id/parent_id 重生成(treeSubTables)。
|
|
645
|
+
- **`regenerateTreeIds(rows, idField, parentField)`**(内部):树表新 id 形如 `_row{随机}`(本表唯一),parent_id 旧 → 新重映射,外部父级置空作根。
|
|
646
|
+
|
|
647
|
+
### provide 新增下发(实际实现)
|
|
648
|
+
|
|
649
|
+
```js
|
|
650
|
+
getIsCompare: () => e.isCompare,
|
|
651
|
+
getOldFormData: () => e.oldFormData,
|
|
652
|
+
getCompareRowKey: () => e.compareRowKey,
|
|
653
|
+
getCompareExcludeTypes: () => e.compareExcludeTypes,
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### 模板
|
|
657
|
+
|
|
658
|
+
index.vue 末尾挂:
|
|
659
|
+
|
|
660
|
+
```html
|
|
661
|
+
<compareDelList
|
|
662
|
+
v-if="showCompareDelList"
|
|
663
|
+
:visiable.sync="showCompareDelList"
|
|
664
|
+
:option="compareDelListOption"
|
|
665
|
+
/>
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
## 七、字段展示改造(`form-item-wrapper.vue`)
|
|
669
|
+
|
|
670
|
+
### inject 新增
|
|
671
|
+
|
|
672
|
+
`getIsCompare` / `getOldFormData` / `getCompareRowKey`(均给默认工厂:非对比场景返回 `false` / `{}`,保证旧调用不受影响)。
|
|
673
|
+
|
|
674
|
+
### computed
|
|
675
|
+
|
|
676
|
+
- `isCompareOn = getIsCompare()`(设计态 `this.designer` 存在、或命中排除类型时强制 false)。
|
|
677
|
+
- `oldRawValue`(原始旧值,用于相等判定):
|
|
678
|
+
- 表格列字段(`this.tableParam && this.tableParam.row`):`this.tableParam.row.hData?.[property]`,`property` 复用 `getPropName` 里已有的取列名逻辑(`getFieldKeyName(field)` / vabSearch 特例)。
|
|
679
|
+
- 主表字段:`getOldFormData()[fieldKeyName]`。
|
|
680
|
+
- `newRawValue`:取 `$parent.fieldModel`。
|
|
681
|
+
- `oldDisplay = $parent.resolveDisplayValue(oldRawValue)`(见 七·五,解析成展示文本)。
|
|
682
|
+
- `newDisplay = getShowValue()`(复用现有展示逻辑)。
|
|
683
|
+
- `isDiff = !$parent.compareEquals(oldRawValue, newRawValue)`(类型化相等判定,见 七·五)。
|
|
684
|
+
|
|
685
|
+
### 模板包裹
|
|
686
|
+
|
|
687
|
+
`isShowWidget()` 编辑分支的 `<slot>` 与只读分支的 `getShowValue()` 外层各包一层:
|
|
688
|
+
|
|
689
|
+
```html
|
|
690
|
+
<compareView
|
|
691
|
+
:isCompare="isCompareOn"
|
|
692
|
+
:isDiff="isDiff"
|
|
693
|
+
:oldVal="oldDisplay"
|
|
694
|
+
:newVal="newDisplay"
|
|
695
|
+
>
|
|
696
|
+
...原内容...
|
|
697
|
+
</compareView>
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
> compareView 内部按 `isCompare && isDiff` 决定是否显示"变更前"图标+popover(把差异判定从组件内上移到字段侧,以支持差异化比较)。
|
|
701
|
+
|
|
702
|
+
### 不参与对比的字段类型(重要)
|
|
703
|
+
|
|
704
|
+
附件/上传类字段值为文件数组,弹出"变更前"旧值无意义(参考实现的附件 tab 也未包 compareView),需排除。判定:
|
|
705
|
+
|
|
706
|
+
```js
|
|
707
|
+
compareExcludeTypes = [
|
|
708
|
+
"file-upload",
|
|
709
|
+
"picture-upload",
|
|
710
|
+
"baseAttachment",
|
|
711
|
+
"vabUpload",
|
|
712
|
+
"vabUpload2",
|
|
713
|
+
"singleUpload",
|
|
714
|
+
];
|
|
715
|
+
// isCompareOn 计算时叠加:!compareExcludeTypes.includes(this.field.type)
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
- 命中排除类型时 `isCompareOn=false`,字段原样渲染,不显示对比图标。
|
|
719
|
+
- 富文本(`rich-editor`)、按钮(`button` 等 static 类)等无值或非数据字段天然不进对比(`newFieldValue` 为空 / 无 fieldModel),可视情况一并纳入排除列表。
|
|
720
|
+
- 排除列表建议做成 form-render 可配置项(`formConfig.compareExcludeTypes`)以便按单据调整。
|
|
721
|
+
|
|
722
|
+
## 七·五、字段差异化对比规则(核心难点)
|
|
723
|
+
|
|
724
|
+
不同字段类型的「存储值」与「展示值」不一致,`compareView` 不能简单地 `oldVal != newVal` 裸比、也不能直接把裸值弹出来。现有 `getOptionLabel()` 只解析当前 `this.fieldModel`,无法解析任意旧值,需扩展。
|
|
725
|
+
|
|
726
|
+
### 各类型的值模型
|
|
727
|
+
|
|
728
|
+
| 字段类型 | 存储值 | 展示值 | 相等判定 | 旧值展示 |
|
|
729
|
+
| ------------------------------------------- | -------------------- | ------------- | ------------------------- | ---------------------------- |
|
|
730
|
+
| input / textarea | 字符串 | 同值 | 归一空值后字符串比 | 原值 |
|
|
731
|
+
| number | 数值 | 格式化 | 数值比(`Number()` 归一) | 格式化旧值 |
|
|
732
|
+
| select / radio | code | options.label | code 比 | 用 options 解析旧 code→label |
|
|
733
|
+
| checkbox / 多选 select | code 数组 | 多 label 拼接 | **数组无序比** | 解析旧数组 → 多 label |
|
|
734
|
+
| switch | 布尔 | 是/否文案 | 布尔比 | 旧布尔 → 文案 |
|
|
735
|
+
| date / time / date-range | 时间串/数组 | 按 format | 归一后比 | 按 format 展示旧值 |
|
|
736
|
+
| cascader / area | 数组路径 | 路径名拼接 | 数组深比 | 解析旧路径 → 名称 |
|
|
737
|
+
| 关联搜索 vabsearch/singerSearch/multiSearch | id(另存 `xxxName`) | 关联 name | id 比 | 展示旧 `xxxName` 字段 |
|
|
738
|
+
|
|
739
|
+
### 判定与展示的分离原则(重要)
|
|
740
|
+
|
|
741
|
+
**差异判定一律用「原始存储值」,弹出的「变更前」一律用「展示文本(label)」。** 二者解耦:
|
|
742
|
+
|
|
743
|
+
- 下拉/单选/多选:`isDiff` 按 code(数组按 code 集合)比;popover 展示旧 code 解析出的 **label**。
|
|
744
|
+
- 关联搜索(vabsearch 等):`isDiff` 按 id 比;popover 展示旧记录的 **name(label)**。
|
|
745
|
+
- 即:`isDiff = !compareEquals(oldRaw, newRaw)`(code/id),`oldVal = resolveDisplayValue(oldRaw)`(label)。
|
|
746
|
+
- 好处:code 相同 label 偶然相同/不同都不误判;用户看到的是可读的中文旧值而非编码。
|
|
747
|
+
|
|
748
|
+
### 设计
|
|
749
|
+
|
|
750
|
+
1. **相等判定 `compareEquals(oldRaw, newRaw)`**(放 fieldMixin,可被具体 widget override):
|
|
751
|
+
- `null / undefined / '' / []` 之间视为"都为空"→ 相等;
|
|
752
|
+
- 数组:长度+元素无序比(多选/cascader/area);
|
|
753
|
+
- 对象:按 key 深比;
|
|
754
|
+
- 标量:`String(a) === String(b)`(吸收 number/string 差异,或按类型精确比)。
|
|
755
|
+
2. **旧值展示 `resolveDisplayValue(rawValue)`**(放 fieldMixin,可 override):把 `getOptionLabel/getShowValue` 里依赖 `this.fieldModel` 的逻辑改造成"接收任意入参",对 select/radio/checkbox 用 `optionItems` 解析入参 →label;date/number 按格式;其它返回原值。
|
|
756
|
+
3. **compareView 接口调整**:由 wrapper 计算好后传入
|
|
757
|
+
- `:isCompare`、`:oldVal="oldDisplay"`(已解析文本,用于弹窗展示)、`:newVal="newDisplay"`、`:isDiff="!compareEquals(oldRaw,newRaw)"`(相等判定用原始值,展示用文本)。
|
|
758
|
+
- compareView 内部:`isCompare && isDiff` 时显示图标 + popover「变更前:{{ oldVal }}」。(相比参考版把"是否差异"的判定从组件内 `oldVal!=newVal` 上移到字段侧,以支持类型化比较。)
|
|
759
|
+
|
|
760
|
+
### 关联字段的特殊说明
|
|
761
|
+
|
|
762
|
+
关联搜索类字段值为 id、展示靠同表的 `xxxName` 字段。由于对比是**逐字段**进行的,`xxxName` 字段本身也会被对比与展示,故:
|
|
763
|
+
|
|
764
|
+
- id 字段:`compareEquals` 用 id 比即可;其展示可直接复用 `xxxName`(或在排除列表里让 id 字段不单独弹提示,只让 name 字段弹)。
|
|
765
|
+
- 建议:**对关联字段,只在其 name 展示字段上挂对比提示**,id 字段纳入"不弹提示"集合,避免同一处两个图标。
|
|
766
|
+
|
|
767
|
+
## 八、"查看删除数据"入口(实际实现)
|
|
768
|
+
|
|
769
|
+
未在容器工具栏内置按钮,改由**业务按钮 onClick 脚本**触发(更灵活,不侵入容器):
|
|
770
|
+
|
|
771
|
+
```js
|
|
772
|
+
// 「查看删除数据」按钮 onClick
|
|
773
|
+
this.getFormRef().openCompareDelList("子表字段名");
|
|
774
|
+
// 需中文表头时传列配置:openCompareDelList('子表字段名', [{ field:'xxx', title:'名称' }, ...])
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
- `getDelData(name)` 实时算出旧有、当前按主键找不到的行;`compareDelList.vue`(el-dialog + el-table)展示,列未传时按数据 key 自动生成。
|
|
778
|
+
- 按钮可加显示条件(脚本里先判断 `getFormRef().getDelData(name).length`)。
|
|
779
|
+
|
|
780
|
+
## 九、内部按钮 onClick 脚本调用方式(API 速查)
|
|
781
|
+
|
|
782
|
+
`this` 为按钮组件,`this.getFormRef()` 取 form-render 实例,注入参数含 `dataId`。**推荐用一行式方法(见第〇章)**,下面是完整 API:
|
|
783
|
+
|
|
784
|
+
```js
|
|
785
|
+
let f = this.getFormRef();
|
|
786
|
+
|
|
787
|
+
// 模式A 新建(onMounted):自动多包取原单 + 清洗 + 填充 + 对比
|
|
788
|
+
f.initChangeFromSource(sourceId, { sourceFormCode:'原单formCode', compareRowKey:'uuid', excludeFields:['status'],
|
|
789
|
+
defaultFields:['billType'], subSourceFields:{ 明细A:'f_source_id' }, treeSubTables:['分类明细'] });
|
|
790
|
+
|
|
791
|
+
// 模式B 已存(对比按钮):自动多包取原单 + 对比
|
|
792
|
+
f.enableCompareBySource(sourceId, { sourceFormCode:'原单formCode', compareRowKey:'uuid' });
|
|
793
|
+
|
|
794
|
+
// 关闭对比
|
|
795
|
+
f.disableCompare();
|
|
796
|
+
|
|
797
|
+
// 查看某子表删除数据(可传列配置作中文表头)
|
|
798
|
+
f.openCompareDelList('子表字段名');
|
|
799
|
+
|
|
800
|
+
// —— 底层/手动版(需自定义取数时)——
|
|
801
|
+
f.loadOldData(sourceId, opts).then(old => { // 仅取数
|
|
802
|
+
f.setFormData(f.sanitizeChangeData(old, {...})); // 手动清洗填充
|
|
803
|
+
f.enableCompare(old, { compareRowKey:'uuid' }); // 手动开启
|
|
804
|
+
});
|
|
805
|
+
f.setOldSubData('子表字段名', 子表旧行); // 子表旧数据增量补入
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
## 十、实施进度(已完成)
|
|
809
|
+
|
|
810
|
+
1. ✅ `compareView.vue` + form-item-wrapper 注入(主表字段对比)。
|
|
811
|
+
2. ✅ `enableCompare` / `setOldSubData` 子表 `hData` 快照 + 表格单元格对比。
|
|
812
|
+
3. ✅ `getDelData`(实时)+ `compareDelList.vue` + `openCompareDelList`。
|
|
813
|
+
4. ✅ `sanitizeChangeData`(系统字段/外键/自定义/默认值/树表 id 重生成)。
|
|
814
|
+
5. ✅ 通用多包 `loadOldData`(读原单模板自动发包)+ 一行式 `initChangeFromSource` / `enableCompareBySource`。
|
|
815
|
+
|
|
816
|
+
## 十·五、跨单据对比(场景 B:订单 → 变更单,不同数据表/不同字段)
|
|
817
|
+
|
|
818
|
+
> **状态:已落地。** 在原「同结构对齐」(源单与变更单同表同字段名)基础上,新增支持**源单与变更单是不同数据表、字段名不同**的场景。
|
|
819
|
+
>
|
|
820
|
+
> 落地方法(`form-render/indexMixin.js`):`normalizeBySourceMapping`(源 → 目标键空间归一化)、`applyCompareSourceTransform`(归一化 + `transformOldData` 钩子统一入口)、`getCompareRowKeyOf`(按子表行主键)、`isCompareSubTable`(未映射子表不参与对比);状态新增 `compareIncludeFields`(白名单)、`compareSubRowKeys`;`loadOldData` 改为「主表先查 → 用真实 id 查明细」并支持 `subParams/commonParams`;`enableCompare / enableCompareBySource / initChangeFromSource` 全部接入。
|
|
821
|
+
|
|
822
|
+
### 10.5.1 业务前提(已确认)
|
|
823
|
+
|
|
824
|
+
| # | 事项 | 结论 |
|
|
825
|
+
| --- | ------------ | ------------------------------------------------------------------------- |
|
|
826
|
+
| 1 | 单据关系 | **订单 → 变更单**。可能是同一张数据表,也可能**不是同一张表、字段名不同** |
|
|
827
|
+
| 2 | 明细行配对 | **有稳定业务键**可配对(如物料编码/行号) |
|
|
828
|
+
| 3 | 对比范围 | **白名单**:只比映射表里明确列出的关键字段 |
|
|
829
|
+
| 4 | 文案 | 「变更前」暂不改 |
|
|
830
|
+
| 5 | 搜索框绑定值 | **可能是编码,也可能是 ID**;业务侧不做反查 |
|
|
831
|
+
| 6 | 明细读脚本 | `getList`,**可能有额外查询参数** |
|
|
832
|
+
| 7 | 明细外键 | `head_table_id` → **主表的 `id` 字段** |
|
|
833
|
+
|
|
834
|
+
### 10.5.2 核心思路
|
|
835
|
+
|
|
836
|
+
从**「结构对齐」**(隐式按同名字段比)改为**「语义映射」**(显式声明源 ↔ 目标字段对应关系):
|
|
837
|
+
|
|
838
|
+
1. 用 `sourceFormCode` 拉**源单模板**取数(已支持);
|
|
839
|
+
2. 按 **`compareMapping`** 把源单数据**归一化到变更单的键空间**(字段名、子表 keyName、明细列、行匹配键);
|
|
840
|
+
3. 归一化之后,现有的 diff / `hData` 快照 / 行级高亮 / 删除行逻辑**几乎不用改**——它们只认变更单的键名。
|
|
841
|
+
|
|
842
|
+
**映射表可选**:同表同字段时不配,自动退化为现在的「结构对齐 + 黑名单」模式,**完全向后兼容**。
|
|
843
|
+
|
|
844
|
+
| 是否配 `compareMapping` | 对齐方式 | 对比范围 |
|
|
845
|
+
| ----------------------- | -------------------- | ----------------------------------------- |
|
|
846
|
+
| 否(同表) | 隐式同名对齐(现状) | 黑名单 `excludeFields` |
|
|
847
|
+
| 是(跨表) | 语义映射 | **白名单**(由 mapping 的 `to` 自动推导) |
|
|
848
|
+
|
|
849
|
+
### 10.5.3 映射表形态
|
|
850
|
+
|
|
851
|
+
```js
|
|
852
|
+
compareMapping: {
|
|
853
|
+
// 主表:源字段 → 变更单字段
|
|
854
|
+
master: [
|
|
855
|
+
{ from: 'f_order_amount', to: 'f_amount' },
|
|
856
|
+
{ from: 'f_delivery_date', to: 'f_ship_date' },
|
|
857
|
+
],
|
|
858
|
+
// 明细:源子表 → 变更单子表
|
|
859
|
+
subs: [
|
|
860
|
+
{
|
|
861
|
+
from: 'order_item', // 订单明细 keyName(源)
|
|
862
|
+
to: 'change_item', // 变更单明细 keyName(目标)
|
|
863
|
+
rowKey: { from: 'f_material_code', to: 'f_mat_no' }, // 业务键,两边可不同名
|
|
864
|
+
fields: [
|
|
865
|
+
{ from: 'f_qty', to: 'f_change_qty' },
|
|
866
|
+
{ from: 'f_price', to: 'f_unit_price' },
|
|
867
|
+
],
|
|
868
|
+
},
|
|
869
|
+
],
|
|
870
|
+
}
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
> **白名单自动推导**:所有 `to` 字段(主表 + 各明细列)自动组成对比白名单,业务无需再写一遍 `includeFields`。未列出的字段一律不参与对比、不显示感叹号、不参与行级高亮判定。
|
|
874
|
+
|
|
875
|
+
### 10.5.4 行匹配(关键技巧:不改 `matchCompareRowKey`)
|
|
876
|
+
|
|
877
|
+
归一化明细行时:
|
|
878
|
+
|
|
879
|
+
```
|
|
880
|
+
归一化旧行[变更单业务键字段] = 源行[源业务键字段] // 如 旧行.f_mat_no = 订单行.f_material_code
|
|
881
|
+
归一化旧行[变更单列名] = 源行[源列名] // 按 fields 映射
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
再把该子表的 `compareRowKey` 设为 `f_mat_no`(**变更单侧**的业务键字段)。于是:
|
|
885
|
+
|
|
886
|
+
- 当前变更单明细行本来就有 `f_mat_no`;
|
|
887
|
+
- 归一化后的旧行也被写入了 `f_mat_no`;
|
|
888
|
+
- `matchCompareRowKey(o, row, 'f_mat_no')` → **直接匹配成功,现有逻辑零改动**。
|
|
889
|
+
|
|
890
|
+
> **多字段组合键**(如 物料+批次):归一化时生成合成键字段(如 `_cmpKey = 'M001|B01'`),并在开启对比时对**当前明细行也注入同样的合成键**,`compareRowKey='_cmpKey'`。单字段业务键则用不上。
|
|
891
|
+
|
|
892
|
+
### 10.5.5 取数流程(必须「主表先查」)
|
|
893
|
+
|
|
894
|
+
**为什么**:明细外键 `head_table_id → 主表.id`,而搜索框存的**可能是编码**。若沿用现在的并行发包(主表和明细同时用搜索框的值查),**存编码时明细必然查空**——明细表里没有"编码"这个关联字段。
|
|
895
|
+
|
|
896
|
+
```
|
|
897
|
+
1. 按 sourceFormCode 拉源单模板
|
|
898
|
+
2. 【串行】主表包:getOne, taBm=源单entity, data:{ [sourceKeyField]: 搜索框的值 }
|
|
899
|
+
↓ sourceKeyField 默认 'id'(后端 getOne 只认 id 时,编码场景可配成 'f_order_no')
|
|
900
|
+
masterId = 主表响应.objx[sourceIdField] // sourceIdField 默认 'id'
|
|
901
|
+
↓ 查不到主表 / 拿不到 id → 中止并提示
|
|
902
|
+
3. 【并行】用 masterId 发:
|
|
903
|
+
- 表头附件包 × N:getList, taBm=附件字段keyName, data:{ id: masterId }
|
|
904
|
+
- 明细包 × N:getList, taBm=明细keyName, data:{ id: masterId, attachmentType, thirdtabm, ...subParams }
|
|
905
|
+
4. 组装 → 归一化(compareMapping) → enableCompare
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
**向后兼容**:搜索框存的就是 id 时,主表返回的 `objx.id` 就是同一个值,明细包参数与现在完全一致 —— 现有模式 A **行为不变**,只多一次串行等待(一个 RTT)。可用 `sourceIdIsKey: true` 保留并行快路径。
|
|
909
|
+
|
|
910
|
+
### 10.5.6 明细额外查询参数
|
|
911
|
+
|
|
912
|
+
**为什么不能直接复用源模板的 `formScriptParam`**:那段脚本在**该 data-table 组件实例**上下文里执行(`this` = 表格组件)。对比取数时源单模板只是一份 JSON,**没有对应组件实例**,跨实例执行有风险。
|
|
913
|
+
|
|
914
|
+
**方案:显式配置(安全可控)**
|
|
915
|
+
|
|
916
|
+
```js
|
|
917
|
+
subParams: {
|
|
918
|
+
'订单明细keyName': { f_status: 1, f_type: 'A' }, // 静态参数
|
|
919
|
+
'订单附件明细': (ctx) => ({ f_biz: ctx.masterData.f_biz }), // 函数:可读主表数据
|
|
920
|
+
},
|
|
921
|
+
commonParams: { ... }, // 所有明细包都带的公共参数
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
merge 进明细包的 `data`(与 `{id, attachmentType, thirdtabm}` 合并)。
|
|
925
|
+
|
|
926
|
+
> 函数形态可拿到 `ctx.masterData`(第 2 步取回的主表数据)—— 这是「主表先查」顺带带来的能力。
|
|
927
|
+
>
|
|
928
|
+
> 兜底开关(可选):`useSourceScriptParam: true` 尝试在 form-render 上下文执行源模板 data-table 的 `formScriptParam`,`try/catch` 失败则忽略;不作为默认。
|
|
929
|
+
|
|
930
|
+
### 10.5.7 配置全貌
|
|
931
|
+
|
|
932
|
+
```js
|
|
933
|
+
formRef.enableCompareBySource(搜索框的值, {
|
|
934
|
+
sourceFormCode: '订单formCode', // ★ 跨表必填,否则按变更单模板枚举子表 → 明细取不到
|
|
935
|
+
|
|
936
|
+
// 主表定位(兼容编码/ID)
|
|
937
|
+
sourceKeyField: 'id', // 主表包用哪个字段查,默认 'id'
|
|
938
|
+
sourceIdField: 'id', // 从主表响应取真实主键的字段名,默认 'id'
|
|
939
|
+
// sourceIdIsKey: true, // 明确传的就是 id → 走并行快路径
|
|
940
|
+
|
|
941
|
+
// 明细额外查询参数
|
|
942
|
+
subParams: { '订单明细': { f_status: 1 } },
|
|
943
|
+
// commonParams: {...},
|
|
944
|
+
|
|
945
|
+
// 跨表映射(场景B)
|
|
946
|
+
compareMapping: { master: [...], subs: [...] },
|
|
947
|
+
// transformOldData: (oldData, sourceTpl) => 归一化后的oldData, // 值转换兜底
|
|
948
|
+
});
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
模式 A(`initChangeFromSource`)同样接收上述选项 —— 跨表时**填充变更单也必须走映射**,否则字段名对不上、数据填不进去。
|
|
952
|
+
|
|
953
|
+
### 10.5.8 语义/边界
|
|
954
|
+
|
|
955
|
+
| 情况 | 处理 |
|
|
956
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
957
|
+
| 源单有、变更单没有的字段 | 映射表不写 → 白名单天然忽略 |
|
|
958
|
+
| 变更单有、源单没有的字段 | 不写就不比;写了 `to` 但源无 `from` → 旧值空 → 显示「变更前:(空)」 |
|
|
959
|
+
| 源明细有、变更单未匹配上 | → 进「查看删除明细」(源单有、当前未引用) |
|
|
960
|
+
| 变更单明细有、源单未匹配上 | → 标「新增行」(绿) |
|
|
961
|
+
| **未映射的子表** | **完全不参与对比**(不高亮、删除列表为空)——不做这条会**满屏绿** |
|
|
962
|
+
| 值需要转换(单位/币种/编码体系) | 用 `transformOldData` 钩子 |
|
|
963
|
+
| 清洗 `sanitizeChangeData` | 作用在**归一化后**的数据上,系统字段清理/树表 id 重生成/附件白名单照常工作;`subSourceFields` 回填订单明细 id 依然推荐(给出硬引用,将来行匹配可从业务键切到来源明细 id) |
|
|
964
|
+
|
|
965
|
+
### 10.5.9 改动清单(8 项,已全部实现)
|
|
966
|
+
|
|
967
|
+
| # | 改动 | 落地方法 |
|
|
968
|
+
| --- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
969
|
+
| 1 | ✅ `compareMapping` + 源数据归一化到变更单键空间 | `normalizeBySourceMapping(srcData, mapping)` → `{ data, includeFields, rowKeyMap }` |
|
|
970
|
+
| 2 | ✅ 白名单对比(由 mapping 的 `to` 自动推导) | 状态 `compareIncludeFields`;`isCompareExcludeField` 改为「白名单优先:设了白名单则不在名单内一律排除,黑名单失效」。wrapper 的 `compareExcluded` 与行级 `isCompareRowValuesChanged` 都走这一个判定 |
|
|
971
|
+
| 3 | ✅ `compareRowKey` 按子表配置 | 状态 `compareSubRowKeys`(由 `rowKey.to` 自动推导,可被 `options.subRowKeys` 覆盖);新增 `getCompareRowKeyOf(subFormName)`,`applyCompareSubSnapshot / getCompareRowClass / getDelData` 全部改用它 |
|
|
972
|
+
| 4 | ✅ 未映射子表不参与对比 | 新增 `isCompareSubTable(subFormName)`(判据:旧数据里有无该子表数组);`getCompareRowClass` 返回 `''`、`getDelData` 返回 `[]`。单元格侧因 `hData` 缺失 → `compareRowIsNew` → 天然不显示感叹号 |
|
|
973
|
+
| 5 | ✅ `initChangeFromSource` 接入映射 | 先 `applyCompareSourceTransform` 归一化,再 `sanitizeChangeData` → `setFormData` → `enableCompare` |
|
|
974
|
+
| 6 | ✅ `transformOldData` 钩子 | `applyCompareSourceTransform` 里,归一化之后调用 `options.transformOldData(data, srcData)` |
|
|
975
|
+
| 7 | ✅ `loadOldData` 主表先查 → 用真实 id 查明细 | 串行:主表包 `data:{[sourceKeyField]: 入参}` → `masterId = objx[sourceIdField]` → 再并行发表头附件包/明细包。`sourceIdIsKey:true` 可走并行快路径;主表查不到或取不到主键则不发明细包 |
|
|
976
|
+
| 8 | ✅ 明细额外查询参数透传 | `commonParams` + `subParams`(对象或 `(ctx)=>对象`,`ctx.masterData/masterId`)merge 进明细包 `data` |
|
|
977
|
+
|
|
978
|
+
**向后兼容**:不配 `compareMapping` 时 `applyCompareSourceTransform` 原样返回,`compareIncludeFields=null` → 走黑名单,`compareSubRowKeys={}` → 走全局 `compareRowKey`,`isCompareSubTable` 对已有子表恒为 true。**同表场景(现有模式 A/B)行为不变**,仅 `loadOldData` 多一次串行等待(可用 `sourceIdIsKey:true` 消除)。
|
|
979
|
+
|
|
980
|
+
## 十一、说明 / 注意事项
|
|
981
|
+
|
|
982
|
+
- **对比图标注入点**:统一在 `form-item-wrapper.vue`,覆盖主表字段与三类表格容器的单元格(均经 field-widget + tableParam.row 渲染);仅对比态包裹 compareView,非对比态零改动。
|
|
983
|
+
- **「查看删除数据」按钮**:未在容器工具栏内置,由业务按钮 onClick 调 `openCompareDelList('子表名')` 触发(更灵活)。
|
|
984
|
+
- **子表快照时序**:`enableCompare`/`setOldSubData` 对当前已加载行打 `hData` 快照;若子表在开启对比后才异步加载,需在其加载完成后再调一次 `setOldSubData` 补快照(多包流程天然满足)。
|
|
985
|
+
- **vxe data-table 行引用**:依赖 `formDataModel[子表名]` 与表格行同引用,`hData` 才能被单元格读到——建议用真实带子表的变更单验证。
|
|
986
|
+
- **性能**:大子表逐行 deepClone `hData`,行数极大时需评估(可改为只存差异或懒计算)。
|