Jelajahi Sumber

Revert "feat: 表格工具栏新增列设置功能"

Archer 1 tahun lalu
induk
melakukan
3895d20ba6

+ 1 - 3
package.json

@@ -106,9 +106,7 @@
     "vite-plugin-purge-icons": "^0.9.2",
     "vite-plugin-style-import": "2.0.0",
     "vite-plugin-svg-icons": "^2.0.1",
-    "vue-tsc": "^1.8.8",
-    "vue-draggable-plus": "^0.2.6",
-    "lodash": "^4.17.21"
+    "vue-tsc": "^1.8.8"
   },
   "engines": {
     "node": ">= 14.18.0"

+ 11 - 35
src/components/Table/src/Table.vue

@@ -17,9 +17,6 @@ import { getSlot } from '@/utils/tsxHelper'
 import TableActions from './components/TableActions.vue'
 // import Sortable from 'sortablejs'
 // import { Icon } from '@/components/Icon'
-import { useAppStore } from '@/store/modules/app'
-
-const appStore = useAppStore()
 
 export default defineComponent({
   name: 'Table',
@@ -124,9 +121,7 @@ export default defineComponent({
       default: () => undefined
     },
     rowKey: propTypes.string.def('id'),
-    emptyText: propTypes.string.def('暂无数据'),
-    // 表格工具栏缓存唯一标识符
-    activeUID: propTypes.string.def(''),
+    emptyText: propTypes.string.def('No Data'),
     defaultExpandAll: propTypes.bool.def(false),
     expandRowKeys: {
       type: Array as PropType<string[]>,
@@ -350,7 +345,7 @@ export default defineComponent({
     const renderTreeTableColumn = (columnsChildren: TableColumn[]) => {
       const { align, headerAlign, showOverflowTooltip, preview } = unref(getProps)
       return columnsChildren.map((v) => {
-        if (v.show === false) return null
+        if (v.hidden) return null
         const props = { ...v } as any
         if (props.children) delete props.children
 
@@ -422,7 +417,7 @@ export default defineComponent({
       } = unref(getProps)
 
       return (columnsChildren || columns).map((v) => {
-        if (v.show === false) return null
+        if (v.hidden) return null
         if (v.type === 'index') {
           return (
             <ElTableColumn
@@ -434,7 +429,6 @@ export default defineComponent({
               headerAlign={v.headerAlign || headerAlign}
               label={v.label}
               width="65px"
-              fixed="left"
             ></ElTableColumn>
           )
         } else if (v.type === 'selection') {
@@ -500,7 +494,6 @@ export default defineComponent({
       if (getSlot(slots, 'append')) {
         tableSlots['append'] = (...args: any[]) => getSlot(slots, 'append', args)
       }
-      const toolbar = getSlot(slots, 'toolbar')
 
       // const { sortable } = unref(getProps)
 
@@ -518,31 +511,14 @@ export default defineComponent({
 
       return (
         <div v-loading={unref(getProps).loading}>
-          <div class="flex justify-between mb-1">
-            <div>{toolbar}</div>
-            <div class="pt-2">
-              {unref(getProps).showAction ? (
-                <TableActions
-                  activeUID={unref(getProps).activeUID}
-                  columns={unref(getProps).columns}
-                  el-table-ref={elTableRef}
-                  onChangSize={changSize}
-                  onRefresh={refresh}
-                />
-              ) : null}
-            </div>
-          </div>
-
-          <ElTable
-            ref={elTableRef}
-            data={unref(getProps).data}
-            {...unref(getBindValue)}
-            header-cell-style={
-              appStore.getIsDark
-                ? { color: '#CFD3DC', 'background-color': '#000' }
-                : { color: '#000', 'background-color': '#f5f7fa' }
-            }
-          >
+          {unref(getProps).showAction ? (
+            <TableActions
+              columns={unref(getProps).columns}
+              onChangSize={changSize}
+              onRefresh={refresh}
+            />
+          ) : null}
+          <ElTable ref={elTableRef} data={unref(getProps).data} {...unref(getBindValue)}>
             {{
               default: () => renderTableColumn(),
               ...tableSlots

+ 53 - 234
src/components/Table/src/components/TableActions.vue

@@ -1,34 +1,24 @@
 <script lang="tsx">
-import { defineComponent, unref, computed, PropType, watch, ref, nextTick } from 'vue'
+import { defineComponent, unref, computed, PropType, watch } from 'vue'
 import {
   ElTooltip,
   ElDropdown,
   ElDropdownMenu,
   ElDropdownItem,
-  ComponentSize,
-  ElPopover,
-  ElCheckbox,
-  ElScrollbar,
-  ElButton,
-  ElTable,
-  ElDivider
+  ComponentSize
+  // ElPopover,
+  // ElTree
 } from 'element-plus'
 import { Icon } from '@/components/Icon'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useAppStore } from '@/store/modules/app'
 import { TableColumn } from '../types'
-import { VueDraggable } from 'vue-draggable-plus'
-import { useRouter } from 'vue-router'
-import { useStorage } from '@/hooks/web/useStorage'
-import cloneDeep from 'lodash/cloneDeep'
-import { propTypes } from '@/utils/propTypes'
-import { moveElementToIndex } from '@/utils/index'
+import { cloneDeep } from 'lodash-es'
+// import { eachTree } from '@/utils/tree'
 
 const appStore = useAppStore()
 const sizeMap = computed(() => appStore.sizeMap)
 
-const { setStorage, getStorage, removeStorage } = useStorage()
-
 const { t } = useI18n()
 
 export default defineComponent({
@@ -37,13 +27,7 @@ export default defineComponent({
     columns: {
       type: Array as PropType<TableColumn[]>,
       default: () => []
-    },
-    elTableRef: {
-      type: Object as PropType<ComponentRef<typeof ElTable>>,
-      default: () => {}
-    },
-    // 表格工具栏缓存唯一标识符
-    activeUID: propTypes.string.def('')
+    }
   },
   emits: ['refresh', 'changSize'],
   setup(props, { emit }) {
@@ -55,142 +39,25 @@ export default defineComponent({
       emit('changSize', size)
     }
 
-    const tableColumns = ref(props.columns)
-    const elTableRef = ref(props.elTableRef)
-    const activeUID = ref(props.activeUID)
-    const numberColumnStatus = ref(false)
-
-    // 获取 table columns 是否已经存在序号列,如果存在则更新初始状态,如果不存在则添加
-    const numberColumnField = tableColumns.value.find((item) => item.type === 'index')
-    if (numberColumnField === undefined) {
-      tableColumns.value.unshift({
-        field: '_serial_number',
-        label: '序号',
-        type: 'index',
-        show: false,
-        disabled: true
-      })
-    } else {
-      numberColumnStatus.value = numberColumnField.show
-    }
-
-    // 备份最初的 table columns
-    const oldTableColumns = cloneDeep(unref(tableColumns))
-
-    const checkAll = ref(false)
-    // 如果为True,则表示为半选状态
-    const isIndeterminate = ref(true)
-
-    // 全选状态改变事件
-    const handleCheckAllChange = (val: boolean) => {
-      tableColumns.value.forEach((item) => {
-        if (item.disabled !== true) {
-          item.show = val
+    const columns = computed(() => {
+      return cloneDeep(props.columns).filter((v) => {
+        // 去掉type为selection的列和expand的列
+        if (v.type !== 'selection' && v.type !== 'expand') {
+          return v
         }
       })
-      isIndeterminate.value = tableColumns.value
-        .filter((item) => !item.disabled)
-        .some((item) => item.show)
-    }
-
-    // 列选中状态改变事件
-    const handleCheckChange = () => {
-      checkAll.value = tableColumns.value
-        .filter((item) => !item.disabled)
-        .every((item) => item.show)
-      if (checkAll.value) {
-        isIndeterminate.value = false
-      } else {
-        isIndeterminate.value = tableColumns.value
-          .filter((item) => !item.disabled)
-          .some((item) => item.show)
-      }
-    }
-
-    // 更新 table columns 中的序号列状态
-    const updateNumberColumnStatus = (syns: boolean, status: boolean = false) => {
-      const numberColumnField = tableColumns.value.find((item) => item.type === 'index')
-      if (numberColumnField) {
-        if (syns) {
-          numberColumnStatus.value = numberColumnField.show
-        } else {
-          numberColumnField.show = status
-        }
-      }
-    }
-
-    const { currentRoute } = useRouter()
-    const fullPath = currentRoute.value.fullPath
-    const cacheTableHeadersKey = `${fullPath}_${activeUID.value}`
-
-    if (cacheTableHeadersKey) {
-      // 获取缓存中的 table columns 状态并覆盖到当前的 table columns 中
-      const cacheData = JSON.parse(getStorage(cacheTableHeadersKey))
-      if (cacheData) {
-        tableColumns.value.forEach((item) => {
-          const fieldData = cacheData[item.field]
-          item._index = fieldData.index
-          item.show = fieldData.show
-          item.fixed = fieldData.fixed
-        })
-        tableColumns.value.sort((a, b) => a._index - b._index)
-        updateNumberColumnStatus(true)
-      }
-    }
+    })
 
     watch(
-      () => tableColumns.value,
-      async (val) => {
-        const cacheData = {}
-        for (let i = 0; i < val.length; i++) {
-          const item = val[i]
-          cacheData[item.field] = {
-            show: item.show,
-            index: i,
-            fixed: item.fixed
-          }
-        }
-        setStorage(cacheTableHeadersKey, JSON.stringify(cacheData))
-        handleCheckChange()
-        await nextTick()
-        elTableRef.value?.doLayout()
+      () => columns.value,
+      (newColumns) => {
+        console.log('columns change:', newColumns)
       },
       {
         deep: true
       }
     )
 
-    watch(
-      () => numberColumnStatus.value,
-      async (val) => {
-        updateNumberColumnStatus(false, val)
-        await nextTick()
-        elTableRef.value?.doLayout()
-      },
-      {
-        deep: true
-      }
-    )
-
-    // 重置所有状态
-    const resetTableColumns = async () => {
-      Object.assign(tableColumns.value, cloneDeep(oldTableColumns))
-      updateNumberColumnStatus(true)
-      await nextTick()
-      // 删除缓存
-      removeStorage(cacheTableHeadersKey)
-    }
-
-    // 更新元素顺序
-    const updateColumnsIndex = (val) => {
-      Object.assign(
-        tableColumns.value,
-        cloneDeep(moveElementToIndex(tableColumns.value, val.oldIndex, val.newIndex))
-      )
-    }
-
-    handleCheckChange()
-
     return () => (
       <>
         <div class="text-right h-28px flex items-center justify-end">
@@ -204,7 +71,7 @@ export default defineComponent({
             </span>
           </ElTooltip>
 
-          <ElTooltip content={t('common.density')} placement="top">
+          <ElTooltip content={t('common.size')} placement="top">
             <ElDropdown trigger="click" onCommand={changSize}>
               {{
                 default: () => {
@@ -239,91 +106,43 @@ export default defineComponent({
             </ElDropdown>
           </ElTooltip>
 
-          <ElTooltip content={t('common.columnSetting')} placement="top">
-            <ElPopover trigger="click" placement="bottom" width="300px">
-              {{
-                default: () => {
-                  return (
-                    <div>
-                      <div style="border-bottom: 1px solid #d4d7de" class="flex justify-between">
-                        <div>
-                          <ElCheckbox
-                            v-model={checkAll.value}
-                            indeterminate={isIndeterminate.value}
-                            onChange={handleCheckAllChange}
-                          >
-                            {t('common.selectAll')}
-                          </ElCheckbox>
-                          <ElCheckbox v-model={numberColumnStatus.value}>
-                            {t('common.SerialNumberColumn')}
-                          </ElCheckbox>
-                        </div>
-                        <ElButton type="primary" link onClick={resetTableColumns}>
-                          {t('common.reset')}
-                        </ElButton>
-                      </div>
-                      <ElScrollbar max-height="400px">
-                        <VueDraggable
-                          modelValue={tableColumns.value}
-                          onEnd={updateColumnsIndex}
-                          handle=".cursor-move"
-                        >
-                          {tableColumns.value.map((element) => {
-                            if (element.type === 'index') return null
-                            return (
-                              <div class="flex justify-between">
-                                <div>
-                                  <span class="cursor-move mr-10px">
-                                    <Icon icon="akar-icons:drag-vertical" />
-                                  </span>
-                                  <ElCheckbox
-                                    v-model={element.show}
-                                    disabled={element.disabled === true}
-                                    onChange={handleCheckChange}
-                                  >
-                                    {element.label}
-                                  </ElCheckbox>
-                                </div>
-                                <div class="mt-7px mr-9px">
-                                  <span
-                                    class={element.fixed === 'left' ? 'color-[#409eff]' : ''}
-                                    onClick={() => {
-                                      element.fixed = element.fixed === 'left' ? undefined : 'left'
-                                    }}
-                                  >
-                                    <Icon icon="radix-icons:pin-left" class="cursor-pointer" />
-                                  </span>
-                                  <ElDivider direction="vertical" />
-                                  <span
-                                    class={element.fixed === 'right' ? 'color-[#409eff]' : ''}
-                                    onClick={() => {
-                                      element.fixed =
-                                        element.fixed === 'right' ? undefined : 'right'
-                                    }}
-                                  >
-                                    <Icon icon="radix-icons:pin-right" class="cursor-pointer" />
-                                  </span>
-                                </div>
-                              </div>
-                            )
-                          })}
-                        </VueDraggable>
-                      </ElScrollbar>
-                    </div>
-                  )
-                },
-                reference: () => {
-                  return (
-                    <Icon
-                      icon="ant-design:setting-outlined"
-                      class="cursor-pointer"
-                      hoverColor="var(--el-color-primary)"
+          {/* <ElTooltip content={t('common.columnSetting')} placement="top"> */}
+          {/* <ElPopover trigger="click" placement="left">
+            {{
+              default: () => {
+                return (
+                  <div>
+                    <ElTree
+                      data={unref(columns)}
+                      show-checkbox
+                      default-checked-keys={unref(defaultCheckeds)}
+                      draggable
+                      node-key="field"
+                      allow-drop={(_draggingNode: any, _dropNode: any, type: string) => {
+                        if (type === 'inner') {
+                          return false
+                        } else {
+                          return true
+                        }
+                      }}
+                      onNode-drag-end={onNodeDragEnd}
+                      onCheck-change={onCheckChange}
                     />
-                  )
-                }
-              }}
-            </ElPopover>
-          </ElTooltip>
+                  </div>
+                )
+              },
+              reference: () => {
+                return (
+                  <Icon
+                    icon="ant-design:setting-outlined"
+                    class="cursor-pointer"
+                    hoverColor="var(--el-color-primary)"
+                  />
+                )
+              }
+            }}
+          </ElPopover> */}
+          {/* </ElTooltip> */}
         </div>
       </>
     )

+ 2 - 2
src/components/Table/src/types/index.ts

@@ -4,9 +4,9 @@ export interface TableColumn {
   label?: string
   type?: string
   /**
-   * 是否显示,必填
+   * 是否隐藏
    */
-  show: boolean
+  hidden?: boolean
   children?: TableColumn[]
   slots?: {
     default?: (...args: any[]) => JSX.Element | JSX.Element[] | null

+ 2 - 15
src/locales/en.ts

@@ -44,14 +44,11 @@ export default {
     refresh: 'Refresh',
     fullscreen: 'Fullscreen',
     size: 'Size',
-    density: 'Density',
     columnSetting: 'Column setting',
     lengthRange: 'The length should be between {min} and {max}',
     notSpace: 'Spaces are not allowed',
     notSpecialCharacters: 'Special characters are not allowed',
-    isEqual: 'The two are not equal',
-    selectAll: 'Select all',
-    SerialNumberColumn: 'Index column'
+    isEqual: 'The two are not equal'
   },
   lock: {
     lockScreen: 'Lock screen',
@@ -111,27 +108,18 @@ export default {
     welcome: 'Welcome to the system',
     message: 'Backstage management system',
     username: 'Username',
-    telephone: 'Telephone',
     password: 'Password',
     register: 'Register',
     checkPassword: 'Confirm password',
     login: 'Sign in',
-    passwordLogin: 'Password login',
-    smsLogin: 'SMS code login',
     otherLogin: 'Sign in with',
     remember: 'Remember me',
     hasUser: 'Existing account? Go to login',
     forgetPassword: 'Forget password',
     usernamePlaceholder: 'Please input username',
-    telephonePlaceholder: 'Please input telephone',
     passwordPlaceholder: 'Please input password',
     code: 'Verification code',
-    getCode: 'Get code',
-    codePlaceholder: 'Please input verification code',
-    SMSCode: 'sms code',
-    getSMSCode: 'get sms code',
-    SMSCodePlaceholder: 'Please input sms code',
-    SMSCodeRetry: 'S retry'
+    codePlaceholder: 'Please input verification code'
   },
   router: {
     login: 'Login',
@@ -454,7 +442,6 @@ export default {
     changeTitle: 'Change title',
     header: 'Header',
     selectAllNone: 'Select all / none',
-    selectAll: 'Select all',
     delOrAddAction: 'Delete or add action',
     showOrHiddenStripe: 'Show or hidden stripe',
     showOrHiddenBorder: 'Show or hidden border',

+ 2 - 15
src/locales/zh-CN.ts

@@ -44,14 +44,11 @@ export default {
     refresh: '刷新',
     fullscreen: '全屏',
     size: '尺寸',
-    density: '密度',
     columnSetting: '列设置',
     lengthRange: '长度在 {min} 到 {max} 个字符',
     notSpace: '不能包含空格',
     notSpecialCharacters: '不能包含特殊字符',
-    isEqual: '两次输入不一致',
-    selectAll: '全选',
-    SerialNumberColumn: '序号列'
+    isEqual: '两次输入不一致'
   },
   lock: {
     lockScreen: '锁定屏幕',
@@ -110,27 +107,18 @@ export default {
     welcome: '欢迎使用本系统',
     message: '开箱即用的中后台管理系统',
     username: '用户名',
-    telephone: '手机号',
     password: '密码',
     register: '注册',
     checkPassword: '确认密码',
     login: '登录',
-    passwordLogin: '密码登录',
-    smsLogin: '短信验证码登录',
     otherLogin: '其它登录方式',
     remember: '记住我',
     hasUser: '已有账号?去登录',
     forgetPassword: '忘记密码',
     usernamePlaceholder: '请输入用户名',
-    telephonePlaceholder: '请输入手机号',
     passwordPlaceholder: '请输入密码',
     code: '验证码',
-    getCode: '获取验证码',
-    codePlaceholder: '请输入验证码',
-    SMSCode: '短信验证码',
-    getSMSCode: '获取短信验证码',
-    SMSCodePlaceholder: '请输入短信验证码',
-    SMSCodeRetry: 'S后重新'
+    codePlaceholder: '请输入验证码'
   },
   router: {
     login: '登录',
@@ -447,7 +435,6 @@ export default {
     changeTitle: '修改标题',
     header: '头部',
     selectAllNone: '全选/全不选',
-    selectAll: '全选',
     delOrAddAction: '删除/添加操作列',
     showOrHiddenStripe: '显示/隐藏斑马纹',
     showOrHiddenBorder: '显示/隐藏边框',

+ 0 - 142
src/utils/index.ts

@@ -122,145 +122,3 @@ export function toAnyString() {
 export function firstUpperCase(str: string) {
   return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
 }
-
-// 根据当前时间获取祝福语
-export const getGreeting = (): string => {
-  const now = new Date()
-  const hour = now.getHours()
-
-  if (hour >= 6 && hour < 10) {
-    return '早上好'
-  } else if (hour >= 10 && hour < 13) {
-    return '中午好'
-  } else if (hour >= 13 && hour < 18) {
-    return '下午好'
-  } else {
-    return '晚上好'
-  }
-}
-
-// 获取当前星期几
-export const getDayOfWeek = (): string => {
-  const daysOfWeek: string[] = [
-    '星期日',
-    '星期一',
-    '星期二',
-    '星期三',
-    '星期四',
-    '星期五',
-    '星期六'
-  ]
-  const date: Date = new Date()
-  const dayOfWeekIndex: number = date.getDay()
-  return daysOfWeek[dayOfWeekIndex]
-}
-
-// 数字转金额
-// 作者:时光足迹
-// 链接:https://juejin.cn/post/7028086399601475591
-// 来源:稀土掘金
-export const formatMoney = (amount, currency = true): string => {
-  const formatter = new Intl.NumberFormat('zh-CN', {
-    minimumFractionDigits: 2,
-    maximumFractionDigits: 2,
-    useGrouping: true
-  })
-
-  const formattedAmount = formatter.format(amount)
-
-  if (currency) {
-    return `¥${formattedAmount}`
-  }
-
-  return formattedAmount
-}
-
-/**
- * 小数转折扣
- * 例子:0.85 -> 8.5折
- * 例子:0.5 -> 5折
- */
-export const convertToDiscount = (decimal: number | undefined): string => {
-  if (decimal === undefined) {
-    return ''
-  }
-  const discount = decimal * 10
-  if (discount === 10) {
-    return '无折扣'
-  }
-  return discount % 1 === 0 ? `${discount}折` : `${discount.toFixed(1)}折`
-}
-
-/**
- * 获取当前时间
- * 返回:yyyy-MM-dd HH:mm:ss
- */
-export const getCurrentDateTime = (): string => {
-  const now: Date = new Date()
-
-  const year: number = now.getFullYear()
-  const month: number = now.getMonth() + 1
-  const day: number = now.getDate()
-  const hours: number = now.getHours()
-  const minutes: number = now.getMinutes()
-  const seconds: number = now.getSeconds()
-
-  // 格式化为字符串
-  const formattedDateTime = `${year}-${padZero(month)}-${padZero(day)} ${padZero(hours)}:${padZero(
-    minutes
-  )}:${padZero(seconds)}`
-
-  return formattedDateTime
-}
-
-/**
- * 获取当前日期
- * 返回:yyyy-MM-dd HH:mm:ss
- */
-export const getCurrentDate = (): string => {
-  const now: Date = new Date()
-
-  const year: number = now.getFullYear()
-  const month: number = now.getMonth() + 1
-  const day: number = now.getDate()
-
-  // 格式化为字符串
-  const formattedDate = `${year}-${padZero(month)}-${padZero(day)}`
-
-  return formattedDate
-}
-
-// 辅助函数:在数字小于10时,在前面补零
-export const padZero = (num: number): string => {
-  return num < 10 ? `0${num}` : `${num}`
-}
-
-// 将base64编码的字符串转换为文件
-export const base64ToFile = (dataURI, filename): File => {
-  const arr = dataURI.split(',')
-  const mime = arr[0].match(/:(.*?);/)[1]
-  const bstr = atob(arr[1])
-  let n = bstr.length
-  const u8arr = new Uint8Array(n)
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n)
-  }
-  return new File([u8arr], filename, { type: mime })
-}
-
-// 将指定索引的元素移动到目标索引的函数
-export const moveElementToIndex = (array: any[], fromIndex: number, toIndex: number) => {
-  const clonedArray = [...array] // 克隆数组以避免修改原始数组
-
-  if (
-    fromIndex >= 0 &&
-    fromIndex < clonedArray.length &&
-    toIndex >= 0 &&
-    toIndex < clonedArray.length
-  ) {
-    const [element] = clonedArray.splice(fromIndex, 1) // 移除指定索引的元素
-    clonedArray.splice(toIndex, 0, element) // 将元素插入目标索引位置
-  }
-
-  return clonedArray
-}