Ver Fonte

下拉表格优化

xiaochan há 2 anos atrás
pai
commit
3ae8e7f5f1

+ 138 - 76
src/components/xiao-chan/combo-grid/XcComboGridV2.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import {computed, defineProps, onMounted, ref, watch} from "vue";
+import {computed, defineProps, nextTick, onMounted, ref, watch} from "vue";
 import XEUtils from 'xe-utils'
 import {onClickOutside} from '@vueuse/core'
 
@@ -19,6 +19,10 @@ const props = defineProps({
   },
   code: String,
   name: String,
+  clearable: {
+    type: Boolean,
+    default: false
+  },
   tableHeader: {
     type: Array,
     default: [
@@ -32,23 +36,25 @@ const emits = defineEmits(['input', 'rowClick', 'clear', 'focus', 'blur', 'updat
 
 const isObj = typeof props.modelValue === 'object'
 const tempData = ref([])
-const isShow = ref(false)
-const divRef = ref()
-const inputRef = ref()
-
-const states = ref({
-  isFocus: false
+const pulldownRef = ref()
+const inputData = ref('')
+const placeholder = ref('')
+const vxeTableRef = ref()
+const theRowIsCurrentlySelected = ref({
+  row: {},
+  index: -1
 })
-
+const currentIndex = ref(-1)
+const inputRef = ref()
+const isShow = ref()
 
 const computedData = computed(() => {
   return props.data === null ? tempData.value : props.data
 })
 
-const inputData = ref('')
-
 const change = XEUtils.debounce(async (value) => {
   emits('input', value)
+  if (XEUtils.isEmpty(value)) return
   if (props.queryDataFunc === null) return
   try {
     let res = await props.queryDataFunc(value)
@@ -60,34 +66,104 @@ const change = XEUtils.debounce(async (value) => {
     }
   } catch {
   }
+  pulldownRef.value.showPanel()
+  currentIndex.value = -1
 }, 500)
 
-const rowClick = (...val) => {
-  console.log('row', ...val)
-}
+const rowClick = (val) => {
+  let {row, rowIndex} = val
+  pulldownRef.value?.hidePanel()
+  if (isObj) {
+    props.modelValue[props.code] = row.code
+    props.modelValue[props.name] = row.name
+  } else {
+    emits('update:modelValue', row.name)
+  }
+
+  emits('rowClick', row, rowIndex)
 
+  theRowIsCurrentlySelected.value = {
+    row, index: rowIndex
+  }
 
-const rowClassName = (...val) => {
-  console.log('rowClassName', ...val)
+  inputRef.value.focus()
+  currentIndex.value = rowIndex
 }
 
+const inputClick = async () => {
+  await pulldownRef.value.togglePanel()
+  if (await pulldownRef.value.isPanelVisible()) {
+    vxeTableRef.value.scrollToRow(theRowIsCurrentlySelected.value.row)
+  }
+}
 
 const handleFocus = () => {
-  states.value.isFocus = true
-  isShow.value = true
+  if (isObj) {
+    placeholder.value = props.modelValue[props.name]
+  } else {
+    placeholder.value = <string>props.modelValue;
+  }
+  inputData.value = ''
 }
 
 const handleBlur = () => {
-  states.value.isFocus = false
+  emits('blur')
+  if (pulldownRef.value.isPanelVisible()) {
+    return
+  }
+  if (isObj) {
+    inputData.value = props.modelValue[props.name]
+  } else {
+    inputData.value = <string>props.modelValue;
+  }
 }
 
-const divClick = () => {
-  console.log('div点击事件')
+const keyUp = () => {
+  currentIndex.value -= 1
+  if (currentIndex.value <= -1) {
+    currentIndex.value = computedData.value.length - 1
+  }
+  let tempData = computedData.value[currentIndex.value]
+  vxeTableRef.value.setCurrentRow(computedData.value[currentIndex.value])
+  vxeTableRef.value.scrollToRow(tempData)
+}
+
+const keyDown = () => {
+  currentIndex.value += 1
+  if (computedData.value.length === currentIndex.value) {
+    currentIndex.value = 0
+  }
+  let tempData = computedData.value[currentIndex.value]
+  vxeTableRef.value.setCurrentRow(computedData.value[currentIndex.value])
+  vxeTableRef.value.scrollToRow(tempData)
+}
+
+const enterToSelect = () => {
+  if (pulldownRef.value.isPanelVisible()) {
+    let temp = vxeTableRef.value.getCurrentRecord()
+    if (!temp) {
+      pulldownRef.value.togglePanel()
+    } else {
+      rowClick({
+        row: temp,
+        rowIndex: currentIndex.value
+      })
+    }
+  } else {
+    pulldownRef.value.showPanel()
+  }
+}
+
+const handleClear = () => {
+  if (isObj) {
+    props.modelValue[props.code] = ''
+    props.modelValue[props.name] = ''
+  } else {
+    emits('update:modelValue', '')
+  }
+  placeholder.value = ''
 }
 
-watch(() => isShow.value, () => {
-  console.log('watch', isShow.value)
-})
 
 onMounted(() => {
   if (isObj) {
@@ -99,67 +175,53 @@ onMounted(() => {
       inputData.value = <string>props.modelValue
     }, {immediate: true, deep: true})
   }
-  onClickOutside(divRef, (event) => {
-    if (event.target.id === inputRef.value.input.id) {
-      isShow.value = true
-    } else {
-      isShow.value = false
-    }
-    console.log(isShow.value)
-
-  })
-
 })
 
 </script>
 
 <template>
-  <el-tooltip placement="bottom"
-              trigger="click"
-              popper-class="popover_padding_zero"
-              :visible="isShow"
-              effect="light"
-              pure
-              :fallback-placements="['bottom-start', 'top-start', 'right', 'left']"
-              :teleported="true"
-              :width="0">
+  <vxe-pulldown
+      v-model="isShow"
+      ref="pulldownRef"
+      transfer>
     <template #default>
-      <el-input
-          style="width: 120px;"
-          @focus="handleFocus"
-          @blur="handleBlur"
-          ref="inputRef"
-          @input="change"
-          v-model="inputData"
-      />
+      <el-input v-model="inputData"
+                @clear="handleClear"
+                ref="inputRef"
+                style="width: 120px;"
+                @keydown.up.prevent="keyUp"
+                @keydown.down.prevent="keyDown"
+                @keydown.enter.prevent="enterToSelect"
+                @input="change"
+                :clearable="props.clearable"
+                @click="inputClick"
+                @blur="handleBlur"
+                :placeholder="placeholder"
+                @focus="handleFocus"/>
     </template>
-    <template #content>
-      <div ref="divRef" style="padding: 5px">
-        <vxe-table
-            :height="200"
-            border
-            :scroll-x="{gt: 20}"
-            :scroll-y="{gt: 50,enabled: true}"
-            :column-config="{resizable: true}"
-            :row-config="{ height: 24}"
-            class="vxe-padding_zero vxe-header-max_content hl-style vxe-scroll_15"
-            header-row-class-name="padding_zero "
-            :row-class-name="rowClassName"
-            @cell-click="rowClick"
-            show-header-overflow
-            show-overflow
-            :data="computedData">
-
-          <vxe-column v-for="item in tableHeader"
-                      :title="item.title"
-                      :field="item.field"
-                      :width="item.width"/>
-          <slot/>
-        </vxe-table>
-      </div>
+    <template #dropdown>
+      <vxe-table
+          ref="vxeTableRef"
+          :height="200"
+          border
+          :scroll-x="{gt: 20}"
+          :scroll-y="{gt: 50,enabled: true}"
+          :column-config="{resizable: true}"
+          :row-config="{ height: 24,isCurrent: true,isHover:true }"
+          class="vxe-padding_zero vxe-header-max_content hl-style vxe-scroll_15"
+          header-row-class-name="padding_zero "
+          @cell-click="rowClick"
+          show-header-overflow
+          show-overflow
+          :data="computedData">
+        <vxe-column v-for="item in tableHeader"
+                    :title="item.title"
+                    :field="item.field"
+                    :width="item.width"/>
+        <slot/>
+      </vxe-table>
     </template>
-
-  </el-tooltip>
+  </vxe-pulldown>
 </template>
 
 <style lang="scss">

+ 11 - 1
src/views/settings/Test.vue

@@ -1,6 +1,10 @@
 <template>
+  {{ obj}}
   <xc-combo-grid-v2
-      v-model="model"
+      v-model="obj"
+      clearable
+      code="codesd"
+      name="namead"
       :query-data-func="queryOperation"/>
 </template>
 
@@ -10,6 +14,12 @@ import {obtainSurgicalItems} from "@/api/zhu-yuan-yi-sheng/shou-shu-shen-qing";
 
 
 const model = ref('')
+
+const obj = ref({
+  codesd : '',
+  namead: ''
+})
+
 const data = ref([])
 
 const queryOperation = (val) => {