Browse Source

✨ feat: 封装表格

Zimo 4 days ago
parent
commit
70a7adc15f
2 changed files with 49 additions and 11 deletions
  1. 36 9
      src/components/ZmTable/ZmTableColumn.vue
  2. 13 2
      src/views/test/index.vue

+ 36 - 9
src/components/ZmTable/ZmTableColumn.vue

@@ -24,20 +24,20 @@ const tableContext = inject(TableContextKey, {
   loading: ref(false)
 })
 
-const defaultOptions: Partial<Props> = {
+const defaultOptions = ref<Partial<Props>>({
   align: 'center',
   resizable: true,
   showOverflowTooltip: true
-}
+})
 
 const bindProps = computed(() => {
   const resolvedAlign =
     props.zmSortable || props.zmFilterable
       ? 'left'
-      : attrs.align || props.align || defaultOptions.align
+      : attrs.align || props.align || defaultOptions.value.align
 
   return {
-    ...defaultOptions,
+    ...defaultOptions.value,
     ...attrs,
     ...props,
     prop: props.prop,
@@ -87,12 +87,39 @@ const handleSearchClick = () => {
   }
 }
 
+const getTextWidth = (text: string, fontSize = 14) => {
+  const span = document.createElement('span')
+  span.style.visibility = 'hidden'
+  span.style.position = 'absolute'
+  span.style.whiteSpace = 'nowrap'
+  span.style.fontSize = `${fontSize}px`
+  span.style.fontFamily = 'PingFang SC'
+  span.innerText = text
+
+  document.body.appendChild(span)
+  const width = span.offsetWidth
+  document.body.removeChild(span)
+
+  return width
+}
+
 const calculativeWidth = () => {
-  console.log('tableContext.data :>> ', tableContext.data.value)
-  const values = tableContext.data.value.map(
-    (item) => props.realValue?.(item[props.prop]) || item[props.prop]
-  )
-  console.log('values :>> ', values)
+  const values = tableContext.data.value
+    .map((item) => props.realValue?.(item[props.prop]) || item[props.prop])
+    .filter(Boolean)
+
+  let labelWidth = getTextWidth(bindProps.value.label || '') + 38
+
+  if (props.zmFilterable || props.zmSortable) {
+    labelWidth += 8
+  }
+
+  if (props.zmFilterable) labelWidth += 22
+  if (props.zmSortable) labelWidth += 22
+
+  const maxWidth = Math.max(...values.map((value) => getTextWidth(value) + 38), labelWidth)
+
+  defaultOptions.value.minWidth = maxWidth
 }
 
 watch(

+ 13 - 2
src/views/test/index.vue

@@ -2,7 +2,7 @@
 import { IotDeviceApi } from '@/api/pms/device'
 import { SortField } from '@/components/ZmTable/token'
 import { useTableComponents } from '@/components/ZmTable/useTableComponents'
-import { DICT_TYPE } from '@/utils/dict'
+import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 
 interface List {
   id: number
@@ -47,6 +47,11 @@ const getList = async () => {
 getList()
 
 const { ZmTable, ZmTableColumn } = useTableComponents<List>()
+
+const realValue = (value: string) => {
+  const option = getDictOptions(DICT_TYPE.PMS_ASSET_PROPERTY).find((item) => item.value === value)
+  return option?.label || value
+}
 </script>
 
 <template>
@@ -68,7 +73,13 @@ const { ZmTable, ZmTableColumn } = useTableComponents<List>()
       <zm-table-column zm-filterable zm-sortable prop="deviceName" label="设备名称" />
       <zm-table-column zm-filterable zm-sortable prop="deptName" label="所在部门" />
       <zm-table-column zm-filterable zm-sortable prop="deviceStatus" label="设备状态" />
-      <zm-table-column zm-filterable zm-sortable prop="assetProperty" label="资产性质">
+      <zm-table-column
+        zm-filterable
+        zm-sortable
+        prop="assetProperty"
+        label="资产性质"
+        :real-value="realValue"
+      >
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.PMS_ASSET_PROPERTY" :value="scope.row.assetProperty" />
         </template>