瀏覽代碼

修改CURD窗口界面。

YangZhiJie 1 年之前
父節點
當前提交
e9d9e33975

+ 2 - 6
src/resource/dictionary/WindowServerUtil.js

@@ -146,11 +146,8 @@ export default {
 
 
   // 根据windowId查询TabId
-  newModelData: function (windowNo, tabIndex, success, error, uuid) {
-    var cacheUuid = null;
-    if (uuid != undefined && uuid != '') {
-      cacheUuid = uuid;
-    }
+  newModelData: function (windowNo, tabIndex, success, error) {
+    
 
     $.ajax({
       type: 'get',
@@ -158,7 +155,6 @@ export default {
       data: {
         windowNo: windowNo,
         tabIndex: tabIndex,
-        uuid: cacheUuid,
       },
       beforeSend: function (request) {
         Common.addTokenToRequest(request);

+ 12 - 1
src/routes/main_routes.js

@@ -5,9 +5,10 @@ const Window = () => import(/* webpackChunkName: "component-2" */ '../window/Win
 
 const Window1 = () => import(/* webpackChunkName: "component-2" */ '../window1/Window.vue');
 const TabFormEdit1 = () => import(/* webpackChunkName: "component-4" */ '../window1/tabFormEdit/TabFormEdit.vue');
+const TabFormEditModal = () => import(/* webpackChunkName: "component-4" */ '../window1/tabFormEdit/TabFormEditModal.vue');
 const TabFormView1 = () => import(/* webpackChunkName: "component-5" */ '../window1/tabFormView/TabFormView.vue');
 
-
+;
 const SheetWindow = () => import(/* webpackChunkName: "component-3" */ '../sheetWindow/SheetWindow.vue');
 const TabFormEdit = () => import(/* webpackChunkName: "component-4" */ '../window/tabFormView/TabFormEdit.vue');
 const TabFormView = () => import(/* webpackChunkName: "component-5" */ '../window/tabFormView/TabFormView.vue');
@@ -58,6 +59,7 @@ const ContainerLayout = () => import(/* webpackChunkName: "component-test-1" */
 const DynamicImport = () => import(/* webpackChunkName: "component-test-2" */ '../../test/DynamicImport.vue');
 const Test = () => import(/* webpackChunkName: "component-test-4" */ '../../test/Test.vue');
 const Training = () => import(/* webpackChunkName: "component-test-5" */ '../../test/Training.vue');
+const TabFormEditModalTest = () => import(/* webpackChunkName: "component-test-5" */ '../../test/window1/TabFormEditModalTest.vue');
 const DataArchive = () => import('../archive/DataArchive.vue');
 const ArchivalRecord = () => import('../archive/ArchivalRecord.vue');
 const ExcelImport = () => import('../customer/ExcelImport.vue');
@@ -156,6 +158,10 @@ export default [
       { path: 'window1/:windowNo', component: Window1 },
 
       // CRUD编辑窗口
+      // eslint-disable-next-line
+      { path: 'window1/TabFormEditModal', component: TabFormEditModal },
+      
+
       // eslint-disable-next-line
       { path: 'window1/window-edit/:type/:uuid', component: TabFormEdit1 },
       // eslint-disable-next-line
@@ -350,6 +356,11 @@ export default [
 
 
       { path: '/test', component: Test },
+      { path: '/TabFormEditModalTest', component: TabFormEditModalTest },
+
+
+      
+
       { path: '/webrt', component: WebRtcCapture },
       { path: '/WebSocketCapture', component: WebSocketCapture },
       { path: '/cropper', component: Cropper },

+ 0 - 3
src/window/tabFormView/TabFormEdit.vue

@@ -345,7 +345,6 @@ export default {
       cancelCommand: false, // 取消命令
       fixedButtonGroupHeight: 0,
       selectedTabIndex: 0, // 选择的页签序号
-      cacheUuid: '',
 
       // 工作流定义Id
       processDefinitionId: '',
@@ -669,7 +668,6 @@ export default {
       this.currIndex = Number(this.$route.query.currIndex);
       this.totalCount = Number(this.$route.query.totalCount);
       this.uuid = this.$route.query.uuid;
-      this.cacheUuid = this.$route.query.cacheUuid;
       this.workflowType = this.$route.query.workflowType;
       this.taskInfoId = this.$route.query.taskInfoId;
       this.isRestoreData = this.$route.query.isRestoreData;
@@ -750,7 +748,6 @@ export default {
                 _self.loading = false;
               }
             },
-            _self.cacheUuid,
           );
         },
         function () {

+ 13 - 15
src/window1/attachment/AttachmentPanel.vue

@@ -1,24 +1,20 @@
 <template>
-  <div class="container-fluid">
-    <div>
-      <h4 class="m-h4">
+  <div>
+    <div class="page-header">
+      <h4 style="display: inline-block">
         {{ $t("lang.attachmentPanel.attachment") }}
-        <a role="button" class="btn btn-primary" @click="addAttachment()">
-          <i class="fa fa-upload" />&nbsp;{{
-            $t("lang.attachmentPanel.addAttachment")
-          }}
-        </a>
       </h4>
+      <a-button type="link" @click="addAttachment">
+        {{ $t("lang.attachmentPanel.addAttachment") }}
+      </a-button>
     </div>
-    <Modal
-      v-model:show="attachmentUploadModal"
+    <a-modal
+      v-model:open="attachmentUploadModal"
       :show-ok-button="false"
-      full="true"
+      width="100%"
+      :title="$t('lang.attachmentPanel.uploadAttachment')"
       @cancel="showAttachmentUpload = false"
     >
-      <template #header>
-        {{ $t("lang.attachmentPanel.uploadAttachment") }}
-      </template>
       <AttachmentUpload
         v-if="showAttachmentUpload"
         :class-name="className"
@@ -29,7 +25,9 @@
         @upload-success="refresh"
         @get-file="getFile"
       />
-    </Modal>
+    </a-modal>
+
+
     <div class="row">
       <div
         v-for="(fileProperty, index) in fileProperties"

+ 0 - 3
src/window1/tabFormEdit/TabFormEdit.vue

@@ -345,7 +345,6 @@ export default {
       cancelCommand: false, // 取消命令
       fixedButtonGroupHeight: 0,
       selectedTabIndex: 0, // 选择的页签序号
-      cacheUuid: '',
 
       // 工作流定义Id
       processDefinitionId: '',
@@ -669,7 +668,6 @@ export default {
       this.currIndex = Number(this.$route.query.currIndex);
       this.totalCount = Number(this.$route.query.totalCount);
       this.uuid = this.$route.query.uuid;
-      this.cacheUuid = this.$route.query.cacheUuid;
       this.workflowType = this.$route.query.workflowType;
       this.taskInfoId = this.$route.query.taskInfoId;
       this.isRestoreData = this.$route.query.isRestoreData;
@@ -750,7 +748,6 @@ export default {
                 _self.loading = false;
               }
             },
-            _self.cacheUuid,
           );
         },
         function () {

+ 2457 - 0
src/window1/tabFormEdit/TabFormEditModal.vue

@@ -0,0 +1,2457 @@
+<!-- 页签表单编辑视图 -->
+<template>
+  <a-modal :open="open" @update:open="$emit('update:open', $event)">
+    <template #title>
+      <!-- header -->
+      <div class="row" style="height: 50px;">
+        <div class="col-md-12">
+          <h3>
+            <a class="a-back">
+              {{ Language.getNameTrl($i18n.locale, window) }}
+            &nbsp;</a>/&nbsp;{{ subTitle() }}
+            <div v-show="type != 'create'" class="btn-group" role="group">
+              <button type="button" class="btn btn-default" @click="pre">
+                <span class="glyphicon glyphicon-chevron-left" aria-hidden="true" />
+              </button>
+              <button type="button" class="btn btn-default">
+                {{ currIndex }}/{{ totalCount }}
+              </button>
+              <button type="button" class="btn btn-default" @click="next">
+                <span class="glyphicon glyphicon-chevron-right" aria-hidden="true" />
+              </button>
+            </div>
+          </h3>
+        </div>
+      </div>
+    </template>
+    <template #footer />
+    <div>
+      <div v-show="showSpaceRow" class="row">
+        <div class="col-md-12">
+          <div class="m-space-btn-group" />
+        </div>
+      </div>
+      <div v-show="!showApproveComment" ref="fixedButtonGroup" class="row m-row fixed-btn-group">
+        <a-float-button-group shape="square" :style="{ left: '10px', top: '10px'}">
+          <a-float-button v-if="allowCreate" :description="$t('lang.tabFormEdit.save')" @click="saveTabData">
+            <template #icon>
+              <SaveOutlined />
+            </template>
+          </a-float-button>
+
+          <a-float-button v-if="allowCreate" :description="$t('lang.tabFormEdit.revert')" @click="cancelModel">
+            <template #icon>
+              <RotateLeftOutlined />
+            </template>
+          </a-float-button>
+          
+          <a-float-button v-if="refreshFlag" :description="$t('lang.tabFormEdit.refresh')" @click="loadData">
+            <template #icon>
+              <ReloadOutlined />
+            </template>
+          </a-float-button>
+
+          
+          <a-float-button
+            v-if="window.htmlHelpUrl != null && window.htmlHelpUrl != ''"
+            @click="openHtmlHelp(window.htmlHelpUrl)"
+          >
+            <template #icon>
+              <SyncOutlined />
+            </template>
+          </a-float-button>
+
+
+          <a-back-top :visibility-height="0" />
+        </a-float-button-group>
+
+  
+        <div class="col-md-12">
+          <div class="btn-group">
+            <TabButton
+              ref="tabButton" :show-tab-dto="tab" :model-data="modelData" :uuid="uuid" :view-type="'EditForm'"
+              :type="type" :tab-buttons="tab.tabFormView ? tab.tabFormView.tabButtons : null" @save-view="backupView"
+              @model-data-changed="modelDataChanged"
+            />
+            <FormFieldDef
+              :tab-form-fields="tabFormFields" :window-no="windowNo" :tab-index="tabIndex"
+              @tab-form-field-property-changed="
+                tabFormFieldPropertyChanged($event)
+              "
+            />
+          </div>
+        </div>
+      </div>
+      <div v-show="showApproveComment" ref="fixedButtonGroup" class="row m-row fixed-btn-group">
+        <a-float-button-group shape="square" :style="{ right: '94px' }">
+          <a-float-button v-if="isView == true && windowDisplayType == 'Grid'" @click="changeWindowDisplayType">
+            <template #icon>
+              <QuestionCircleOutlined />
+            </template>
+            {{ $t("lang.tabFormEdit.formView") }}
+          </a-float-button>
+          <a-float-button />
+
+          <a-float-button>
+            <template #icon>
+              <SyncOutlined />
+            </template>
+          </a-float-button>
+          <a-back-top :visibility-height="0" />
+        </a-float-button-group>
+
+
+  
+        <div class="col-md-12">
+          <div class="btn-group">
+            <button
+              type="button" class="btn btn-default"
+            />
+            <button
+              v-if="isView == true && windowDisplayType == 'Report'" type="button" class="btn btn-default"
+              @click="changeWindowDisplayType"
+            >
+              {{ $t("lang.tabFormEdit.reportView") }}
+            </button>
+          </div>
+        </div>
+      </div>
+      <div v-if="windowDisplayType == 'Grid'">
+        <div v-if="tab != null && tab.tabFormView != null" class="m-row clearfix">
+          <div class="col-xs-12">
+            <div
+              v-if="singleColumn" :class="{
+                'form-inline': tab.tabFormView.multipleColumn,
+                'form-horizontal': !tab.tabFormView.multipleColumn,
+              }"
+            >
+              <template v-for="fieldItem in tabFormFields">
+                <FieldEditView
+                  v-if="tab.tabDataSource" ref="fieldItem1" :key="'FieldEditView_' +
+                    windowNo +
+                    '_' +
+                    tabIndex +
+                    '_' +
+                    fieldItem.fieldName +
+                    '_' +
+                    fieldItem.entityFieldIndex
+                  " :class-name="tab.tabDataSource.className" :field="fieldItem" :model-data="modelData"
+                  :window-no="windowNo" :tab-index="tabIndex" :js-url="jsUrl"
+                  :is-chinese-english="window.isChineseEnglish" :multiple-column="tab.tabFormView.multipleColumn"
+                  @value-changed="valueChanged($event, fieldItem)" @execute-callout="executeCallout(fieldItem)"
+                />
+              </template>
+            </div>
+          </div>
+        </div>
+
+        <div
+          v-if="
+            tab != null &&
+              tab.tabFormView != null &&
+              tab.tabFormView.fieldGroups != null &&
+              tab.tabFormView.fieldGroups.length > 0
+          " class="m-row clearfix"
+        >
+          <ul id="myTabs" class="nav nav-tabs" role="tablist">
+            <li
+              v-for="(fieldGroup, fieldGroupIndex) in tab.tabFormView.fieldGroups" :key="fieldGroup.groupName"
+              role="presentation" :class="{ active: selectedTabIndex == fieldGroupIndex }"
+              @click="selectedTabIndex = fieldGroupIndex"
+            >
+              <a :id="'tab-' + fieldGroupIndex" role="tab" data-toggle="tab" aria-controls="home" aria-expanded="true">
+                {{ Language.getGroupNameTrl($i18n.locale, fieldGroup) }}
+              </a>
+            </li>
+          </ul>
+          <div id="myTabContent" class="tab-content">
+            <div
+              v-for="(fieldGroup, fieldGroupIndex) in tab.tabFormView.fieldGroups"
+              v-show="selectedTabIndex == fieldGroupIndex" id="home" :key="fieldGroup.groupName" role="tabpanel"
+              class="tab-pane fade active in" aria-labelledby="home-tab"
+            >
+              <div v-if="fieldGroup.show">
+                <div
+                  :class="{
+                    'form-inline': tab.tabFormView.multipleColumn,
+                    'form-horizontal': !tab.tabFormView.multipleColumn,
+                  }"
+                >
+                  <template v-for="fieldItem in fieldGroup.fields">
+                    <FieldEditView
+                      v-if="tab.tabDataSource" ref="fieldItem2" :key="'FieldEditView_' +
+                        windowNo +
+                        '_' +
+                        tabIndex +
+                        '_' +
+                        fieldItem.fieldName +
+                        '_' +
+                        fieldItem.entityFieldIndex
+                      " :class-name="tab.tabDataSource.className" :field="fieldItem" :model-data="modelData"
+                      :window-no="windowNo" :tab-index="tabIndex" :js-url="jsUrl"
+                      :is-chinese-english="window.isChineseEnglish" :multiple-column="tab.tabFormView.multipleColumn"
+                      @value-changed="valueChanged($event, fieldItem)" @execute-callout="executeCallout(fieldItem)"
+                    />
+                  </template>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <template v-if="modelData != null">
+          <div
+            v-for="subTab in tab.subTabs"
+            :id="'SubTabGridEdit-' + windowNo + '-' + tabIndex + '-' + modelData.id + '-subTab-' + subTab.tabIndex"
+            :key="'SubTabGridEdit-' + windowNo + '-' + tabIndex + '-' + modelData.id + '-subTab-' + subTab.tabIndex"
+            class="row clearfix"
+          >
+            <div class="col-md-12">
+              <SubTabGridEdit
+                :ref="'subTab' + subTab.tabIndex" :window-no="windowNo" :tab-index="subTab.tabIndex"
+                :fixed-button-group-height="fixedButtonGroupHeight" :tab="subTab" :parent-model-data="modelData"
+                :parent-tab="tab" :js-url="jsUrl" :is-chinese-english="window.isChineseEnglish" @save-view="backupView"
+                @refresh-parent="refreshParent" @change-root-parent-model-data="changeRootParentModelData"
+              />
+            </div>
+          </div>
+        </template>
+      </div>
+      <div v-else style="height: 400px; overflow: scroll">
+        <ProcessReportResultPreview
+          v-if="
+            processReportResult != null &&
+              (processReportResult.reportResults != null ||
+                processReportResult.processResult != null)
+          " :process-report-result="processReportResult" :pdf-only="false" :excel-only="false"
+        />
+      </div>
+
+      <div v-if="attributeKey != null && attributeKey != ''" class="row clearfix">
+        <div class="col-md-12">
+          <AttributePanel
+            ref="attributePanel" :attribute-key="attributeKey" :attribute-value-key="attributeValueKey"
+            :window-no="windowNo"
+          />
+        </div>
+      </div>
+
+      <div
+        v-if="
+          window != null &&
+            tab != null &&
+            tab.tabDataSource != null &&
+            !window.hideCreateRecordButton
+        " class="row clearfix"
+      >
+        <AttachmentPanel
+          v-if="type == 'edit' && tab.tabDataSource" :class-name="tab.tabDataSource.className"
+          :record-id="recordId" :tab-index="tabIndex" :window-no="windowNo"
+        />
+      </div>
+
+      <div v-if="showApproveComment" class="row clearfix">
+        <div class="col-md-12">
+          <ApproveComment
+            ref="approveComment" :workflow-type="'UserDefine'" :parent-widget="'TabFormEdit'"
+            :work-flow="window.workflow" :window-no="windowNo" :process-definition-id="processDefinitionId"
+            :show-choice-button="showChoiceButton" :process-instance-id="processInstanceId" :task-info-id="taskInfoId"
+            :record-id="modelData.id" :show-tab-dto="tab" :model-data="modelData" :uuid="uuid"
+            :workflow-class-name="tab.tabDataSource.className" @save-data="saveTabData"
+          />
+        </div>
+      </div>
+
+      <!-- 历史审批记录 -->
+      <div v-if="modelData != null" class="row clearfix">
+        <div class="col-md-12">
+          <HistoryApproveComment :record-id="modelData.id" :process-instance-id="processInstanceId" />
+        </div>
+      </div>
+
+      <a-modal v-model:open="modal1" :title="$t('lang.tabFormEdit.validateError')">
+        <div>
+          {{ $t("lang.tabFormEdit.validateError", { errorCount: errorCount, errorMsg: errorMsg, }) }}
+        </div>
+      </a-modal>
+
+      <a-modal v-model:open="modal2" :title="$t('lang.tabFormEdit.describe3')" @ok="dataRestore()" @cancel="cancelRestore()">
+        <div>{{ $t("lang.tabFormEdit.describe4") }}</div>
+      </a-modal>
+
+      <a-modal v-model:open="modal3" :title="$t('lang.tabFormEdit.describe5')" @ok="cancelOk()" @cancel="cancelNo()">
+        <div>{{ $t("lang.tabFormEdit.describe6") }}</div>
+      </a-modal>
+      <Loading v-if="loading" />
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import Common from '../../common/Common.js';
+
+import WindowServerUtil from '../../resource/dictionary/WindowServerUtil.js';
+import WindowClientUtil from '../../resource/dictionary/WindowClientUtil.js';
+import TabFormView from '../tabFormView/TabFormView.js';
+import FieldUtil from '../../resource/dictionary/FieldUtil.js';
+
+import Context from '../common/Context.js';
+import ProcessReportResource from '../../api/dic/ProcessReportResource.js';
+import CurdWindowResource from '../../api/dic/CurdWindowResource.js';
+import UserStorageResource from '../../api/base/UserStorageResource.js';
+import Language from '../../common/Language.js';
+
+import SubTabGridEdit from '../tabGridView/SubTabGridEdit.vue';
+import FieldEditView from './TabFormFieldEdit.vue';
+import TabButton from '../tabView/TabButton.vue';
+import FormFieldDef from '../tab-form-common/FormFieldDef.vue';
+import AttachmentPanel from '../attachment/AttachmentPanel.vue';
+
+import AttributePanel from '../attribute/AttributePanel.vue';
+import HistoryApproveComment from '../../workflow/HistoryApproveComment.vue';
+import ApproveComment from '../../workflow/ApproveComment.vue';
+
+import DataRecoveryResource from '../../api/base/DataRecoveryResource.js';
+import JsUtil from '../../common/JsUtil.js';
+import { Notify } from 'pc-component-v3';
+import { SaveOutlined, RotateLeftOutlined, ReloadOutlined, SyncOutlined, QuestionCircleOutlined } from '@ant-design/icons-vue';
+export default {
+  components: {
+    SubTabGridEdit,
+    FieldEditView,
+    TabButton,
+    FormFieldDef,
+    AttachmentPanel,
+    AttributePanel,
+    ApproveComment,
+    HistoryApproveComment,
+    SaveOutlined,
+    RotateLeftOutlined, 
+    ReloadOutlined,
+    SyncOutlined,
+    QuestionCircleOutlined,
+  },
+
+  /**
+       * 在离开路由之前,检验数据是否已保存
+       */
+  beforeRouteLeave: function (to, from, next) {
+    var _self = this;
+    if (_self.windowDisplayType == 'Grid') {
+      if (_self.cancelCommand == false && _self.isModelDataChanged() == true) {
+        Notify.notice(_self.$t('lang.tabFormEdit.dataNotSaved'), _self.$t('lang.tabFormEdit.describe1'), false);
+        next(false);
+      } else {
+        next();
+      }
+    } else {
+      next();
+    }
+    if (_self.autoSaveInterval != null) {
+      clearInterval(_self.autoSaveInterval);
+    }
+  },
+  
+  props: {
+    open: {
+      type: Boolean,
+      default: false,
+    },  
+    // CURD窗口Id
+    windowNo: {
+      type: String,
+      default: '',
+    },
+    // 页签编号
+    tabIndex: {
+      type: Number,
+      default: 0,
+    },
+    // 数据记录Id
+    modelDataId:{
+      type: Number,
+      default: null,
+    },
+    // 窗口类型(create:创建数据,edit:编辑数据,restore:恢复数据)
+    type: {
+      type: String,
+      default: '',
+    },
+    // 当前记录所在的页码
+    currentPage: {
+      type: Number,
+      default: 0,
+    },
+    // 当前记录的排序
+    currentIndex:{
+      type: Number,
+      default: 0,
+    },
+    // 记录的总数量
+    totalRecords:{
+      type: Number,
+      default: 0,
+    },
+    // 窗口唯一Id(必须是唯一的)
+    uuid: {
+      type: String,
+      default: '',
+    },
+    // 是否恢复草稿数据(false:不恢复,true:恢复)
+    isRestoreData: {
+      type: Boolean,
+      default: false,
+    }, 
+    // 工作流任务Id(taskId)
+    taskInfoId: {
+      type: String,
+      default: null,
+    },
+    // 工作流任务类型(approve:审批任务,copyTask:抄送任务)
+    workflowType: {
+      type: String,
+      default: null,
+    },
+  },
+  emits: ['update:open', 'OpenTabFormView'],
+  data: function () {
+    this.Language = Language;
+    return {
+      recordId: '', // 记录Id
+      window: {}, // 窗口数据
+      tab: {}, // 父页签
+      tabFormFields: [],
+      modelData: {},
+      errorCount: 0, // 校验错误数量
+      errorMsg: '', // 校验错误信息
+      error: 0,
+      currPage: 1,
+      attributeKey: null,
+      attributeValueKey: null,
+      currIndex: 0,
+      totalCount: 0,
+      buttonGroupInitLeft: 0,
+      buttonGroupInitTop: 0,
+      showSpaceRow: false,
+      filterParams: null,
+      cancelCommand: false, // 取消命令
+      fixedButtonGroupHeight: 0,
+      selectedTabIndex: 0, // 选择的页签序号
+      processDefinitionId: '', // 工作流定义Id
+      processInstanceId: undefined,
+      windowDisplayType: 'Grid', // 显示类型
+      processReportResult: undefined,
+      isView: true, // 是否显示模式切换按钮
+      autoSaveInterval: null, // 自动保存定时器
+      dataRecoveryDto: undefined,
+      jsUrl: null,
+      loading: false,
+      modal1: false,
+      modal2: false,
+      modal3: false,
+      refreshFlag: false,
+    };
+  },
+
+  computed: {
+    /**
+         * 是否允许新建
+         * tab
+         */
+    allowCreate: function () {
+      var _self = this;
+      var allTabReadOnly = true;
+      // 如果所有的页签都是只读
+      if (_self.window != undefined && _self.window.tabs != undefined) {
+        for (
+          var tabIndex = 0; tabIndex < _self.window.tabs.length; tabIndex++
+        ) {
+          if (
+            _self.window.tabs[tabIndex].isReadOnly == undefined ||
+            _self.window.tabs[tabIndex].isReadOnly == false
+          ) {
+            allTabReadOnly = false;
+            break;
+          }
+        }
+      }
+      return !allTabReadOnly;
+    },
+
+    /**
+         * 页签是否单列
+         */
+    singleColumn: function () {
+      var _self = this;
+      if (_self.tab.multipleColumn == true) {
+        return false;
+      } else {
+        return true;
+      }
+    },
+
+    /**
+         * 是否显示审批面板
+         * 处于审批中的单据,显示审批面板
+         */
+    showApproveComment: function () {
+      // 判断是否显示审批按钮
+      if (
+        this.window != undefined &&
+        this.window.hasWorkflow != undefined &&
+        this.modelData != undefined &&
+        this.modelData.data != undefined &&
+        this.modelData.data.processInstanceId != undefined &&
+        this.modelData.data.processInstanceId.displayValue != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0] != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0].length > 0
+      ) {
+        return true;
+      }
+      return false;
+    },
+
+    /**
+         * 是否显示审批评论面板
+         * 审批完成的单据,显示审批评论面板
+         */
+    showChoiceButton: function () {
+      if (
+        this.window != undefined &&
+        this.window.workflow != undefined &&
+        this.modelData != undefined &&
+        this.modelData.data != undefined &&
+        this.modelData.data.processInstanceId != undefined &&
+        this.modelData.data.processInstanceId.displayValue != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0] != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0].length > 0 &&
+        this.modelData.data.documentStatus != undefined &&
+        this.modelData.data.documentStatus.displayValue != undefined &&
+        this.modelData.data.documentStatus.displayValue[0] != undefined &&
+        this.modelData.data.documentStatus.displayValue[0].length > 0 &&
+        this.modelData.data.documentStatus.displayValue[0] == 'PROCESSING' &&
+        this.taskInfoId != undefined &&
+        this.workflowType != 'copyTask'
+      ) {
+        return true;
+      }
+      return false;
+    },
+  },
+
+  watch: {
+    open: function(currentValue, oldValue){
+      if(currentValue === true){
+        this.initView();
+      }
+    },  
+    modelData: {
+      deep: true,
+      handler(curVal, oldVal) {
+        var _self = this;
+        this.tabButtonsShowLogical();
+        this.reportViewsShowLogical();
+        if (_self.autoSaveInterval != null) {
+          clearInterval(_self.autoSaveInterval);
+          _self.autoSaveInterval = null;
+          _self.startSaveInterval();
+        } else {
+          _self.startSaveInterval();
+        }
+      },
+    },
+
+    /**
+     * 显示界面发生改变的时候,重新执行显示逻辑
+     */
+    windowDisplayType: function (newValue, oldValue) {
+      this.reportViewsShowLogical();
+    },
+  },
+
+  beforeCreate: function () {
+    console.log('WindowEdit beforeCreate.');
+  },
+
+  created: function () {
+    console.log('WindowEdit created.');
+  },
+
+  beforeMount: function () {
+    console.log('WindowEdit beforeMount.');
+  },
+
+  mounted: function () {
+    var _self = this;
+    console.log('WindowEdit mounted.');
+    this.initView();
+
+    // 按钮栏实现滚动
+    _self.$nextTick(function () {
+      // var fixedButtonGroup = $(_self.$refs.fixedButtonGroup);
+      // var buttonInitTop = fixedButtonGroup.offset().top;
+
+      // _self.fixedButtonGroupHeight = fixedButtonGroup.outerHeight();
+
+      // 按钮组实现悬浮
+      // $(window).scroll(function () {
+      //   var windowTop = $(window).scrollTop();
+      //   if (windowTop > buttonInitTop + fixedButtonGroup.outerHeight()) {
+      //     fixedButtonGroup.offset({
+      //       top: windowTop,
+      //       left: fixedButtonGroup.offset().left,
+      //     });
+      //   } else {
+      //     fixedButtonGroup.offset({
+      //       top: buttonInitTop,
+      //     });
+      //   }
+      // });
+    });
+
+    $(window).resize(function () {
+      _self.$nextTick(function () {
+        _self.computerButtonGroupLeftTop();
+      });
+    });
+
+    window.addEventListener('beforeunload', e => this.beforeunloadFn(e));
+  },
+
+  unmounted() {
+    window.removeEventListener('beforeunload', e => this.beforeunloadFn(e));
+    let _self = this;
+    if (_self.autoSaveInterval != null) {
+      clearInterval(_self.autoSaveInterval);
+    }
+  },
+
+  methods: {
+    /**
+         * 删除草稿数据
+         * @author GuoZhiBo 20210926
+         */
+    deleteDataRecoveryDto: function () {
+      var _self = this;
+      if (_self.autoSaveInterval != null) {
+        clearInterval(_self.autoSaveInterval);
+        _self.autoSaveInterval = null;
+      }
+      _self.dataRecoveryDto = {
+        windowId: _self.windowNo,
+        type: _self.type,
+      };
+      DataRecoveryResource.deleteDataRecoveryDto(_self.dataRecoveryDto).then(
+        successData => {
+          if (successData != null) {
+            console.log('删除自动保存数据失败。');
+          }
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+    /**
+         * 恢复草稿数据
+         * @author GuoZhiBo 20210926
+         */
+    dataRestore: function () {
+      var _self = this;
+      _self.restoreModelData(_self.dataRecoveryDto.modelData);
+      _self.modal2 = false;
+    },
+    /**
+         * 恢复modelData数据
+         * @param {Object} cacheModelData
+         * @author GuoZhiBo 20210926
+         */
+    restoreModelData: function (cacheModelData) {
+      var _self = this;
+      // 恢复父页签的数据
+      cacheModelData.restore = true;
+      _self.modelData = cacheModelData;
+      _self.$nextTick(function () {
+        if (
+          cacheModelData.saveDatas != undefined &&
+          cacheModelData.saveDatas.length > 0
+        ) {
+          // bug fixed by jack 2021-10-08
+          // 子页签修改的时候,不会影响父页签的属性,如果直接使用saveDatas,那么子页签属性发生改变的时候,deep watch parentModelData 也会发生改变。
+          const saveDatasTemp = cacheModelData.saveDatas;
+          cacheModelData.saveDatas = null;
+
+          saveDatasTemp.forEach(function (saveData) {
+            // 恢复子页签的数据
+            var subTabId = 'subTab' + saveData.tabIndex;
+            var tabElements = _self.$refs[subTabId];
+            if (tabElements && tabElements.length > 0) {
+              var tabElement = tabElements[0];
+              if (tabElement) {
+                saveData.editMode = true;
+                tabElement.addModelData(saveData);
+              }
+            }
+          });
+        } else {
+          // BUG描述:父子页签,编辑以后撤销,子页签数据不显示
+          // BUG修复:刷新子页签的数据
+          // bug fixed by jack 20180203
+
+          for (var index = 0; index < _self.tab.subTabs.length; index++) {
+            var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+            _self.$refs[subTabId][0].queryGridData();
+          }
+        }
+      });
+    },
+    /**
+         * 取消恢复
+         * @author GuoZhiBo 20210926
+         */
+    cancelRestore: function () {
+      var _self = this;
+      _self.modal2 = false;
+      //删除草稿数据
+      _self.deleteDataRecoveryDto();
+    },
+
+    /**
+         * 打开帮助页面
+         */
+    openHtmlHelp: function (htmlHelpUrl) {
+      window.open(htmlHelpUrl);
+    },
+
+    // 初始化界面
+    initView: function () {
+      console.debug('initView');
+
+      var _self = this;
+      this.recordId = this.modelDataId;
+      this.currPage = this.currentPage;
+      this.currIndex = this.currentIndex;
+      this.totalCount = this.totalRecords;
+      if (_self.type == 'edit') {
+        if (this.isRestoreData === true) {
+          this.restoreView();
+        } else {
+          this.initEditView();
+        }
+      } else if (this.type == 'create') {
+        this.initCreateView();
+      } else if (this.type == 'restore') {
+        // 恢复视图
+        this.restoreView();
+      }
+    },
+
+    // 初始化新建界面
+    initCreateView: function () {
+      var _self = this;
+
+      if (_self.$refs.loading != undefined) {
+        _self.loading = true;
+      }
+      DataRecoveryResource.queryDataRecoveryDtoByUserId(
+        _self.windowNo,
+        _self.type,
+      ).then(
+        successData => {
+          if (successData != null) {
+            _self.modal2 = true;
+            _self.dataRecoveryDto = successData;
+          }
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+
+      _self.processInstanceId = '';
+      WindowServerUtil.getWindowById(
+        _self.windowNo,
+        function (window) {
+          WindowClientUtil.parseFilterSchema(window);
+          var tab = WindowClientUtil.getTab(window, _self.tabIndex);
+          WindowClientUtil.parseSubTab(window, tab);
+          WindowClientUtil.parseFieldGroup(tab);
+          WindowClientUtil.restoreWindowTabFieldGroupsVisible(window);
+
+          _self.tabFormFields = WindowClientUtil.getDetailField(tab);
+          _self.window = window;
+          _self.jsUrl = window.jsUrl;
+          _self.tab = tab;
+          TabFormView.restoreTabFormFieldDef(
+            _self.windowNo,
+            _self.tabIndex,
+            _self.tabFormFields,
+          );
+
+          WindowServerUtil.newModelData(
+            _self.windowNo,
+            _self.tabIndex,
+            function (modelData) {
+              if (_self.$refs.loading != undefined) {
+                _self.loading = false;
+              }
+
+              modelData.editMode = true;
+
+              _self.modelData = modelData;
+              _self.recordId = undefined;
+              // add by jack 20180914
+              // 自动点击菜单
+              _self.autoClickMenu();
+            },
+            function () {
+              if (_self.$refs.loading != undefined) {
+                _self.loading = false;
+              }
+            },
+          );
+        },
+        function () {
+          if (_self.$refs.loading != undefined) {
+            _self.loading = false;
+          }
+        },
+      );
+    },
+
+    // 初始化编辑界面
+    initEditView: function () {
+      var _self = this;
+      _self.loading = true;
+      _self.processInstanceId = '';
+
+      if (_self.taskInfoId) {
+        CurdWindowResource.uniqueByNoWithWorkflow(
+          null,
+          _self.taskInfoId,
+          _self.windowNo,
+        ).then(
+          successData => {
+
+            initWindowAfterLoaded(successData);
+          },
+          errorData => {
+            _self.loading = false;
+            Common.processException(errorData);
+          },
+        );
+      } else {
+        WindowServerUtil.getWindowById(
+          _self.windowNo,
+          function (window) {
+            initWindowAfterLoaded(window);
+          },
+          function () {
+            _self.loading = false;
+          },
+        );
+      }
+
+      function initWindowAfterLoaded(window) {
+        WindowClientUtil.parseFilterSchema(window);
+        var tab = WindowClientUtil.getTab(window, _self.tabIndex);
+        WindowClientUtil.parseSubTab(window, tab);
+        WindowClientUtil.parseFieldGroup(tab);
+        WindowClientUtil.restoreWindowTabFieldGroupsVisible(window);
+
+        _self.tabFormFields = WindowClientUtil.getDetailField(tab);
+        _self.window = window;
+        _self.jsUrl = window.jsUrl;
+        _self.tab = tab;
+        TabFormView.restoreTabFormFieldDef(
+          _self.windowNo,
+          _self.tabIndex,
+          _self.tabFormFields,
+        );
+
+        if (_self.window.workflow != undefined && _self.modelData.id > 0) {
+          _self.processDefinitionId = _self.window.workflow.deploymentId;
+        }
+        if (
+          _self.window.reportViewDto != null &&
+          _self.window.reportViewDto.reportViewItemDtos != null &&
+          _self.window.reportViewDto.reportViewItemDtos.length > 0 &&
+          _self.workflowType == 'approve'
+        ) {
+          var isflag = false;
+          _self.window.reportViewDto.reportViewItemDtos.forEach(function (item) {
+            if (item.defaultDisplayReport) {
+              isflag = true;
+            }
+          });
+          if (isflag) {
+            _self.windowDisplayType = 'Report';
+          } else {
+            _self.windowDisplayType = 'Grid';
+          }
+        } else {
+          _self.windowDisplayType = 'Grid';
+          _self.isView = false;
+        }
+
+        _self.loading = false;
+        _self.loadData();
+      }
+    },
+    /**
+         * 切换显示模式
+         * @author GuoZhiBo 20210419
+         */
+    changeWindowDisplayType: function () {
+      var _self = this;
+      if (_self.windowDisplayType == 'Grid') {
+        _self.windowDisplayType = 'Report';
+      } else {
+        _self.windowDisplayType = 'Grid';
+        _self.$nextTick(function () {
+          for (var index = 0; index < _self.tab.subTabs.length; index++) {
+            var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+            _self.$refs[subTabId][0].queryGridData();
+          }
+        });
+      }
+    },
+
+    // 恢复视图
+    restoreView: function () {
+      let _self = this;
+      let key = _self.uuid + '_modelData';
+
+      _self.loading = true;
+      _self.processInstanceId = '';
+
+      WindowServerUtil.getWindowById(
+        _self.windowNo,
+        function (window) {
+          WindowClientUtil.parseFilterSchema(window);
+          var tab = WindowClientUtil.getTab(window, _self.tabIndex);
+          WindowClientUtil.parseSubTab(window, tab);
+          WindowClientUtil.parseFieldGroup(tab);
+          WindowClientUtil.restoreWindowTabFieldGroupsVisible(window);
+
+          _self.tabFormFields = WindowClientUtil.getDetailField(tab);
+          _self.window = window;
+          _self.jsUrl = window.jsUrl;
+          _self.tab = tab;
+          TabFormView.restoreTabFormFieldDef(
+            _self.windowNo,
+            _self.tabIndex,
+            _self.tabFormFields,
+          );
+
+          if (_self.window.workflow != undefined && _self.modelData.id > 0) {
+            _self.processDefinitionId = _self.window.workflow.deploymentId;
+          }
+
+          _self.loading = false;
+          if (_self.isRestoreData == true) {
+            DataRecoveryResource.queryDataRecoveryDtoByUserId(
+              _self.windowNo,
+              _self.type,
+            ).then(
+              successData => {
+                if (successData != null) {
+                  _self.restoreModelData(successData.modelData);
+                }
+              },
+              errorData => {
+                Common.processException(errorData);
+              },
+            );
+          } else {
+            UserStorageResource.uniqueByKey(key).then(
+              successData => {
+                // if(successData.errorCode != 0) {
+                //   Notify.error('提示', successData.errorMessage, false);
+                //   return;
+                // }
+                if (successData.data != null && successData.data != '') {
+                  let cacheModelData = JSON.parse(successData.data);
+
+                  cacheModelData.restore = true;
+
+                  // 恢复父页签的数据
+                  _self.modelData = cacheModelData;
+
+                  _self.$nextTick(function () {
+                    if (
+                      cacheModelData.saveDatas != undefined &&
+                      cacheModelData.saveDatas.length > 0
+                    ) {
+                      cacheModelData.saveDatas.forEach(function (saveData) {
+                        // 恢复子页签的数据
+                        var subTabId = 'subTab' + saveData.tabIndex;
+                        var tabElements = _self.$refs[subTabId];
+                        if (tabElements && tabElements.length > 0) {
+                          var tabElement = tabElements[0];
+                          if (tabElement) {
+                            tabElement.addModelData(saveData);
+                          }
+                        }
+                      });
+                    } else {
+                      // BUG描述:父子页签,编辑以后撤销,子页签数据不显示
+                      // BUG修复:刷新子页签的数据
+                      // bug fixed by jack 20180203
+
+                      for (
+                        var index = 0; index < _self.tab.subTabs.length; index++
+                      ) {
+                        var subTabId =
+                          'subTab' + this.tab.subTabs[index].tabIndex;
+                        _self.$refs[subTabId][0].queryGridData();
+                      }
+                    }
+                  });
+                  console.log(cacheModelData);
+                }
+              },
+              errorData => {
+                Common.processException(errorData);
+              },
+            );
+          }
+        },
+        function () {
+          _self.loading = false;
+        },
+      );
+    },
+
+    /**
+         * 数据发生改变
+         * eg:生单界面回传了新的modelData数据
+         */
+    modelDataChanged: function (newModelData) {
+      var _self = this;
+      // 恢复父页签的数据
+      newModelData.visible = true;
+      if (
+        newModelData.saveDatas != undefined &&
+        newModelData.saveDatas.length > 0
+      ) {
+        newModelData.saveDatas.forEach(function (item) {
+          item.visible = true;
+        });
+      }
+      // 恢复父页签的数据
+      _self.modelData = newModelData;
+
+      _self.$nextTick(function () {
+        if (
+          newModelData.saveDatas != undefined &&
+          newModelData.saveDatas.length > 0
+        ) {
+          let firstModelData = newModelData.saveDatas[0];
+
+          // 恢复子页签的数据
+          let subTabId = 'subTab' + firstModelData.tabIndex;
+          var tabElements = _self.$refs[subTabId];
+          if (tabElements && tabElements.length > 0) {
+            var tabElement = tabElements[0];
+            if (tabElement) {
+              tabElement.replaceModelDatas(newModelData.saveDatas);
+            }
+          }
+          // bug fixed by jack 2022-01-17
+          // 修复生单界面跳转回来以后,如果子页签 行数多的话,输入非常卡的BUG。
+          newModelData.saveDatas = null;
+        } else {
+          // BUG描述:父子页签,编辑以后撤销,子页签数据不显示
+          // BUG修复:刷新子页签的数据
+          // bug fixed by jack 20180203
+          for (var index = 0; index < _self.tab.subTabs.length; index++) {
+            let subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+            _self.$refs[subTabId][0].queryGridData();
+          }
+        }
+      });
+    },
+
+    /**
+         * 获取界面的数据
+         * eg:生单界面获取modelData数据
+         */
+    getModelData: function () {
+      var _self = this;
+      var subTabAllData = _self.getSubTabAllData();
+      if (subTabAllData.length > 0) {
+        _self.modelData.saveDatas = subTabAllData;
+      } else {
+        _self.modelData.saveDatas = null;
+      }
+      return _self.modelData;
+    },
+
+    executeProcess: function (processReportNo) {
+      var _self = this;
+      var ids = [];
+      if (_self.modelDatas) {
+        _self.modelDatas.forEach(function (modelData) {
+          if (modelData.select == true) {
+            ids.push(modelData.id);
+          }
+        });
+      } else if (_self.modelData) {
+        ids.push(_self.modelData.id);
+      }
+      ProcessReportResource.runProcessByIds(processReportNo, ids).then(
+        successData => {
+          var processReportResult = successData;
+          if (_self.processReportResult == undefined) {
+            if (
+              processReportResult.reportResults != undefined &&
+              processReportResult.reportResults.length > 0
+            ) {
+              processReportResult.reportResults.forEach(function (item, index) {
+                if (item.reportDefinitionType !== 'ExcelReport') {
+                  item.previewIndex = 1;
+                } else {
+                  item.previewIndex = 2;
+                }
+                if (index == 0) {
+                  item['showPreview'] = true;
+                } else {
+                  item['showPreview'] = false;
+                }
+              });
+            }
+            _self.processReportResult = processReportResult;
+          } else {
+            if (
+              processReportResult.reportResults != undefined &&
+              processReportResult.reportResults.length > 0
+            ) {
+              processReportResult.reportResults.forEach(function (item, index) {
+                item.previewIndex = 1;
+                if (index == 0) {
+                  item.showPreview = true;
+                } else {
+                  item.showPreview = false;
+                }
+                _self.processReportResult.reportResults.push(item);
+              });
+            }
+          }
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+    getContext: Context,
+
+    /**
+     * 报表视图显示逻辑
+     */
+    reportViewsShowLogical: function () {
+      var _self = this;
+
+      if (_self.windowDisplayType != 'Report') {
+        // add by jack 2023-12-05
+        // 如果不处于报表界面,那么不执行下述业务逻辑
+        return;
+      }
+
+      if (
+        _self.window.reportViewDto != null &&
+        _self.window.reportViewDto.reportViewItemDtos != null
+      ) {
+        _self.processReportResult = undefined;
+        for (
+          let index = 0; index < _self.window.reportViewDto.reportViewItemDtos.length; index++
+        ) {
+          let reportViewItemDto =
+            _self.window.reportViewDto.reportViewItemDtos[index];
+          var logic = reportViewItemDto.showLogical;
+          if (logic == null || logic == '') {
+            reportViewItemDto.invisible = false;
+            _self.executeProcess(reportViewItemDto.processReportNo);
+            return;
+          }
+
+          let functionName = 'form_view_showlogical_' + index;
+
+
+          const executeFunction = function () {
+            let actions = {
+              subTabsRef: _self.getSubTabs(),
+            };
+
+            let context = new _self.getContext(_self.modelData, actions);
+
+            try {
+              reportViewItemDto.invisible = !_self[functionName](context);
+
+              if (reportViewItemDto.invisible == false) {
+                _self.executeProcess(reportViewItemDto.processReportNo);
+              }
+
+            } catch (e) {
+              console.error(e);
+              Notify.error('数据字典定义异常', '【' + logic + '】报表显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+            }
+          };
+
+          if (this[functionName] == null) {
+            const jsUrl = this.jsUrl;
+            if (jsUrl == null || jsUrl == undefined) {
+              Notify.error('数据字典定义异常', '【' + logic + '】报表显示逻辑的JS文件不存在,请联系管理员检查数据字典是否存在JS文件', false);
+              return;
+            }
+            let promise = JsUtil.dynamicLoadJsFunction(jsUrl, logic);
+            promise.then(targetFunction => {
+              _self[functionName] = targetFunction;
+              if (targetFunction == null) {
+                Notify.error('数据字典定义异常', '【' + logic + '】报表显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+                return;
+              }
+
+
+
+              executeFunction();
+            }, errorData => {
+              console.error(errorData);
+            });
+          } else {
+            executeFunction();
+          }
+
+        }
+      }
+    },
+
+    /**
+         * 获取子页签的集合
+         */
+    getSubTabs: function () {
+      var _self = this;
+      let subTabsRef = [];
+      for (var tabIndex = 0; tabIndex < _self.tab.subTabs.length; tabIndex++) {
+        var subTabId = 'subTab' + this.tab.subTabs[tabIndex].tabIndex;
+        subTabsRef.push(_self.$refs[subTabId][0]);
+      }
+      return subTabsRef;
+    },
+
+    // 备份视图
+    backupView: function () {
+      var _self = this;
+      var subTabChangedData = _self.getSubTabChangedData();
+      if (subTabChangedData.length > 0) {
+        _self.modelData.saveDatas = subTabChangedData;
+      } else {
+        _self.modelData.saveDatas = null;
+      }
+
+      _self.modelData.restore = null;
+      // bug 修复:生单功能问题:新建单据,再点击生单,会提示需要保存或撤销,必须先保存一次如此提示过后,才可以点击生单按钮进入来源单据选择页面,并且在勾选来源单据后点击确定无反应
+      _self.cancelCommand = true;
+
+      let key = _self.uuid + '_modelData';
+
+      let userStorageDtos = [{
+        key: key,
+        value: JSON.stringify(_self.modelData),
+      }];
+
+      let promise = new Promise(function (reslove, reject) {
+        // 组装查询条件,然后放到后台数据库当中
+        UserStorageResource.uploadUserStorage(userStorageDtos).then(
+          successData => {
+            reslove();
+          },
+          errorData => {
+            Common.processException(errorData);
+            reject();
+          },
+        );
+      });
+
+      return promise;
+    },
+
+    loadData: function () {
+      var _self = this;
+
+      if (_self.recordId == undefined) {
+        return;
+      }
+
+      var tabLoadParam = {
+        windowNo: _self.windowNo,
+        tabIndex: _self.tabIndex,
+        recordId: _self.recordId,
+      };
+      _self.loading = true;
+      WindowServerUtil.loadTabSingleData(
+        tabLoadParam,
+        function (modelData) {
+          _self.modelData = modelData;
+
+          // 判断是否有属性
+          if (
+            modelData.data.attributeKey != undefined &&
+            modelData.data.attributeKey.displayValue != undefined
+          ) {
+            let displayValue = modelData.data.attributeKey.displayValue;
+            if (displayValue.length > 0) {
+              _self.attributeKey = displayValue[0];
+            }
+          }
+          // 判断是否有属性值
+          if (
+            modelData.data.attributeValueKey != undefined &&
+            modelData.data.attributeValueKey.displayValue != undefined
+          ) {
+            let displayValue1 = modelData.data.attributeValueKey.displayValue;
+            if (displayValue1.length > 0) {
+              _self.attributeValueKey = displayValue1[0];
+            }
+          }
+
+          // 判断是否显示审批状态
+          if (
+            _self.modelData != null &&
+            _self.modelData.data != null &&
+            _self.modelData.data.processInstanceId != null
+          ) {
+            let displayValue =
+              _self.modelData.data.processInstanceId.displayValue;
+            if (displayValue != null && displayValue.length > 0) {
+              _self.processInstanceId = displayValue[0];
+            } else {
+              _self.processInstanceId = '';
+            }
+          } else {
+            _self.processInstanceId = '';
+          }
+
+          _self.loading = false;
+        },
+        function () {
+          _self.loading = false;
+        },
+      );
+    },
+
+    // 保存
+    saveTabData: function (command) {
+      var _self = this;
+      var fieldWidgets1 = _self.$refs.fieldItem1;
+      var fieldWidgets2 = _self.$refs.fieldItem2;
+
+      // 保存的时候取消判断
+      _self.cancelCommand = true;
+
+      _self.errorMsg = '';
+      var promises = [];
+      _self.error = 0;
+
+      if (fieldWidgets1 != undefined) {
+        fieldWidgets1.forEach(function (w) {
+          var validateResult = w.performValide();
+          if (!validateResult) {
+            _self.error++;
+          }
+        });
+      }
+
+      if (fieldWidgets2 != undefined) {
+        fieldWidgets2.forEach(function (w) {
+          var validateResult = w.performValide();
+          if (!validateResult) {
+            _self.error++;
+          }
+        });
+      }
+
+      var subTabValidateResults = _self.getSubTabValidatePromise();
+      if (
+        subTabValidateResults != undefined &&
+        subTabValidateResults.length > 0
+      ) {
+        subTabValidateResults.forEach(function (subTabValidateResult) {
+          if (subTabValidateResult != true) {
+            _self.error++;
+          }
+        });
+      }
+
+      if (_self.attributeKey != null) {
+        var attributeValidateResult =
+          _self.$refs.attributePanel.performValide();
+        if (attributeValidateResult != true) {
+          _self.error++;
+        }
+        var attributeValueDtos = _self.$refs.attributePanel.getValue();
+      }
+
+      console.log('check finished');
+      if (_self.error == 0) {
+        executeSave();
+      } else {
+        _self.errorCount = _self.error;
+        _self.modal1 = true;
+      }
+
+      function executeSave() {
+        _self.modelData.changed = true;
+
+        var subTabChangedData = _self.getSubTabChangedData();
+        if (subTabChangedData.length > 0) {
+          _self.modelData.saveDatas = subTabChangedData;
+        } else {
+          _self.modelData.saveDatas = null;
+        }
+
+        var tabSaveData = {
+          attributeValueDtos: attributeValueDtos,
+          persistenceData: _self.modelData,
+        };
+
+        _self.loading = true;
+        WindowServerUtil.saveTabData(
+          tabSaveData,
+          function (id) {
+            _self.loading = false;
+
+            // 自动关闭
+            var saveClose = Common.getRouteParam('saveClose');
+            if (saveClose == 'true') {
+              window.setTimeout(function () {
+                window.close();
+              }, 1000);
+              Notify.success(_self.$t('lang.tabFormEdit.savingSucceeded'), _self.$t('lang.tabFormEdit.describe2'), 1500);
+              return;
+            } else {
+              Notify.success(_self.$t('lang.tabFormEdit.savingSucceeded'), _self.$t('lang.tabFormEdit.dataSavingSucceeded'), 1500);
+            }
+
+            _self.modelData.id = id;
+            _self.callAfterSaveLogical();
+
+            if (_self.taskInfoId && _self.$refs.approveComment && command) {
+              // 从后台加载modelData数据
+
+              _self.loading = true;
+
+              CurdWindowResource.loadTabData(
+                _self.windowNo,
+                _self.tabIndex,
+                id,
+              ).then(
+                successData => {
+                  _self.loading = false;
+                  _self.$refs.approveComment.saveData(command, successData);
+                },
+                errorData => {
+                  _self.loading = false;
+                  Common.processException(errorData);
+                },
+              );
+
+              return;
+            }
+            //删除草稿数据
+            _self.deleteDataRecoveryDto();
+
+            var currIndex = _self.currIndex;
+            var totalCount = _self.totalCount;
+
+            if (_self.type == 'edit') {
+              let data = {
+                windowNo: _self.windowNo,
+                tabIndex: _self.tabIndex,
+                modelDataId: id,
+                currentPage: _self.currPage,
+                currentIndex: currIndex,
+                totalRecords: totalCount,
+                uuid: _self.uuid,
+              };
+              _self.$emit('OpenTabFormView', data);
+            } else if (_self.type == 'create') {
+              _self.$router.push(
+                '/desktop/window/window-read/view/' +
+                _self.windowNo +
+                '/' +
+                _self.tabIndex +
+                '/' +
+                id +
+                '?currPage=' +
+                _self.currPage +
+                '&currIndex=' +
+                1 +
+                '&totalCount=' +
+                (Number(totalCount) + 1) +
+                '&uuid=' +
+                _self.uuid,
+              );
+            } else if (_self.type == 'restore') {
+              _self.$router.push(
+                '/desktop/window/window-read/view/' +
+                _self.windowNo +
+                '/' +
+                _self.tabIndex +
+                '/' +
+                id +
+                '?currPage=' +
+                1 +
+                '&currIndex=' +
+                1 +
+                '&totalCount=' +
+                1 +
+                '&uuid=' +
+                _self.uuid,
+              );
+            }
+          },
+          function () {
+            _self.loading = false;
+          },
+        );
+      }
+    },
+
+    // 改变字段分组的显示和隐藏
+    changeFieldGroupStatus: function (fieldGroup) {
+      fieldGroup.show = !fieldGroup.show;
+      var index = this.tab.tabFormView.fieldGroups.indexOf(fieldGroup);
+      if (index != -1) {
+        this.tab.tabFormView.fieldGroups[index] = fieldGroup;
+        localStorage.setItem(
+          'FieldGroupStatus_' +
+          this.windowNo +
+          '_' +
+          this.tabIndex +
+          '_' +
+          fieldGroup.groupName,
+          fieldGroup.show,
+        );
+      }
+    },
+
+    /**
+         * 执行Callout
+         */
+    executeCallout: function (fieldItem) {
+      var _self = this;
+      if (fieldItem.calloutProcessReportNo != null) {
+        _self.callout(fieldItem.calloutProcessReportNo);
+      }
+    },
+
+    // 值改变事件
+    valueChanged: function (newFieldValue, fieldItem) {
+      var _self = this;
+      console.log(fieldItem.fieldName + ' ValueChanged.');
+      console.log(newFieldValue);
+      var oldFieldValue = this.modelData.data[fieldItem.fieldName];
+      if (FieldUtil.isFieldValueEqual(newFieldValue, oldFieldValue) == false) {
+        this.modelData.data[fieldItem.fieldName] = newFieldValue;
+        if (
+          fieldItem.calloutProcessReportNo != undefined &&
+          fieldItem.calloutProcessReportNo != null
+        ) {
+          _self.callout(fieldItem.calloutProcessReportNo);
+        }
+
+        if (
+          fieldItem.calloutLogical != undefined &&
+          fieldItem.calloutLogical != null
+        ) {
+          _self.executeCalloutJs(fieldItem, fieldItem.calloutLogical);
+        }
+
+        if (
+          _self.modelData.changed &&
+          fieldItem.displayType == 'ListBoxEditor'
+        ) {
+          // 值改变时,刷新所有下拉框的keyValues
+          _self.refreshSelectField(fieldItem.fieldName);
+        }
+
+        // add by jack 20170808
+        _self.modelData.changed = true;
+
+        let clearDynamicValidField = function (item) {
+          var fieldName1 = item.fieldName;
+          var dynamicValidFields = item.dynamicValidFields;
+          if (
+            fieldName0 != fieldName1 &&
+            dynamicValidFields != undefined &&
+            dynamicValidFields.indexOf(fieldName0) >= 0
+          ) {
+            var fieldValue0 = _self.modelData.data[fieldName1];
+            fieldValue0.id = undefined;
+            if (fieldValue0.displayValue != undefined) {
+              fieldValue0.displayValue.splice(
+                0,
+                fieldValue0.displayValue.length,
+              );
+            } else {
+              fieldValue0.displayValue = [];
+            }
+            _self.modelData.data[fieldName1] = fieldValue0;
+          }
+        };
+
+        // 遍历所有的字段,判断是否有动态约束
+        // 如果有关联的动态约束,则清空字段
+        var fieldName0 = fieldItem.fieldName;
+        _self.tabFormFields.forEach(function (item) {
+          clearDynamicValidField(item);
+        });
+
+        let fieldGroups = _self.tab.tabFormView.fieldGroups;
+        if (fieldGroups != null && fieldGroups.length > 0) {
+          fieldGroups.forEach(fieldGroup => {
+            if (fieldGroup.fields != null && fieldGroup.fields != null) {
+              fieldGroup.fields.forEach(field => {
+                clearDynamicValidField(field);
+              });
+            }
+          });
+        }
+      }
+    },
+
+    // 刷新下拉选择框keyValues
+    refreshSelectField: function (valueChangedFieldName) {
+      var _self = this;
+
+      if (_self.tabFormFields) {
+        _self.tabFormFields.forEach(function (item) {
+          if (item.displayType == 'ListBoxEditor') {
+            var name1 = ':' + valueChangedFieldName;
+            //var name2 = ":Parent_" + valueChangedFieldName;
+            var showLogical = item.showLogical;
+            if (showLogical != undefined && showLogical.indexOf(name1) >= 0) {
+              refresh(item);
+            }
+          }
+        });
+      }
+
+      if (_self.fieldGroup) {
+        _self.fieldGroup.fields.forEach(function (item) {
+          if (item.displayType == 'ListBoxEditor') {
+            var name1 = ':' + valueChangedFieldName;
+            //var name2 = ":Parent_" + valueChangedFieldName;
+            var showLogical = item.showLogical;
+            if (showLogical != undefined && showLogical.indexOf(name1) >= 0) {
+              refresh(item);
+            }
+          }
+        });
+      }
+
+      function refresh(item) {
+        var obj = {
+          windowNo: _self.windowNo,
+          tabIndex: _self.tabIndex,
+          fieldName: item.fieldName,
+          modelData: _self.modelData,
+        };
+
+        console.log('WindowEdit RefreshField');
+
+        $.ajax({
+          url: Common.getApiURL('FieldResource/refreshField'),
+          async: false,
+          dataType: 'json',
+          type: 'post',
+          data: JSON.stringify(obj),
+          contentType: 'application/json',
+          beforeSend: function (request) {
+            Common.addTokenToRequest(request);
+          },
+          success: function (data) {
+            if (data != undefined) {
+              item.keyValues = data.keyValues;
+            }
+          },
+          error: function (XMLHttpRequest, textStatus, errorThrown) {
+            Common.processException(XMLHttpRequest, textStatus, errorThrown);
+          },
+        });
+      }
+    },
+
+    /**
+         * 子页签触发父页签刷新
+         * @return {[type]} [description]
+         */
+    refreshParent: function () {
+      this.loadData();
+    },
+
+    /**
+         * 执行JS Callout
+         */
+    executeCalloutJs: function (fieldItem, scriptText) {
+      var _self = this;
+
+      // add by jack 20180529
+      var subTabChangedData = _self.getSubTabChangedData();
+      if (subTabChangedData.length > 0) {
+        _self.modelData.saveDatas = subTabChangedData;
+      } else {
+        _self.modelData.saveDatas = null;
+      }
+
+      let functionName = fieldItem.fieldName.replace('.', '_') + '_calloutjs';
+
+      let executeFunction = function () {
+        let actions = {
+          subTabsRef: _self.getSubTabs(),
+        };
+        let context = new _self.getContext(_self.modelData, actions);
+        try {
+          _self[functionName](context);
+        } catch (e) {
+          console.error(e);
+          Notify.error('数据字典定义异常', '【' + scriptText + '】前端列显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+        }
+      };
+
+      if (_self[functionName] == null) {
+        // 执行服务端的脚本
+        const jsUrl = _self.jsUrl;
+        if (jsUrl == null || jsUrl == undefined) {
+          Notify.error('数据字典定义异常', '【' + scriptText + '】Callout前端逻辑的JS文件不存在,请联系管理员检查数据字典是否JS文件。', false);
+          return;
+        }
+        let promise = JsUtil.dynamicLoadJsFunction(jsUrl, scriptText);
+        promise.then(targetFunction => {
+          console.log(targetFunction);
+          if (targetFunction == null) {
+            Notify.error('数据字典定义异常', '【' + scriptText + '】Callout前端逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+            return;
+          }
+
+          _self[functionName] = targetFunction;
+          executeFunction();
+
+        }, errorData => {
+          console.error(errorData);
+        });
+      } else {
+        executeFunction();
+      }
+    },
+
+    /**
+         * callout
+         * @param  {[type]} calloutProcessReportNo [description]
+         * @return {[type]}                  [description]
+         */
+    callout: function (calloutProcessReportNo) {
+      var _self = this;
+
+      // add by jack 20180529
+      var subTabChangedData = _self.getSubTabChangedData();
+      if (subTabChangedData.length > 0) {
+        _self.modelData.saveDatas = subTabChangedData;
+      } else {
+        _self.modelData.saveDatas = null;
+      }
+
+      // 查询流程和报表的定义
+      ProcessReportResource.uniqueByNo(calloutProcessReportNo).then(
+        successData => {
+          if (successData == null) {
+            return;
+          }
+
+          // 执行服务端的脚本
+          ProcessReportResource.runCallout(
+            calloutProcessReportNo,
+            _self.modelData,
+          ).then(
+            successData => {
+              if (successData && successData.modelData) {
+                _self.modelData = successData.modelData;
+              }
+              // add by jack 20180529
+              // add by jack 20220601
+              _self.modelData.saveDatas = undefined;
+            },
+            errorData => {
+              Common.processException(errorData);
+            },
+          );
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+
+    },
+
+    // 获取子页签全部的数据
+    getSubTabAllData: function () {
+      var subTabAllRecords = [];
+      if (this.tab.subTabs != undefined) {
+        for (var index = 0; index < this.tab.subTabs.length; index++) {
+          var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+          var modelDatas = this.$refs[subTabId][0].getAllModelData();
+          if (modelDatas != undefined && modelDatas.length > 0) {
+            modelDatas.forEach(function (modelData) {
+              subTabAllRecords.push(modelData);
+            });
+          }
+        }
+      }
+      console.log(subTabAllRecords);
+      return subTabAllRecords;
+    },
+
+    // 获取子页签发生改变的数据
+    getSubTabChangedData: function () {
+      var subTabChangedRecords = [];
+      if (this.tab.subTabs != undefined) {
+        for (var index = 0; index < this.tab.subTabs.length; index++) {
+          var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+          var modelDatas = this.$refs[subTabId][0].getChangedModelData();
+          if (modelDatas != undefined && modelDatas.length > 0) {
+            modelDatas.forEach(function (modelData) {
+              subTabChangedRecords.push(modelData);
+            });
+          }
+        }
+      }
+      console.log(subTabChangedRecords);
+      return subTabChangedRecords;
+    },
+    // 获取子页签数据校验的Promise
+    getSubTabValidatePromise: function () {
+      var _self = this;
+
+      var subTabValidates = [];
+      if (this.tab.subTabs != undefined) {
+        for (var index = 0; index < this.tab.subTabs.length; index++) {
+          var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+          var result = this.$refs[subTabId][0].performValidate();
+          if (result != undefined && result.length > 0) {
+            subTabValidates = subTabValidates.concat(result);
+          }
+        }
+      }
+      return subTabValidates;
+    },
+
+    /**
+         * 表单字段的属性(显示)属性发生改变事件
+         */
+    tabFormFieldPropertyChanged: function (tabFormFieldClone) {
+      TabFormView.restoreTabFormFieldDef(
+        this.windowNo,
+        this.tabIndex,
+        this.tabFormFields,
+      );
+    },
+
+    /**
+         * 撤销提示
+         */
+    cancelModel: function () {
+      var _self = this;
+      _self.modal3 = true;
+    },
+    /**
+         * 取消
+         */
+    cancelNo: function () {
+      var _self = this;
+      _self.modal3 = false;
+    },
+    /**
+         * 撤销
+         * @return {void}
+         */
+    cancelOk: function () {
+      var _self = this;
+      var currPage = _self.currPage;
+      var currIndex = _self.currIndex;
+      var totalCount = _self.totalCount;
+
+      _self.cancelCommand = true;
+      _self.modal3 = false;
+      if (_self.recordId == null || _self.recordId == '') {
+        _self.$router.push(
+          '/desktop/window/' +
+          _self.windowNo +
+          '?currPage=' +
+          currPage +
+          '&uuid=' +
+          this.uuid,
+        );
+      } else {
+        // bug fixed by jack,编辑后直接取消
+        // var cacheData = localStorage.getItem(_self.uuid);
+        // if (cacheData != undefined && cacheData.length > 0) {
+        //     cacheData = JSON.parse(cacheData);
+
+        //     var window = cacheData.window;
+        //     var tab = cacheData.tab;
+
+        //     if (window == undefined || tab == undefined) {
+        //         _self.$router.push('/desktop/window/' + _self.windowNo + "?currPage=" + currPage + "&uuid=" + this.uuid);
+        //         return;
+        //     }
+        // }
+
+        _self.$router.push(
+          '/desktop/window/window-read/view/' +
+          _self.windowNo +
+          '/' +
+          _self.tabIndex +
+          '/' +
+          _self.recordId +
+          '?currPage=' +
+          currPage +
+          '&currIndex=' +
+          currIndex +
+          '&totalCount=' +
+          totalCount +
+          '&uuid=' +
+          this.uuid,
+        );
+      }
+      //删除草稿数据
+      _self.deleteDataRecoveryDto();
+    },
+    /**
+         * 子标题
+         * @return {String} 子标题
+         */
+    subTitle: function () {
+      var _self = this;
+      var subTitle = '';
+      if (_self.modelData != null && _self.modelData.data == null) {
+        return subTitle;
+      }
+      if (
+        _self.modelData != null &&
+        _self.modelData.data != null &&
+        _self.modelData.data.documentNo != null
+      ) {
+        subTitle =
+          _self.modelData.data.documentNo.displayValue == null ?
+            '' :
+            _self.modelData.data.documentNo.displayValue[0];
+      } else if (
+        _self.modelData != null &&
+        _self.modelData.data != null &&
+        _self.modelData.data.no != null
+      ) {
+        subTitle =
+          _self.modelData.data.no.displayValue == null ?
+            '' :
+            _self.modelData.data.no.displayValue[0];
+      } else if (
+        _self.modelData != null &&
+        _self.modelData.data != null &&
+        _self.modelData.data.name != null
+      ) {
+        subTitle =
+          _self.modelData.data.name.displayValue == null ?
+            '' :
+            _self.modelData.data.name.displayValue[0];
+      }
+      return subTitle;
+    },
+
+
+    /**
+         * 上一条数据
+         * @return {void}
+         */
+    pre: function () {
+      var _self = this;
+      if (_self.isModelDataChanged() == true) {
+        Notify.notice(_self.$t('lang.tabFormEdit.dataNotSaved'), _self.$t('lang.tabFormEdit.describe1'), false);
+        return;
+      }
+
+      if (_self.currIndex <= 1) {
+        return;
+      }
+      _self.currIndex--;
+      var tabQueryParam = {
+        range: {
+          start: _self.currIndex - 1,
+          length: 1,
+        },
+        tabIndex: _self.tabIndex,
+        windowNo: _self.windowNo,
+      };
+
+      UserStorageResource.uniqueByKey(_self.uuid).then(
+        successData => {
+          // if(successData.errorCode != 0) {
+          //   Notify.error('提示', successData.errorMessage, false);
+          //   return;
+          // }
+          let simpleFilterParams = null;
+
+          let complexFilterParams = null;
+
+          if (successData.data != null && successData.data != '') {
+            let temp = JSON.parse(successData.data);
+            // 分页数据
+
+            // 简单过滤条件
+            tabQueryParam.simpleFilterCondition = temp.simpleFilterParams;
+            // 复杂过滤条件
+            tabQueryParam.filterParams = temp.complexFilterParams;
+            // 排序
+            tabQueryParam.sortStr = temp.sortStr;
+          }
+
+          _self.loadTabData(tabQueryParam);
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+
+    /**
+         * 下一条数据
+         * @return {void}
+         */
+    next: function () {
+      var _self = this;
+
+      if (_self.isModelDataChanged() == true) {
+        Notify.notice(_self.$t('lang.tabFormEdit.dataNotSaved'), _self.$t('lang.tabFormEdit.describe1'), false);
+        return;
+      }
+
+      var totalCount = _self.totalCount;
+      if (_self.currIndex >= totalCount) {
+        return;
+      }
+      _self.currIndex++;
+      var tabQueryParam = {
+        range: {
+          start: _self.currIndex - 1,
+          length: 1,
+        },
+        tabIndex: _self.tabIndex,
+        windowNo: _self.windowNo,
+      };
+
+      UserStorageResource.uniqueByKey(_self.uuid).then(
+        successData => {
+          // if(successData.errorCode != 0) {
+          //   Notify.error('提示', successData.errorMessage, false);
+          //   return;
+          // }
+          if (successData.data != null && successData.data != '') {
+            let temp = JSON.parse(successData.data);
+            // 分页数据
+
+            // 简单过滤条件
+            tabQueryParam.simpleFilterCondition = temp.simpleFilterParams;
+            // 复杂过滤条件
+            tabQueryParam.filterParams = temp.complexFilterParams;
+            // 排序
+            tabQueryParam.sortStr = temp.sortStr;
+          }
+
+          _self.loadTabData(tabQueryParam);
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+
+    /**
+         * 加载一条数据
+         * @param  {Object} tabQueryParam 查询条件
+         * @return {void}
+         */
+    loadTabData: function (tabQueryParam) {
+      var _self = this;
+      _self.loading = true;
+      WindowServerUtil.queryTabData(
+        tabQueryParam,
+        function (gridData) {
+          var dataLists = gridData.dataList;
+          if (dataLists != undefined && dataLists.length > 0) {
+            _self.modelData = dataLists[0];
+          }
+          _self.loading = false;
+        },
+        function () {
+          _self.loading = false;
+        },
+      );
+    },
+
+    /**
+         * 计算按钮坐标
+         *
+         */
+    computerButtonGroupLeftTop: function () {
+      var _self = this;
+      var fixedButtonGroup = $(_self.$refs.fixedButtonGroup);
+      if (fixedButtonGroup != undefined) {
+        var offset = fixedButtonGroup.offset();
+        if (offset != undefined) {
+          _self.buttonGroupInitLeft = offset.left;
+          _self.buttonGroupInitTop = offset.top;
+        }
+      }
+    },
+
+    /**
+         * ModelData 是否发生变化
+         */
+    isModelDataChanged: function () {
+      var _self = this;
+
+      // 判断当前数据是否发生改变
+      if (_self.modelData.changed == true) {
+        return true;
+      }
+
+      // 判断子页签数据是否发生改变
+      var subTabChangedData = _self.getSubTabChangedData();
+      if (subTabChangedData != undefined && subTabChangedData.length > 0) {
+        return true;
+      }
+
+      return false;
+    },
+
+    /**
+         * 自动点击菜单
+         */
+    autoClickMenu: function () {
+      var _self = this;
+      // 判断是否有URL参数 自动点击菜单 canAutoClickMenu
+      var canAutoClickMenu = Common.getRouteParam('canAutoClickMenu');
+
+      if (
+        (canAutoClickMenu == null || canAutoClickMenu == '') &&
+        canAutoClickMenu != 'true'
+      ) {
+        const route1 = this.$route;
+        let path = route1.path;
+        let query = route1.query; // 这里可以用Vue的方法获取参数,也可以用正则的方法获取url中的参数
+
+        query.canAutoClickMenu = true;
+
+        // !!!!不推荐使用push的方式进行更新路由参数这样会增加路由的历史记录 (浏览器的后退键被破坏)
+        this.$router.push({ path, query });
+
+        // 推荐使用
+        // this.$router.replace({path, query}); // 更新url上面的内容,且页面不会重载 / 刷新
+
+
+        if (_self.type == 'create') {
+          if (
+            _self.tab &&
+            _self.tab.tabButtons &&
+            _self.tab.tabButtons.length > 0
+          ) {
+            for (var i = 0; i < _self.tab.tabButtons.length; i++) {
+              var itemButton = _self.tab.tabButtons[i];
+              if (itemButton.createAutoClick == true) {
+                _self.backupView().then(
+                  successData => {
+                    _self.$refs.tabButton.execute(itemButton);
+                  },
+                  errorData => { },
+                );
+                break;
+              }
+            }
+          }
+        }
+      }
+    },
+
+    /**
+         * 开启草稿保存功能,每隔15秒保存一次
+         * @author GuoZhiBo 20211008
+         */
+    startSaveInterval: function () {
+      var _self = this;
+      _self.autoSaveInterval = setInterval(function () {
+        var subTabChangedData = _self.getSubTabChangedData();
+
+        // bug fixed by jack
+        // 这里不能对 _self.modelData.saveDatas 属性赋值,否则在 当页签的GridBody中修改了某个值以后,
+        // 其监听 parentModelData 也会发生改变,导致性能很差
+        var modelDataClone = JSON.parse(JSON.stringify(_self.modelData));
+        if (subTabChangedData.length > 0) {
+          var subTabChangedDataClone = JSON.parse(
+            JSON.stringify(subTabChangedData),
+          );
+          modelDataClone.saveDatas = subTabChangedDataClone;
+        } else {
+          modelDataClone.saveDatas = null;
+        }
+
+        if (_self.dataRecoveryDto == undefined) {
+          _self.dataRecoveryDto = {
+            modelData: modelDataClone,
+            windowId: _self.windowNo,
+            type: _self.type,
+          };
+        } else {
+          _self.dataRecoveryDto.modelData = modelDataClone;
+        }
+        DataRecoveryResource.saveDataRecoveryDto(
+          _self.dataRecoveryDto,
+          function (data) {
+            console.log('草稿数据保存成功.');
+          },
+          function (xmlHttpRequest) {
+            console.log('草稿数据保存失败: %s 。', xmlHttpRequest.responseText);
+          },
+        );
+      }, 15000);
+    },
+
+    /**
+         * 页签按钮的显示逻辑
+         */
+    tabButtonsShowLogical: function () {
+      let _self = this;
+      if (
+        this.tab.tabFormView != null &&
+        this.tab.tabFormView.tabButtons != null
+      ) {
+        for (
+          let index = 0; index < this.tab.tabFormView.tabButtons.length; index++
+        ) {
+          let tabButton = this.tab.tabFormView.tabButtons[index];
+          if (tabButton.editMode == true) {
+            var logic = tabButton.showLogical;
+            if (logic == null || logic == '') {
+              tabButton.invisible = false;
+              return;
+            }
+
+            let functionName = 'form_edit_show_logical_' + index;
+
+            let executeFunction = function () {
+              let actions = {
+                subTabsRef: _self.getSubTabs(),
+              };
+              try {
+                let context = new _self.getContext(_self.modelData, actions);
+                tabButton.invisible = !_self[functionName](context);
+              } catch (error) {
+                console.error(error);
+                Notify.error('数据字典定义异常', '【' + logic + '】按钮显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+              }
+            };
+            if (this[functionName] == null) {
+              const jsUrl = this.jsUrl;
+              if (jsUrl == null || jsUrl == undefined) {
+                Notify.error('数据字典定义异常', '【' + logic + '】按钮显示逻辑的JS文件不存在,请联系管理员检查数据字典是否存在JS文件', false);
+                return;
+              }
+              let promise = JsUtil.dynamicLoadJsFunction(jsUrl, logic);
+
+              promise.then(targetFunction => {
+
+
+                if (targetFunction == null) {
+                  Notify.error('数据字典定义异常', '【' + logic + '】按钮显示逻辑逻辑定义异常,请联系管理员检查数据字典的定义', false);
+                  return;
+                }
+                console.log(targetFunction);
+                this[functionName] = targetFunction;
+                executeFunction();
+
+              }, errorData => {
+                console.error(errorData);
+              });
+            } else {
+              executeFunction();
+            }
+          }
+        }
+      }
+    },
+
+    /**
+     * 调用保存后的业务逻辑
+     */
+    callAfterSaveLogical: function () {
+      var _self = this;
+      if (
+        this.tab != null &&
+        this.tab.tabFormView != null &&
+        this.tab.tabFormView.logicalAfterSave != null &&
+        this.tab.tabFormView.logicalAfterSave.length > 0
+      ) {
+        var logic = this.tab.tabFormView.logicalAfterSave;
+        if (logic == null || logic == '') {
+          return;
+        }
+
+        let functionName = 'form_edit_logical_after_save';
+
+        const executeFunction = function () {
+          let actions = {
+            subTabsRef: _self.getSubTabs(),
+          };
+
+          let context = new _self.getContext(_self.modelData, actions);
+
+          try {
+            _self[functionName](context);
+          } catch (e) {
+            console.error(e);
+            Notify.error('数据字典定义异常', '【' + logic + '】保存后业务逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+          }
+        };
+
+
+        if (_self[functionName] == null) {
+          const jsUrl = this.jsUrl;
+          if (jsUrl == null || jsUrl == undefined) {
+            Notify.error('数据字典定义异常', '【' + logic + '】保存后业务逻辑的JS文件不存在,请联系管理员检查数据字典是否存在JS文件', false);
+            return;
+          }
+          let promise = JsUtil.dynamicLoadJsFunction(jsUrl, logic);
+          promise.then(targetFunction => {
+
+
+            if (targetFunction == null) {
+              Notify.error('数据字典定义异常', '【' + logic + '】保存后业务逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+              return;
+            }
+
+            _self[functionName] = targetFunction;
+
+            executeFunction();
+          }, errorData => {
+            console.error(errorData);
+          });
+        } else {
+          executeFunction();
+        }
+      }
+    },
+
+    /**
+         * 当页面卸载(关闭)或刷新时调用
+         */
+    beforeunloadFn: function (e) {
+      e = e || window.event;
+      if (e) {
+        e.returnValue = '关闭提示';
+      }
+      return '关闭提示';
+    },
+
+    /**
+         * 子页签(表格)修改父页签的数据
+         * @param { String } fieldName 字段名称
+         * @param { com.leanwo.prodog.restful.base.model.FieldValue } fieldValue 字段的值
+         * @author YangZhiJie 20211012
+         */
+    changeRootParentModelData: function (data) {
+      if (data === undefined || data === null) {
+        console.error('子页签修改父页签的数据,但数据为空。');
+        return;
+      }
+
+      const fieldName = data.fieldName;
+      const fieldValue = data.fieldValue;
+
+      if (fieldName === undefined || fieldName === null) {
+        console.error(
+          '子页签修改父页签的数据,但字段名称 %s 为空。',
+          fieldName,
+        );
+        return;
+      }
+
+      if (fieldValue === undefined || fieldValue === null) {
+        console.error('子页签修改父页签的数据,但字段值 %s 为空。', fieldName);
+        return;
+      }
+
+      let fieldItem = null;
+
+      for (let index = 0; index < this.tabFormFields.length; index++) {
+        if (this.tabFormFields[index].fieldName === fieldName) {
+          fieldItem = this.tabFormFields[index];
+          break;
+        }
+      }
+
+      if (fieldItem === null) {
+        console.error(
+          '子页签修改父页签的数据,但找不到字段 %s 的定义。',
+          fieldName,
+        );
+        return;
+      }
+
+      console.debug('子页签修改父页签的数据。', fieldName, fieldValue);
+      this.valueChanged(fieldValue, fieldItem);
+    },
+  },
+};
+</script>
+
+<style scoped>
+.field-group {
+  padding-left: 30px;
+  padding-right: 30px;
+}
+
+.fieldGroup-head {
+  cursor: pointer;
+}
+
+.a-back {
+  cursor: pointer;
+  text-decoration: none;
+}
+
+.m-space-btn-group {
+  height: 34px;
+}
+
+.m-row {
+  margin-bottom: 15px;
+}
+
+.fixed-btn-group {
+  z-index: 3;
+  background-color: #f7f7f7;
+}
+</style>
+
+<style>
+.btn-group-fixed {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 3;
+}
+
+.m-image {
+  height: 50px;
+  cursor: pointer;
+}
+</style>

+ 34 - 0
src/window1/tabFormEdit/TabFormEditState.js

@@ -0,0 +1,34 @@
+import { reactive, ref } from 'vue';
+
+
+export function use(){
+    const state = reactive({
+        window: null,   // CURD窗口编号 
+    });
+
+}
+
+
+/**
+ * 是否允许新建数据
+ * @param {*} window CURD窗口定义
+ * @returns 
+ */
+const allowCreate = function (window) {
+    var allTabReadOnly = true;
+    // 如果所有的页签都是只读
+    if (window != undefined && window.tabs != undefined) {
+        for (
+            var tabIndex = 0; tabIndex < window.tabs.length; tabIndex++
+        ) {
+            if (
+                window.tabs[tabIndex].isReadOnly == undefined ||
+                window.tabs[tabIndex].isReadOnly == false
+            ) {
+                allTabReadOnly = false;
+                break;
+            }
+        }
+    }
+    return !allTabReadOnly;
+}

+ 2179 - 0
src/window1/tabFormView/TabFormViewModal.vue

@@ -0,0 +1,2179 @@
+<template>
+  <a-modal :open="open" @update:open="$emit('update:open', $event)">
+    <template #title>
+      <a-page-header
+        style="padding: 0 20px 0 0;"
+        :title="Language.getNameTrl($i18n.locale, window)"
+        :sub-title="subTitle()"
+      >
+        <template #extra>
+          <a-button key="1" title="上一页" @click="pre">
+            <template #icon>
+              <CaretLeftOutlined />
+            </template>
+          </a-button>
+          
+          <a-button key="2" title="下一页" @click="next">
+            <template #icon>
+              <CaretRightOutlined />
+            </template>
+          </a-button>
+
+          <a-button key="3" title="历史记录" @click="auditData">
+            <template #icon>
+              <SmallDashOutlined />
+            </template>
+            {{ currIndex }}/{{ totalCount }}
+          </a-button>
+
+          
+          <a-tooltip v-if="!(window.htmlHelpUrl != null && window.htmlHelpUrl != '')" title="帮助">
+            <QuestionCircleOutlined style="font-size: 2rem;" @click="openHtmlHelp(window.htmlHelpUrl)" />
+          </a-tooltip>
+        </template>
+      </a-page-header>
+    </template>
+
+    <template #footer />
+
+
+    <a-space>
+      <a-button
+        v-if="showCreateButton && windowDisplayType == 'Grid'" 
+        @click="createRecord"
+      >
+        {{ $t("lang.tabFormView.create") }}
+      </a-button>
+      <a-button
+        v-if="showEditButton && windowDisplayType == 'Grid'" 
+        @click="editRecord"
+      >
+        {{ $t("lang.tabFormView.edit") }}
+      </a-button>
+      <a-button @click="refresh">
+        {{ $t("lang.tabFormView.refresh") }}
+      </a-button>
+      <a-button
+        v-if="isView == true && windowDisplayType == 'Grid'" 
+        @click="changeWindowDisplayType"
+      >
+        {{ $t("lang.tabFormView.reportView") }}
+      </a-button>
+      <a-button
+        v-if="isView == true && windowDisplayType == 'Report'" 
+        @click="changeWindowDisplayType"
+      >
+        {{ $t("lang.tabFormView.formView") }}
+      </a-button>
+
+      <a-button
+        v-if="showDeleteButton && windowDisplayType == 'Grid'" 
+        @click="deleteRecord(true)"
+      >
+        {{ $t("lang.tabFormView.remove") }}
+      </a-button>
+
+      <a-button v-if="showRedrawButton" @click="abandonWorkflow">
+        {{ $t("lang.tabFormView.redraw") }}
+      </a-button>
+    </a-space>
+
+
+    <div>
+      <!-- header -->
+      <div style="position: relative">
+        <div v-show="showSpaceRow" class="row">
+          <div class="col-md-12">
+            <div class="m-space-btn-group" />
+          </div>
+        </div>
+
+        <div ref="fixedButtonGroup" class="row m-row fixed-btn-group">
+          <div class="col-md-12">
+            <div class="btn-group">
+              <TabButton
+                :show-tab-dto="tab" :model-data="modelData" :uuid="uuid" :view-type="'Form'"
+                :tab-buttons="tab.tabFormView ? tab.tabFormView.tabButtons : null"
+                :curd-window-function-access="curdWindowFunctionAccess" @save-view="backupView"
+                @process-execute-finish="refresh" @model-data-changed="modelDataChanged"
+              />
+
+              <FormFieldDef
+                :tab-form-fields="tabFormFields" :window-no="windowNo" :tab-index="tabIndex"
+                @tab-form-field-property-changed="
+                  tabFormFieldPropertyChanged($event)
+                "
+              />
+            </div>
+          </div>
+        </div>
+        <img
+          v-if="processInstanceId != undefined" style="
+          position: absolute;
+          right: 0px;
+          top: 118px;
+          z-index: 2;
+          width: 100px;
+        " :src="getWorkFlowImageUrl()"
+        />
+      </div>
+      <div v-if="windowDisplayType == 'Grid'">
+        <!-- eslint-disable-next-line -->
+        <div v-html="headerHtml" />
+
+        <div v-if="tab != null && tab.tabFormView != null" class="m-row clearfix">
+          <div class="col-xs-12">
+            <div
+              :class="{
+                'form-inline': tab.tabFormView.multipleColumn,
+                'form-horizontal': !tab.tabFormView.multipleColumn,
+              }"
+            >
+              <template
+                v-for="fieldItem in tabFormFields" :key="
+                  'TabFormFieldView_' +
+                    windowNo +
+                    '_' +
+                    tabIndex +
+                    '_' +
+                    fieldItem.fieldName +
+                    '_' +
+                    fieldItem.entityFieldIndex
+                "
+              >
+                <TabFormFieldView
+                  ref="fieldItem1" :class-name="tab.tabDataSource.className" :field="fieldItem"
+                  :model-data="modelData" :multiple-column="tab.tabFormView.multipleColumn" :js-url="jsUrl"
+                  :is-chinese-english="window.isChineseEnglish" @execute-callout="executeCallout(fieldItem)"
+                />
+              </template>
+            </div>
+          </div>
+        </div>
+
+        <div
+          v-if="
+            tab != null &&
+              tab.tabFormView != null &&
+              tab.tabFormView.fieldGroups != null &&
+              tab.tabFormView.fieldGroups.length > 0
+          " class="m-row clearfix"
+        >
+          <ul id="myTabs" class="nav nav-tabs" role="tablist">
+            <li
+              v-for="(fieldGroup, fieldGroupIndex) in tab.tabFormView.fieldGroups" :key="fieldGroup.groupName"
+              role="presentation" :class="{ active: selectedTabIndex == fieldGroupIndex }"
+              @click="selectedTabIndex = fieldGroupIndex"
+            >
+              <a :id="'tab-' + fieldGroupIndex" role="tab" data-toggle="tab" aria-controls="home" aria-expanded="true">
+                {{ Language.getGroupNameTrl($i18n.locale, fieldGroup) }}
+              </a>
+            </li>
+          </ul>
+
+          <div id="myTabContent" class="tab-content">
+            <div
+              v-for="(fieldGroup, fieldGroupIndex) in tab.tabFormView.fieldGroups"
+              v-show="selectedTabIndex == fieldGroupIndex" id="home" :key="fieldGroup.groupName" role="tabpanel"
+              class="tab-pane fade active in" aria-labelledby="home-tab"
+            >
+              <div v-if="fieldGroup.show">
+                <div
+                  :class="{
+                    'form-inline': tab.tabFormView.multipleColumn,
+                    'form-horizontal': !tab.tabFormView.multipleColumn,
+                  }"
+                >
+                  <template
+                    v-for="fieldItem in fieldGroup.fields" :key="
+                      'TabFormFieldView_' +
+                        windowNo +
+                        '_' +
+                        tabIndex +
+                        '_' +
+                        fieldItem.fieldName +
+                        '_' +
+                        fieldItem.entityFieldIndex
+                    "
+                  >
+                    {{ window.isChineseEnglish }}
+                    <TabFormFieldView
+                      ref="fieldItem2" :class-name="tab.tabDataSource.className" :field="fieldItem"
+                      :model-data="modelData" :multiple-column="tab.tabFormView.multipleColumn" :js-url="jsUrl"
+                      :is-chinese-english="window.isChineseEnglish" @execute-callout="executeCallout(fieldItem)"
+                    />
+                  </template>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <!-- eslint-disable-next-line -->
+        <div v-html="footerHtml" />
+
+        <template v-if="modelData != null">
+          <div
+            v-for="subTab in tab.subTabs"
+            :id="'SubTabGridEdit-' + windowNo + '-' + tabIndex + '-' + modelData.id + '-subTab-' + subTab.tabIndex"
+            :key="'SubTabGridEdit-' + windowNo + '-' + tabIndex + '-' + modelData.id + '-subTab-' + subTab.tabIndex"
+            class="row clearfix"
+          >
+            <div class="col-md-12">
+              <SubTabGridEdit
+                :ref="'subTab' + subTab.tabIndex" :window-no="windowNo" :tab-index="subTab.tabIndex"
+                :fixed-button-group-height="fixedButtonGroupHeight" :is-show-edit="false" :tab="subTab"
+                :parent-model-data="modelData" :parent-tab="tab" :js-url="jsUrl"
+                :is-chinese-english="window.isChineseEnglish" @save-view="backupView"
+                @process-execute-finish="refresh"
+              />
+            </div>
+          </div>
+        </template>
+
+        <div v-if="attributeKey != null && attributeKey === true" class="row clearfix">
+          <div class="col-md-12">
+            <AttributeViewPanel
+              ref="attributePanel" :attribute-key="attributeKey"
+              :attribute-value-key="attributeValueKey" :window-no="windowNo"
+            />
+          </div>
+        </div>
+      </div>
+      <div v-else style="height: 400px; overflow: scroll">
+        <ProcessReportResultPreview
+          v-if="
+            processReportResult != null &&
+              (processReportResult.reportResults != null ||
+                processReportResult.processResult != null)
+          " :process-report-result="processReportResult" :pdf-only="false" :excel-only="false"
+        />
+      </div>
+
+      <div v-if="showApply" class="row clearfix">
+        <div v-if="window.workflow.workflowType === 'UserDefine'" class="col-md-12">
+          <WorkflowUserDefine
+            ref="workflowUserDefine" :work-flow="window.workflow"
+            :process-definition-id="processDefinitionId" :model-data="modelData" @apply="apply"
+          />
+        </div>
+        <div v-else-if="window.workflow.workflowType === 'OTHER'" class="col-md-12">
+          <WorkflowStart :work-flow="window.workflow" :process-definition-id="processDefinitionId" @apply="apply" />
+        </div>
+        <div v-else class="col-md-12">
+          <WorkflowSelectUser
+            ref="workflow" :work-flow="window.workflow" :window-no="windowNo"
+            :process-definition-id="processDefinitionId" :model-data="modelData" :record-id="recordId" @apply="apply"
+          />
+        </div>
+      </div>
+
+      <div v-if="showApproveComment" class="row clearfix">
+        <div class="col-md-12">
+          <ApproveComment
+            ref="approveComment" :parent-widget="'TabFormView'" :workflow-type="workflowType"
+            :work-flow="window.workflow" :window-no="windowNo" :process-definition-id="processDefinitionId"
+            :show-choice-button="showChoiceButton" :process-instance-id="processInstanceId" :task-info-id="taskInfoId"
+            :record-id="modelData.id" :show-tab-dto="tab" :model-data="modelData" :uuid="uuid"
+            :workflow-class-name="tab.tabDataSource.className" @save-view="backupView"
+          />
+        </div>
+      </div>
+
+
+      <!-- 历史审批记录 -->
+      <div v-if="showHistoryApproveComment" class="row clearfix">
+        <div class="col-md-12">
+          <HistoryApproveComment :record-id="modelData.id" :process-instance-id="processInstanceId" />
+        </div>
+      </div>
+
+      <div
+        v-if="
+          window != null &&
+            tab != null &&
+            tab.tabDataSource != null &&
+            !window.hideCreateRecordButton && showAttachmentPanel == true
+        "
+      >
+        <AttachmentPanel
+          v-if="type == 'view'" :is-show-edit="true" :class-name="tab.tabDataSource.className"
+          :record-id="recordId" :tab-index="tabIndex" :window-no="windowNo"
+          :curd-window-function-access="curdWindowFunctionAccess"
+        />
+      </div>
+
+      <a-modal 
+        v-model:open="modal2" 
+        width="100%" 
+        @ok="showAuditPanel = false; 
+             modal2 = false" 
+        @cancel="showAuditPanel = false"
+      >
+        <template #title>
+          {{ $t("lang.tabFormView.recordInformation") }}{{ currIndex }}/{{ totalCount }} - {{ tab.name }}
+        </template>
+        <TabAudit
+          v-if="showAuditPanel" :window-no="windowNo" :tab-index="tabIndex" :tab="tab"
+          :model-data="modelData"
+        />
+      </a-modal>
+
+      <a-modal v-model:open="modal3" width="100%" title="创建评论">
+        <CurdWindowCommentCreate ref="curdCommentCreate" :record-id="modelData.id" :window-no="modelData.windowNo" />
+        <template #footer>
+          <a-button type="primary" @click="saveAndSendNotification">
+            确认
+          </a-button>
+          <a-button @click="modal3 = false">
+            取消
+          </a-button>
+        </template>
+      </a-modal>
+
+      <div>
+        <div class="page-header">
+          <h4 style="display: inline-block">
+            评论信息
+          </h4>
+          <a-button type="link" @click="openCurdWindowComment">发表评论</a-button>
+        </div>
+        <CurdWindowComment ref="curdComment" :record-id="modelData.id" />
+      </div>
+
+
+
+      <Loading v-if="loading" />
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import Common from '../../common/Common.js';
+
+import WindowServerUtil from '../../resource/dictionary/WindowServerUtil.js';
+import WindowClientUtil from '../../resource/dictionary/WindowClientUtil.js';
+import TabFormView from './TabFormView.js';
+import FieldUtil from '../../resource/dictionary/FieldUtil.js';
+import ProcessReportResource from '../../api/dic/ProcessReportResource.js';
+import UserStorageResource from '../../api/base/UserStorageResource.js';
+import UserReadDocumentResource from '../../api/base/UserReadDocumentResource.js';
+import Language from '../../common/Language.js';
+import Context from '../common/Context.js';
+import CurdWindowResource from '../../api/dic/CurdWindowResource.js';
+
+import SubTabGridEdit from '../tabGridView/SubTabGridEdit.vue';
+import TabFormFieldView from './TabFormFieldView.vue';
+import TabButton from '../tabView/TabButton.vue';
+import FormFieldDef from '../tab-form-common/FormFieldDef.vue';
+import AttachmentPanel from '../attachment/AttachmentPanel.vue';
+
+import AttributeViewPanel from '../attribute/AttributeViewPanel.vue';
+import WorkflowSelectUser from '../../workflow/WorkflowSelectUser.vue';
+import WorkflowStart from '../../workflow/WorkflowStart.vue';
+import WorkflowUserDefine from '../../workflow/WorkflowUserDefine.vue';
+import TabAudit from '../tabView/TabAudit.vue';
+import ApproveComment from '../../workflow/ApproveComment.vue';
+
+
+import CurdWindowResourceV2 from '../../api/dic/CurdWindowResourceV2.js';
+import CurdWindowEditResource from '../../api/dic/CurdWindowEditResource.js';
+import JsUtil from '../../common/JsUtil.js';
+import { Notify, Uuid } from 'pc-component-v3';
+
+
+import CurdWindowComment from './CurdWindowComment.vue';
+import CurdWindowCommentCreate from './CurdWindowCommentCreate.vue';
+import NotificationPanel from '../../customer/NotificationPanel.vue';
+import HistoryApproveComment from '../../workflow/HistoryApproveComment.vue';
+
+import { CaretRightOutlined, CaretLeftOutlined, SmallDashOutlined, ExclamationCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons-vue';
+import { createVNode } from 'vue';
+import { Modal } from 'ant-design-vue';
+
+export default {
+
+  components: {
+    SubTabGridEdit,
+    TabFormFieldView,
+    TabButton,
+    FormFieldDef,
+    AttachmentPanel,
+    AttributeViewPanel,
+    WorkflowSelectUser,
+    WorkflowStart,
+    ApproveComment,
+    TabAudit,
+    WorkflowUserDefine,
+    CurdWindowComment,
+    CurdWindowCommentCreate,
+    NotificationPanel,
+    HistoryApproveComment,
+    CaretRightOutlined, 
+    CaretLeftOutlined,
+    SmallDashOutlined,
+    ExclamationCircleOutlined,
+    Modal,
+    QuestionCircleOutlined,
+  },
+
+  props: {
+    open: {
+      type: Boolean,
+      default: false,
+    },
+    // CURD窗口Id
+    windowNo: {
+      type: String,
+      default: '',
+    },
+    // 页签编号
+    tabIndex: {
+      type: Number,
+      default: 0,
+    },
+    // 数据记录Id
+    modelDataId: {
+      type: Number,
+      default: null,
+    },
+    // 窗口类型(view:视图数据,restore:恢复数据)
+    type: {
+      type: String,
+      default: '',
+    },
+    // 当前记录所在的页码
+    currentPage: {
+      type: Number,
+      default: 0,
+    },
+    // 当前记录的排序
+    currentIndex: {
+      type: Number,
+      default: 0,
+    },
+    // 记录的总数量
+    totalRecords: {
+      type: Number,
+      default: 0,
+    },
+    // 窗口唯一Id(必须是唯一的)
+    uuid: {
+      type: String,
+      default: '',
+    },
+    // 工作流任务Id(taskId)
+    taskInfoId: {
+      type: String,
+      default: null,
+    },
+    // 工作流任务类型(approve:审批任务,copyTask:抄送任务)
+    workflowType: {
+      type: String,
+      default: null,
+    },
+  },
+
+  emits: ['update:open', 'OpenTabEditView'],
+  
+  data: function () {
+    this.Language = Language;
+    return {
+      window: {}, // 窗口数据
+      tab: {}, // 父页签
+      tabFormFields: [],
+      multipeColumnFields: [],
+      modelData: {},
+      errorCount: 0, // 校验错误数量
+      errorMsg: '', // 校验错误信息
+      error: 0,
+      headerHtml: '', // Tab头HTML
+      footerHtml: '', // Tab尾HTML
+      headerApiUrl: '', // Tab头API URL
+      footerApiUrl: '', // Tab尾API URL
+      currPage: 1,
+      attributeKey: undefined,
+      attributeValueKey: undefined,
+      processInstanceId: undefined,
+      currIndex: 0,
+      totalCount: 0,
+      buttonGroupInitLeft: 0,
+      buttonGroupInitTop: 0,
+      showSpaceRow: false,
+
+      // 工作流定义Id
+      processDefinitionId: '',
+      showAuditPanel: false,
+      fixedButtonGroupHeight: 0,
+      selectedTabIndex: 0, // 选择的页签序号
+      windowDisplayType: 'Grid', //显示类型
+      processReportResult: undefined,
+      isView: true, //是否显示模式切换按钮
+      curdWindowFunctionAccess: null, //权限
+      jsUrl: null,
+      loading: false,
+      modal2: false,
+      modal3: false,
+      notificationModal: false,
+    };
+  },
+
+  computed: {
+
+    /**
+     * 是否显示审批按钮
+     */
+    showApply: function () {
+      // 判断是否显示审批按钮
+      if (this.window == undefined) {
+        return false;
+      }
+
+      if (this.window.workflow == undefined) {
+        return false;
+      }
+
+      // 已经审批的单据,不显示审批按钮。
+      if (
+        this.modelData != undefined &&
+        this.modelData.data != undefined &&
+        this.modelData.data.processInstanceId != undefined &&
+        this.modelData.data.processInstanceId.displayValue != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0] != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0].length > 0
+      ) {
+        return false;
+      }
+
+      if (this.modelData == undefined || this.modelData.data == undefined) {
+        return false;
+      }
+
+      return true;
+    },
+
+    /**
+     * 是否显示审批面板
+     * 处于审批中的单据,显示审批面板
+     */
+    showApproveComment: function () {
+      // 判断是否显示审批按钮
+      if (
+        this.window != undefined &&
+        this.window.hasWorkflow != undefined &&
+        this.modelData != undefined &&
+        this.modelData.data != undefined &&
+        this.modelData.data.processInstanceId != undefined &&
+        this.modelData.data.processInstanceId.displayValue != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0] != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0].length > 0
+      ) {
+        return true;
+      }
+      return false;
+    },
+
+    /**
+     * 是否显示历史审批记录面板
+     * 处于审批中的单据,显示审批面板
+     */
+    showHistoryApproveComment: function () {
+      if (
+        this.window != null &&
+        this.window.workflow != null &&
+        this.modelData != null
+      ) {
+        return true;
+      }
+      return false;
+    },
+
+    /**
+         * 是否显示审批评论面板
+         * 审批完成的单据,显示审批评论面板
+         */
+    showChoiceButton: function () {
+      if (
+        this.window != undefined &&
+        this.window.workflow != undefined &&
+        this.modelData != undefined &&
+        this.modelData.data != undefined &&
+        this.modelData.data.processInstanceId != undefined &&
+        this.modelData.data.processInstanceId.displayValue != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0] != undefined &&
+        this.modelData.data.processInstanceId.displayValue[0].length > 0 &&
+        this.modelData.data.documentStatus != undefined &&
+        this.modelData.data.documentStatus.displayValue != undefined &&
+        this.modelData.data.documentStatus.displayValue[0] != undefined &&
+        this.modelData.data.documentStatus.displayValue[0].length > 0 &&
+        this.modelData.data.documentStatus.displayValue[0] == 'PROCESSING' &&
+        this.taskInfoId != undefined &&
+        this.workflowType != 'copyTask'
+      ) {
+        return true;
+      }
+      return false;
+    },
+
+    /**
+         * 是否显示编辑
+         * 审批完成的单据,显示审批评论面板
+         */
+    showEditButton: function () {
+      if (this.window == undefined || this.window.tabs == undefined) {
+        return false;
+      } else if (this.window.readOnly) {
+        return false;
+      }
+
+      if (this.curdWindowFunctionAccess == undefined || this.curdWindowFunctionAccess.allowUpdate == undefined || this.curdWindowFunctionAccess.allowUpdate == false) {
+        return false;
+      }
+
+      if (
+        this.window != undefined &&
+        this.window.workflow != undefined &&
+        this.modelData != undefined &&
+        this.modelData.data != undefined &&
+        this.modelData.data.documentStatus != undefined &&
+        this.modelData.data.documentStatus.displayValue != undefined &&
+        this.modelData.data.documentStatus.displayValue[0] != undefined &&
+        this.modelData.data.documentStatus.displayValue[0].length > 0 &&
+        (this.modelData.data.documentStatus.displayValue[0] == 'APPROVED' ||
+          this.modelData.data.documentStatus.displayValue[0] == 'REJECTED' ||
+          this.modelData.data.documentStatus.displayValue[0] == 'PROCESSING')
+      ) {
+        return false;
+      }
+      return true;
+    },
+
+    /**
+     * 是否显示附件上传按钮
+     */
+    showAttachmentPanel: function () {
+      if (this.curdWindowFunctionAccess == undefined
+        || this.curdWindowFunctionAccess.allowUploadAttachment == undefined
+        || this.curdWindowFunctionAccess.allowUploadAttachment == false) {
+        return false;
+      }
+      return true;
+    },
+
+    /**
+         * 是否显示新建按钮
+         */
+    showCreateButton: function () {
+      if (this.window == undefined || this.window.tabs == undefined) {
+        return false;
+      } else if (this.window.readOnly) {
+        return false;
+      }
+
+      if (this.curdWindowFunctionAccess == undefined || this.curdWindowFunctionAccess.allowCreate == undefined || this.curdWindowFunctionAccess.allowCreate == false) {
+        return false;
+      }
+
+      var _self = this;
+
+      if (_self.tab.isReadOnly == true) {
+        return false;
+      }
+
+      // 处于审批界面
+      if (_self.$route.query.workflowType === 'approve') {
+        return false;
+      }
+
+      return true;
+    },
+
+    /**
+         * 是否显示删除按钮
+         */
+    showDeleteButton: function () {
+      if (this.window == undefined || this.window.tabs == undefined) {
+        return false;
+      } else if (this.window.readOnly) {
+        return false;
+      }
+
+      if (this.curdWindowFunctionAccess == undefined || this.curdWindowFunctionAccess.allowDelete == undefined || this.curdWindowFunctionAccess.allowDelete == false) {
+        return false;
+      }
+
+      var _self = this;
+
+      if (_self.tab.isReadOnly == true) {
+        return false;
+      }
+
+      // 处于审批界面
+      if (_self.$route.query.workflowType === 'approve') {
+        return false;
+      }
+
+      return true;
+    },
+
+    /**
+         * 是否显示弃审按钮
+         */
+    showRedrawButton: function () {
+      if (this.window == undefined || this.window.tabs == undefined) {
+        return false;
+      } else if (this.window.readOnly) {
+        return false;
+      }
+
+      var _self = this;
+
+      if (_self.tab.isReadOnly == true) {
+        return false;
+      }
+
+      // 处于审批界面
+      if (_self.$route.query.workflowType === 'approve') {
+        return false;
+      }
+      // 处于抄送界面
+      if (_self.$route.query.workflowType === 'copyTask') {
+        return false;
+      }
+
+      if (
+        _self.modelData != undefined &&
+        _self.modelData.data != undefined &&
+        _self.modelData.data.documentStatus != undefined
+      ) {
+        let documentStatus =
+          _self.modelData.data.documentStatus.displayValue[0];
+        if (documentStatus == 'REJECTED' || documentStatus == 'APPROVED') {
+          return false;
+        }
+      }
+
+      if (
+        _self.window.workflow != undefined &&
+        _self.processInstanceId != undefined &&
+        _self.processInstanceId != ''
+      ) {
+        return true;
+      }
+
+
+
+      return false;
+    },
+  },
+
+  watch: {
+
+    modelData: {
+      deep: true,
+      handler(curVal, oldVal) {
+        this.tabButtonsShowLogical();
+        this.reportViewsShowLogical();
+      },
+    },
+
+    /**
+     * 显示界面发生改变的时候,重新执行显示逻辑
+     */
+    windowDisplayType: function (newValue, oldValue) {
+      this.reportViewsShowLogical();
+    },
+  },
+
+  mounted: function () {
+    console.log('WindowView mounted.');
+
+    var _self = this;
+
+    // 按钮栏实现滚动
+    // _self.$nextTick(function () {
+    // var fixedButtonGroup = $(_self.$refs.fixedButtonGroup);
+    // _self.computerButtonGroupLeftTop();
+    // $(window).scroll(function (){
+    //     if ($(window).scrollTop() > _self.buttonGroupInitTop) {
+    //         _self.showSpaceRow = true;
+    //         _self.$nextTick(function (){
+    //         	fixedButtonGroup.addClass('btn-group-fixed');
+    //         	fixedButtonGroup.css('left', _self.buttonGroupInitLeft + 'px');
+    //         });
+    //     } else {
+    //         _self.showSpaceRow = false;
+    //         _self.$nextTick(function (){
+    //         	fixedButtonGroup.removeClass('btn-group-fixed');
+    //         	fixedButtonGroup.css('left', '');
+    //         });
+    //     }
+
+    //     if ($(window).scrollTop() <= 10){
+    // 		_self.computerButtonGroupLeftTop();
+    //     }
+    // });
+
+    // var fixedButtonGroup = $(_self.$refs.fixedButtonGroup);
+    // var buttonInitTop = fixedButtonGroup.offset().top;
+
+    // _self.fixedButtonGroupHeight = fixedButtonGroup.outerHeight();
+
+    // // 按钮组实现悬浮
+    // $(window).scroll(function () {
+    //   var windowTop = $(window).scrollTop();
+    //   if (windowTop > buttonInitTop + fixedButtonGroup.outerHeight()) {
+    //     fixedButtonGroup.offset({
+    //       top: windowTop,
+    //       left: fixedButtonGroup.offset().left,
+    //     });
+    //   } else {
+    //     fixedButtonGroup.offset({
+    //       top: buttonInitTop,
+    //     });
+    //   }
+    // });
+    // });
+
+    // $(window).resize(function () {
+    //   _self.$nextTick(function () {
+    //     _self.computerButtonGroupLeftTop();
+    //   });
+    // });
+
+    // 获取待审阅的数据
+    let userReadDocumentId = this.$route.query.userReadDocumentId;
+    if (userReadDocumentId != null && userReadDocumentId != '') {
+      UserReadDocumentResource.setProcessed(userReadDocumentId).then(
+        successData => {
+          if (successData.errorCode === 1) {
+            Notify.error(_self.$t('lang.tabFormView.dataException'), _self.$t('lang.tabFormView.reviewDataHasBeenDeleted'), false);
+          } else if (successData.errorCode === 2) {
+            console.log('单据已经审阅');
+            _self.initView();
+          } else if (successData.errorCode === 3) {
+            Notify.error(_self.$t('lang.tabFormView.dataException'), _self.$t('lang.tabFormView.describe1'), false);
+          } else if (successData.errorCode === 0) {
+            console.log('设置单据已经审阅成功。');
+            _self.initView();
+          }
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    } else {
+      console.debug('call init view method.');
+      _self.initView();
+    }
+  },
+  methods: {
+
+    /**
+     * 打开评论界面进行评论
+     * @author GuoZhiBo 20171201
+     */
+    openCurdWindowComment: function () {
+      var _self = this;
+      _self.modal3 = true;
+    },
+
+    saveAndSendNotification: function () {
+      var _self = this;
+      _self.$refs.curdCommentCreate.photograph();
+      _self.sendNotification();
+    },
+
+    // 发送通知
+    sendNotification: function () {
+      var _self = this;
+      var notification = _self.$refs.curdCommentCreate.getNotification();
+      var recordIds = [];
+      recordIds.push(_self.modelData.id);
+      if (recordIds.length == 0) {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe7'), true);
+        return;
+      }
+      // if (notification.userIds == null || notification.userIds.length == 0) {
+      //   Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe8'), true);
+      //   _self.modal3 = false;
+      //   return;
+      // }
+      if (notification.theme == null || notification.theme.trim() == '') {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe9'), true);
+        return;
+      }
+      if (notification.contentText == null || notification.contentText.trim() == '') {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe10'), true);
+        return;
+      }
+      notification.windowNo = _self.modelData.windowNo;
+      notification.tabIndex = _self.tabIndex;
+      notification.recordIds = recordIds;
+      notification.className = _self.tab.tabDataSource.className;
+      notification.category = 'CurdWindow';
+      notification.documentName = 'view';
+      if (_self.modelData.data.processInstanceId != undefined || _self.modelData.data.processInstanceId != null) {
+        notification.processInstanceId = _self.modelData.data.processInstanceId.displayValue[0];
+      }
+      if (_self.modelData.data.documentNo != undefined || _self.modelData.data.documentNo != null) {
+        notification.documentNo = _self.modelData.data.documentNo.displayValue[0];
+      }
+      if (_self.modelData.data.documentCreateUser != undefined || _self.modelData.data.documentCreateUser != null) {
+        notification.documentUserNickName = _self.modelData.data.documentCreateUser.displayValue[0];
+      }
+
+      _self.loading = true;
+      $.ajax({
+        url: Common.getApiURL('notificationResource/send'),
+        type: 'post',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        contentType: 'application/json',
+        data: JSON.stringify(notification),
+        success: function (data) {
+          _self.loading = false;
+          Notify.success(_self.$t('lang.tabButton.describe11'), '操作成功', true);
+          _self.modal3 = false;
+          _self.$refs.curdComment.getCurdComment();
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading = false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+
+    /**
+         * 获取审批图片
+         */
+    getWorkFlowImageUrl: function () {
+      var _self = this;
+      if (
+        _self.modelData != undefined &&
+        _self.modelData.data != undefined &&
+        _self.modelData.data.documentStatus != undefined
+      ) {
+        var documentStatus =
+          _self.modelData.data.documentStatus.displayValue[0];
+        if (documentStatus == undefined || documentStatus == 'EDIT') {
+          return '/static/assets/client-base-v4/image-workflow/edit.png';
+        } else if (documentStatus == 'APPROVED') {
+          return '/static/assets/client-base-v4/image-workflow/approved.png';
+        } else if (documentStatus == 'REJECTED') {
+          return '/static/assets/client-base-v4/image-workflow/rejected.png';
+        } else if (documentStatus == 'PROCESSING') {
+          return '/static/assets/client-base-v4/image-workflow/processing.png';
+        } else if (documentStatus == 'WITHDRAW') {
+          return '/static/assets/client-base-v4/image-workflow/withdraw.png';
+        }
+      }
+    },
+    /**
+         * 切换显示模式
+         * @author GuoZhiBo 20210419
+         */
+    changeWindowDisplayType: function () {
+      var _self = this;
+      if (_self.windowDisplayType == 'Grid') {
+        _self.windowDisplayType = 'Report';
+      } else {
+        _self.windowDisplayType = 'Grid';
+        _self.$nextTick(function () {
+          for (var index = 0; index < _self.tab.subTabs.length; index++) {
+            var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+            _self.$refs[subTabId][0].queryGridData();
+          }
+        });
+      }
+    },
+    // 执行流程
+    executeProcess: function (processReportNo) {
+      var _self = this;
+      var ids = [];
+      if (_self.modelDatas) {
+        _self.modelDatas.forEach(function (modelData) {
+          if (modelData.select == true) {
+            ids.push(modelData.id);
+          }
+        });
+      } else if (_self.modelData) {
+        ids.push(_self.modelData.id);
+      }
+      ProcessReportResource.runProcessByIds(processReportNo, ids).then(
+        successData => {
+          var processReportResult = successData;
+          if (_self.processReportResult == undefined) {
+            if (
+              processReportResult.reportResults != undefined &&
+              processReportResult.reportResults.length > 0
+            ) {
+              processReportResult.reportResults.forEach(function (item, index) {
+                if (item.reportDefinitionType !== 'ExcelReport') {
+                  item.previewIndex = 1;
+                } else {
+                  item.previewIndex = 2;
+                }
+                if (index == 0) {
+                  item.showPreview = true;
+                } else {
+                  item.showPreview = false;
+                }
+              });
+            }
+            _self.processReportResult = processReportResult;
+          } else {
+            if (
+              processReportResult.reportResults != undefined &&
+              processReportResult.reportResults.length > 0
+            ) {
+              processReportResult.reportResults.forEach(function (item, index) {
+                item.previewIndex = 1;
+                if (index == 0) {
+                  item.showPreview = true;
+                } else {
+                  item.showPreview = false;
+                }
+                _self.processReportResult.reportResults.push(item);
+              });
+            }
+          }
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+    getContext: Context,
+    /**
+         * 弃审
+         */
+    abandonWorkflow: function () {
+      var _self = this;
+      _self.loading = true;
+      var obj = {
+        className: _self.tab.tabDataSource.className,
+        tabIndex: _self.tabIndex,
+        windowNo: _self.window.no,
+        recordId: _self.modelData.id,
+      };
+      $.ajax({
+        url: Common.getApiURL('WorkflowResource/abandonWorkflow'),
+        type: 'post',
+        contentType: 'application/json',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        data: JSON.stringify(obj),
+        success: function (data) {
+          _self.loading = false;
+          _self.refresh();
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading = false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+    /**
+         * 打开帮助页面
+         */
+    openHtmlHelp: function (htmlHelpUrl) {
+      window.open(htmlHelpUrl);
+    },
+    auditData: function () {
+      var _self = this;
+      _self.showAuditPanel = true;
+      _self.modal2 = true;
+    },
+
+    // 初始化界面
+    initView: function () {
+      this.recordId = this.modelDataId;
+      this.currPage = this.currentPage;
+      this.currIndex = this.currentIndex;
+      this.totalCount = this.totalRecords;
+
+      if (this.type == 'view') {
+        this.initReadView();
+      } else if (this.type == 'restore') {
+        // 恢复视图
+        this.restoreView();
+      }
+      if (this.workflowType == 'copyTask') {
+        $.ajax({
+          url: Common.getApiURL('WorkflowResource/processTaskInfo'),
+          type: 'get',
+          dataType: 'json',
+          contentType: 'application/json',
+          beforeSend: function (request) {
+            Common.addTokenToRequest(request);
+          },
+          data: {
+            taskInfoId: this.taskInfoId,
+          },
+          success: function (data) { },
+          error: function (XMLHttpRequest, textStatus, errorThrown) {
+            Common.processException(XMLHttpRequest, textStatus, errorThrown);
+          },
+        });
+      }
+    },
+
+    // 初始化编辑界面
+    initReadView: function () {
+      var _self = this;
+      _self.loading = true;
+
+      if (_self.taskInfoId) {
+        CurdWindowResource.uniqueByNoWithWorkflow(
+          null,
+          _self.taskInfoId,
+          _self.windowNo,
+        ).then(
+          successData => {
+            initWindowAfterLoaded(successData);
+            _self.uniqueByNoAccessControl();
+          },
+          errorData => {
+            _self.loading = false;
+            Common.processException(errorData);
+          },
+        );
+      } else {
+        WindowServerUtil.getWindowById(
+          _self.windowNo,
+          function (window) {
+            initWindowAfterLoaded(window);
+            _self.uniqueByNoAccessControl();
+          },
+          function () {
+            _self.loading = false;
+          },
+        );
+      }
+
+      function initWindowAfterLoaded(window) {
+        WindowClientUtil.parseFilterSchema(window);
+        var tab = WindowClientUtil.getTab(window, _self.tabIndex);
+        WindowClientUtil.parseSubTab(window, tab);
+        WindowClientUtil.parseFieldGroup(tab);
+        WindowClientUtil.restoreWindowTabFieldGroupsVisible(window);
+        _self.tabFormFields = WindowClientUtil.getDetailField(tab);
+        _self.window = window;
+        _self.jsUrl = window.jsUrl;
+        _self.tab = tab;
+        TabFormView.restoreTabFormFieldDef(
+          _self.windowNo,
+          _self.tabIndex,
+          _self.tabFormFields,
+        );
+        _self.loadData();
+
+        if (_self.window.workflow != undefined) {
+          _self.processDefinitionId = _self.window.workflow.deploymentId;
+        }
+        _self.initHeaderAndFooterApiUrl();
+        _self.loadHeaderAndFooterContent(_self.recordId);
+        _self.loading = false;
+        if (
+          _self.window.reportViewDto != null &&
+          _self.window.reportViewDto.reportViewItemDtos != null &&
+          _self.window.reportViewDto.reportViewItemDtos.length > 0
+        ) {
+          var isflag = false;
+          _self.window.reportViewDto.reportViewItemDtos.forEach(function (item) {
+            if (item.defaultDisplayReport) {
+              isflag = true;
+            }
+          });
+          if (isflag) {
+            _self.windowDisplayType = 'Report';
+          } else {
+            _self.windowDisplayType = 'Grid';
+          }
+        } else {
+          _self.windowDisplayType = 'Grid';
+          _self.isView = false;
+        }
+      }
+    },
+
+    // 恢复视图
+    restoreView: function () {
+      var _self = this;
+      _self.uuid = this.$route.query.uuid;
+
+      _self.loading = true;
+      WindowServerUtil.getWindowById(
+        _self.windowNo,
+        function (window) {
+          WindowClientUtil.parseFilterSchema(window);
+          var tab = WindowClientUtil.getTab(window, _self.tabIndex);
+          WindowClientUtil.parseSubTab(window, tab);
+          WindowClientUtil.parseFieldGroup(tab);
+          WindowClientUtil.restoreWindowTabFieldGroupsVisible(window);
+          _self.tabFormFields = WindowClientUtil.getDetailField(tab);
+          _self.window = window;
+          _self.jsUrl = window.jsUrl;
+          _self.tab = tab;
+          TabFormView.restoreTabFormFieldDef(
+            _self.windowNo,
+            _self.tabIndex,
+            _self.tabFormFields,
+          );
+
+          _self.uniqueByNoAccessControl();
+
+          let key = _self.uuid + '_modelData';
+          UserStorageResource.uniqueByKey(key).then(
+            successData => {
+              // if(successData.errorCode != 0) {
+              //   Notify.error('提示', successData.errorMessage, false);
+              //   return;
+              // }
+              if (successData.data != null && successData.data != '') {
+                let cacheModelData = JSON.parse(successData.data);
+                _self.$nextTick(function () {
+                  if (
+                    cacheModelData.saveDatas != undefined &&
+                    cacheModelData.saveDatas.length > 0
+                  ) {
+                    cacheModelData.saveDatas.forEach(function (saveData) {
+                      // 恢复子页签的数据
+                      var subTabId = 'subTab' + saveData.tabIndex;
+                      _self.$refs[subTabId][0].addModelData(saveData);
+                    });
+                  } else {
+                    // BUG描述:父子页签,编辑以后撤销,子页签数据不显示
+                    // BUG修复:刷新子页签的数据
+                    // bug fixed by jack 20180203
+
+                    for (
+                      var index = 0; index < _self.tab.subTabs.length; index++
+                    ) {
+                      var subTabId =
+                        'subTab' + this.tab.subTabs[index].tabIndex;
+                      _self.$refs[subTabId][0].queryGridData();
+                    }
+                  }
+                });
+
+                _self.initHeaderAndFooterApiUrl();
+                _self.loadHeaderAndFooterContent(_self.recordId);
+              }
+            },
+            errorData => {
+              Common.processException(errorData);
+            },
+          );
+
+          if (_self.window.workflow != undefined) {
+            _self.processDefinitionId = _self.window.workflow.deploymentId;
+          }
+          _self.loading = false;
+        },
+        function () {
+          _self.loading = false;
+        },
+      );
+    },
+
+    // 备份视图
+    backupView: function () {
+      var _self = this;
+      var subTabChangedData = _self.getSubTabChangedData();
+      if (subTabChangedData.length > 0) {
+        _self.modelData.saveDatas = subTabChangedData;
+      } else {
+        _self.modelData.saveDatas = null;
+      }
+
+      let key = _self.uuid + '_modelData';
+      let userStorageDtos = [{
+        key: key,
+        value: JSON.stringify(_self.modelData),
+      }];
+
+      // 组装查询条件,然后放到后台数据库当中
+      UserStorageResource.uploadUserStorage(userStorageDtos).then(
+        successData => { },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+
+    uniqueByNoAccessControl: function () {
+      // 权限
+      CurdWindowResourceV2.uniqueByNoAccessControl(
+        this.windowNo,
+      ).then(successData => {
+        if (successData.errorCode === 0) {
+          this.curdWindowFunctionAccess = successData.data;
+          if (this.curdWindowFunctionAccess.readOnly != null && this.curdWindowFunctionAccess.readOnly === true) {
+            this.window.readOnly = true;
+          }
+        }
+      }, errorData => {
+        Common.processException(errorData);
+      });
+    },
+
+    /**
+         * 数据发生改变
+         * eg:生单界面回传了新的modelData数据
+         */
+    modelDataChanged: function (newModelData) {
+      this.refresh();
+    },
+
+    /**
+         * 获取界面的数据
+         * eg:生单界面获取modelData数据
+         */
+    getModelData: function () {
+      var _self = this;
+      var subTabChangedData = _self.getSubTabChangedData();
+      if (subTabChangedData.length > 0) {
+        _self.modelData.saveDatas = subTabChangedData;
+      } else {
+        _self.modelData.saveDatas = null;
+      }
+      return _self.modelData;
+    },
+
+    /**
+         * 初始化表头和表尾API方法
+         * @return {[type]} [description]
+         */
+    initHeaderAndFooterApiUrl: function () {
+      if (this.tab != undefined && this.tab.tabFormView != undefined) {
+        this.headerApiUrl = this.tab.tabFormView.headerApiUrl;
+        this.footerApiUrl = this.tab.tabFormView.footerApiUrl;
+      }
+    },
+
+    /**
+         * 加载表头和表位的方法
+         * @return {[type]} [description]
+         */
+    loadHeaderAndFooterContent: function (recordId) {
+      var _self = this;
+      if (this.headerApiUrl != undefined && this.headerApiUrl.length > 0) {
+        $.ajax({
+          url: Common.getApiURL(_self.headerApiUrl),
+          type: 'post',
+          contentType: 'application/json',
+          beforeSend: function (request) {
+            Common.addTokenToRequest(request);
+          },
+          data: JSON.stringify({
+            recordId: recordId,
+          }),
+          dataType: 'text',
+          success: function (data) {
+            _self.headerHtml = data;
+          },
+          error: function (XMLHttpRequest, textStatus, errorThrown) {
+            Common.processException(XMLHttpRequest, textStatus, errorThrown);
+          },
+        });
+      } else {
+        _self.headerHtml = '';
+      }
+      if (this.footerApiUrl != undefined && this.footerApiUrl.length > 0) {
+        $.ajax({
+          url: Common.getApiURL(_self.footerApiUrl),
+          type: 'post',
+          contentType: 'application/json',
+          beforeSend: function (request) {
+            Common.addTokenToRequest(request);
+          },
+          data: JSON.stringify({
+            recordId: recordId,
+          }),
+          dataType: 'text',
+          success: function (data) {
+            _self.footerHtml = data;
+          },
+          error: function (XMLHttpRequest, textStatus, errorThrown) {
+            Common.processException(XMLHttpRequest, textStatus, errorThrown);
+          },
+        });
+      } else {
+        _self.footerHtml = '';
+      }
+    },
+
+    /**
+         * 刷新数据
+         */
+    refresh: function () {
+      var _self = this;
+      _self.loadData();
+      // add by jack 2018-03-22
+      if (_self.recordId != null) {
+        _self.loadHeaderAndFooterContent(_self.recordId);
+      }
+    },
+
+    loadData: function () {
+      var _self = this;
+
+      if (_self.recordId == undefined) {
+        return;
+      }
+
+      var tabLoadParam = {
+        windowNo: _self.windowNo,
+        tabIndex: _self.tabIndex,
+        recordId: _self.recordId,
+      };
+
+      _self.processInstanceId = '';
+
+      _self.loading = true;
+
+      WindowServerUtil.loadTabSingleData(
+        tabLoadParam,
+        function (modelData) {
+          _self.modelData = modelData;
+
+          // 判断是否显示审批状态
+          if (
+            _self.modelData != null &&
+            _self.modelData.data != null &&
+            _self.modelData.data.processInstanceId != null
+          ) {
+            let displayValue =
+              _self.modelData.data.processInstanceId.displayValue;
+            if (displayValue != null && displayValue.length > 0) {
+              _self.processInstanceId = displayValue[0];
+            } else {
+              _self.processInstanceId = '';
+            }
+          } else {
+            _self.processInstanceId = '';
+          }
+
+          // 判断是否有属性
+          if (
+            _self.modelData != null &&
+            _self.modelData.data != null &&
+            _self.modelData.data.attributeKey != null &&
+            _self.modelData.data.attributeKey.displayValue != null
+          ) {
+            let displayValue = _self.modelData.data.attributeKey.displayValue;
+            if (displayValue.length > 0) {
+              _self.attributeKey = displayValue[0];
+            }
+          }
+
+          // 判断是否有属性值
+          if (
+            _self.modelData != null &&
+            _self.modelData.data != null &&
+            _self.modelData.data.attributeKey != null &&
+            _self.modelData.data.attributeValueKey != undefined &&
+            _self.modelData.data.attributeValueKey.displayValue != undefined
+          ) {
+            var displayValue1 =
+              _self.modelData.data.attributeValueKey.displayValue;
+            if (displayValue1.length > 0) {
+              _self.attributeValueKey = displayValue1[0];
+            }
+          }
+
+          _self.loading = false;
+        },
+        function () {
+          _self.loading = false;
+        },
+      );
+    },
+
+    // 改变字段分组的显示和隐藏
+    changeFieldGroupStatus: function (fieldGroup) {
+      fieldGroup.show = !fieldGroup.show;
+      var index = this.tab.tabFormView.fieldGroups.indexOf(fieldGroup);
+      if (index != -1) {
+        this.tab.tabFormView.fieldGroups[index] = fieldGroup;
+        localStorage.setItem(
+          'FieldGroupStatus_' +
+          this.windowNo +
+          '_' +
+          this.tabIndex +
+          '_' +
+          fieldGroup.groupName,
+          fieldGroup.show,
+        );
+      }
+    },
+
+    // 获取子页签发生改变的数据
+    getSubTabChangedData: function () {
+      var subTabChangedRecords = [];
+      if (this.tab.subTabs != undefined) {
+        for (var index = 0; index < this.tab.subTabs.length; index++) {
+          var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+          var modelDatas = this.$refs[subTabId][0].getChangedModelData();
+          if (modelDatas != undefined && modelDatas.length > 0) {
+            modelDatas.forEach(function (modelData) {
+              subTabChangedRecords.push(modelData);
+            });
+          }
+        }
+      }
+      console.log(subTabChangedRecords);
+      return subTabChangedRecords;
+    },
+    // 获取子页签数据校验的Promise
+    getSubTabValidatePromise: function () {
+      var _self = this;
+
+      var validatePromises = [];
+      if (this.tab.subTabs != undefined) {
+        for (var index = 0; index < this.tab.subTabs.length; index++) {
+          var subTabId = 'subTab' + this.tab.subTabs[index].tabIndex;
+          var subTabValidates = this.$refs[subTabId][0].performValidate();
+          validatePromises = validatePromises.concat(subTabValidates);
+        }
+      }
+      return validatePromises;
+    },
+
+    /**
+         * 表单字段的属性(显示)属性发生改变事件
+         */
+    tabFormFieldPropertyChanged: function () {
+      TabFormView.restoreTabFormFieldDef(
+        this.windowNo,
+        this.tabIndex,
+        this.tabFormFields,
+      );
+    },
+
+    // 新建数据
+    createRecord: function () {
+      let _self = this;
+      var currIndex = this.currIndex;
+      var totalCount = this.totalCount;
+      if (this.curdWindowFunctionAccess.allowCreate != null && this.curdWindowFunctionAccess.allowCreate === true) {
+        let data = {
+          type: 'create',
+          windowNo: _self.windowNo,
+          tabIndex: _self.tabIndex,
+          modelDataId: _self.modelData.id,
+          currentPage: _self.currPage,
+          currentIndex: currIndex,
+          totalRecords: totalCount,
+          isRestoreData: true,
+          uuid: _self.uuid,
+        };
+        _self.$emit('OpenTabEditView', data);
+
+      } else {
+        Notify.error(this.$t('lang.tabFormView.clickNewError'), this.$t('lang.tabFormView.describe3'), false);
+      }
+    },
+
+    /**
+         * 编辑数据
+         * @return {void}
+         */
+    editRecord: function () {
+      var _self = this;
+      if (this.curdWindowFunctionAccess.allowUpdate != null && this.curdWindowFunctionAccess.allowUpdate === true) {
+        this.backupView();
+
+        let data = {
+          type: 'edit',
+          windowNo: _self.windowNo,
+          tabIndex: _self.tabIndex,
+          modelDataId: _self.modelData.id,
+          currentPage: _self.currPage,
+          currentIndex: _self.currIndex,
+          totalRecords: _self.totalCount,
+          isRestoreData: false,
+          uuid: _self.uuid,
+        };
+        _self.$emit('OpenTabEditView', data);
+      } else {
+        Notify.error(_self.$t('lang.tabFormView.clickEditError'), _self.$t('lang.tabFormView.describe4'), false);
+      }
+    },
+
+    /**
+     * 删除当前的数据
+     * @return {[type]} [description]
+     */
+    deleteRecord: function (isAlert) {
+      var _self = this;
+      if (this.modelData == undefined || this.modelData.id == undefined) {
+        return;
+      }
+
+      if (this.curdWindowFunctionAccess.allowDelete != null && this.curdWindowFunctionAccess.allowDelete === true) {
+        if (isAlert) {
+          Modal.confirm({
+            title: _self.$t('lang.tabFormView.deleteConfirmation'),
+            icon: createVNode(ExclamationCircleOutlined),
+            content: _self.$t('lang.tabFormView.someWhat'),
+            okText: _self.$t('lang.tabFormView.determine'),
+            okType: 'danger',
+            cancelText: _self.$t('lang.tabFormView.cancel'),
+            onOk() {
+              _self.deleteRecord(false);
+            },
+            onCancel() {
+              console.log('Cancel');
+            },
+          });
+          return;
+        }
+
+        if (this.modelData.id < 0) {
+          _self.$emit('update:open', false);
+          return;
+        }
+
+        var tabDeleteData = {
+          windowNo: _self.windowNo,
+          tabIndex: _self.tabIndex,
+          modelDatas: [_self.modelData],
+        };
+
+        WindowServerUtil.deleteTabData(tabDeleteData, function (result) {
+          _self.$emit('update:open', false);
+        });
+      } else {
+        Notify.error(_self.$t('lang.tabFormView.clickDeleteError'), _self.$t('lang.tabFormView.describe5'), false);
+      }
+    },
+
+    /**
+         * 子标题
+         * @return {String} 子标题
+         */
+    subTitle: function () {
+      var _self = this;
+      var subTitle = '';
+      if (_self.modelData == null || _self.modelData.data == undefined) {
+        return subTitle;
+      }
+      if (_self.modelData.data.documentNo != undefined) {
+        subTitle =
+          _self.modelData.data.documentNo.displayValue == undefined ?
+            '' :
+            _self.modelData.data.documentNo.displayValue[0];
+      } else if (_self.modelData.data.no != undefined) {
+        subTitle =
+          _self.modelData.data.no.displayValue == undefined ?
+            '' :
+            _self.modelData.data.no.displayValue[0];
+      } else if (_self.modelData.data.name != undefined) {
+        subTitle =
+          _self.modelData.data.name.displayValue == undefined ?
+            '' :
+            _self.modelData.data.name.displayValue[0];
+      }
+      return subTitle;
+    },
+
+
+    /**
+         * 审批
+         * @return {void}
+         */
+    apply: function () {
+      var _self = this;
+
+      if (
+        _self.processInstanceId != null &&
+        _self.processInstanceId.length > 0
+      ) {
+        return;
+      }
+
+      var userData = null;
+      var approveUsers = null;
+      var copyUsers = null;
+      var userTaskDtos = null;
+      let userSelectDtos = null;
+      if (this.window.workflow.workflowType === 'UserDefine') {
+        try {
+          let param = this.$refs.workflowUserDefine.getData();
+          userSelectDtos = param.userSelectDtos;
+          copyUsers = param.copyUsers;
+        } catch (exception) {
+          Notify.error(_self.$t('lang.tabFormView.describe6'), exception.message, false);
+          return;
+        }
+      } else if (this.window.workflow.workflowType === 'OTHER') {
+        userSelectDtos = null;
+        copyUsers = null;
+      } else {
+        userData = _self.$refs.workflow.getUserData();
+        approveUsers = userData.applyUsers;
+        copyUsers = userData.copyUsers;
+        userTaskDtos = userData.userTaskDtos;
+
+        // 检查结点数据是否完整
+        for (var i = 0; i < userTaskDtos.length; i++) {
+          if (
+            userTaskDtos[i].assignees.length == undefined ||
+            userTaskDtos[i].assignees.length == 0
+          ) {
+            Notify.error(
+              _self.$t('lang.tabFormView.submitFailed'),
+              _self.$t('lang.tabFormView.describe7', { userTaskDtoName: userTaskDtos[i].name }),
+              false,
+            );
+            return;
+          }
+        }
+      }
+
+      var deploymentId = _self.window.workflow.deploymentId;
+      var recordId = _self.recordId;
+      var windowNo = _self.windowNo;
+
+      var workflowStartParam = {
+        deploymentId: deploymentId,
+        recordId: recordId,
+        windowNo: windowNo,
+        approveUsers: approveUsers,
+        copyUsers: copyUsers,
+        userTaskDtos: userTaskDtos,
+        tabIndex: _self.tab.tabIndex,
+        className: _self.tab.tabDataSource ?
+          _self.tab.tabDataSource.className :
+          null,
+        userSelectDtos: userSelectDtos,
+      };
+
+      _self.loading = true;
+      $.ajax({
+        url: Common.getApiURL('WorkflowExtResource/startWorkflow'),
+        type: 'post',
+        dataType: 'json',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        contentType: 'application/json',
+        data: JSON.stringify(workflowStartParam),
+        success: function (data) {
+          _self.loading = false;
+          Notify.success(_self.$t('lang.tabFormView.notice'), _self.$t('lang.tabFormView.describe8'), true);
+          _self.finishTask();
+          _self.refresh();
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading = false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    /**
+     * 完成任务
+     */
+    finishTask: function () {
+      let _self = this;
+      let taskId = this.$route.query.taskId;
+      if (taskId == null) {
+        return;
+      }
+      $.ajax({
+        url: Common.getApiURL('WorkflowResource/finishTask'),
+        type: 'get',
+        dataType: 'json',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        contentType: 'application/json',
+        data: { taskId: taskId },
+        success: function (data) {
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    /**
+         * 上一条数据
+         * @return {void}
+         */
+    pre: function () {
+      var _self = this;
+      if (_self.currIndex <= 1) {
+        return;
+      }
+      _self.currIndex--;
+      var tabQueryParam = {
+        range: {
+          start: _self.currIndex - 1,
+          length: 1,
+        },
+        windowNo: _self.windowNo,
+        tabIndex: _self.tabIndex,
+      };
+
+      UserStorageResource.uniqueByKey(_self.uuid).then(
+        successData => {
+          // if(successData.errorCode != 0) {
+          //   Notify.error('提示', successData.errorMessage, false);
+          //   return;
+          // }
+          let simpleFilterParams = null;
+
+          let complexFilterParams = null;
+
+          if (successData.data != null && successData.data != '') {
+            let temp = JSON.parse(successData.data);
+            // 分页数据
+
+            // 简单过滤条件
+            tabQueryParam.simpleFilterCondition = temp.simpleFilterParams;
+            // 复杂过滤条件
+            tabQueryParam.filterParams = temp.complexFilterParams;
+            // 排序
+            tabQueryParam.sortStr = temp.sortStr;
+          }
+
+          _self.loadTabData(tabQueryParam);
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+
+    /**
+         * 下一条数据
+         * @return {void}
+         */
+    next: function () {
+      var _self = this;
+      var totalCount = _self.totalCount;
+      if (_self.currIndex >= totalCount) {
+        return;
+      }
+      _self.currIndex++;
+      var tabQueryParam = {
+        range: {
+          start: _self.currIndex - 1,
+          length: 1,
+        },
+        windowNo: _self.windowNo,
+        tabIndex: _self.tabIndex,
+      };
+
+      UserStorageResource.uniqueByKey(_self.uuid).then(
+        successData => {
+          // if(successData.errorCode != 0) {
+          //   Notify.error('提示', successData.errorMessage, false);
+          //   return;
+          // }
+          if (successData.data != null && successData.data != '') {
+            let temp = JSON.parse(successData.data);
+            // 分页数据
+
+            // 简单过滤条件
+            tabQueryParam.simpleFilterCondition = temp.simpleFilterParams;
+            // 复杂过滤条件
+            tabQueryParam.filterParams = temp.complexFilterParams;
+            // 排序
+            tabQueryParam.sortStr = temp.sortStr;
+          }
+
+          _self.loadTabData(tabQueryParam);
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+
+    /**
+         * 加载一条数据
+         * @param  {Object} tabQueryParam 查询条件
+         * @return {void}
+         */
+    loadTabData: function (tabQueryParam) {
+      var _self = this;
+
+      _self.processInstanceId = '';
+
+      _self.loading = true;
+      WindowServerUtil.queryTabData(
+        tabQueryParam,
+        function (gridData) {
+          var dataLists = gridData.dataList;
+          if (dataLists != undefined && dataLists.length > 0) {
+            _self.modelData = dataLists[0];
+            if (_self.modelData) {
+              _self.recordId = _self.modelData.id;
+              _self.loadHeaderAndFooterContent(_self.recordId);
+
+              if (_self.modelData.data.processInstanceId != undefined) {
+                var displayValue =
+                  _self.modelData.data.processInstanceId.displayValue;
+                if (displayValue != undefined && displayValue.length > 0) {
+                  _self.processInstanceId = displayValue[0];
+                }
+              }
+            }
+          }
+          _self.loading = false;
+        },
+        function () {
+          _self.loading = false;
+        },
+      );
+    },
+
+    /**
+         * 计算按钮坐标
+         *
+         */
+    computerButtonGroupLeftTop: function () {
+      var _self = this;
+      var fixedButtonGroup = $(_self.$refs.fixedButtonGroup);
+      if (fixedButtonGroup != undefined) {
+        var offset = fixedButtonGroup.offset();
+        if (offset != undefined) {
+          _self.buttonGroupInitLeft = offset.left;
+          _self.buttonGroupInitTop = offset.top;
+        }
+      }
+    },
+
+    /**
+         * 执行Callout
+         */
+    executeCallout: function (fieldItem) {
+      var _self = this;
+      if (fieldItem.calloutProcessReportNo != null) {
+        _self.callout(fieldItem.calloutProcessReportNo);
+      }
+    },
+
+    /**
+         * callout
+         * @param  {[type]} calloutProcessReportNo [description]
+         * @return {[type]}                  [description]
+         */
+    callout: function (calloutProcessReportNo) {
+      var _self = this;
+
+      // 查询流程和报表的定义
+      ProcessReportResource.uniqueByNo(calloutProcessReportNo).then(
+        successData => {
+          if (successData == null) {
+            return;
+          }
+
+          // 执行服务端的脚本
+          ProcessReportResource.runCallout(
+            calloutProcessReportNo,
+            _self.modelData,
+          ).then(
+            successData => {
+              if (successData && successData.modelData) {
+                _self.modelData = successData.modelData;
+              }
+            },
+            errorData => {
+              Common.processException(errorData);
+            },
+          );
+        },
+        errorData => {
+          Common.processException(errorData);
+        },
+      );
+    },
+
+    /**
+         * 页签按钮的显示逻辑
+         */
+    tabButtonsShowLogical: function () {
+      let _self = this;
+      if (
+        this.tab.tabFormView != null &&
+        this.tab.tabFormView.tabButtons != null
+      ) {
+        for (
+          let index = 0; index < this.tab.tabFormView.tabButtons.length; index++
+        ) {
+          let tabButton = this.tab.tabFormView.tabButtons[index];
+          if (tabButton.editMode != true) {
+            var logic = tabButton.showLogical;
+
+            if (logic == null || logic == '') {
+              tabButton.invisible = false;
+              return;
+            }
+
+            let functionName = 'form_view_show_logical_' + index;
+
+            let executeFunction = function () {
+              try {
+                let context = new _self.getContext(_self.modelData);
+                tabButton.invisible = !_self[functionName](context);
+              } catch (error) {
+                console.error(error);
+                Notify.error('数据字典定义异常', '【' + tabButton.name + '】页签按钮显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+              }
+            };
+
+            if (_self[functionName] == null) {
+              const jsUrl = _self.jsUrl;
+              if (jsUrl == null || jsUrl == undefined) {
+                Notify.error('数据字典定义异常', '【' + tabButton.name + '】页签按钮显示逻辑的JS文件不存在,请联系管理员检查数据字典是否存在JS文件。', false);
+                return;
+              }
+              let promise = JsUtil.dynamicLoadJsFunction(jsUrl, logic);
+              promise.then(targetFunction => {
+
+
+                if (targetFunction == null) {
+                  Notify.error('数据字典定义异常', '【' + tabButton.name + '】页签按钮显示逻辑不存在,请联系管理员检查数据字典的定义。', false);
+                  return;
+                }
+
+                _self[functionName] = targetFunction;
+
+                executeFunction();
+              }, errorData => {
+                console.error(errorData);
+              });
+            } else {
+              executeFunction();
+            }
+          }
+        }
+      }
+    },
+
+    /**
+     * 报表视图显示逻辑
+     */
+    reportViewsShowLogical: function () {
+      var _self = this;
+
+      if (_self.windowDisplayType != 'Report') {
+        // add by jack 2023-12-05
+        // 如果不处于报表界面,那么不执行下述业务逻辑
+        return;
+      }
+
+
+      if (
+        _self.window.reportViewDto != null &&
+        _self.window.reportViewDto.reportViewItemDtos != null
+      ) {
+        _self.processReportResult = undefined;
+        for (
+          let index = 0; index < _self.window.reportViewDto.reportViewItemDtos.length; index++
+        ) {
+          let reportViewItemDto =
+            _self.window.reportViewDto.reportViewItemDtos[index];
+          var logic = reportViewItemDto.showLogical;
+          if (logic == null || logic == '') {
+            reportViewItemDto.invisible = false;
+            _self.executeProcess(reportViewItemDto.processReportNo);
+            return;
+          }
+
+
+          let executeFunction = function () {
+            let context = new _self.getContext(_self.modelData);
+
+            reportViewItemDto.invisible = !_self[functionName](context);
+
+            if (reportViewItemDto.invisible == false) {
+              _self.executeProcess(reportViewItemDto.processReportNo);
+            }
+          };
+
+          let functionName = 'form_view_showlogical_' + index;
+
+          if (this[functionName] == null) {
+
+            const jsUrl = _self.jsUrl;
+            if (jsUrl == null || jsUrl == undefined) {
+              Notify.error('数据字典定义异常', '【' + reportViewItemDto.processReportName + '】CURD报表显示逻辑的JS文件不存在,请联系管理员检查数据字典是否存在JS文件。', false);
+              return;
+            }
+            let promise = JsUtil.dynamicLoadJsFunction(jsUrl, logic);
+            promise.then(targetFunction => {
+              if (targetFunction == null) {
+                Notify.error('数据字典定义异常', '【' + reportViewItemDto.processReportName + '】CURD报表显示逻辑不存在,请联系管理员检查数据字典的定义。', false);
+                return;
+              }
+              _self[functionName] = targetFunction;
+
+              executeFunction();
+            });
+          } else {
+            executeFunction();
+          }
+        }
+      }
+    },
+
+  },
+};
+</script>
+
+<style scoped>
+.field-group {
+  padding-left: 30px;
+  padding-right: 30px;
+}
+
+.fieldGroup-head {
+  cursor: pointer;
+}
+
+.a-back {
+  cursor: pointer;
+  text-decoration: none;
+}
+
+h3 {
+  line-height: inherit !important;
+}
+
+.m-space-btn-group {
+  height: 34px;
+}
+
+.m-row {
+  margin-bottom: 15px;
+}
+
+.fixed-btn-group {
+  z-index: 3;
+  background-color: #f7f7f7;
+}
+</style>
+
+<style>
+.btn-group-fixed {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 3;
+}
+
+.m-image {
+  height: 50px;
+  cursor: pointer;
+}
+</style>

+ 1 - 1
src/window1/tabGridView/NewTabButton.vue

@@ -93,7 +93,7 @@
 
   
   <a-modal v-model:open="modal1Open">
-    <component :is="modal1Component" v-model:open="modal1Open" @refresh="" />
+    <component :is="modal1Component" v-model:open="modal1Open" />
   </a-modal>
 </template>
 

+ 91 - 0
test/window1/TabFormEditModalTest.vue

@@ -0,0 +1,91 @@
+<template>
+  <TabFormEditModal
+    v-model:open="openTabEditModal" 
+    :is-restore-data="tabEditViewIsRestoreData" 
+    :window-no="curdWindowNo" 
+    :tab-index="tabIndex" 
+    :type="tabEditViewType"
+    :model-data-id="tabEditViewRecordId"
+    width="100%" 
+    @open-tab-form-view="openTabFormViewModal"
+  />
+  <TabFormViewModal
+    v-model:open="openTabViewModal" 
+    :window-no="curdWindowNo" 
+    :tab-index="tabIndex" 
+    :type="tabFormViewType"
+    :model-data-id="tabFormViewRecordId"  
+    width="100%"
+    @open-tab-edit-view="openTabEditView"
+  />
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+import TabFormEditModal from '../../src/window1/tabFormEdit/TabFormEditModal.vue';
+import TabFormViewModal from '../../src/window1/tabFormView/TabFormViewModal.vue';
+
+const curdWindowNo = ref('20240910_193059');
+const tabIndex = ref(0);
+
+
+
+const openTabEditModal = ref(false);
+
+const tabEditViewType = ref('');
+const tabEditViewRecordId = ref(null);
+const tabEditViewCurrentPage = ref(null);
+const tabEditViewCurrentIndex = ref(null);
+const tabEditViewTotalRecords = ref(null);
+const tabEditViewIsRestoreData = ref(false);
+
+const openTabViewModal = ref(true);
+const tabFormViewRecordId = ref(476306266914880);
+const tabFormViewType = ref('view');
+
+/**
+ * 打开页签视图模式
+ * @param param 信息
+ *          属性1: type: 类型,
+ *          属性1: windowNo: CURD窗口编号,
+ *          属性2: tabIndex: CURD页签编号,
+ *          属性3: modelDataId: 数据记录id,
+ *          属性4: currentPage: 当前记录所在的页码,
+ *          属性5: currentIndex: 当前记录的排序,
+ *          属性6: totalRecords: 记录的总数量,
+ *          属性7: uuid: 窗口唯一Id,
+ */
+const openTabFormViewModal = function(param){
+  tabFormViewRecordId.value = param.modelDataId;
+  openTabEditModal.value = false;
+  openTabViewModal.value = true;
+};
+
+/**
+ * 打开页签编辑模式
+ * @param param 信息
+ *          属性1: type: 类型,
+ *          属性1: windowNo: CURD窗口编号,
+ *          属性2: tabIndex: CURD页签编号,
+ *          属性3: modelDataId: 数据记录id,
+ *          属性4: currentPage: 当前记录所在的页码,
+ *          属性5: currentIndex: 当前记录的排序,
+ *          属性6: totalRecords: 记录的总数量,
+ *          属性7: uuid: 窗口唯一Id,
+ */
+const openTabEditView = function(param){
+  tabEditViewType.value = param.type;
+  curdWindowNo.value = param.windowNo;
+  tabIndex.value = param.tabIndex;
+  tabEditViewRecordId.value = param.modelDataId;
+  tabEditViewCurrentPage.value = param.currentPage;
+  tabEditViewCurrentIndex.value = param.currentIndex;
+  tabEditViewTotalRecords.value = param.totalRecords;
+  tabEditViewIsRestoreData.value = param.isRestoreData;
+  
+  openTabViewModal.value = false;
+  openTabEditModal.value = true;
+};
+
+</script>