This is an automated email from the ASF dual-hosted git repository.

liyang pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git


The following commit(s) were added to refs/heads/kylin5 by this push:
     new 93fee73901 KYLIN-5823,improve text recognition dialog of add batch 
dimensions
93fee73901 is described below

commit 93fee7390113733c4b0c367734b953c0cc271b16
Author: huangchunyan <qingyanxiaon...@163.com>
AuthorDate: Fri Apr 5 17:16:33 2024 +0800

    KYLIN-5823,improve text recognition dialog of add batch dimensions
---
 .../RecognizeAggregateModal.vue                    | 208 ++++++++++++---------
 .../common/RecognizeAggregateModal/handler.js      |   3 +-
 .../common/RecognizeAggregateModal/locales.js      |  10 +-
 .../common/RecognizeAggregateModal/store.js        |  24 ++-
 .../studio/StudioModel/DimensionsModal/index.vue   |  71 +++++--
 .../studio/StudioModel/DimensionsModal/locales.js  |   4 +-
 6 files changed, 203 insertions(+), 117 deletions(-)

diff --git 
a/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
 
b/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
index 7ca329cbbf..4ca6f00b91 100644
--- 
a/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
+++ 
b/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
@@ -1,83 +1,83 @@
 <template>
-    <el-dialog class="recognize-aggregate-modal" width="960px"
-      append-to-body
-      :title="$t('title')"
-      :visible="isShow"
-      :close-on-press-escape="false"
-      :close-on-click-modal="false"
-      :before-close="handleCancel"
-      @closed="handleClosed"
-    >
-      <div class="dialog-content">
-        <div class="recognize-area">
-          <div class="recognize-header" v-if="errorLines.length">
-            <div class="result-counter">
-              <span class="error">{{$tc('errorCount', errorCount, { count: 
errorCount })}}</span>
-              <el-tooltip :content="$t('repeatTip')" placement="top">
-                <span class="warning">{{$tc('repeatCount', repeatCount, { 
count: repeatCount })}}</span>
-              </el-tooltip>
-            </div>
-            <div class="result-actions">
-              <el-button icon-button text type="primary" size="mini" 
icon="el-ksd-n-icon-arrow-up-outlined" @click="handlePrevious" /><!--
-           --><el-button icon-button text type="primary" size="mini" 
icon="el-ksd-n-icon-arrow-down-outlined" @click="handleNext" />
-            </div>
-          </div>
-          <AceEditor :key="isShow" :placeholder="'123'" class="text-input" 
ref="editorRef" :value="form.text" @input="handleInputText" />
-          <div class="actions">
-            <el-tooltip placement="left">
-              <div slot="content">{{$t('dexecute')}}<span 
class="accelerator-key">{{$t('acceleratorKey')}}</span></div>
-              <el-button icon-button class="recognize" size="small" 
type="primary" icon="el-ksd-n-icon-play-filled" :disabled="!form.text" 
@click="handleRecognize" />
+  <el-dialog class="recognize-aggregate-modal" width="960px"
+    append-to-body
+    :title="$t('title')"
+    :visible="isShow"
+    :close-on-press-escape="false"
+    :close-on-click-modal="false"
+    :before-close="handleCancel"
+    @closed="handleClosed"
+  >
+    <div class="dialog-content">
+      <div class="recognize-area">
+        <div class="recognize-header" v-if="errorLines.length">
+          <div class="result-counter">
+            <span class="error">{{$tc('errorCount', errorCount, { count: 
errorCount })}}</span>
+            <el-tooltip :content="$t('repeatTip')" placement="top">
+              <span class="warning">{{$tc('repeatCount', repeatCount, { count: 
repeatCount })}}</span>
             </el-tooltip>
           </div>
-        </div>
-        <div class="recognize-results" v-loading="loadingRecognize">
-          <template v-if="form.dimensions.length">
-            <div class="results-header">
-              {{$tc('selectedDimensionCount', selectedDimensionCount, { count: 
selectedDimensionCount })}}
-              <template>
-                <span class="divide ksd-ml-8 
ksd-mr-8">|</span><span>{{$t('usedDimensionCount', {count: 
usedDimensionCount})}}</span>
-              </template>
-            </div>
-            <div class="list-actions">
-              <el-checkbox :key="isSelectAll" :indeterminate="isIndeterminate" 
:checked="isSelectAll" @change="handleSelectAll" />
-              <div class="header-dimension-name">{{$t('dimensionName')}}</div>
-              <div class="header-data-type">{{$t('dataType')}}</div>
-            </div>
-            <RecycleScroller
-              class="dimension-list"
-              :items="dimensionList"
-              :item-size="37"
-              key-field="value"
-            >
-              <template slot-scope="{ item }">
-                <div class="dimension" @click="handleCheckDimension(item)">
-                  <el-checkbox :key="item.isChecked" :checked="item.isChecked" 
@change="handleCheckDimension(item)" />
-                  <span class="name">{{ item.label }}</span>
-                  <span class="data-type">{{ item.dataType }}</span>
-                  <div v-if="item.isDisabled" class="current-used-mask" />
-                </div>
-              </template>
-            </RecycleScroller>
-          </template>
-          <div class="all-dimension-error" v-else-if="isAllDimensionError">
-            <i class="el-ksd-n-icon-error-circle-filled" />
-            <span>{{$t('recognizeFailed')}}</span>
+          <div class="result-actions">
+            <el-button icon-button text type="primary" size="mini" 
icon="el-ksd-n-icon-arrow-up-outlined" @click="handlePrevious" /><!--
+          --><el-button icon-button text type="primary" size="mini" 
icon="el-ksd-n-icon-arrow-down-outlined" @click="handleNext" />
           </div>
-          <EmptyData v-else :showImage="false" :content="$t('emptyText')" />
+        </div>
+        <AceEditor :key="isShow" :placeholder="'123'" class="text-input" 
ref="editorRef" :value="form.text" @input="handleInputText" />
+        <div class="actions">
+          <el-tooltip placement="left">
+            <div slot="content">{{$t('dexecute')}}<span 
class="accelerator-key">{{$t('acceleratorKey')}}</span></div>
+            <el-button icon-button class="recognize" size="small" 
type="primary" icon="el-ksd-n-icon-play-filled" :disabled="!form.text" 
@click="handleRecognize" />
+          </el-tooltip>
         </div>
       </div>
-      <div slot="footer" class="dialog-footer ky-no-br-space">
-        <el-button size="medium" @click="handleCancel">
-          {{$t('kylinLang.common.cancel')}}
-        </el-button>
-        <el-button type="primary" size="medium" 
:disabled="!selectedDimensionCount" @click="handleSubmit">
-          {{$t('kylinLang.common.save')}}
-        </el-button>
+      <div class="recognize-results" v-loading="loadingRecognize">
+        <template v-if="form.dimensions.length">
+          <div class="results-header">
+            {{$tc('selectedDimensionCount', selectedDimensionCount, { count: 
selectedDimensionCount })}}
+            <template v-if="type !== 'TABLE_INDEX'">
+              <span class="divide ksd-ml-8 
ksd-mr-8">|</span><span>{{$t('usedDimensionCount', {count: 
usedDimensionCount})}}</span>
+            </template>
+          </div>
+          <div class="list-actions">
+            <el-checkbox :key="isSelectAll" :indeterminate="isIndeterminate" 
:checked="isSelectAll" @change="handleSelectAll" />
+            <div class="header-dimension-name">{{$t('dimensionName')}}</div>
+            <div class="header-data-type">{{$t('dataType')}}</div>
+          </div>
+          <RecycleScroller
+            class="dimension-list"
+            :items="dimensionList"
+            :item-size="37"
+            key-field="value"
+          >
+            <template slot-scope="{ item }">
+              <div class="dimension" @click="handleCheckDimension(item)">
+                <el-checkbox :key="item.isChecked" :checked="item.isChecked" 
@change="handleCheckDimension(item)" />
+                <span class="name">{{ item.label }}</span>
+                <span class="data-type">{{ item.dataType }}</span>
+                <div v-if="item.isDisabled" class="current-used-mask" />
+              </div>
+            </template>
+          </RecycleScroller>
+        </template>
+        <div class="all-dimension-error" v-else-if="isAllDimensionError">
+          <i class="el-ksd-n-icon-error-circle-filled" />
+          <span>{{$t('recognizeFailed')}}</span>
+        </div>
+        <EmptyData v-else :showImage="false" :content="$t('emptyText')" />
       </div>
-    </el-dialog>
-  </template>
+    </div>
+    <div slot="footer" class="dialog-footer ky-no-br-space">
+      <el-button size="medium" @click="handleCancel">
+        {{$t('kylinLang.common.cancel')}}
+      </el-button>
+      <el-button type="primary" size="medium" 
:disabled="!selectedDimensionCount" @click="handleSubmit">
+        {{$t('kylinLang.common.save')}}
+      </el-button>
+    </div>
+  </el-dialog>
+</template>
   
-  <script>
+<script>
   import Vue from 'vue'
   import AceEditor from 'vue2-ace-editor'
   import { Component, Watch } from 'vue-property-decorator'
@@ -92,6 +92,7 @@
   vuex.registerModule(['modals', 'RecognizeAggregateModal'], store)
 
   const TABLE_INDEX = 'TABLE_INDEX'
+  const DIMENSION = 'DIMENSION'
 
   @Component({
     components: {
@@ -105,6 +106,7 @@
         type: state => state.type,
         status: state => state.status,
         form: state => state.form,
+        usedColumns: state => state.usedColumns,
         errors: state => state.errors,
         errorLines: state => state.errorLines,
         errorInEditor: state => state.errorInEditor,
@@ -119,7 +121,7 @@
         'hierarchyItems',
         'joints',
         'jointItems',
-        'tableIndexCols'
+        'allColumns'
       ])
     },
     methods: {
@@ -181,16 +183,17 @@
     }
     get isIndeterminate () {
       const { selectedDimensionCount, isSelectAll } = this
-      return selectedDimensionCount && !isSelectAll
+      return selectedDimensionCount > 0 && !isSelectAll
     }
     isColumnUsedInCurrent (column) {
-      const { type, includes, mandatories, hierarchyItems, jointItems, 
tableIndexCols } = this
+      const { type, includes, mandatories, hierarchyItems, jointItems, 
usedColumns } = this
       switch (type) {
         case AGGREGATE_TYPE.INCLUDE: return includes.includes(column)
         case AGGREGATE_TYPE.MANDATORY: return mandatories.includes(column)
         case AGGREGATE_TYPE.HIERARCHY: return hierarchyItems.includes(column)
         case AGGREGATE_TYPE.JOINT: return jointItems.includes(column)
-        case TABLE_INDEX: return tableIndexCols.includes(column)
+        case DIMENSION: return usedColumns.find(d => d.column === column)
+        case TABLE_INDEX:
         default: return false
       }
     }
@@ -213,6 +216,7 @@
             joints.some(joint => joint.items.some((item, idx) => idx !== 
groupIdx && item === column))
         // 包含维度不做判断
         case AGGREGATE_TYPE.INCLUDE:
+        case DIMENSION:
         default: return false
       }
     }
@@ -237,6 +241,22 @@
         default: return 'Unknow Error'
       }
     }
+    getRecognizeColumn (columnText) {
+      const { type, modelDimensions, allColumns } = this
+      switch (type) {
+        case AGGREGATE_TYPE.MANDATORY:
+        case AGGREGATE_TYPE.HIERARCHY:
+        case AGGREGATE_TYPE.JOINT:
+        case AGGREGATE_TYPE.INCLUDE:
+          return modelDimensions.find(d => d.column === columnText)
+        case TABLE_INDEX:
+          return allColumns.find(d => d.column === columnText)
+        case DIMENSION:
+          return allColumns.find(d => d.column === columnText)
+        default: return null
+      }
+    }
+
     setNotInModelError (column) {
       const { errors } = this
       if (!errors.notInModel.includes(column)) this.setModal({ errors: { 
...errors, notInModel: [...errors.notInModel, column] } })
@@ -271,7 +291,7 @@
           <div class="ace_placeholder">
             <div>
               {this.$t('inputPlaceholder1')}
-              <el-tooltip
+              {/* <el-tooltip
                 popperClass="recognize-aggregate-placeholder-tooltip"
                 placement="top"
               >
@@ -280,7 +300,7 @@
                   <li>{this.$t('inputPlaceholderTooltip2')}</li>
                 </ul>
                 <span 
class="how-to-use">{this.$t('inputPlaceholderTooltipTrigger')}</span>
-              </el-tooltip>
+              </el-tooltip> */}
             </div>
             <div>
               {this.$t('inputPlaceholder2')}
@@ -322,7 +342,7 @@
       }
     }
     handleRecognize () {
-      const { type, form, modelDimensions } = this
+      const { type, form } = this
       const dimensions = []
       this.clearupErrors()
       let formattedText = ''
@@ -330,23 +350,23 @@
       for (const text of form.text.replace(/\n*/g, '').split(/,\n*/g)) {
         const columnText = text.trim().toLocaleUpperCase()
         if (columnText) {
-          const dimension = modelDimensions.find(d => d.column === columnText)
-          if (dimension) {
-            if (![AGGREGATE_TYPE.INCLUDE, TABLE_INDEX].includes(type) && 
!this.isColumnInIncludes(dimension.column)) {
-              this.setNotInIncludesError(dimension.column)
-            } else if (!this.isColumnUsedInOther(dimension.column)) {
-              const duplicate = dimensions.some(d => d.value === 
dimension.column)
+          const recognizeColumn = this.getRecognizeColumn(columnText)
+          if (recognizeColumn) {
+            if (![AGGREGATE_TYPE.INCLUDE, TABLE_INDEX, 
DIMENSION].includes(type) && !this.isColumnInIncludes(recognizeColumn.column)) {
+              this.setNotInIncludesError(recognizeColumn.column)
+            } else if (!this.isColumnUsedInOther(recognizeColumn.column)) {
+              const duplicate = dimensions.some(d => d.value === 
recognizeColumn.column)
               if (!duplicate) {
                 const isFormChecked = form.dimensions.find(d => d.value === 
columnText)?.isChecked
                 const isChecked = isFormChecked ?? true
-                const isDisabled = this.isColumnUsedInCurrent(dimension.column)
-                const dataType = dimension.type
-                dimensions.push({ value: dimension.column, label: 
dimension.column, isChecked, isDisabled, dataType })
+                const isDisabled = 
this.isColumnUsedInCurrent(recognizeColumn.column)
+                const dataType = recognizeColumn.type ?? 
recognizeColumn.datatype
+                dimensions.push({ value: recognizeColumn.column, label: 
recognizeColumn.column, isChecked, isDisabled, dataType })
               } else {
-                this.setDuplicateError(dimension.column)
+                this.setDuplicateError(recognizeColumn.column)
               }
             } else {
-              this.setUsedInOthersError(dimension.column)
+              this.setUsedInOthersError(recognizeColumn.column)
             }
           } else {
             this.setNotInModelError(columnText)
@@ -394,16 +414,18 @@
     }
     handleCancel (done) {
       if (typeof done === 'function') done()
+      this.resetModal()
       this.hideModal()
     }
     handleSubmit () {
       const { form, callback } = this
       callback(form.dimensions.filter(d => !d.isDisabled && d.isChecked).map(d 
=> d.value))
+      this.resetModal()
       this.hideModal()
     }
   }
-  </script>
-  <style lang="less">
+</script>
+<style lang="less">
   @import '../../../assets/styles/variables.less';
   .recognize-aggregate-modal {
     .el-dialog {
@@ -606,5 +628,5 @@
   .accelerator-key {
     color: @text-disabled-color;
   }
-  </style>
+</style>
   
\ No newline at end of file
diff --git a/kystudio/src/components/common/RecognizeAggregateModal/handler.js 
b/kystudio/src/components/common/RecognizeAggregateModal/handler.js
index db4eb83cf2..1f98e89e8b 100644
--- a/kystudio/src/components/common/RecognizeAggregateModal/handler.js
+++ b/kystudio/src/components/common/RecognizeAggregateModal/handler.js
@@ -39,6 +39,7 @@ export function updatePlaceHolder (editor, renderPlaceholder) 
{
       editor.on('input', editor.$updatePlaceholder)
     }
     editor.$updatePlaceholder(editor, renderPlaceholder)
+    editor.focus()
   }
 }
 
@@ -70,7 +71,7 @@ export function scrollToLineAndHighlight (editor, line) {
 export function searchColumnInEditor (editor, column) {
   const { $search: editorSearch } = editor
   const session = editor.getSession()
-  column = column.replace(/[\\$|\\/|\\^|\\?]/g, ($1) => {
+  column = 
column.replace(/[\\$|\\/|\\^|\\?|\\(|\\)|\\{|\\|\\-}|\\&|\\*|\\(|\\)]/g, ($1) 
=> {
     return `\\${$1}`
   })
 
diff --git a/kystudio/src/components/common/RecognizeAggregateModal/locales.js 
b/kystudio/src/components/common/RecognizeAggregateModal/locales.js
index c60a41ecea..aba1a18916 100644
--- a/kystudio/src/components/common/RecognizeAggregateModal/locales.js
+++ b/kystudio/src/components/common/RecognizeAggregateModal/locales.js
@@ -9,11 +9,11 @@ export default {
     repeatCount: ' | {count} duplicate | {count} duplicates',
     selectedDimensionCount: 'Select {count} results | Select {count} result | 
Select {count} results',
     usedDimensionCount: '{count} already exists',
-    inputPlaceholder1: 'Please paste the text, separated by "," to identify 
the selected column.',
-    inputPlaceholder2: 'Example: CUSTOMER.C_CUSTKEY, CUSTOMER.C_CUSTKEY',
-    inputPlaceholderTooltip1: 'Method 1: Enter the formula A1 & "," on a new 
column in Excel, enter and drag the bottom right corner of the cell to add in 
bulk;',
-    inputPlaceholderTooltip2: 'Method 2: Select all the cells that need to 
added in bulk, right-click and select the cell format (shortcut cmd & ctrl + 
1). Select "Custom", enter English format General "," or @ "," in the type, 
confirm and add in bulk.',
-    inputPlaceholderTooltipTrigger: 'Not sure how to batch add characters?',
+    inputPlaceholder1: 'Please enter "table.column", separated by commas in 
English. If you are using the computed column, enter the "fact table.computed 
column".',
+    inputPlaceholder2: 'e.g. CUSTOMER.C_CUSTKEY1, CUSTOMER.C_CUSTKEY2',
+    // inputPlaceholderTooltip1: 'Method 1: Enter the formula A1 & "," on a 
new column in Excel, enter and drag the bottom right corner of the cell to add 
in bulk;',
+    // inputPlaceholderTooltip2: 'Method 2: Select all the cells that need to 
added in bulk, right-click and select the cell format (shortcut cmd & ctrl + 
1). Select "Custom", enter English format General "," or @ "," in the type, 
confirm and add in bulk.',
+    // inputPlaceholderTooltipTrigger: 'Not sure how to batch add characters?',
     recognizeFailed: 'Recognize failed. No result, please check and try again',
     columnDuplicate: 'Duplicate with {column}',
     columnNotInModel: 'Column {column} does not exist in the current model',
diff --git a/kystudio/src/components/common/RecognizeAggregateModal/store.js 
b/kystudio/src/components/common/RecognizeAggregateModal/store.js
index 47ab670b4b..d2d2009ab0 100644
--- a/kystudio/src/components/common/RecognizeAggregateModal/store.js
+++ b/kystudio/src/components/common/RecognizeAggregateModal/store.js
@@ -30,6 +30,8 @@ function getInitialState () {
     isShow: false,
     model: null,
     aggregate: null,
+    allColumns: [],
+    usedColumns: null,
     type: AGGREGATE_TYPE.INCLUDE,
     status: ALERT_STATUS.INIT,
     groupIdx: null,
@@ -88,9 +90,21 @@ export default {
       const { aggregate } = state
       return aggregate?.jointArray ?? []
     },
-    tableIndexCols (state) {
-      const { allColumns } = state
-      return allColumns.filter(c => c.isUsed).map(c => c.fullName)
+    allColumns (state) {
+      const { allColumns, type } = state
+      const cloneColumns =  objectClone(allColumns).map((d) => {
+        switch (type) {
+          case 'TABLE_INDEX':
+            d.column = d.label
+            return d
+          case 'DIMENSION': 
+            const tableAlias = d.tableName ? d.tableName : d.tableAlias
+            d.column = `${tableAlias}.${d.column}`
+            return d
+          default: return d
+        }
+      })
+      return cloneColumns
     },
     hierarchyItems (state) {
       const { aggregate, groupIdx } = state
@@ -107,9 +121,9 @@ export default {
   },
   actions: {
     [types.CALL_MODAL] ({ commit }, args) {
-      const { aggregate, type, model, allColumns = [], groupIdx = null } = args
+      const { aggregate, type, model, allColumns = [], groupIdx = null, 
usedColumns = [] } = args
       return new Promise(resolve => {
-        commit(types.SET_MODAL, { aggregate, model, type, groupIdx, 
allColumns, callback: resolve })
+        commit(types.SET_MODAL, { aggregate, model, type, groupIdx, 
allColumns, usedColumns, callback: resolve })
         commit(types.SHOW_MODAL)
       })
     }
diff --git 
a/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue 
b/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue
index 64e98f5e18..f9c2475702 100644
--- a/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue
+++ b/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue
@@ -11,8 +11,11 @@
     @close="isShow && handleClose(false)">
     <template v-if="isFormShow">
       <div class="ksd-mb-10 ksd-right">
-        <el-button @click="changeSyncName">{{!syncCommentToName ? 
$t('syncName') : $t('resetSyncName')}}</el-button>
-        <el-input :placeholder="$t('searchColumn')" style="width:230px;" 
@input="changeSearchVal" v-model="searchChar">
+        <el-tooltip placement="top" :content="$t('textRecognitionTips')">
+          <el-button size="small" nobg-text icon="el-ksd-n-icon-view-outlined" 
@click="handleDimensionRecognize">{{ $t('textRecognition') }}</el-button>
+        </el-tooltip><!--
+        --><el-button @click="changeSyncName">{{!syncCommentToName ? 
$t('syncName') : $t('resetSyncName')}}</el-button><!--
+        --><el-input :placeholder="$t('searchColumn')" class="ksd-ml-8" 
style="width:230px;" @input="changeSearchVal" v-model="searchChar">
           <i slot="prefix" class="el-input__icon el-ksd-icon-search_22"></i>
         </el-input>
       </div>
@@ -349,6 +352,9 @@ vuex.registerModule(['modals', 'DimensionsModal'], store)
       loadDataSourceByProject: 'LOAD_DATASOURCE',
       saveSampleData: 'SAVE_SAMPLE_DATA'
     }),
+    ...mapActions('RecognizeAggregateModal', {
+      callRecognizeAggregateModal: types.CALL_MODAL
+    }),
     tableRowClassName ({row, rowIndex}, table) {
       return 'guide-' + table.alias + row.name
     }
@@ -419,6 +425,44 @@ export default class DimensionsModal extends Vue {
     return !this.unflattenComputedColumns.includes(row.columnName)
   }
 
+  async handleDimensionRecognize () {
+    const selectedColumns = await this.callRecognizeAggregateModal({
+      type: 'DIMENSION',
+      allColumns: this.allColumns,
+      usedColumns: this.getAllSelectedColumns()
+    })
+    if (!selectedColumns.length) return
+    const batchRecognizeColumns = {}
+    selectedColumns.forEach(col => {
+      const [ table, column ] = col.split('.')
+      batchRecognizeColumns[table] = batchRecognizeColumns[table] ? 
[...batchRecognizeColumns[table], column] : [column]
+    })
+    const allTables = [...this.factTable, ...this.lookupTable, this.ccTable]
+    allTables.forEach(t => {
+      const tableAlias = t.alias ? t.alias : t.columns.length && 
t.columns[0].tableAlias
+      let isTableNeedRender = false
+      if (batchRecognizeColumns[tableAlias]) {
+        batchRecognizeColumns[tableAlias].forEach(col => {
+          const index = indexOfObjWithSomeKey(t.columns, 'column', col)
+          if (index !== -1) {
+            this.$set(t.columns[index], 'isSelected', true)
+            isTableNeedRender = true
+          }
+        })
+      }
+      if (!this.searchChar && isTableNeedRender) {
+        this.$nextTick(() => {
+          this.renderTableColumnSelected(t)
+        })
+      }
+    })
+    if (this.searchChar) {
+      this.$nextTick(() => {
+        this.renderTableColumnSelected(this.pagerSearchTable[0])
+      })
+    }
+  }
+
   // 同步或撤销注释到名称
   changeSyncName () {
     if (!this.syncCommentToName) {
@@ -612,8 +656,7 @@ export default class DimensionsModal extends Vue {
     }
     return idx
   }
-  // 检测是否有重名
-  checkHasSameNamedColumn () {
+  get allColumns () {
     let columns = []
     for (let k = 0; k < this.factTable.length; k++) {
       columns = columns.concat(this.factTable[k].columns)
@@ -625,33 +668,37 @@ export default class DimensionsModal extends Vue {
     if (this.ccTable.columns) {
       columns = columns.concat(this.ccTable.columns)
     }
+    return columns
+  }
+  // 检测是否有重名
+  checkHasSameNamedColumn () {
     return () => {
       let hasPassValidate = true
       this.errorGuidList = []
-      columns.forEach((col) => {
+      this.allColumns.forEach((col) => {
         this.$set(col, 'validateNameRule', false)
         this.$set(col, 'validateSameName', false)
         this.$set(col, 'validateNameMaxLen', false)
         this.isClickSubmit = false
       })
-      let selectedColumns = columns.filter((col) => {
+      let selectedColumns = this.allColumns.filter((col) => {
         return col.isSelected === true
       })
       selectedColumns.forEach((col) => {
         if (countObjWithSomeKey(selectedColumns, 'alias', col.alias) > 1) {
           hasPassValidate = false
-          let idx = this.getIdxBySelected(col, columns)
-          this.$set(columns[idx], 'validateSameName', true)
+          let idx = this.getIdxBySelected(col, this.allColumns)
+          this.$set(this.allColumns[idx], 'validateSameName', true)
           this.errorGuidList.push(col.guid || col.table_guid)
         } else if (!this.checkDimensionNameRegex(col.alias)) {
           hasPassValidate = false
-          let idx = this.getIdxBySelected(col, columns)
-          this.$set(columns[idx], 'validateNameRule', true)
+          let idx = this.getIdxBySelected(col, this.allColumns)
+          this.$set(this.allColumns[idx], 'validateNameRule', true)
           this.errorGuidList.push(col.guid || col.table_guid)
         } else if (col.alias.length > this.dimMeasNameMaxLength) {
           hasPassValidate = false
-          let idx = this.getIdxBySelected(col, columns)
-          this.$set(columns[idx], 'validateNameMaxLen', true)
+          let idx = this.getIdxBySelected(col, this.allColumns)
+          this.$set(this.allColumns[idx], 'validateNameMaxLen', true)
           this.errorGuidList.push(col.guid || col.table_guid)
         }
       })
diff --git 
a/kystudio/src/components/studio/StudioModel/DimensionsModal/locales.js 
b/kystudio/src/components/studio/StudioModel/DimensionsModal/locales.js
index d001604ca6..cb41b64bf9 100644
--- a/kystudio/src/components/studio/StudioModel/DimensionsModal/locales.js
+++ b/kystudio/src/components/studio/StudioModel/DimensionsModal/locales.js
@@ -30,6 +30,8 @@ export default {
     lockLookupTableTip: 'Unable to use columns from this table for dimensions. 
Because the join relationship of this dimension table  won\'t be precomputed.',
     useCCBylockLookupTableTip: 'Unable to use certain computed columns. 
Because the join relationships of related dimension tables won\'t be 
precomputed.',
     streamTips: 'For fusion model, the time partition column can’t be deleted 
from the dimension.',
-    secStorTips: 'When the tiered storage is ON, the time partition column 
can\'t be deleted from the dimension.'
+    secStorTips: 'When the tiered storage is ON, the time partition column 
can\'t be deleted from the dimension.',
+    textRecognition: 'Text Recognition',
+    textRecognitionTips: 'Batch selection of columns by automatic recognition 
of pasted text'
   }
 }

Reply via email to