Sfoglia il codice sorgente

Merge branch 'master' of https://a.leanwo.com:3000/prodog-client-2023/client-base-v4

liuyanpeng 1 anno fa
parent
commit
7f38e13862

+ 0 - 777
src/window1/tabFormEdit/SubOneToOneFormFieldEdit.vue

@@ -1,777 +0,0 @@
-<template>
-  <div
-    v-if="modelData && modelData.data != undefined && field.visible"
-    v-show="showField"
-    class="form-group"
-    :class="formGroupClass"
-  >
-    <label
-      v-tooltip.right="field.help"
-      class="control-label"
-      :class="formGroupLabelClass"
-      :style="field.cssStyle"
-    >
-      <span v-if="field.mandatory" class="required-mark">*</span>
-      <font size="2">{{ Language.getDisplayNameTrl($i18n.locale, field) }}</font><br />
-      <font v-if="isChineseEnglish && $i18n.locale == 'zh-CN'" size="0.5">{{ field.displayNameEng }}</font>
-    </label>
-    <div class="input-group" :class="inputGroupClass">
-      <input
-        v-if="fieldUtil.isTextType(field)"
-        v-model="displayValue"
-        autocomplete="off"
-        type="text"
-        class="form-control"
-        :name="field.displayName"
-        :readonly="readOnly"
-        :disabled="readOnly"
-      />
-
-      <input
-        v-if="fieldUtil.isNumberType(field)"
-        v-model="displayValue"
-        autocomplete="off"
-        type="number"
-        class="form-control"
-        :name="field.displayName"
-        :readonly="readOnly"
-        :disabled="readOnly"
-        onmousewheel="return false;"
-        @mousewheel="mouseWheelEvent"
-        @change="numberFormat"
-      />
-
-      <switches
-        v-if="fieldUtil.isCheckBoxType(field)"
-        v-model="displayValue"
-        :selected="displayValue"
-        color="green"
-        :type-bold="true"
-        :disabled="readOnly"
-      />
-
-      <RedGreenSelect
-        v-if="fieldUtil.isRedGreenEditorType(field)"
-        v-model="displayValue"
-        type="string"
-        :disabled="readOnly"
-      />
-
-      <input
-        v-if="fieldUtil.isPasswordType(field)"
-        v-model="displayValue"
-        autocomplete="off"
-        type="password"
-        class="form-control"
-        :name="field.displayName"
-        :readonly="readOnly"
-        :disabled="readOnly"
-      />
-
-      <textarea
-        v-if="fieldUtil.isTextAreaType(field)"
-        v-model="displayValue"
-        class="form-control"
-        rows="3"
-        :name="field.displayName"
-        :style="field.cssStyle"
-        :readonly="readOnly"
-        :disabled="readOnly"
-      />
-
-      <Date
-        v-if="fieldUtil.isDateType(field)"
-        :model-value="displayValue"
-        :data-vv-name="field.displayName"
-        :name="field.displayName"
-        :data-vv-value-path="displayValue"
-        :readonly="readOnly"
-        style="width:100%"
-        @update:model-value="textChanged"
-      />
-
-      <Time
-        v-if="fieldUtil.isTimeType(field)"
-        v-model="displayValue"
-        class="form-control"
-        :data-vv-name="field.displayName"
-        :name="field.displayName"
-        :data-vv-value-path="displayValue"
-        :readonly="readOnly"
-      />
-
-      <DateTime
-        v-if="fieldUtil.isDateTimeType(field)"
-        :model-value="displayValue"
-        :readonly="readOnly"
-        style="width:100%"
-        @update:model-value="textChanged"
-      />
-
-      <YearPicker
-        v-if="fieldUtil.isYearType(field)"
-        :value="displayValue"
-        :readonly="readOnly"
-        @selected="textChanged"
-      />
-
-      <VueMonthlyPicker
-        v-if="fieldUtil.isYearMonthType(field)"
-        id="month-picker"
-        v-model="month"
-        date-format="YYYY-MM"
-        class="vue-monthly-picker m-date-fieldEditView"
-        @selected="refresh"
-      />
-
-      <ImageWidget
-        v-if="fieldUtil.isImageType(field)"
-        :uuid="uuid1"
-        :pattern-json="field.pattern"
-        :field="field"
-        :field-value="fieldValue"
-        :class-name="className"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <ImageListWidget
-        v-if="fieldUtil.isImageListType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :class-name="className"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <VideoListWidget
-        v-if="fieldUtil.isVideoType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :class-name="className"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <FileListWidget
-        v-if="fieldUtil.isFileType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :class-name="className"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <EnumRadioGroupWidget
-        v-if="fieldUtil.isRadioButtonGroupType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :data-vv-name="field.displayName"
-        :name="field.displayName"
-        :data-vv-value-path="displayValue"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <ManyToManySetSearchWidget
-        v-if="fieldUtil.isManyToManySetType(field)"
-        :info-window-no="field.infoWindowNo"
-        :field="field"
-        :field-value="fieldValue"
-        :readonly="readOnly"
-        :model-data="modelData"
-        :window-no="windowNo"
-        :tab-index="tabIndex"
-        @value-changed="valueChanged"
-      />
-
-      <SearchWidget
-        v-if="fieldUtil.isSearchType(field)"
-        :info-window-no="field.infoWindowNo"
-        :field="field"
-        :field-value="fieldValue"
-        :readonly="readOnly"
-        :model-data="modelData"
-        :window-no="windowNo"
-        :tab-index="tabIndex"
-        @value-changed="valueChanged"
-      />
-
-      <EnumSelectWidget
-        v-if="fieldUtil.isEnumListType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :name="field.displayName"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <EnumMultiSelectWidget
-        v-if="fieldUtil.isEnumMultiType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :name="field.displayName"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-      />
-
-      <SelectWidget
-        v-if="fieldUtil.isSelectType(field)"
-        ref="selectWidget"
-        :field="field"
-        :field-value="fieldValue"
-        :window-no="windowNo"
-        :tab-index="tabIndex"
-        :readonly="readOnly"
-        :model-data="modelData"
-        @value-changed="valueChanged"
-      />
-
-      <ButtonWidget
-        v-if="fieldUtil.isButtonType(field)"
-        :field="field"
-        :field-value="fieldValue"
-        :readonly="readOnly"
-        @value-changed="valueChanged"
-        @execute-callout="executeCallout"
-      />
-
-      <RichTextAreaEditorWidget
-        v-if="fieldUtil.isRichTextAreaEditor(field)"
-        :display-value="displayValue"
-        :class-name="className"
-        :field-value="fieldValue"
-        :readonly="isReadOnly"
-        @value-changed="valueChanged"
-      />
-
-      <p v-show="!validateMandatory" class="required-mark required-error">
-        该字段为必填字段
-      </p>
-    </div>
-  </div>
-</template>
-
-<script>
-import fieldUtil from '../../resource/dictionary/FieldUtil.js';
-
-import WindowClientUtil from '../../resource/dictionary/WindowClientUtil.js';
-import Language from '../../common/Language.js';
-import Context from '../common/Context.js';
-
-import SearchWidget from '../tabFormWidget/SearchWidget.vue';
-import ImageListWidget from '../tabFormWidget/ImageListWidget.vue';
-import EnumSelectWidget from '../tabFormWidget/EnumSelectWidget.vue';
-import SelectWidget from '../tabFormWidget/SelectWidget.vue';
-import EnumRadioGroupWidget from '../tabFormWidget/EnumRadioGroupWidget.vue';
-import VideoListWidget from '../tabFormWidget/VideoListWidget.vue';
-import FileListWidget from '../tabFormWidget/FileListWidget.vue';
-import ButtonWidget from '../tabFormWidget/ButtonWidget.vue';
-
-import EnumMultiSelectWidget from '../tabFormWidget/EnumMultiSelectWidget.vue';
-import ManyToManySetSearchWidget from '../tabFormWidget/ManyToManySetSearchWidget.vue';
-import RedGreenSelect from '../../widget/RedGreenSelect.vue';
-import ImageWidget from '../tabFormWidget/ImageWidget.vue';
-import RichTextAreaEditorWidget from '../tabFormWidget/RichTextAreaEditorWidget.vue';
-import JsUtil from '../../common/JsUtil.js';
-import { Notify, Uuid } from 'pc-component-v3';
-
-
-
-
-
-
-
-
-
-export default {
-
-  components: {
-    SearchWidget,
-    ImageListWidget,
-    EnumSelectWidget,
-    SelectWidget,
-    EnumRadioGroupWidget,
-    VideoListWidget,
-    FileListWidget,
-    EnumMultiSelectWidget,
-    ManyToManySetSearchWidget,
-    ImageWidget,
-    RedGreenSelect,
-    ButtonWidget,
-    RichTextAreaEditorWidget,
-  },
-  
-  props: {
-   
-    windowNo: {
-      type: String,
-      default: null,
-    },
-    tabIndex: {
-      type: Number,
-      default: null,
-    },
-    className: {
-      type: String,
-      default: null,
-    },
-    multipleColumn: {
-      type: Boolean,
-      default: null,
-    },
-    jsUrl: {
-      type: String,
-      default: null,
-    },
-    field: {
-      type: Object,
-      default : function(){
-        return null;
-      },
-    },
-    modelData: {
-      type: Object,
-      default : function(){
-        return null;
-      },
-    },
-    isChineseEnglish: {
-      type: Boolean,
-      default: null,
-    },
-  },
-
-  
-  emits: ['executeCallout', 'valueChanged'],
-
-  data: function () {
-    this.Language = Language;
-    // eslint-disable-next-line
-    var value =
-      this.modelData == undefined ||
-      this.modelData.data == undefined ||
-      this.modelData.data[this.field.fieldName] == undefined
-        ? ''
-        : this.modelData.data[this.field.fieldName].displayValue[
-          this.field.entityFieldIndex
-        ];
-
-    var fieldValue =
-      this.modelData == undefined || this.modelData.data == undefined
-        ? []
-        : this.modelData.data[this.field.fieldName];
-
-    return {
-      displayValue: value,
-      fieldValue: fieldValue,
-      fieldUtil: fieldUtil,
-      validateMandatory: true, // 验证强制字段是否通过
-      month: undefined,
-      uuid1: Uuid.createUUID(),
-      showField: true, // 显示字段
-    };
-  },
-
-  computed: {
-    readOnly: function () {
-      if (this.field == undefined) {
-        return true;
-      }
-
-      if (this.field != undefined && this.field.readOnly == true) {
-        return true;
-      }
-
-      if (this.field != undefined && this.field.entityFieldIndex > 0) {
-        return true;
-      }
-
-      if (
-        this.modelData != undefined &&
-        this.modelData.id > 0 &&
-        (this.field.updatable == undefined || this.field.updatable == false)
-      ) {
-        return true;
-      }
-
-      return this.field.readOnly;
-    },
-
-    /**
-     * 表单组的CSS样式
-     * 对应 bootstrap 表单 form-group
-     */
-    formGroupClass: function () {
-      return {
-        'form-group-single-row':
-          this.field != undefined && this.field.singleRow,
-        'form-group-multiple-row':
-          this.field != undefined && !this.field.singleRow,
-        'form-group-multiple-column':
-          this.field != undefined && this.multipleColumn == true, // 多列
-      };
-    },
-
-    /**
-     * 标题的CSS样式
-     * 对应 bootstrap 表单 label 样式
-     */
-    formGroupLabelClass: function () {
-      return {
-        'm-sr-only':
-          this.field == null || !this.field.visible || !this.field.showLabel, // 显示/隐藏
-        'col-xs-5 col-sm-4 col-md-3 col-lg-2':
-          this.field != null && this.multipleColumn == false, // 单列
-        'label-multiple-column':
-          this.field != null && this.multipleColumn == true, // 多列
-      };
-    },
-
-    /**
-     * 控件的CSS样式
-     * 对应 bootstrap 表单 input-group
-     */
-    inputGroupClass: function () {
-      return {
-        'col-xs-7 col-sm-8 col-md-9 col-lg-10':
-          this.field != null && this.multipleColumn == false, // 单列
-        'input-group-multiple-column': this.multipleColumn, // 多列
-        'input-group-single-row':
-          this.field != undefined &&
-          this.field.singleRow == true &&
-          this.multipleColumn, // 单独一行
-      };
-    },
-
-    /**
-     * 控件的CSS样式
-     * 对应 bootstrap 表单 input-group 内的元素
-     */
-    inputGroupItemClass: function () {
-      return {};
-    },
-  },
-
-  watch: {
-    displayValue: function (currentValue, oldValue) {
-      if (
-        fieldUtil.isSearchType(this.field) == false &&
-        this.field.entityFieldIndex == 0 &&
-        fieldUtil.isSelectType(this.field) == false &&
-        fieldUtil.isRadioButtonGroupType(this.field) == false &&
-        fieldUtil.isEnumListType(this.field) == false &&
-        fieldUtil.isManyToManySetType(this.field) == false
-      ) {
-        // add by jack 20240220
-        // 修复bug:当modelData.data的值从外部修改以后,修改执行 watch->'modelData.data'  中的 this.displayValue = ? 方法
-        // 执行完成以后,watch->displayValue 又会执行,会触发valueChanged事件,这会导致 callout/calloutjs 会被多次执行。
-        // 所以在触发 valueChanged 的之前,先判断currentValue与modelData中的值是否相等,
-        // 如果相等,说明是外部修改了modelData,然后执行了 watch->'modelData.data' 方法修改了 displayValue,此时不触发valueChanged事件。
-        // 如果不相等,说明是DOM修改了,触发修改了displayValue,此时触发valueChanged事件。
-
-        const modelDataFieldDisplayValue = this.getModelDataFieldDisplayValue();
-
-        if (currentValue !== oldValue && currentValue !== modelDataFieldDisplayValue) {
-          var newFieldValue = {
-            displayValue: [currentValue],
-            fieldType: 'String',
-          };
-          this.$emit('valueChanged', newFieldValue);
-        }
-      }
-    },
-
-    'modelData.data': {
-      deep: true,
-      handler(curVal, oldVal) {
-        if(curVal == undefined ||
-            curVal[this.field.fieldName] == undefined ||
-            curVal[this.field.fieldName].displayValue == undefined ||
-            curVal[this.field.fieldName].displayValue.length < this.field.entityFieldIndex + 1){
-          this.displayValue = '';
-        }else{
-          let tempValue = curVal[this.field.fieldName].displayValue[this.field.entityFieldIndex];
-          if(fieldUtil.isCheckBoxType(this.field)){
-            if(typeof(tempValue) =='string'){
-              this.displayValue = (tempValue === 'true') ? true : false;
-            }
-            if(typeof(tempValue) =='boolean'){
-              this.displayValue = (tempValue === true) ? true : false;
-            }
-          }else{
-            this.displayValue = tempValue;
-          }          
-        }
-        this.fieldValue = curVal == undefined ? [] : curVal[this.field.fieldName];
-        this.showLogical();
-      },
-    },
-
-    month: function () {
-      this.textChanged(this.month);
-    },
-  },
-
-  mounted: function () {},
-
-  methods: {
-
-    
-    /**
-     * 获取Context
-     */
-    getContext: Context,
-
-
-    /**
-     * 获取modelData中字段的显示值
-     */
-    getModelDataFieldDisplayValue : function(){
-      if(this.modelData == null 
-          || this.field == null
-          || this.modelData.data[this.field.fieldName] == undefined
-          || this.modelData.data[this.field.fieldName].displayValue == undefined
-          || this.modelData.data[this.field.fieldName].displayValue.length < this.field.entityFieldIndex + 1){
-        return null;
-      }
-      return this.modelData.data[this.field.fieldName].displayValue[this.field.entityFieldIndex];
-    },
-
-
-    // 值改变事件
-    valueChanged: function (newFieldValue) {
-      // this.fieldValue = newFieldValue;
-      this.$emit('valueChanged', newFieldValue);
-    },
-
-    /**
-     * 执行Callout
-     */
-    executeCallout: function (field) {
-      this.$emit('executeCallout', field);
-    },
-
-    //年份选择器值改变
-    textChanged: function (value) {
-      var newFieldValue = {
-        displayValue: [value],
-        fieldType: 'String',
-      };
-      this.$emit('valueChanged', newFieldValue);
-    },
-
-    validateRule: function (field) {
-      return field.mandatory ? 'required' : '';
-    },
-
-    performValide: function () {
-      var _self = this;
-      _self.validateMandatory = true;
-
-      if (this.field.mandatory == true) {
-        if (
-          fieldUtil.isRadioButtonGroupType(this.field) ||
-          fieldUtil.isSelectType(this.field) ||
-          fieldUtil.isSearchType(this.field)
-        ) {
-          var idValue =
-            this.modelData == undefined ||
-            this.modelData.data == undefined ||
-            this.modelData.data[this.field.fieldName] == undefined
-              ? undefined
-              : this.modelData.data[this.field.fieldName].id;
-          if (idValue == null || idValue == '' || idValue < 1) {
-            _self.validateMandatory = false;
-          }
-        } else if (fieldUtil.isCheckBoxType(this.field)) {
-          return true;
-        } else if (fieldUtil.isRedGreenEditorType(this.field)) {
-          return true;
-        } else {
-          var stringValue =
-            this.modelData == undefined ||
-            this.modelData.data == undefined ||
-            this.modelData.data[this.field.fieldName] == undefined
-              ? ''
-              : this.modelData.data[this.field.fieldName].displayValue[0];
-          if (stringValue == undefined || stringValue === '') {
-            _self.validateMandatory = false;
-          }
-        }
-      }
-      return _self.validateMandatory;
-    },
-
-    /**
-     * 年份变化
-     */
-    yearChange: function () {},
-
-    /**
-     * 年月选择完成
-     */
-    refresh: function () {},
-
-    numberFormat: function () {
-      if (
-        this.fieldItem &&
-        this.fieldItem.pattern &&
-        this.fieldItem.pattern != ''
-      ) {
-        var _self = this;
-        fieldUtil.formatNumber(
-          this.displayValue,
-          this.fieldItem.pattern,
-          function (formatValue) {
-            _self.displayValue = formatValue;
-          },
-        );
-      }
-    },
-
-    /**
-     * 禁止滚轮滚动影响数字
-     */
-    mouseWheelEvent: function (event) {
-      if (event || Window.event) {
-        event.preventDefault();
-      }
-    },
-
-    /**
-     * 响应显示逻辑
-     */
-    showLogical: function () {
-      let _self = this;
-      var logic = this.field.showLogical;
-      if (logic == null || logic == '') {
-        this.showField = true;
-        return;
-      }
-
-      const functionName =
-        this.field.fieldName.replace('.', '_') + '_showLogical';
-
-
-      let executeFunction = function(){
-        try{
-          let context = new _self.getContext(_self.modelData);
-          _self.showField = _self[functionName](context);
-        }catch(error){
-          console.error(error);
-          Notify.error('数据字典定义异常', '【' + logic + '】前端列显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
-        }
-      };
-
-      if (_self[functionName] == null) {
-        const jsUrl = _self.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(_self[functionName] == null){
-            Notify.error('数据字典定义异常', '【' + logic + '】前端列显示逻辑方法不存在,请联系管理员检查数据字典。', false);
-            return;
-          }
-          executeFunction();
-        }, errorData => {
-          console.error(errorData);
-        });
-      }else{
-        executeFunction();
-      }
-    },
-  },
-};
-</script>
-<style scoped>
-.required-mark {
-  color: red;
-  margin-right: 10px;
-}
-
-input::-webkit-outer-spin-button,
-input::-webkit-inner-spin-button {
-  -webkit-appearance: none !important;
-  margin: 0;
-}
-
-input[type="number"] {
-  -moz-appearance: textfield;
-}
-textarea {
-  overflow-y: auto !important;
-  overflow-x: hidden !important;
-}
-
-.form-group-single-row {
-  display: block;
-  width: 100%;
-}
-
-.input-group-item {
-  word-break: break-all;
-}
-
-.input-group-item-manytomany {
-  color: #333;
-  background-color: #f0f0f0;
-  border: 1px solid #ccc;
-  border-radius: 4px;
-  height: 26px;
-  margin: 4px 4px 0px 0px;
-  padding: 6px 0.25em;
-}
-
-.label-multiple-column {
-  width: 120px;
-}
-
-.form-group-multiple-column {
-  margin-top: 5px;
-}
-
-@media (max-width: 768px) {
-  .input-group-single-row {
-    width: 100%;
-  }
-
-  .input-group-item {
-    padding-top: 0px;
-  }
-}
-
-@media (min-width: 768px) {
-  .label-multiple-column {
-    text-overflow: ellipsis;
-    text-align: right;
-    padding-right: 5px;
-  }
-
-  .input-group-multiple-column {
-    width: 230px;
-  }
-
-  .input-group-single-row {
-    width: calc(100% - 200px) !important;
-    word-wrap: break-word;
-  }
-}
-
-.m-sr-only {
-  visibility: hidden;
-}
-</style>
-
-
-<style>
-.m-date-fieldEditView > div:first-child {
-  width: 100%;
-}
-</style>

+ 474 - 128
src/window1/tabFormEdit/SubOneToOneTabEdit.vue

@@ -1,19 +1,24 @@
 <template>
+  <a-page-header
+    :title="Language.getNameTrl($i18n.locale, tab)"
+    style="border-bottom: 1px solid rgb(235, 237, 240); padding: 0px;"
+  />
+
   <div class="m-row clearfix">
     <div>
-      <div
+      <div 
+        v-if="tabFormFields && mModelData"
         :class="{
           'form-inline': tab.tabFormView.multipleColumn,
           'form-horizontal': !tab.tabFormView.multipleColumn,
         }"
       >
         <template
-          v-for="fieldItem in tabFormFields"
-          :key="
+          v-for="fieldItem in tabFormFields" :key="
             'FieldEditView_' +
               windowNo +
               '_' +
-              tabIndex +
+              tab.tabIndex +
               '_' +
               fieldItem.fieldName +
               '_' +
@@ -21,16 +26,16 @@
           "
         >
           <FieldEditView
-            ref="fieldItem1"
-            :class-name="tab.tabDataSource.className"
+            ref="fieldItem1" 
+            :class-name="tab.tabDataSource.className" 
             :field="fieldItem"
-            :model-data="oneToOneModelData"
-            :window-no="windowNo"
-            :tab-index="tabIndex"
+            :model-data="mModelData" 
+            :window-no="windowNo" 
+            :tab-index="tab.tabIndex" 
             :js-url="jsUrl"
-            :is-chinese-english="curdWindow.isChineseEnglish"
+            :is-chinese-english="curdWindow.isChineseEnglish" 
             :multiple-column="tab.tabFormView.multipleColumn"
-            @value-changed="valueChanged($event, fieldItem)"
+            @value-changed="valueChanged($event, fieldItem)" 
             @execute-callout="executeCallout(fieldItem)"
           />
         </template>
@@ -39,151 +44,492 @@
   </div>
 </template>
 
-<script>
+<script setup>
 import Common from '../../common/Common';
 import { Notify } from 'pc-component-v3';
-import FieldEditView from './SubOneToOneFormFieldEdit.vue';
+import FieldEditView from './TabFormFieldEdit.vue';
 import WindowClientUtil from '../../resource/dictionary/WindowClientUtil.js';
 import WindowServerUtil from '../../resource/dictionary/WindowServerUtil.js';
+import { ref, defineExpose, defineEmits, defineProps, watch } from 'vue';
+import { debounce } from 'lodash';
+import ProcessReportResource from '../../api/dic/ProcessReportResource.js';
+import FieldUtil from '../../resource/dictionary/FieldUtil.js';
 
-export default {
-  components: {
-    FieldEditView,
-  },
+import Context from '../common/Context.js';
+import { getCurrentInstance } from 'vue';
+import JsUtil from '../../common/JsUtil.js';
 
-  props: {
-    subOneToOneTab: {
-      type: Object,
-      default: null,
-    },
-    tab: {
-      type: Object,
-      default: null,
-    },
-    modelData: {
-      type: Object,
-      default: null,
-    },
-    modelDataCreate: {
-      type: Object,
-      default: null,
-    },
-    curdWindow: {
-      type: Object,
-      default: null,
-    },
+import Language from '../../common/Language.js';
 
-    windowNo: {
-      type: String,
-      default: null,
-    },
-    tabIndex: {
-      type: Number,
-      default: null,
-    },
 
-    type: {
-      type: String,
-      default: null,
-    },
-    jsUrl: {
-      type: String,
-      default: null,
+// proxy 就是当前组件实例,可以理解为组件级别的 this,没有全局的、路由、状态管理之类的
+const { proxy, appContext } = getCurrentInstance();
+
+// 接受父组件传递的数据
+const props = defineProps({
+  tab: {
+    type: Object,
+    default: () => {
+      return {};
     },
-    recordId: {
-      type: String,
-      default: null,
+  },
+  parentModelData: {
+    type: Object,
+    default: () => {
+      return {};
     },
-    isChineseEnglish: {
-      type: Boolean,
-      default: null,
+  },
+  curdWindow: {
+    type: Object,
+    default: () => {
+      return {};
     },
   },
 
-  emits: ['executeCallout', 'valueChanged'],
+  windowNo: {
+    type: String,
+    default: null,
+  },
 
-  data() {
-    return {
-      tabFormFields: [],
-      oneToOneModelData: null,
-    };
+  type: {
+    type: String,
+    default: null,
+  },
+  jsUrl: {
+    type: String,
+    default: null,
   },
 
-  watch: {
-    subOneToOneTab: {
-      handler(newVal) {
-        if (newVal) {
-          this.tabFormFields = WindowClientUtil.getDetailField(newVal);
-          if (this.type === 'create') {
-            this.getOneToOneModelData(newVal.tabIndex);
-          } else {
-            this.getOneToOneTabData(newVal.tabIndex);
-          }
-        }
-      },
-      immediate: true,
-    },
+  isChineseEnglish: {
+    type: Boolean,
+    default: false,
   },
+});
 
-  methods: {
-    // 获取一对一页签modelData(新建)
-    getOneToOneModelData: function (tabIndex) {
-      const _self = this;
-      WindowServerUtil.newModelData(
-        _self.windowNo,
-        0,
-        _self.modelDataCreate,
-        function (response) {
-          if (response.errorCode != 0) {
-            Notify.error('数据新建异常', response.errorMessage, false);
-            return;
-          }
-          let modelData = response.data;
+const mModelData = ref({});
+const tabFormFields = ref([]);
+const fieldGroup = ref([]);
+const oldCommand = ref(null);
 
-          modelData.editMode = true;
+const emits = defineEmits(['executeCallout', 'valueChanged']);
 
-          _self.oneToOneModelData = modelData;
+const getContext = Context;
 
-        },
-      );
+/**
+ * 查询一对一页签数据
+ */
+const getOneToOneTabData = function () {
+  const params = {
+    windowNo: props.windowNo,
+    tabIndex: props.tab.tabIndex,
+    parentId: props.parentModelData == undefined ? undefined : props.parentModelData.id,
+  };
+  $.ajax({
+    url: Common.getApiURL('CurdWindowResource/oneToOneTabData'),
+    async: false,
+    dataType: 'json',
+    type: 'post',
+    data: JSON.stringify(params),
+    contentType: 'application/json',
+    beforeSend: function (request) {
+      Common.addTokenToRequest(request);
+    },
+    success: function (data) {
+      mModelData.value = data;
     },
+    error: function (XMLHttpRequest, textStatus, errorThrown) {
+      Common.processException(XMLHttpRequest, textStatus, errorThrown);
+    },
+  });
+};
 
-    // 查询一对一页签数据(编辑)
-    getOneToOneTabData: function (tabIndex) {
-      const _self = this;
-      const params = {
-        tabIndex,
-        windowNo: this.windowNo,
-        parentId: _self.modelData == undefined ? undefined : _self.modelData.id,
-      };
-      $.ajax({
-        url: Common.getApiURL('CurdWindowResource/oneToOneTabData'),
-        async: false,
-        dataType: 'json',
-        type: 'post',
-        data: JSON.stringify(params),
-        contentType: 'application/json',
-        beforeSend: function (request) {
-          Common.addTokenToRequest(request);
-        },
-        success: function (data) {
-          _self.oneToOneModelData = data;
+
+/**
+ * 获取一对一页签modelData(新建)
+ * @param tabIndex 
+ */
+const createOneToOneModelData = function () {
+  WindowServerUtil.newModelData(
+    props.windowNo,
+    props.tab.tabIndex,
+    null,
+    function (response) {
+      if (response.errorCode != 0) {
+        Notify.error('数据新建异常', response.errorMessage, false);
+        return;
+      }
+      let newModelData = response.data;
+      newModelData.editMode = true;
+      mModelData.value = newModelData;
+    },
+  );
+};
+
+/**
+ * 执行Callout
+ */
+const executeCallout = function (fieldItem) {
+  if (fieldItem.calloutProcessReportNo != null) {
+    callout(fieldItem.calloutProcessReportNo);
+  }
+};
+
+
+
+/**
+ * callout
+ * @param  {[type]} calloutProcessReportNo [description]
+ * @return {[type]}                  [description]
+ */
+const callout = function (calloutProcessReportNo) {
+
+  // add by jack 20180529
+  var subTabChangedData = getSubTabChangedData();
+  if (subTabChangedData.length > 0) {
+    mModelData.value.vaue.saveDatas = subTabChangedData;
+  } else {
+    mModelData.value.vaue.saveDatas = null;
+  }
+
+  // 查询流程和报表的定义
+  ProcessReportResource.uniqueByNo(calloutProcessReportNo).then(
+    successData => {
+      if (successData == null) {
+        return;
+      }
+      // 执行服务端的脚本
+      ProcessReportResource.runCallout(
+        calloutProcessReportNo,
+        mModelData.value.vaue,
+      ).then(
+        successData => {
+          if (successData && successData.modelData) {
+            mModelData.value.vaue = successData.modelData;
+          }
+          // add by jack 20180529
+          // add by jack 20220601
+          mModelData.value.vaue.saveDatas = undefined;
         },
-        error: function (XMLHttpRequest, textStatus, errorThrown) {
-          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        errorData => {
+          Common.processException(errorData);
         },
-      });
-    },
-    valueChanged(newFieldValue, fieldItem) {
-      console.log(newFieldValue, fieldItem, 'oneToOne数据---');
-      this.$emit('valueChanged', newFieldValue, fieldItem);
+      );
     },
-    executeCallout(field) {
-      this.$emit('executeCallout', field);
+    errorData => {
+      Common.processException(errorData);
     },
+  );
+};
+
+
+// 获取子页签发生改变的数据
+const getSubTabChangedData = function () {
+  var subTabChangedRecords = [];
+  if (props.tab.subTabs != undefined) {
+    for (var index = 0; index < props.tab.subTabs.length; index++) {
+      var subTabId = 'subTab' + props.tab.subTabs[index].tabIndex;
+      // TODO
+      // var modelDatas = $refs[subTabId][0].getChangedModelData();
+      // if (modelDatas != undefined && modelDatas.length > 0) {
+      //   modelDatas.forEach(function (modelData) {
+      //     subTabChangedRecords.push(modelData);
+      //   });
+      // }
+    }
+  }
+  console.log(subTabChangedRecords);
+  return subTabChangedRecords;
+};
+
+
+
+/**
+ * 延迟获取页面的数据
+ */
+const debounceNewAction = debounce(() => {
+  if (props.type === 'create') {
+    createOneToOneModelData();
+  } else {
+    getOneToOneTabData();
+  }
+}, 1000);
+
+
+watch(
+  () => [props.windowNo, props.tab, props.parentModelData, props.type],
+  (newValue, oldValue) => {
+    let newCommand = newValue[0] 
+      + (newValue[1] != null ? (newValue[1].name + newValue[1].tabIndex) : '-')
+      + (newValue[2] != null ? newValue[2].id : '-')
+      + newValue[3];
+    if(newCommand != oldCommand.value){
+      debounceNewAction();
+    }
+    oldCommand.value = newCommand;
+  },
+  { immediate: true },
+);
+
+watch(
+  () => props.tab,
+  (newValue, oldValue) => {
+    tabFormFields.value = WindowClientUtil.getDetailField(newValue);
+    console.log(tabFormFields.value);
   },
+  { immediate: true },
+);
+
+
+
+// 值改变事件
+const valueChanged = function (newFieldValue, fieldItem) {
+  console.log(fieldItem.fieldName + ' ValueChanged.');
+  console.log(newFieldValue);
+  var oldFieldValue = mModelData.value.data[fieldItem.fieldName];
+  if (FieldUtil.isFieldValueEqual(newFieldValue, oldFieldValue) == false) {
+    mModelData.value.data[fieldItem.fieldName] = newFieldValue;
+    if (
+      fieldItem.calloutProcessReportNo != undefined &&
+      fieldItem.calloutProcessReportNo != null
+    ) {
+      callout(fieldItem.calloutProcessReportNo);
+    }
+
+    if (
+      fieldItem.calloutLogical != undefined &&
+      fieldItem.calloutLogical != null
+    ) {
+      executeCalloutJs(fieldItem, fieldItem.calloutLogical);
+    }
+
+    if (
+      mModelData.value.changed &&
+      fieldItem.displayType == 'ListBoxEditor'
+    ) {
+      // 值改变时,刷新所有下拉框的keyValues
+      refreshSelectField(fieldItem.fieldName);
+    }
+
+    // add by jack 20170808
+    mModelData.value.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 = mModelData.value.data[fieldName1];
+        fieldValue0.id = undefined;
+        if (fieldValue0.displayValue != undefined) {
+          fieldValue0.displayValue.splice(
+            0,
+            fieldValue0.displayValue.length,
+          );
+        } else {
+          fieldValue0.displayValue = [];
+        }
+        mModelData.value.data[fieldName1] = fieldValue0;
+      }
+    };
+
+    // 遍历所有的字段,判断是否有动态约束
+    // 如果有关联的动态约束,则清空字段
+    var fieldName0 = fieldItem.fieldName;
+    tabFormFields.value.forEach(function (item) {
+      clearDynamicValidField(item);
+    });
+
+    let fieldGroups = props.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
+const refreshSelectField = function (valueChangedFieldName) {
+
+  if (tabFormFields.value) {
+    tabFormFields.value.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 (fieldGroup.value) {
+    fieldGroup.value.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: props.windowNo,
+      tabIndex: props.tab.tabIndex,
+      fieldName: item.fieldName,
+      modelData: mModelData.value,
+    };
+
+    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);
+      },
+    });
+  }
+};
+
+
+
+/**
+ * 执行JS Callout
+ */
+const executeCalloutJs = function (fieldItem, scriptText) {
+
+  // add by jack 20180529
+  var subTabChangedData = getSubTabChangedData();
+  if (subTabChangedData.length > 0) {
+    mModelData.value.saveDatas = subTabChangedData;
+  } else {
+    mModelData.value.saveDatas = null;
+  }
+
+  let functionName = fieldItem.fieldName.replace('.', '_') + '_calloutjs';
+
+  let executeFunction = function () {
+    let actions = {
+      subTabsRef: getSubTabs(),
+    };
+    let context = new getContext(mModelData, actions);
+    try {
+      proxy[functionName](context);
+    } catch (e) {
+      console.error(e);
+      Notify.error('数据字典定义异常', '【' + scriptText + '】前端列显示逻辑定义异常,请联系管理员检查数据字典的定义。', false);
+    }
+  };
+
+  if (proxy[functionName] == null) {
+    // 执行服务端的脚本
+    const jsUrl = props.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;
+      }
+
+      proxy[functionName] = targetFunction;
+      executeFunction();
+
+    }, errorData => {
+      console.error(errorData);
+    });
+  } else {
+    executeFunction();
+  }
+};
+
+
+
+/**
+ * 获取子页签的集合
+  */
+const getSubTabs = function () {
+  let subTabsRef = [];
+  for (var tabIndex = 0; tabIndex < props.tab.subTabs.length; tabIndex++) {
+    var subTabId = 'subTab' + props.tab.subTabs[tabIndex].tabIndex;
+    // TODO
+    // subTabsRef.push($refs[subTabId][0]);
+  }
+  return subTabsRef;
+};
+
+
+const fieldItem1 = ref();
+const fieldItem2 = ref();
+
+/**
+ * 执行验证
+ * @returns 验证错误的数量
+ */
+const performValide = function(){
+  let error = 0;
+
+  if (fieldItem1.value != undefined) {
+    fieldItem1.value.forEach(function (w) {
+      var validateResult = w.performValide();
+      if (!validateResult) {
+        error++;
+      }
+    });
+  }
+
+  if (fieldItem2.value != undefined) {
+    fieldItem2.value.forEach(function (w) {
+      var validateResult = w.performValide();
+      if (!validateResult) {
+        error++;
+      }
+    });
+  }
+
+  return error;
+};
+
+
+const getModelData = function(){
+  return mModelData.value;
+};
+
+defineExpose({
+  performValide,
+  getModelData,
+});
+
 </script>
 
-<style scoped>
-</style>
+<style scoped></style>

+ 48 - 10
src/window1/tabFormEdit/TabFormEditModal.vue

@@ -165,7 +165,7 @@
               tab.tabFormView.fieldGroups.length > 0
           " class="m-row clearfix"
         >
-          <ul id="myTabs" class="nav nav-tabs" role="tablist">
+          <!-- <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 }"
@@ -175,14 +175,20 @@
                 {{ Language.getGroupNameTrl($i18n.locale, fieldGroup) }}
               </a>
             </li>
-          </ul>
+          </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"
+              v-for="(fieldGroup) in tab.tabFormView.fieldGroups"
+              id="home" :key="fieldGroup.groupName" role="tabpanel"
               class="tab-pane fade active in" aria-labelledby="home-tab"
             >
               <div v-if="fieldGroup.show">
+                <a-page-header
+                  :title="Language.getGroupNameTrl($i18n.locale, fieldGroup)"
+                  style="border-bottom: 1px solid rgb(235, 237, 240); padding: 0px;"
+                />
                 <div
                   :class="{
                     'form-inline': tab.tabFormView.multipleColumn,
@@ -210,18 +216,18 @@
             </div>
           </div>
         </div>
-        <template v-if="modelData && tab.subOneToOneTabs && tab.subOneToOneTabs.length">
+
+        <template v-if="modelData && tab.subOneToOneTabs && tab.subOneToOneTabs.length > 0">
           <div v-for="oneToOneTab in tab.subOneToOneTabs " :key="'SubOneToOneTabGridEdit-' + windowNo + '-' + tabIndex + '-' + modelData.id + '-oneToOneTab-' + oneToOneTab.tabIndex">
             <SubOneToOneTabEdit
-              :sub-one-to-one-tab="oneToOneTab" :tab="tab" :model-data="modelData"
-              :window-no="windowNo" :model-data-create="modelDataCreate"
-              :tab-index="tabIndex"
+              ref="subOneToOneTabEdit"
+              :tab="oneToOneTab" 
+              :parent-model-data="modelData"
+              :window-no="windowNo" 
               :type="type"
               :js-url="jsUrl"
-              :record-id="recordId"
               :curd-window="curdWindow"
               :is-chinese-english="curdWindow.isChineseEnglish"
-              @value-changed="valueChanged" @execute-callout="executeCallout"
             />
           </div>
         </template>
@@ -1441,6 +1447,13 @@ export default {
         var attributeValueDtos = _self.$refs.attributePanel.getValue();
       }
 
+      // 对OneToOne页签进行校验
+      if(_self.$refs.subOneToOneTabEdit != null){
+        _self.$refs.subOneToOneTabEdit.forEach(function (w) {
+          _self.error += w.performValide();
+        });
+      }
+
       console.log('check finished');
       if (_self.error == 0) {
         executeSave();
@@ -1459,6 +1472,15 @@ export default {
           _self.modelData.saveDatas = null;
         }
 
+        var subOneToOneTabDatas = _self.getSubOneToOneTabEditData();
+        if(subOneToOneTabDatas != null && subOneToOneTabDatas.length > 0){
+          if(_self.modelData.saveDatas == null){
+            _self.modelData.saveDatas = [];
+          }
+          _self.modelData.saveDatas.push(...subOneToOneTabDatas);
+        }
+
+
         var tabSaveData = {
           attributeValueDtos: attributeValueDtos,
           persistenceData: _self.modelData,
@@ -1873,6 +1895,22 @@ export default {
       console.log(subTabChangedRecords);
       return subTabChangedRecords;
     },
+
+    /**
+     * 获取OneToOne页签的数据
+     */
+    getSubOneToOneTabEditData: function(){
+      var subOneToOneTabRecords = [];
+      if (this.$refs.subOneToOneTabEdit != undefined) {
+        this.$refs.subOneToOneTabEdit.forEach(function (w) {
+          const oneToOneTabData = w.getModelData();
+          subOneToOneTabRecords.push(oneToOneTabData);
+        });
+      }
+      console.log(subOneToOneTabRecords);
+      return subOneToOneTabRecords;
+    },
+
     // 获取子页签数据校验的Promise
     getSubTabValidatePromise: function () {
       var _self = this;

+ 144 - 93
src/window1/tabFormView/SubOneToOneTabView.vue

@@ -1,19 +1,24 @@
 <template>
+  <a-page-header
+    :title="Language.getNameTrl($i18n.locale, tab)"
+    style="border-bottom: 1px solid rgb(235, 237, 240); padding: 0px;"
+  />
+
   <div class="m-row clearfix">
     <div>
       <div
+        v-if="tabFormFields && mModelData"
         :class="{
           'form-inline': tab.tabFormView.multipleColumn,
           'form-horizontal': !tab.tabFormView.multipleColumn,
         }"
       >
         <template
-          v-for="fieldItem in tabFormFields"
-          :key="
+          v-for="fieldItem in tabFormFields" :key="
             'FieldEditView_' +
               windowNo +
               '_' +
-              tabIndex +
+              tab.tabIndex +
               '_' +
               fieldItem.fieldName +
               '_' +
@@ -21,15 +26,9 @@
           "
         >
           <FieldEditView
-            ref="fieldItem1"
-            :class-name="tab.tabDataSource.className"
-            :field="fieldItem"
-            :model-data="modelData"
-            :window-no="windowNo"
-            :tab-index="tabIndex"
-            :js-url="jsUrl"
-            :is-chinese-english="curdWindow.isChineseEnglish"
-            :multiple-column="tab.tabFormView.multipleColumn"
+            ref="fieldItem1" :class-name="tab.tabDataSource.className" :field="fieldItem"
+            :model-data="mModelData" :window-no="windowNo" :tab-index="tab.tabIndex" :js-url="jsUrl"
+            :is-chinese-english="curdWindow.isChineseEnglish" :multiple-column="tab.tabFormView.multipleColumn"
             @execute-callout="executeCallout(fieldItem)"
           />
         </template>
@@ -38,106 +37,158 @@
   </div>
 </template>
 
-<script>
+<script setup>
 import Common from '../../common/Common';
 import FieldEditView from './TabFormFieldView.vue';
 import WindowClientUtil from '../../resource/dictionary/WindowClientUtil.js';
+import Language from '../../common/Language.js';
+import ProcessReportResource from '../../api/dic/ProcessReportResource.js';
+import { ref, reactive, defineEmits, defineProps, watch } from 'vue';
+import { debounce } from 'lodash';
 
-export default {
-  components: {
-    FieldEditView,
-  },
 
-  props: {
-    subOneToOneTab: {
-      type: Object,
-      default: null,
-    },
-    tab: {
-      type: Object,
-      default: null,
+// 接受父组件传递的数据
+const props = defineProps({
+  tab: {
+    type: Object,
+    default: ()=>{
+      return {};
     },
-    modelData: {
-      type: Object,
-      default: null,
+  },
+  parentModelData: {
+    type: Object,
+    default: ()=>{
+      return {};
     },
-    curdWindow: {
-      type: Object,
-      default: null,
+  },
+  curdWindow: {
+    type: Object,
+    default: ()=>{
+      return {};
     },
+  },
 
-    windowNo: {
-      type: String,
-      default: null,
-    },
-    tabIndex: {
-      type: Number,
-      default: null,
-    },
+  windowNo: {
+    type: String,
+    default: null,
+  },
 
-    jsUrl: {
-      type: String,
-      default: null,
-    },
-    isChineseEnglish: {
-      type: Boolean,
-      default: null,
-    },
+  jsUrl: {
+    type: String,
+    default: null,
+  },
+  
+  isChineseEnglish: {
+    type: Boolean,
+    default: false,
   },
+});
 
-  emits: ['executeCallout'],
+const mModelData = ref({});
+const tabFormFields = ref([]);
 
-  data() {
-    return {
-      oneToOneModelData: [],
-    };
-  },
-  watch: {
-    subOneToOneTab: {
-      handler(newVal) {
-        if (newVal) {
-          this.tabFormFields = WindowClientUtil.getDetailField(newVal);
-          this.getOneToOneTabData(newVal.tabIndex);
-        }
-      },
-      immediate: true,
+const emits = defineEmits([]);
+
+
+
+/**
+ * 查询一对一页签数据
+ */
+const getOneToOneTabData = function () {
+  const params = {
+    windowNo: props.windowNo,
+    tabIndex: props.tab.tabIndex,
+    parentId: props.parentModelData == undefined ? undefined : props.parentModelData.id,
+  };
+  $.ajax({
+    url: Common.getApiURL('CurdWindowResource/oneToOneTabData'),
+    async: false,
+    dataType: 'json',
+    type: 'post',
+    data: JSON.stringify(params),
+    contentType: 'application/json',
+    beforeSend: function (request) {
+      Common.addTokenToRequest(request);
     },
-  },
+    success: function (data) {
+      mModelData.value = data;
+    },
+    error: function (XMLHttpRequest, textStatus, errorThrown) {
+      Common.processException(XMLHttpRequest, textStatus, errorThrown);
+    },
+  });
+};
 
-  methods: {
-    // 查询一对一页签数据
-    getOneToOneTabData: function (tabIndex) {
-      const _self = this;
-      const params = {
-        tabIndex,
-        windowNo: this.windowNo,
-        parentId: _self.modelData == undefined ? undefined : _self.modelData.id,
-      };
-      $.ajax({
-        url: Common.getApiURL('CurdWindowResource/oneToOneTabData'),
-        async: false,
-        dataType: 'json',
-        type: 'post',
-        data: JSON.stringify(params),
-        contentType: 'application/json',
-        beforeSend: function (request) {
-          Common.addTokenToRequest(request);
-        },
-        success: function (data) {
-          _self.oneToOneModelData = data;
+
+/**
+ * 执行Callout
+ */
+const executeCallout = function (fieldItem) {
+  if (fieldItem.calloutProcessReportNo != null) {
+    callout(fieldItem.calloutProcessReportNo);
+  }
+};
+
+/**
+ * callout
+ * @param  {[type]} calloutProcessReportNo [description]
+ * @return {[type]}                  [description]
+ */
+const callout = function (calloutProcessReportNo) {
+  // 查询流程和报表的定义
+  ProcessReportResource.uniqueByNo(calloutProcessReportNo).then(
+    successData => {
+      if (successData == null) {
+        return;
+      }
+
+      // 执行服务端的脚本
+      ProcessReportResource.runCallout(
+        calloutProcessReportNo,
+        mModelData.value,
+      ).then(
+        successData => {
+          if (successData && successData.modelData) {
+            mModelData.value = successData.modelData;
+          }
         },
-        error: function (XMLHttpRequest, textStatus, errorThrown) {
-          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        errorData => {
+          Common.processException(errorData);
         },
-      });
+      );
     },
-
-    executeCallout(field) {
-      this.$emit('executeCallout', field);
+    errorData => {
+      Common.processException(errorData);
     },
-  },
+  );
 };
+
+/**
+ * 延迟获取页面的数据
+ */
+const debounceGetOneToOneTabData = debounce(() => {
+  getOneToOneTabData();
+}, 1000);
+
+
+watch(
+  () => [props.windowNo, props.tab, props.parentModelData],
+  (newValue, oldValue) => {
+    debounceGetOneToOneTabData();
+  },
+  { immediate: true },
+);
+
+watch(
+  () => props.tab, 
+  (newValue, oldValue) => {
+    tabFormFields.value = WindowClientUtil.getDetailField(newValue);
+    console.log(tabFormFields.value);
+  },
+  { immediate: true },
+);
+
+
 </script>
 
-<style scoped>
-</style>
+<style scoped></style>

+ 14 - 9
src/window1/tabFormView/TabFormViewModal.vue

@@ -158,7 +158,7 @@
               tab.tabFormView.fieldGroups.length > 0
           " class="m-row clearfix"
         >
-          <ul id="myTabs" class="nav nav-tabs" role="tablist">
+          <!-- <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 }"
@@ -168,14 +168,19 @@
                 {{ Language.getGroupNameTrl($i18n.locale, fieldGroup) }}
               </a>
             </li>
-          </ul>
+          </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"
+              v-for="(fieldGroup) in tab.tabFormView.fieldGroups"
+              id="home" :key="fieldGroup.groupName" role="tabpanel"
               class="tab-pane fade active in" aria-labelledby="home-tab"
             >
+              <a-page-header
+                :title="Language.getGroupNameTrl($i18n.locale, fieldGroup)"
+                style="border-bottom: 1px solid rgb(235, 237, 240); padding: 0px;"
+              />
+  
               <div v-if="fieldGroup.show">
                 <div
                   :class="{
@@ -210,16 +215,15 @@
         <!-- eslint-disable-next-line -->
         <div v-html="footerHtml" />
 
-        <template v-if="modelData && tab.subOneToOneTabs && tab.subOneToOneTabs.length">
-          <div v-for="oneToOneTab in tab.subOneToOneTabs " :key="'SubOneToOneTabGridEdit-' + windowNo + '-' + tabIndex + '-' + modelData.id + '-oneToOneTab-' + oneToOneTab.tabIndex">
+        <template v-if="modelData && tab.subOneToOneTabs && tab.subOneToOneTabs.length > 0">
+          <div v-for="oneToOneTab in tab.subOneToOneTabs " :key="'SubOneToOneTabView-' + windowNo + '-' + tabIndex + '-' + oneToOneTab.tabIndex + '-' + modelData.id">
             <SubOneToOneTabView
-              :sub-one-to-one-tab="oneToOneTab" :tab="tab" :model-data="modelData"
+              :tab="oneToOneTab" 
+              :parent-model-data="modelData"
               :window-no="windowNo"
-              :tab-index="tabIndex"
               :js-url="jsUrl"
               :curd-window="curdWindow"
               :is-chinese-english="curdWindow.isChineseEnglish"
-              @execute-callout="executeCallout(fieldItem)"
             />
           </div>
         </template>
@@ -403,6 +407,7 @@ import { CaretRightOutlined, CaretLeftOutlined, SmallDashOutlined, ExclamationCi
 import { createVNode } from 'vue';
 import { Modal } from 'ant-design-vue';
 import SubOneToOneTabView from './SubOneToOneTabView.vue';
+
 export default {
 
   components: {

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

@@ -1,6 +1,5 @@
 <template>
   <div class="button_list">
-    <div v-if="leftTabButton.length === 0" />
     <a-space v-if="leftTabButton && leftTabButton.length" size="small">
       <template v-for="(item, index) in leftTabButton" :key="index">
         <a-button

+ 3 - 0
src/window1/tabGridView/TabGridEdit.vue

@@ -674,6 +674,9 @@ export default {
         this.tabIndex,
         this.tabGridFields,
       );
+
+      console.log(_self.tabGridFields);
+
       if (
         _self.tab.tabDataSource.tabDataSourceGroupDtos &&
         _self.tab.tabDataSource.tabDataSourceGroupDtos.length

+ 12 - 12
webpack.dev.js

@@ -62,71 +62,71 @@ module.exports = WebpackMerge.merge(baseConfig, {
     
     proxy: {
       '/api': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/static': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/content': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/dashboard': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/assets': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/mock': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/authApi': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/Dictionary': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/Files': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: false,
         changeOrigin: true,
         secure:true,
       },
       '/WebSocket': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: true,
         changeOrigin: true,
       },
       '/TrainVideo': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: true,
         changeOrigin: true,
       },
       '/module': {
-        target: 'http://192.168.1.5:10023/',
+        target: 'http://192.168.1.108:10023/',
         ws: true,
         changeOrigin: true,
         secure:true,