Procházet zdrojové kódy

vbTable组件优化修复,增加treeTable懒加载功能

Yue před 2 roky
rodič
revize
539319335b
19 změnil soubory, kde provedl 655 přidání a 958 odebrání
  1. 2 0
      .gitignore
  2. 0 3
      UI/VA.Vue_V1.0/.eslintrc-auto-import.json
  3. 8 0
      UI/VA.Vue_V1.0/src/api/system/_menu.ts
  4. 3 1
      UI/VA.Vue_V1.0/src/components/modal/VbModal.vue
  5. 75 95
      UI/VA.Vue_V1.0/src/components/table/VbDataTable.vue
  6. 36 4
      UI/VA.Vue_V1.0/src/components/table/VbTreeTable.vue
  7. 65 34
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/TableContent.vue
  8. 103 143
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableBodyRow.vue
  9. 116 0
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableBodyTd.vue
  10. 84 192
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableTreeRow.vue
  11. 86 192
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableTreeRowChild.vue
  12. 10 40
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-fixed/TableFixed.vue
  13. 4 0
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-fixed/TableRightFixed.vue
  14. 8 26
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-head/TableHeadRow.vue
  15. 1 163
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-toolbar/TableLeftToolbar.vue
  16. 0 42
      UI/VA.Vue_V1.0/src/components/table/table-partials/table-toolbar/TableToolbar.vue
  17. 20 7
      UI/VA.Vue_V1.0/src/views/system/dept/index.vue
  18. 33 16
      UI/VA.Vue_V1.0/src/views/system/menu/index.vue
  19. 1 0
      UI/VA.Vue_V1.0/src/views/system/post/index.vue

+ 2 - 0
.gitignore

@@ -56,3 +56,5 @@ build/
 ### VS  ###
 .vs/
 
+/vite/auto-import/*.d.ts
+/dist.rar

+ 0 - 3
UI/VA.Vue_V1.0/.eslintrc-auto-import.json

@@ -5,9 +5,6 @@
     "ComponentPublicInstance": true,
     "ComputedRef": true,
     "EffectScope": true,
-    "ElInput": true,
-    "ElSelect": true,
-    "ElTreeSelect": true,
     "InjectionKey": true,
     "JwtService": true,
     "LayoutService": true,

+ 8 - 0
UI/VA.Vue_V1.0/src/api/system/_menu.ts

@@ -10,6 +10,14 @@ class menuApi {
       params: query,
     })
   }
+  // 查询子菜单列表
+  listChildren = (query: any) => {
+    return Rs.get({
+      url: "/system/menu/list/children",
+      method: "get",
+      params: query,
+    })
+  }
 
   // 查询菜单详细
   getMenu = (menuId: string) => {

+ 3 - 1
UI/VA.Vue_V1.0/src/components/modal/VbModal.vue

@@ -284,7 +284,9 @@ defineExpose({ show, resetForm, validateForm, changePrefixTitle, modalFormRef })
             </template>
           </div>
           <div class="modal-footer" :class="modalFooterClass" :style="modalFooterStyle">
-            <slot v-if="$slots.footer"></slot>
+            <template v-if="$slots.footer">
+              <slot name="footer" />
+            </template>
             <template v-else>
               <button v-if="closeBtn" type="button" :class="closeBtnClass" :style="closeBtnStyle" @click="cancel">
                 {{ closeBtnText }}

+ 75 - 95
UI/VA.Vue_V1.0/src/components/table/VbDataTable.vue

@@ -19,16 +19,16 @@ const props = withDefaults(
     autoSearch?: boolean //参数变动时自动查询(深监听)
     data?: Array<any>
     total?: number //总数
-    selectedItems?: Array<any>
+    selectedIds?: Array<any>
     scroll?: Scroll
     currentPage?: number //当前页数
     //itemsPerPage?: number //每页数量
     pageArray?: Array<number> //下拉选择每页数量
     pageDropdown?: boolean //是否下拉选择
-    hasCheckbox?: boolean //是否有选择框
     checkboxField?: string //选择框字段
     checkMultiple?: boolean //是否多选
     checkPageMultiple?: boolean //是否跨页多选
+    hasCheckbox?: boolean //是否有选择框 (checkMultiple 和 checkPageMultiple 为true 时不起作用)
     rowClickFun?: (r: any) => void
     sortField?: string //排序字段
     sortOrder?: "asc" | "desc"
@@ -54,6 +54,9 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    isLazy?: boolean
+    rootId?: string
     searchFormRowItems?: Array<VbFormRowItem>
     searchFormItems?: Array<VbFormItem>
     searchFormSpan?: number
@@ -63,26 +66,6 @@ const props = withDefaults(
     showRightColumnBtn?: boolean //是否显示右边toolbar的选择列按钮
     customSearchFun?: () => void
     resetSearchFormFun?: () => void
-    // btnCreatePerm?: string
-    // btnEditPerm?: string
-    // btnDeletePerm?: string
-    // btnImportPerm?: string
-    // btnExportPerm?: string
-    // btnCreateShow?: boolean
-    // btnEditShow?: boolean
-    // btnDeleteShow?: boolean
-    // btnImportShow?: boolean
-    // btnExportShow?: boolean
-    // btnCreateFun?: () => void
-    // btnEditFun?: () => void
-    // btnDeleteFun?: () => void
-    // btnImportFun?: () => void
-    // btnExportFun?: () => void
-    // btnCreateDisabledFun?: (selectedRows: number) => boolean
-    // btnEditDisabledFun?: (selectedRows: number) => boolean
-    // btnDeleteDisabledFun?: (selectedRows: number) => boolean
-    // btnImportDisabledFun?: (selectedRows: number) => boolean
-    // btnExportDisabledFun?: (selectedRows: number) => boolean
     modal?: any
     formData?: any
     resetFormFun?: () => void
@@ -100,19 +83,18 @@ const props = withDefaults(
   {
     currentPage: 1,
     method: "get",
-    selectedItems: () => {
+    selectedIds: () => {
       return []
     },
     queryParams: {},
     total: 0,
-    //itemsPerPage: 10,
     pageDropdown: true,
     pageArray: () => {
       return [10, 25, 50]
     },
     initSearch: true,
     autoSearch: false,
-    hasCheckbox: true,
+    hasCheckbox: false,
     checkMultiple: false,
     sortOrder: "asc",
     pagination: true,
@@ -139,13 +121,13 @@ const props = withDefaults(
   }
 )
 const emits = defineEmits<{
-  (e: "update:selectedItems", v: Array<any>): void
+  (e: "update:selectedIds", v: Array<any>): void
   (e: "update:currentPage", v: number): void
   (e: "update:formData", v: any): void
   (e: "page-change", v: number): void
   (e: "on-items-per-page-change", v: number): void
   (e: "on-sort", v: Sort): void
-  (e: "on-items-change", isChecked: boolean, v: any, row: any): void
+  (e: "on-items-change", isChecked: boolean, selectedValue: string, row: any): void
   (e: "on-items-select", row: any): void
   (e: "on-items-all-change", isChecked: boolean, rows: Array<any>): void
 }>()
@@ -153,19 +135,11 @@ const id = ref("")
 const checkboxField = ref(props.checkboxField ? props.checkboxField : props.header[0].field)
 const currentPage = ref(props.currentPage)
 const itemsInTable = ref(props.pagination ? props.pageArray[0] : 1000)
-const selectedItems = ref(props.selectedItems)
+const selectedIds = ref(props.selectedIds)
 const remoteTotal = ref<number>(0)
 const remoteData = ref<Array<any>>([])
 const { data, queryParams, loading } = toRefs(props)
 const tableLoading = ref(false)
-// const _loading: WritableComputedRef<boolean> = computed({
-//   get(): boolean {
-//     return loading.value || tableLoading.value
-//   },
-//   set(value: boolean): void {
-//     tableLoading.value = value
-//   },
-// })
 const _loading = computed(() => {
   return loading.value || tableLoading.value
 })
@@ -209,7 +183,7 @@ const pageChange = (page: number) => {
   emits("update:currentPage", page)
   emits("page-change", page)
   currentPage.value = page
-  remote()
+  query()
 }
 const onSort = (sort: Sort) => {
   if (sort.order) {
@@ -220,14 +194,14 @@ const onSort = (sort: Sort) => {
     delete queryParams.value.isAsc
   }
   emits("on-sort", sort)
-  remote()
+  query()
 }
 const onSelectAll = (isChecked: boolean, rows: Array<any>) => {
   emits("on-items-all-change", isChecked, rows)
 }
-const onItemChange = (isChecked: boolean, v: any, row: any) => {
-  emits("update:selectedItems", selectedItems.value)
-  emits("on-items-change", isChecked, v, row)
+const onItemChange = (isChecked: boolean, selectedValue: string, row: any) => {
+  emits("update:selectedIds", selectedIds.value)
+  emits("on-items-change", isChecked, selectedValue, row)
   if (isChecked) {
     emits("on-items-select", row)
   }
@@ -236,13 +210,16 @@ const onItemsPerPageChange = (v: number) => {
   allData.value = []
   emits("on-items-per-page-change", v)
 }
-// const onItemSelect = (selectedItems: any) => {
-//   emits("on-items-select", selectedItems)
-// }
-
-function remote() {
-  tableLoading.value = true
+let treeData: any = []
+let treeAllData: any = []
+function query() {
   remoteData.value = []
+  treeData = []
+  treeAllData = []
+  remote(props.isLazy ? props.rootId : undefined)
+}
+
+function remote(id?: string) {
   const params = props.noPage
     ? queryParams.value
     : Object.assign(
@@ -253,12 +230,31 @@ function remote() {
         },
         queryParams.value
       )
-  const queryParam = props.method.toLocaleLowerCase() == "get" ? { params } : { data: params }
+  let curData: any = {}
+  if (props.isLazy) {
+    curData = treeAllData.find((v: any) => {
+      return v[checkboxField.value] == id
+    })
+    if (!id && !curData) {
+      throw new Error("懒加载模式,未获取到 parentId ,请检查")
+    }
+    if (curData?.children && curData?.children.length) {
+      return
+    }
+    if (!props.keyField) {
+      throw new Error("懒加载模式,请配置 keyField")
+    }
+    params[props.keyField] = id
+  }
+  tableLoading.value = true
+
   if (props.remoteFun) {
     props.remoteFun(params).then((res: any) => {
       processData(res.rows || res.data, res.total)
     })
   } else if (props.url) {
+    const queryParam = props.method.toLocaleLowerCase() == "get" ? { params } : { data: params }
+
     const configs = Object.assign(
       { url: props.url, method: props.method, successAlert: false },
       props.configs,
@@ -272,10 +268,22 @@ function remote() {
         tableLoading.value = false
       })
   }
+
   function processData(data: any, total: number) {
-    remoteData.value = data
     remoteTotal.value = total || 0
     tableLoading.value = false
+    if (props.isLazy) {
+      if (curData) {
+        curData.children = data
+        treeAllData.push(...curData.children)
+      } else {
+        treeData.push(...data)
+        treeAllData.push(...treeData)
+      }
+      remoteData.value = JSON.parse(JSON.stringify(treeData))
+    } else {
+      remoteData.value = data
+    }
     if (props.checkPageMultiple) {
       remoteData.value.forEach((v: any) => {
         if (
@@ -289,12 +297,17 @@ function remote() {
     } else {
       allData.value = remoteData.value
     }
+
     nextTick(bindEvent)
   }
 }
+
+function lazyLoad(id: string) {
+  return remote(id)
+}
+
 const defaultHandleFuns = {
   handleCreate: () => {
-    console.log("TC")
     props.resetFormFun && props.resetFormFun()
     if (props.modal) {
       props.modal.show()
@@ -307,8 +320,6 @@ const defaultHandleFuns = {
     if (!row) {
       return
     }
-    console.log("TU", e, row)
-
     if (props.getEntiyFun) {
       props.getEntiyFun(row[checkboxField.value]).then((res) => {
         emits("update:formData", res.data)
@@ -318,7 +329,8 @@ const defaultHandleFuns = {
         }
       })
     } else {
-      emits("update:formData", row)
+      const _row = Object.assign({}, row)
+      emits("update:formData", _row)
       if (props.modal) {
         props.modal.show()
         props.modal.changePrefixTitle("修改")
@@ -326,7 +338,6 @@ const defaultHandleFuns = {
     }
   },
   handleDelete: (e?: any, rows?: any) => {
-    console.log("TD")
     rows = rows || getSelecteds()
     if (!rows) {
       return
@@ -409,7 +420,7 @@ function loadHandleBtns() {
 
 function search() {
   table.value.reset()
-  remote()
+  query()
 }
 function bindEvent() {
   if (props.rowClickFun) {
@@ -430,7 +441,7 @@ function bindEvent() {
   }
 }
 function getSelectedIds() {
-  return selectedItems.value
+  return selectedIds.value
 }
 function getSelected() {
   const items = getSelecteds()
@@ -438,7 +449,7 @@ function getSelected() {
 }
 function getSelecteds() {
   const selectedArr: Array<any> = []
-  selectedItems.value.forEach((v) => {
+  selectedIds.value.forEach((v) => {
     const item = allData.value.find((vv: any) => {
       return vv[checkboxField.value] == v
     })
@@ -460,7 +471,6 @@ function customSearch() {
 watch(
   () => itemsInTable.value,
   (val) => {
-    //console.log("WATCH_I")
     currentPage.value = 1
     emits("on-items-per-page-change", val)
     search()
@@ -470,8 +480,6 @@ watch(
 watch(
   () => props.queryParams,
   (val) => {
-    //console.log("WATCH_Q")
-
     currentPage.value = 1
     queryParams.value = val
     search()
@@ -481,18 +489,7 @@ watch(
     deep: props.autoSearch,
   }
 )
-// watch(table, (val) => {
-//   if (val) {
-//     if (props.scroll?.x) {
-//       val.value.style.width = Number(props.scroll.x) ? props.scroll.x + "px" : props.scroll.x
-//       val.value.style.overflowX = "auto"
-//     }
-//     if (props.scroll?.y) {
-//       val.value.style.height = Number(props.scroll.y) ? props.scroll.y + "px" : props.scroll.y
-//       val.value.style.overflowY = "auto"
-//     }
-//   }
-// })
+
 function init() {
   id.value = Math.floor(Math.random() * 999999999) + ""
   loadHandleBtns()
@@ -503,31 +500,12 @@ function init() {
     bindEvent()
   }
 }
+
 onMounted(init)
 defineExpose({ search, getSelectedIds, getSelected, getSelecteds, getData, defaultHandleFuns })
 </script>
 
 <template>
-  <!-- :btnCreateShow="btnCreateShow"
-      :btnEditShow="btnEditShow"
-      :btnDeleteShow="btnDeleteShow"
-      :btnImportShow="btnImportShow"
-      :btnExportShow="btnExportShow"
-      :btnCreatePerm="btnCreatePerm"
-      :btnEditPerm="btnEditPerm"
-      :btnDeletePerm="btnDeletePerm"
-      :btnImportPerm="btnImportPerm"
-      :btnExportPerm="btnExportPerm"
-      :btnCreateFun="btnCreateFun"
-      :btnEditFun="btnEditFun"
-      :btnDeleteFun="btnDeleteFun"
-      :btnImportFun="btnImportFun"
-      :btnExportFun="btnExportFun"
-      :btnCreateDisabledFun="btnCreateDisabledFun"
-      :btnEditDisabledFun="btnEditDisabledFun"
-      :btnDeleteDisabledFun="btnDeleteDisabledFun"
-      :btnImportDisabledFun="btnImportDisabledFun"
-      :btnExportDisabledFun="btnExportDisabledFun" -->
   <div
     class="vb-table"
     :id="id"
@@ -535,7 +513,7 @@ defineExpose({ search, getSelectedIds, getSelected, getSelecteds, getData, defau
   >
     <TableToolbar
       v-if="showToolbar"
-      :selected-rows="selectedItems.length"
+      :selected-rows="selectedIds.length"
       :show-right-toolbar="showRightToolbar"
       :show-right-search-btn="showRightSearchBtn"
       :show-right-column-btn="showRightColumnBtn"
@@ -560,10 +538,10 @@ defineExpose({ search, getSelectedIds, getSelected, getSelecteds, getData, defau
       @on-sort="onSort"
       :header="displayColumns"
       :data="dataToDisplay"
-      v-model:selected-items="selectedItems"
-      :has-checkbox="hasCheckbox"
+      v-model:selected-ids="selectedIds"
       :checkbox-field="checkboxField"
       :check-multiple="checkMultiple || checkPageMultiple"
+      :has-checkbox="checkMultiple || checkPageMultiple || hasCheckbox"
       :empty-table-text="emptyTableText"
       :sort-field="sortField"
       :sort-order="sortOrder"
@@ -584,7 +562,9 @@ defineExpose({ search, getSelectedIds, getSelected, getSelecteds, getData, defau
       :key-field="keyField"
       :parent-field="parentField"
       :children-field="childrenField"
+      :leaf-field="leafField"
       :expand-depth="expandDepth"
+      :lazy-load="isLazy ? lazyLoad : undefined"
     >
       <template v-for="(_, name) in $slots" #[name]="{ row: item }">
         <slot :name="name" :row="item" />

+ 36 - 4
UI/VA.Vue_V1.0/src/components/table/VbTreeTable.vue

@@ -10,6 +10,7 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
     header: Array<Header>
     url?: string
     remoteFun?: (q: any) => Promise<any>
@@ -57,6 +58,8 @@ const props = withDefaults(
     handleFuns?: object
     handleDisabledFuns?: object
     customBtns?: Array<ToolBtn>
+    isLazy?: boolean
+    rootId?: string
   }>(),
   {
     currentPage: 1,
@@ -69,6 +72,8 @@ const props = withDefaults(
     checkMultiple: false,
     sortOrder: "asc",
     pagination: false,
+    isLazy: false,
+    rootId: "0",
   }
 )
 const emits = defineEmits<{
@@ -78,7 +83,7 @@ const emits = defineEmits<{
   (e: "page-change", v: number): void
   (e: "on-items-per-page-change", v: number): void
   (e: "on-sort", v: Sort): void
-  (e: "on-items-change", isChecked: boolean, v: any, row: any): void
+  (e: "on-items-change", isChecked: boolean, selectedValue: string, row: any): void
   (e: "on-items-select", row: any): void
   (e: "on-items-all-change", isChecked: boolean, rows: Array<any>): void
 }>()
@@ -95,9 +100,9 @@ const onSort = (sort: Sort) => {
 const onSelectAll = (isChecked: boolean, rows: Array<any>) => {
   emits("on-items-all-change", isChecked, rows)
 }
-const onItemChange = (isChecked: boolean, v: any, row: any) => {
+const onItemChange = (isChecked: boolean, selectedValue: string, row: any) => {
   emits("update:selectedItems", selectedItems.value)
-  emits("on-items-change", isChecked, v, row)
+  emits("on-items-change", isChecked, selectedValue, row)
 }
 const onItemSelect = (row: any) => {
   emits("on-items-select", row)
@@ -109,7 +114,31 @@ const treeTable = ref()
 function search() {
   treeTable.value.search()
 }
-defineExpose({ search, treeTable })
+
+function getSelectedIds() {
+  return treeTable.value.getSelectedIds()
+}
+
+function getSelected() {
+  const s = treeTable.value.getSelected()
+  if (treeTable.value) {
+    console.log("----", s)
+  }
+  return s
+}
+
+function getSelecteds() {
+  return treeTable.value.getSelecteds()
+}
+
+function getData() {
+  return treeTable.value.getData()
+}
+
+const defaultHandleFuns = computed(() => {
+  return treeTable.value?.defaultHandleFuns
+})
+defineExpose({ search, getSelectedIds, getSelected, getSelecteds, getData, defaultHandleFuns, treeTable })
 </script>
 <template>
   <VbDataTable
@@ -122,6 +151,7 @@ defineExpose({ search, treeTable })
     :key-field="keyField"
     :children-field="childrenField"
     :parent-field="parentField"
+    :leaf-field="leafField"
     :expand-depth="expandDepth"
     :data="data"
     :url="url"
@@ -163,6 +193,8 @@ defineExpose({ search, treeTable })
     :export-name="exportName"
     :modal="modal"
     :reset-form-fun="resetFormFun"
+    :is-lazy="isLazy"
+    :root-id="rootId"
     v-model:form-data="formData"
     @page-change="pageChange"
     @on-items-change="onItemChange"

+ 65 - 34
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/TableContent.vue

@@ -10,7 +10,7 @@ const props = withDefaults(
   defineProps<{
     header: Array<Header>
     data: Array<any>
-    selectedItems?: Array<unknown>
+    selectedIds?: Array<unknown>
     hasCheckbox?: boolean //是否有选择框
     checkboxField?: string //选择框字段
     checkMultiple?: boolean //是否多选
@@ -36,9 +36,11 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    lazyLoad?: (v: string) => void
   }>(),
   {
-    selectedItems: () => {
+    selectedIds: () => {
       return []
     },
     hasCheckbox: true,
@@ -56,47 +58,72 @@ const props = withDefaults(
   }
 )
 const emits = defineEmits<{
-  (e: "update:selectedItems", v: Array<any>): void
+  (e: "update:selectedIds", v: Array<any>): void
   (e: "on-sort", v: Sort): void
-  (e: "on-items-change", isChecked: boolean, v: any, row: any): void
+  (e: "on-items-change", isChecked: boolean, selectedValue: string, row: any): void
   (e: "on-items-all-change", isChecked: boolean, rows: Array<any>): void
 }>()
 const table = ref()
-const selectedItems = ref(props.selectedItems)
+const selectedIds = ref(props.selectedIds)
 
 const allSelectedItems = ref<Array<unknown>>([])
-const check = ref<boolean>(false)
+const checkAll = computed(() => {
+  const flag =
+    allSelectedItems.value.length > 0 &&
+    Array.from(new Set([...selectedIds.value, ...allSelectedItems.value])).length ==
+      Array.from(new Set([...selectedIds.value])).length
+  return flag
+})
 
 const reset = () => {
-  selectedItems.value = []
+  selectedIds.value = []
   allSelectedItems.value = []
-  check.value = false
+  emits("update:selectedIds", selectedIds.value)
 }
 
 const onSelectAll = (checked: any) => {
-  check.value = checked
   if (checked) {
-    selectedItems.value = [...new Set([...selectedItems.value, ...allSelectedItems.value])]
+    selectedIds.value = [...new Set([...selectedIds.value, ...allSelectedItems.value])]
   } else {
-    selectedItems.value = []
+    selectedIds.value = []
   }
-
-  emits("update:selectedItems", selectedItems.value)
-  emits("on-items-all-change", check.value, selectedItems.value)
+  document.querySelectorAll(".table-box tr td.check-box input").forEach((v: any) => {
+    nextTick(() => {
+      v.checked = checked
+    })
+  })
+  emits("update:selectedIds", selectedIds.value)
+  emits("on-items-all-change", checkAll.value, selectedIds.value)
 }
 
-const onSelectItemsChange = (isChecked: boolean, v: any, row: any) => {
-  emits("update:selectedItems", v)
-  selectedItems.value = []
-  v.forEach((item: any) => {
-    if (!selectedItems.value.includes(item)) selectedItems.value.push(item)
-  })
-  check.value =
-    Array.from(new Set([...selectedItems.value, ...allSelectedItems.value])).length ==
-    Array.from(new Set([...selectedItems.value])).length
-  emits("on-items-change", isChecked, v, row)
+const onSelectItemsChange = (isChecked: boolean, selectedValue: string, row: any) => {
+  if (props.checkMultiple || props.multiplePageCheck) {
+    if (isChecked) {
+      selectedIds.value = Array.from(new Set([...selectedIds.value, selectedValue]))
+    } else {
+      selectedIds.value = selectedIds.value.filter((vv) => {
+        return vv != selectedValue
+      })
+    }
+  } else {
+    selectedIds.value = []
+    if (isChecked) {
+      selectedIds.value.push(selectedValue)
+      const val = selectedValue
+      document.querySelectorAll(".table-box tr td.check-box input")?.forEach((vv: any) => {
+        const item = vv as HTMLInputElement
+        if (item.value != val) {
+          //下一帧更新才生效
+          nextTick(() => {
+            item.checked = false
+          })
+        }
+      })
+    }
+  }
 
-  //console.log("SELECT_ITEM", selectedItems.value)
+  emits("update:selectedIds", selectedIds.value)
+  emits("on-items-change", isChecked, selectedValue, row)
 }
 
 const onSort = (sort: Sort) => {
@@ -120,20 +147,18 @@ const tableStyle = computed(() => {
 watch(
   () => props.data,
   () => {
-    selectedItems.value = props.multiplePageCheck ? selectedItems.value : []
+    selectedIds.value = props.multiplePageCheck ? selectedIds.value : []
     allSelectedItems.value = []
-    check.value = false
     props.data.forEach((item: any) => {
       if (item[props.checkboxField]) {
-        allSelectedItems.value.push(item[props.checkboxField])
+        allSelectedItems.value.push(item[props.checkboxField] + "")
       }
     })
-    //console.log("allSelectedItems:", allSelectedItems.value)
   }
 )
 
 defineExpose({
-  selectedItems,
+  selectedIds: selectedIds,
   reset,
 })
 </script>
@@ -147,9 +172,9 @@ defineExpose({
       :table="table"
       :header="header"
       :data="data"
-      v-model:selected-items="selectedItems"
+      v-model:selected-items="selectedIds"
       :fixed-number="fixedNumber"
-      :checkbox-all-value="check"
+      :check-all="checkAll"
       :checkbox-field="checkboxField"
       :has-checkbox="hasCheckbox"
       :check-multiple="checkMultiple"
@@ -168,7 +193,9 @@ defineExpose({
       :key-field="keyField"
       :children-field="childrenField"
       :parent-field="parentField"
+      :leaf-field="leafField"
       :expand-depth="expandDepth"
+      :lazy-load="lazyLoad"
     >
       <template v-for="(_, name) in $slots" v-slot:[name]="{ row: item }">
         <slot :name="name" :row="item" />
@@ -189,7 +216,7 @@ defineExpose({
           v-else
           @onSort="onSort"
           @on-select-all="onSelectAll"
-          :checkbox-all-value="check"
+          :check-all="checkAll"
           :has-checkbox="hasCheckbox"
           :check-multiple="checkMultiple"
           :sort-field="sortField"
@@ -208,7 +235,7 @@ defineExpose({
         <TableBodyRow
           v-if="data.length !== 0"
           @on-change="onSelectItemsChange"
-          v-model:currently-selected-items="selectedItems"
+          v-model:currently-selected-items="selectedIds"
           :check-multiple="checkMultiple"
           :data="data"
           :header="header"
@@ -226,7 +253,9 @@ defineExpose({
           :key-field="keyField"
           :parent-field="parentField"
           :children-field="childrenField"
+          :leaf-field="leafField"
           :expand-depth="expandDepth"
+          :lazy-load="lazyLoad"
         >
           <template v-for="(_, name) in $slots" v-slot:[name]="{ row: item }">
             <slot v-if="!name.toString().endsWith('_header')" :name="name" :row="item" />
@@ -265,6 +294,8 @@ defineExpose({
       :parent-field="parentField"
       :children-field="childrenField"
       :expand-depth="expandDepth"
+      :leaf-field="leafField"
+      :lazy-load="lazyLoad"
     >
       <template v-for="(_, name) in $slots" #[name]="{ row: item }">
         <slot :name="name" :row="item" />

+ 103 - 143
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableBodyRow.vue

@@ -2,13 +2,11 @@
 import { ref, watch, onMounted } from "vue"
 import type { Header } from "@/components/table/table-partials/models"
 import TableTreeRow from "./TableTreeRow.vue"
-import configs from "@/core/config"
 
 const props = withDefaults(
   defineProps<{
     header: Array<Header>
     data: Array<any>
-    currentlySelectedItems?: Array<any>
     hasCheckbox?: boolean //是否有选择框
     checkMultiple?: boolean //是否多选
     checkboxField?: string //选择框字段
@@ -24,6 +22,9 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    lazyLoad?: (v: string) => void
+    isLazy?: boolean
   }>(),
   {
     currentlySelectedItems: () => {
@@ -41,75 +42,52 @@ const props = withDefaults(
   }
 )
 const emits = defineEmits<{
-  (e: "on-change", isChecked: boolean, v: any, row: any): void
-  (e: "update:currentlySelectedItems", v: any): void
+  (e: "on-change", isChecked: boolean, selectedValue: string, row: any): void
 }>()
-const selectedItems = ref<Array<any>>([])
 
-watch(
-  () => [...props.currentlySelectedItems],
-  (currentValue) => {
-    if (props.currentlySelectedItems.length !== 0) {
-      selectedItems.value = [...new Set([...selectedItems.value, ...currentValue])]
-    } else {
-      selectedItems.value = []
-    }
-  }
-)
-const tooltip = (col: Header) => {
-  if (typeof col.tooltip == "string") {
-    return col.tooltip
-  } else if (col.tooltip) {
-    return "primary"
-  }
-  return undefined
-}
 const onChange = (event: Event) => {
   const target = event.target as HTMLInputElement
-  selectedItems.value = props.checkMultiple ? selectedItems.value : target.checked ? [target.value] : []
   const row = props.data.find((v: any) => {
     return v[props.checkboxField] == target.value
   })
-  emits("on-change", target.checked, selectedItems.value, row)
-  emits("update:currentlySelectedItems", selectedItems.value)
-}
-const tdStyle = (column: Header) => {
-  const style: any = {}
-  if (column.align) {
-    style.textAlign = column.align
-  }
 
-  return style
+  emits("on-change", target.checked, target.value, row)
 }
-const tdClass = (column: Header) => {
-  let classStr = ""
-  if (column.tdClass) {
-    classStr += column.tdClass
-  }
-  return classStr
+
+const onSelectItemsChange = (isChecked: boolean, selectedValue: string, row: any) => {
+  emits("on-change", isChecked, selectedValue, row)
 }
-const tbody = ref<HTMLElement>()
-function init() {
-  if (props.isTree && tbody.value) {
-    tbody.value.querySelectorAll("td.tree-icon>.icon")?.forEach((v) => {
-      v.addEventListener("click", () => {
-        const parent = v.parentElement?.parentElement
-        const id = parent?.id
-        if (parent == null || !id) {
-          return
-        }
 
-        if (parent.className.search("tr-expand") >= 0) {
-          parent.className = parent.className.replace("tr-expand", "tr-collapse")
-          v.children[0].className = v.children[0].className.replace("ki-minus-folder", "ki-add-folder")
-          hideChildren(id)
-        } else if (parent.className.search("tr-collapse") >= 0) {
-          parent.className = parent.className.replace("tr-collapse", "tr-expand")
-          v.children[0].className = v.children[0].className.replace("ki-add-folder", "ki-minus-folder")
-          showChildren(id)
-        }
-      })
-    })
+function iconClick(e: Event) {
+  const target = (e.target as HTMLElement).closest(".icon") as HTMLElement
+  const parent = target.closest("tr") as HTMLElement
+  const id = parent?.id
+  if (parent == null || !id) {
+    return
+  }
+  if (props.lazyLoad) {
+    // 已有children可展开的直接展开,不在调用懒加载
+    if (parent.className.search("hasChildren") >= 0) {
+      toggle(parent, target, id)
+    } else {
+      const parentId = id.replace("tr_", "")
+      props.lazyLoad(parentId)
+      parent.className = parent.className.replace("tr-collapse", "tr-expand")
+      target.children[0].className = target.children[0].className.replace("ki-add-folder", "ki-minus-folder")
+    }
+  } else {
+    toggle(parent, target, id)
+  }
+  function toggle(parent: HTMLElement, el: HTMLElement, id: string) {
+    if (parent.className.search("tr-expand") >= 0) {
+      parent.className = parent.className.replace("tr-expand", "tr-collapse")
+      el.children[0].className = el.children[0].className.replace("ki-minus-folder", "ki-add-folder")
+      hideChildren(id)
+    } else if (parent.className.search("tr-collapse") >= 0) {
+      parent.className = parent.className.replace("tr-collapse", "tr-expand")
+      el.children[0].className = el.children[0].className.replace("ki-add-folder", "ki-minus-folder")
+      showChildren(id)
+    }
   }
   function hideChildren(parentId: string) {
     const children = document.querySelectorAll(`[data-parent="${parentId}"]`)
@@ -132,100 +110,82 @@ function init() {
     }
   }
 }
+
+const tbody = ref<HTMLElement>()
+function init() {
+  if (props.isTree && tbody.value) {
+    const clickEvent = iconClick
+    tbody.value.querySelectorAll("td.tree-icon>.icon")?.forEach((v: any) => {
+      v.removeEventListener("click", clickEvent, true)
+      v.addEventListener("click", clickEvent, true)
+    })
+  }
+}
+watch(
+  () => props.data,
+  () => {
+    nextTick(init)
+  }
+)
+
 onMounted(init)
 </script>
 
 <template>
-  <tbody ref="tbody" class="fw-semibold text-gray-600">
+  <tbody v-if="data.length" ref="tbody" class="fw-semibold text-gray-600">
     <template v-for="(row, i) in data" :key="i">
       <template v-if="isTree">
-        <TransitionGroup name="fade">
-          <TableTreeRow
-            :key="i"
-            :row="row"
-            :header="header"
-            :interval-left="intervalLeft"
-            :icon-field="iconField"
-            :key-field="keyField"
-            :parent-field="parentField"
-            :children-field="childrenField"
-            :expand-depth="expandDepth"
-            :currently-selected-items="currentlySelectedItems"
-            :has-checkbox="hasCheckbox"
-            :checkbox-field="checkboxField"
-            :td-tr-class="tdTrClass"
-            :row-span-suffix="rowSpanSuffix"
-          >
-            <template v-for="(_, name) in $slots" #[name]="{ row: item }">
-              <slot :name="name" :row="item" />
-            </template>
-          </TableTreeRow>
-        </TransitionGroup>
+        <TableTreeRow
+          :key="i"
+          :row="row"
+          :header="header"
+          :interval-left="intervalLeft"
+          :icon-field="iconField"
+          :key-field="keyField"
+          :parent-field="parentField"
+          :children-field="childrenField"
+          :leaf-field="leafField"
+          :expand-depth="expandDepth"
+          :check-multiple="checkMultiple"
+          :has-checkbox="hasCheckbox"
+          :checkbox-field="checkboxField"
+          :td-tr-class="tdTrClass"
+          :row-span-suffix="rowSpanSuffix"
+          :is-lazy="lazyLoad != null"
+          @on-change="onSelectItemsChange"
+        >
+          <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+            <slot :name="name" :row="item" />
+          </template>
+        </TableTreeRow>
       </template>
       <tr v-else :class="tdTrClass" :id="`tr_${row[checkboxField]}`">
-        <td v-if="hasCheckbox">
+        <td v-if="hasCheckbox" class="check-box">
           <div class="form-check form-check-sm form-check-custom form-check-solid">
-            <input
-              class="form-check-input"
-              type="checkbox"
-              :value="row[checkboxField]"
-              v-model="selectedItems"
-              @change="onChange"
-            />
+            <input class="form-check-input" type="checkbox" :value="row[checkboxField]" @change="onChange" />
           </div>
         </td>
-        <template v-for="(column, j) in header" :key="j">
-          <td
-            v-if="row[column.field + props.rowSpanSuffix]"
-            :style="tdStyle(column)"
-            :class="tdClass(column)"
-            :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
-          >
-            <template v-if="$slots[column.field]">
-              <slot :name="`${column.field}`" :row="row">
-                {{ row }}
-              </slot>
-            </template>
-            <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
-              {{ i + 1 }}
-            </template>
-            <template v-else-if="tooltip(column)">
-              <vb-tooltip
-                :effect="tooltip(column)"
-                :content="row[column.field]"
-                :auto-hide="true"
-                :delay="500"
-              ></vb-tooltip>
-            </template>
-            <template v-else>
-              {{ row[column.field] }}
-            </template>
-          </td>
-          <td
-            v-else-if="row[column.field + props.rowSpanSuffix] != 0"
-            :style="tdStyle(column)"
-            :class="tdClass(column)"
-          >
-            <template v-if="$slots[column.field]">
-              <slot :name="`${column.field}`" :row="row">
-                {{ row }}
-              </slot>
-            </template>
-            <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
-              {{ i + 1 }}
-            </template>
-            <template v-else-if="tooltip(column)">
-              <vb-tooltip
-                :effect="tooltip(column)"
-                :content="row[column.field]"
-                :auto-hide="true"
-                :delay="500"
-              ></vb-tooltip>
-            </template>
-            <template v-else>
-              {{ row[column.field] }}
-            </template>
-          </td>
+        <template v-for="(column, i) in header" :key="i">
+          <template v-if="row[column.field + props.rowSpanSuffix]">
+            <TableBodyTd
+              :row="row"
+              :column="column"
+              :index="i + 1"
+              :is-tree="false"
+              :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
+            >
+              <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+                <slot :name="name" :row="item"></slot>
+              </template>
+            </TableBodyTd>
+          </template>
+          <template v-else-if="row[column.field + props.rowSpanSuffix] != 0">
+            <TableBodyTd :row="row" :column="column" :index="i + 1" :is-tree="false">
+              <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+                <slot :name="name" :row="item"></slot>
+              </template>
+            </TableBodyTd>
+          </template>
         </template>
       </tr>
     </template>

+ 116 - 0
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableBodyTd.vue

@@ -0,0 +1,116 @@
+<script setup lang="ts">
+import type { Header } from "@/components/table/table-partials/models"
+import configs from "@/core/config"
+
+const props = withDefaults(
+  defineProps<{
+    row: any
+    column: Header
+    index?: number
+    isTree?: boolean
+    isExpand?: boolean
+    hasChildren?: boolean
+    depth?: number
+    rowspan?: number | string
+    intervalLeft?: number
+    iconField?: string
+    leafField?: string
+    isLazy?: boolean
+  }>(),
+  {
+    isTree: false,
+    checkboxField: "id",
+    iconField: "name",
+    leafField: "isLeaf",
+    depth: 0,
+    intervalLeft: 10,
+  }
+)
+
+const isLeaf = computed(() => {
+  return !!props.row[props.leafField]
+})
+
+const tooltip = (col: Header) => {
+  if (typeof col.tooltip == "string") {
+    return col.tooltip
+  } else if (col.tooltip) {
+    return "primary"
+  }
+  return undefined
+}
+const tdStyle = (column: Header) => {
+  const style: any = {}
+  if (column.align) {
+    style.textAlign = column.align
+  }
+  if (props.isTree && column.field == props.iconField) {
+    style.textAlign = "left"
+  }
+  return style
+}
+const tdClass = (column: Header) => {
+  let classStr = ""
+  if (column.tdClass) {
+    classStr += column.tdClass
+  }
+  if (props.isTree && column.field == props.iconField) {
+    classStr += " tree-icon"
+  }
+  return classStr
+}
+function init() {
+  //
+}
+
+onMounted(init)
+</script>
+<template>
+  <td :style="tdStyle(column)" :class="tdClass(column)" :rowspan="rowspan">
+    <span
+      v-if="isTree && column.field == iconField"
+      class="me-2"
+      :class="{ icon: !isLeaf }"
+      :style="`margin-left: ${intervalLeft * depth}px!important`"
+    >
+      <template v-if="hasChildren || !isLeaf">
+        <KTIcon
+          v-if="isLazy ? false : isExpand"
+          icon-name="minus-folder"
+          icon-type="duotone"
+          class="fs-2 text-primary"
+          style="transform: translateY(3px)"
+        ></KTIcon>
+        <KTIcon
+          v-else
+          icon-name="add-folder"
+          icon-type="duotone"
+          class="fs-2 text-primary"
+          style="transform: translateY(3px)"
+        ></KTIcon>
+      </template>
+      <template v-else>
+        <KTIcon
+          icon-name="folder"
+          icon-type="duotone"
+          class="fs-2 text-primary"
+          style="transform: translateY(3px)"
+        ></KTIcon>
+      </template>
+    </span>
+    <template v-if="$slots[column.field]">
+      <slot :name="`${column.field}`" :row="row">
+        {{ row }}
+      </slot>
+    </template>
+    <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
+      {{ index }}
+    </template>
+    <template v-else-if="tooltip(column)">
+      <vb-tooltip :effect="tooltip(column)" :content="row[column.field]" :auto-hide="true" :delay="500"></vb-tooltip>
+    </template>
+    <template v-else>
+      {{ row[column.field] }}
+    </template>
+  </td>
+</template>

+ 84 - 192
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableTreeRow.vue

@@ -2,7 +2,7 @@
 import { ref, onMounted, computed } from "vue"
 import type { Header } from "@/components/table/table-partials/models"
 import TableTreeRowChild from "./TableTreeRowChild.vue"
-import configs from "@/core/config"
+import TableBodyTd from "./TableBodyTd.vue"
 
 const props = withDefaults(
   defineProps<{
@@ -21,6 +21,8 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    isLazy?: boolean
   }>(),
   {
     checkboxField: "id",
@@ -28,19 +30,21 @@ const props = withDefaults(
     parentField: "parent_id",
     childrenField: "children",
     iconField: "name",
+    leafField: "isLeaf",
     depth: 0,
     expandDepth: 0,
     intervalLeft: 10,
   }
 )
 const emits = defineEmits<{
-  (e: "on-change", isChecked: boolean, v: any, row: any): void
-  (e: "update:currentlySelectedItems", v: any): void
+  (e: "on-change", isChecked: boolean, selectedValue: string, row: any): void
 }>()
-const selectedItems = ref<Array<any>>([])
+
 const isExpand = computed(() => {
-  return props.expandDepth > props.depth
+  return props.isLazy ? true : props.expandDepth > props.depth
 })
+
+const show = ref(true)
 const hasChildren = computed(() => {
   return props.row[props.childrenField] && props.row[props.childrenField].length
 })
@@ -50,49 +54,17 @@ const trClass = computed(() => {
   if (hasChildren.value) {
     _trClass += `hasChildren ${isExpand.value ? "tr-expand" : "tr-collapse"} `
   }
-  _trClass += props.depth > props.expandDepth ? "hide" : "show"
+  _trClass += !props.isLazy && props.depth > props.expandDepth ? "hide" : "show"
   return _trClass
 })
 
-const tooltip = (col: Header) => {
-  if (typeof col.tooltip == "string") {
-    return col.tooltip
-  } else if (col.tooltip) {
-    return "primary"
-  }
-  return undefined
-}
-const tdStyle = (column: Header) => {
-  const style: any = {}
-  if (column.align) {
-    style.textAlign = column.align
-  }
-  if (column.field == props.iconField) {
-    style.textAlign = "left"
-  }
-
-  return style
-}
-const tdClass = (column: Header) => {
-  let classStr = ""
-  if (column.tdClass) {
-    classStr += column.tdClass
-  }
-  if (column.field == props.iconField) {
-    classStr += " tree-icon"
-  }
-  return classStr
-}
 const onChange = (event: Event) => {
   const target = event.target as HTMLInputElement
-  selectedItems.value = props.checkMultiple ? selectedItems.value : target.checked ? [target.value] : []
-  // const row = props.data.find((v: any) => {
-  //   return v[props.checkboxField] == target.value
-  // })
-  emits("on-change", target.checked, selectedItems.value, props.row)
-  emits("update:currentlySelectedItems", selectedItems.value)
+  emits("on-change", target.checked, target.value, props.row)
+}
+const onSelectItemsChange = (isChecked: boolean, selectedValue: string, row: any) => {
+  emits("on-change", isChecked, selectedValue, row)
 }
-
 function init() {
   //console.log("TREE_ROW", props.row)
 }
@@ -102,160 +74,80 @@ onMounted(() => {
 })
 </script>
 <template>
-  <tr :class="trClass" :id="`tr_${row[keyField]}`" :data-parent="`tr_${row[parentField]}`">
-    <td v-if="hasCheckbox">
-      <div class="form-check form-check-sm form-check-custom form-check-solid">
-        <input
-          class="form-check-input"
-          type="checkbox"
-          :value="row[checkboxField]"
-          v-model="selectedItems"
-          @change="onChange"
-        />
-      </div>
-    </td>
-    <template v-for="(column, i) in header" :key="i">
-      <td
-        v-if="row[column.field + props.rowSpanSuffix]"
-        :style="tdStyle(column)"
-        :class="tdClass(column)"
-        :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
-      >
-        <!-- <span
-          v-if="column.field == iconField"
-          class="icon"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        ></span> -->
-        <span
-          v-if="column.field == iconField"
-          class="icon me-2"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        >
-          <template v-if="hasChildren">
-            <KTIcon
-              v-if="isExpand"
-              icon-name="minus-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-            <KTIcon
-              v-else
-              icon-name="add-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-          <template v-else>
-            <KTIcon
-              icon-name="folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-        </span>
-
-        <template v-if="$slots[column.field]">
-          <slot :name="`${column.field}`" :row="row">
-            {{ row }}
-          </slot>
-        </template>
-        <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
-          {{ i + 1 }}
-        </template>
-        <template v-else-if="tooltip(column)">
-          <vb-tooltip
-            :effect="tooltip(column)"
-            :content="row[column.field]"
-            :auto-hide="true"
-            :delay="500"
-          ></vb-tooltip>
-        </template>
-        <template v-else>
-          {{ row[column.field] }}
-        </template>
+  <template v-if="show">
+    <tr :class="trClass" :id="`tr_${row[keyField]}`" :data-parent="`tr_${row[parentField]}`">
+      <td v-if="hasCheckbox" class="check-box">
+        <div class="form-check form-check-sm form-check-custom form-check-solid">
+          <input class="form-check-input" type="checkbox" :value="row[checkboxField]" @change="onChange" />
+        </div>
       </td>
-      <td v-else-if="row[column.field + props.rowSpanSuffix] != 0" :style="tdStyle(column)" :class="tdClass(column)">
-        <!-- <span
-          v-if="column.field == iconField"
-          class="icon"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        ></span> -->
-        <span
-          v-if="column.field == iconField"
-          class="icon me-2"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        >
-          <template v-if="hasChildren">
-            <KTIcon
-              v-if="isExpand"
-              icon-name="minus-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-            <KTIcon
-              v-else
-              icon-name="add-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-          <template v-else>
-            <KTIcon
-              icon-name="folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-        </span>
-        <template v-if="$slots[column.field]">
-          <slot :name="`${column.field}`" :row="row">
-            {{ row }}
-          </slot>
-        </template>
-        <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
-          {{ i + 1 }}
+      <template v-for="(column, i) in header" :key="i">
+        <template v-if="row[column.field + props.rowSpanSuffix]">
+          <TableBodyTd
+            :row="row"
+            :column="column"
+            :index="i + 1"
+            :is-tree="true"
+            :isExpand="isExpand"
+            :depth="depth"
+            :interval-left="intervalLeft"
+            :icon-field="iconField"
+            :leaf-field="leafField"
+            :is-lazy="isLazy"
+            :has-children="hasChildren"
+            :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
+          >
+            <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+              <slot :name="name" :row="item"></slot>
+            </template>
+          </TableBodyTd>
         </template>
-        <template v-else-if="tooltip(column)">
-          <vb-tooltip
-            :effect="tooltip(column)"
-            :content="row[column.field]"
-            :auto-hide="true"
-            :delay="500"
-          ></vb-tooltip>
+        <template v-else-if="row[column.field + props.rowSpanSuffix] != 0">
+          <TableBodyTd
+            :row="row"
+            :column="column"
+            :index="i + 1"
+            :is-tree="true"
+            :isExpand="isExpand"
+            :depth="depth"
+            :interval-left="intervalLeft"
+            :icon-field="iconField"
+            :leaf-field="leafField"
+            :has-children="hasChildren"
+            :is-lazy="isLazy"
+          >
+            <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+              <slot :name="name" :row="item"></slot>
+            </template>
+          </TableBodyTd>
         </template>
-        <template v-else>
-          {{ row[column.field] }}
+      </template>
+    </tr>
+    <template v-if="hasChildren">
+      <TableTreeRowChild
+        v-for="(child, i) in row[props.childrenField]"
+        :key="i"
+        :row="child"
+        :header="header"
+        :depth="depth + 1"
+        :expand-depth="expandDepth"
+        :has-checkbox="hasCheckbox"
+        :checkbox-field="checkboxField"
+        :td-tr-class="tdTrClass"
+        :row-span-suffix="rowSpanSuffix"
+        :icon-field="iconField"
+        :key-field="keyField"
+        :check-multiple="checkMultiple"
+        :parent-field="parentField"
+        :children-field="childrenField"
+        :leaf-field="leafField"
+        :is-lazy="isLazy"
+        @on-change="onSelectItemsChange"
+      >
+        <template v-for="(_, name) in $slots" #[name]="{ row }">
+          <slot :name="name" :row="row"></slot>
         </template>
-      </td>
+      </TableTreeRowChild>
     </template>
-  </tr>
-  <template v-if="hasChildren">
-    <TableTreeRowChild
-      v-for="(child, i) in row[props.childrenField]"
-      :key="i"
-      :row="child"
-      :header="header"
-      :depth="depth + 1"
-      :expand-depth="expandDepth"
-      :currently-selected-items="currentlySelectedItems"
-      :has-checkbox="hasCheckbox"
-      :checkbox-field="checkboxField"
-      :td-tr-class="tdTrClass"
-      :row-span-suffix="rowSpanSuffix"
-      :icon-field="iconField"
-      :key-field="keyField"
-      :parent-field="parentField"
-      :children-field="childrenField"
-    >
-      <template v-for="(_, name) in $slots" #[name]="{ row: item }">
-        <slot :name="name" :row="item"></slot>
-      </template>
-    </TableTreeRowChild>
   </template>
 </template>

+ 86 - 192
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-body/TableTreeRowChild.vue

@@ -1,8 +1,8 @@
 <script setup lang="ts">
 import { ref, onMounted, computed } from "vue"
 import type { Header } from "@/components/table/table-partials/models"
-import TableTreeRow from "./TableTreeRow.vue"
-import configs from "@/core/config"
+import TableTreeRowChild from "./TableTreeRow.vue"
+import TableBodyTd from "./TableBodyTd.vue"
 
 const props = withDefaults(
   defineProps<{
@@ -10,7 +10,6 @@ const props = withDefaults(
     row: any
     depth?: number
     expandDepth?: number
-    currentlySelectedItems?: Array<any>
     hasCheckbox?: boolean //是否有选择框
     checkMultiple?: boolean //是否多选
     checkboxField?: string //选择框字段
@@ -21,6 +20,8 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    isLazy?: boolean
   }>(),
   {
     checkboxField: "id",
@@ -28,19 +29,21 @@ const props = withDefaults(
     parentField: "parent_id",
     childrenField: "children",
     iconField: "name",
+    leafField: "isLeaf",
     depth: 0,
     expandDepth: 0,
     intervalLeft: 10,
   }
 )
 const emits = defineEmits<{
-  (e: "on-change", isChecked: boolean, v: any, row: any): void
-  (e: "update:currentlySelectedItems", v: any): void
+  (e: "on-change", isChecked: boolean, selectedValue: string, row: any): void
 }>()
-const selectedItems = ref<Array<any>>([])
+
 const isExpand = computed(() => {
-  return props.expandDepth > props.depth
+  return props.isLazy ? true : props.expandDepth > props.depth
 })
+
+const show = ref(true)
 const hasChildren = computed(() => {
   return props.row[props.childrenField] && props.row[props.childrenField].length
 })
@@ -50,47 +53,17 @@ const trClass = computed(() => {
   if (hasChildren.value) {
     _trClass += `hasChildren ${isExpand.value ? "tr-expand" : "tr-collapse"} `
   }
-  _trClass += props.depth > props.expandDepth ? "hide" : "show"
+  _trClass += !props.isLazy && props.depth > props.expandDepth ? "hide" : "show"
   return _trClass
 })
-const tooltip = (col: Header) => {
-  if (typeof col.tooltip == "string") {
-    return col.tooltip
-  } else if (col.tooltip) {
-    return "primary"
-  }
-  return undefined
-}
-const tdStyle = (column: Header) => {
-  const style: any = {}
-  if (column.align) {
-    style.textAlign = column.align
-  }
-  if (column.field == props.iconField) {
-    style.textAlign = "left"
-  }
-  return style
-}
-const tdClass = (column: Header) => {
-  let classStr = ""
-  if (column.tdClass) {
-    classStr += column.tdClass
-  }
-  if (column.field == props.iconField) {
-    classStr += " tree-icon"
-  }
-  return classStr
-}
+
 const onChange = (event: Event) => {
   const target = event.target as HTMLInputElement
-  selectedItems.value = props.checkMultiple ? selectedItems.value : target.checked ? [target.value] : []
-  // const row = props.data.find((v: any) => {
-  //   return v[props.checkboxField] == target.value
-  // })
-  emits("on-change", target.checked, selectedItems.value, props.row)
-  emits("update:currentlySelectedItems", selectedItems.value)
+  emits("on-change", target.checked, target.value, props.row)
+}
+const onSelectItemsChange = (isChecked: boolean, selectedValue: string, row: any) => {
+  emits("on-change", isChecked, selectedValue, row)
 }
-
 function init() {
   //console.log("TREE_ROW", props.row)
 }
@@ -100,159 +73,80 @@ onMounted(() => {
 })
 </script>
 <template>
-  <tr :class="trClass" :id="`tr_${row[keyField]}`" :data-parent="`tr_${row[parentField]}`">
-    <td v-if="hasCheckbox">
-      <div class="form-check form-check-sm form-check-custom form-check-solid">
-        <input
-          class="form-check-input"
-          type="checkbox"
-          :value="row[checkboxField]"
-          v-model="selectedItems"
-          @change="onChange"
-        />
-      </div>
-    </td>
-    <template v-for="(column, i) in header" :key="i">
-      <td
-        v-if="row[column.field + props.rowSpanSuffix]"
-        :style="tdStyle(column)"
-        :class="tdClass(column)"
-        :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
-      >
-        <!-- <span
-          v-if="column.field == iconField"
-          class="icon"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        ></span> -->
-        <span
-          v-if="column.field == iconField"
-          class="icon me-2"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        >
-          <template v-if="hasChildren">
-            <KTIcon
-              v-if="isExpand"
-              icon-name="minus-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-            <KTIcon
-              v-else
-              icon-name="add-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-          <template v-else>
-            <KTIcon
-              icon-name="folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-        </span>
-        <template v-if="$slots[column.field]">
-          <slot :name="`${column.field}`" :row="row">
-            {{ row }}
-          </slot>
-        </template>
-        <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
-          {{ i + 1 }}
-        </template>
-        <template v-else-if="tooltip(column)">
-          <vb-tooltip
-            :effect="tooltip(column)"
-            :content="row[column.field]"
-            :auto-hide="true"
-            :delay="500"
-          ></vb-tooltip>
-        </template>
-        <template v-else>
-          {{ row[column.field] }}
-        </template>
+  <template v-if="show">
+    <tr :class="trClass" :id="`tr_${row[keyField]}`" :data-parent="`tr_${row[parentField]}`">
+      <td v-if="hasCheckbox" class="check-box">
+        <div class="form-check form-check-sm form-check-custom form-check-solid">
+          <input class="form-check-input" type="checkbox" :value="row[checkboxField]" @change="onChange" />
+        </div>
       </td>
-      <td v-else-if="row[column.field + props.rowSpanSuffix] != 0" :style="tdStyle(column)" :class="tdClass(column)">
-        <!-- <span
-          v-if="column.field == iconField"
-          class="icon"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        ></span> -->
-        <span
-          v-if="column.field == iconField"
-          class="icon me-2"
-          :style="`margin-left: ${intervalLeft * depth}px!important`"
-        >
-          <template v-if="hasChildren">
-            <KTIcon
-              v-if="isExpand"
-              icon-name="minus-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-            <KTIcon
-              v-else
-              icon-name="add-folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-          <template v-else>
-            <KTIcon
-              icon-name="folder"
-              icon-type="duotone"
-              class="fs-2 text-primary"
-              style="transform: translateY(3px)"
-            ></KTIcon>
-          </template>
-        </span>
-        <template v-if="$slots[column.field]">
-          <slot :name="`${column.field}`" :row="row">
-            {{ row }}
-          </slot>
+      <template v-for="(column, i) in header" :key="i">
+        <template v-if="row[column.field + props.rowSpanSuffix]">
+          <TableBodyTd
+            :row="row"
+            :column="column"
+            :index="i + 1"
+            :is-tree="true"
+            :isExpand="isExpand"
+            :depth="depth"
+            :interval-left="intervalLeft"
+            :icon-field="iconField"
+            :leaf-field="leafField"
+            :is-lazy="isLazy"
+            :has-children="hasChildren"
+            :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
+          >
+            <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+              <slot :name="name" :row="item"></slot>
+            </template>
+          </TableBodyTd>
         </template>
-        <template v-else-if="column.field == configs.TABLE_INDEX_FIELD">
-          {{ i + 1 }}
+        <template v-else-if="row[column.field + props.rowSpanSuffix] != 0">
+          <TableBodyTd
+            :row="row"
+            :column="column"
+            :index="i + 1"
+            :is-tree="true"
+            :isExpand="isExpand"
+            :depth="depth"
+            :interval-left="intervalLeft"
+            :icon-field="iconField"
+            :leaf-field="leafField"
+            :has-children="hasChildren"
+            :is-lazy="isLazy"
+          >
+            <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+              <slot :name="name" :row="item"></slot>
+            </template>
+          </TableBodyTd>
         </template>
-        <template v-else-if="tooltip(column)">
-          <vb-tooltip
-            :effect="tooltip(column)"
-            :content="row[column.field]"
-            :auto-hide="true"
-            :delay="500"
-          ></vb-tooltip>
-        </template>
-        <template v-else>
-          {{ row[column.field] }}
+      </template>
+    </tr>
+    <template v-if="hasChildren">
+      <TableTreeRowChild
+        v-for="(child, i) in row[props.childrenField]"
+        :key="i"
+        :row="child"
+        :header="header"
+        :depth="depth + 1"
+        :expand-depth="expandDepth"
+        :has-checkbox="hasCheckbox"
+        :checkbox-field="checkboxField"
+        :td-tr-class="tdTrClass"
+        :row-span-suffix="rowSpanSuffix"
+        :icon-field="iconField"
+        :key-field="keyField"
+        :check-multiple="checkMultiple"
+        :parent-field="parentField"
+        :children-field="childrenField"
+        :leaf-field="leafField"
+        :is-lazy="isLazy"
+        @on-change="onSelectItemsChange"
+      >
+        <template v-for="(_, name) in $slots" #[name]="{ row }">
+          <slot :name="name" :row="row"></slot>
         </template>
-      </td>
+      </TableTreeRowChild>
     </template>
-  </tr>
-  <template v-if="hasChildren">
-    <TableTreeRow
-      v-for="(child, i) in row[props.childrenField]"
-      :key="i"
-      :row="child"
-      :header="header"
-      :depth="depth + 1"
-      :expand-depth="expandDepth"
-      :currently-selected-items="currentlySelectedItems"
-      :has-checkbox="hasCheckbox"
-      :checkbox-field="checkboxField"
-      :td-tr-class="tdTrClass"
-      :row-span-suffix="rowSpanSuffix"
-      :icon-field="iconField"
-      :key-field="keyField"
-      :parent-field="parentField"
-      :children-field="childrenField"
-    >
-      <template v-for="(_, name) in $slots" #[name]="{ row: item }">
-        <slot :name="name" :row="item"></slot>
-      </template>
-    </TableTreeRow>
   </template>
 </template>

+ 10 - 40
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-fixed/TableFixed.vue

@@ -9,8 +9,8 @@ const props = withDefaults(
     table: any
     header: Array<Header>
     data: Array<any>
-    selectedItems: Array<any>
     fixedNumber: number
+    checkAll?: boolean //是否全部选中
     hasCheckbox?: boolean //是否有选择框
     checkboxField?: string //选择框字段
     checkMultiple?: boolean //是否多选
@@ -31,6 +31,8 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    lazyLoad?: (v: string) => void
   }>(),
   {
     hasCheckbox: true,
@@ -45,37 +47,18 @@ const props = withDefaults(
 const emits = defineEmits<{
   (e: "on-sort", v: Sort): void
   (e: "on-select-all", v: any): void
-  (e: "update:selectedItems", v: Array<any>): void
   (e: "on-sort", v: Sort): void
-  (e: "on-change", isChecked: boolean, v: any, row: any): void
+  (e: "on-change", isChecked: boolean, selectedValue: string, row: any): void
   (e: "on-items-all-change", isChecked: boolean, rows: Array<any>): void
 }>()
 const fixedNum = ref(props.hasCheckbox ? props.fixedNumber + 1 : props.fixedNumber)
 const tableBox = ref()
-const selectedItems = ref(props.selectedItems)
-
-const allSelectedItems = ref<Array<unknown>>([])
-const check = ref<boolean>(false)
 
 const onSelectAll = (checked: any) => {
-  check.value = checked
-  if (checked) {
-    selectedItems.value = [...new Set([...selectedItems.value, ...allSelectedItems.value])]
-  } else {
-    selectedItems.value = []
-  }
-  emits("on-select-all", check.value)
+  emits("on-select-all", checked)
 }
-const onSelectItemsChange = (isChecked: boolean, v: any, row: any) => {
-  emits("update:selectedItems", v)
-  selectedItems.value = []
-  v.forEach((item: any) => {
-    if (!selectedItems.value.includes(item)) selectedItems.value.push(item)
-  })
-  check.value =
-    Array.from(new Set([...selectedItems.value, ...allSelectedItems.value])).length ==
-    Array.from(new Set([...selectedItems.value])).length
-  emits("on-change", isChecked, v, row)
+const onSelectItemsChange = (isChecked: boolean, selectedValue: string, row: any) => {
+  emits("on-change", isChecked, selectedValue, row)
 }
 const onSort = (v: Sort) => {
   emits("on-sort", v)
@@ -89,20 +72,6 @@ function onScroll() {
     }
   }
 }
-watch(
-  () => props.data,
-  () => {
-    selectedItems.value = props.multiplePageCheck ? selectedItems.value : []
-    allSelectedItems.value = []
-    check.value = false
-    props.data.forEach((item: any) => {
-      if (item[props.checkboxField]) {
-        allSelectedItems.value.push(item[props.checkboxField])
-      }
-    })
-    //console.log("allSelectedItems:", allSelectedItems.value)
-  }
-)
 
 watch(
   () => props.table,
@@ -137,7 +106,7 @@ onBeforeUnmount(() => {
         v-else
         @on-sort="onSort"
         @on-select-all="onSelectAll"
-        :checkbox-all-value="check"
+        :check-all="checkAll"
         :has-checkbox="hasCheckbox"
         :check-multiple="checkMultiple"
         :sort-field="sortField"
@@ -153,7 +122,6 @@ onBeforeUnmount(() => {
       <TableBodyRow
         v-if="data.length !== 0"
         @on-change="onSelectItemsChange"
-        v-model:currently-selected-items="selectedItems"
         :check-multiple="checkMultiple"
         :data="data"
         :header="header"
@@ -168,7 +136,9 @@ onBeforeUnmount(() => {
         :key-field="keyField"
         :children-field="childrenField"
         :parent-field="parentField"
+        :leaf-field="leafField"
         :expand-depth="expandDepth"
+        :lazy-load="lazyLoad"
       >
         <template v-for="(_, name) in $slots" v-slot:[name]="{ row: item }">
           <slot v-if="!name.toString().endsWith('_header')" :name="name" :row="item" />

+ 4 - 0
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-fixed/TableRightFixed.vue

@@ -26,6 +26,8 @@ const props = withDefaults(
     keyField?: string
     parentField?: string
     childrenField?: string
+    leafField?: string
+    lazyLoad?: (v: string) => void
   }>(),
   {
     hasCheckbox: true,
@@ -117,7 +119,9 @@ onBeforeUnmount(() => {
         :key-field="keyField"
         :children-field="childrenField"
         :parent-field="parentField"
+        :leaf-field="leafField"
         :expand-depth="expandDepth"
+        :lazy-load="lazyLoad"
       >
         <template v-for="(_, name) in $slots" v-slot:[name]="{ row: item }">
           <slot v-if="!name.toString().endsWith('_header')" :name="name" :row="item" />

+ 8 - 26
UI/VA.Vue_V1.0/src/components/table/table-partials/table-content/table-head/TableHeadRow.vue

@@ -1,10 +1,9 @@
 <script setup lang="ts">
-import { ref, watch } from "vue"
 import type { Sort, Header } from "@/components/table/table-partials/models"
 const props = withDefaults(
   defineProps<{
     header: Array<Header>
-    checkboxAllValue?: boolean
+    checkAll?: boolean
     hasCheckbox?: boolean //是否有选择框
     checkMultiple?: boolean //是否多选
     sortField?: string //排序字段
@@ -16,7 +15,7 @@ const props = withDefaults(
     thTrClass?: string
   }>(),
   {
-    checkboxAllValue: false,
+    checkAll: false,
     hasCheckbox: true,
     checkMultiple: true,
     sortOrder: "asc",
@@ -32,19 +31,15 @@ const emits = defineEmits<{
   (e: "on-select-all", v: any): void
 }>()
 
-const checked = ref<boolean>(false)
+const { checkAll } = toRefs(props)
 const columnFieldAndOrder = ref<Sort>({
   label: props.sortField,
   order: props.sortOrder,
 })
-watch(
-  () => props.checkboxAllValue,
-  (currentValue) => {
-    checked.value = currentValue
-  }
-)
-const selectAll = () => {
-  emits("on-select-all", checked.value)
+
+const onChange = (event: Event) => {
+  const target = event.target as HTMLInputElement
+  emits("on-select-all", target.checked)
 }
 const onSort = (label?: string, sortEnabled?: boolean) => {
   if (sortEnabled) {
@@ -63,13 +58,6 @@ const onSort = (label?: string, sortEnabled?: boolean) => {
     emits("on-sort", columnFieldAndOrder.value)
   }
 }
-// const sortArrow = computed(() => {
-//   return columnFieldAndOrder.value.order === "asc"
-//     ? "&#x2191;"
-//     : columnFieldAndOrder.value.order === "desc"
-//     ? "&#x2193;"
-//     : ""
-// })
 
 const thStyle = (column: Header) => {
   const style: any = {
@@ -106,13 +94,7 @@ const convertHeader = (col: Header): any => {
     <tr class="text-uppercase gs-0" :class="thTrClass">
       <th v-if="hasCheckbox" :class="thClass()" :style="{ width: '40px', textAlign: 'center' }">
         <div class="form-check form-check-sm form-check-custom form-check-solid">
-          <input
-            v-if="checkMultiple"
-            class="form-check-input"
-            type="checkbox"
-            v-model="checked"
-            @change="selectAll()"
-          />
+          <input v-if="checkMultiple" class="form-check-input" type="checkbox" v-model="checkAll" @change="onChange" />
         </div>
       </th>
       <template v-for="(column, i) in header" :key="i">

+ 1 - 163
UI/VA.Vue_V1.0/src/components/table/table-partials/table-toolbar/TableLeftToolbar.vue

@@ -4,39 +4,9 @@ import type { ToolBtn } from "@/components/table/table-partials/models"
 const props = withDefaults(
   defineProps<{
     selectedRows: number
-    // modalFormRowItems?: Array<VbFormRowItem>
-    // modalFormItems?: Array<VbFormItem>
-    // modalFormSpan?: number
-    // btnCreatePerm?: string
-    // btnEditPerm?: string
-    // btnDeletePerm?: string
-    // btnImportPerm?: string
-    // btnExportPerm?: string
-    // btnCreateShow?: boolean
-    // btnEditShow?: boolean
-    // btnDeleteShow?: boolean
-    // btnImportShow?: boolean
-    // btnExportShow?: boolean
-    // btnCreateFun?: () => void
-    // btnEditFun?: () => void
-    // btnDeleteFun?: () => void
-    // btnImportFun?: () => void
-    // btnExportFun?: () => void
-    // btnCreateDisabledFun?: (selectedRows: number) => boolean
-    // btnEditDisabledFun?: (selectedRows: number) => boolean
-    // btnDeleteDisabledFun?: (selectedRows: number) => boolean
-    // btnImportDisabledFun?: (selectedRows: number) => boolean
-    // btnExportDisabledFun?: (selectedRows: number) => boolean
-    // toolBtns?: DefaultToolBtns
     customBtns?: Array<ToolBtn>
   }>(),
-  {
-    // btnCreateShow: true,
-    // btnEditShow: true,
-    // btnDeleteShow: true,
-    // btnImportShow: true,
-    // btnExportShow: true,
-  }
+  {}
 )
 const { selectedRows } = toRefs(props)
 const defaultBtn: ToolBtn = {
@@ -47,146 +17,14 @@ const defaultBtn: ToolBtn = {
   //iconType: "component",
   //icon: `<KTIcon icon-name="plus-square" icon-type="duotone"></KTIcon>`,
 }
-// const defaultToolBtns: DefaultToolBtns = {
-//   create: {
-//     key: "create",
-//     name: "新增",
-//     show: props.btnCreateShow,
-//     permission: props.btnCreatePerm ?? defaultBtn.permission,
-//     clickFun: () => {
-//       if (props.btnCreateFun) {
-//         props.btnCreateFun()
-//       }
-//     },
-//     btnClass: "btn btn-light-primary",
-//     iconType: "class",
-//     icon: "bi bi-plus-square me-1",
-//     // iconType: "component",
-//     // icon: {
-//     //   name: "KTIcon",
-//     //   attr: {
-//     //     iconName: "plus-square",
-//     //     iconType: "duotone",
-//     //     class: "fs-4 me-1",
-//     //   },
-//     // },
-//   },
-//   edit: {
-//     key: "edit",
-//     name: "修改",
-//     show: props.btnEditShow,
-//     permission: props.btnEditPerm ?? defaultBtn.permission,
-//     clickFun: () => {
-//       if (props.btnEditFun) {
-//         props.btnEditFun()
-//       }
-//     },
-//     disabledFun: (v: number) => v != 1,
-//     btnClass: "btn btn-light-success",
-//     iconType: "class",
-//     icon: "bi bi-pencil-square me-1",
-
-//     // iconType: "component",
-//     // icon: {
-//     //   name: "KTIcon",
-//     //   attr: {
-//     //     iconName: "message-edit",
-//     //     iconType: "duotone",
-//     //     class: "fs-4 me-1",
-//     //   },
-//     // },
-//   },
-//   delete: {
-//     key: "delete",
-//     name: "删除",
-//     show: props.btnDeleteShow,
-//     permission: props.btnDeletePerm ?? defaultBtn.permission,
-//     clickFun: () => {
-//       if (props.btnDeleteFun) {
-//         props.btnDeleteFun()
-//       }
-//     },
-//     disabledFun: (v: number) => v == 0,
-//     btnClass: "btn btn-light-danger",
-//     iconType: "class",
-//     icon: "bi bi-dash-square me-1",
-//     // iconType: "component",
-//     // icon: {
-//     //   name: "KTIcon",
-//     //   attr: {
-//     //     iconName: "minus-square",
-//     //     iconType: "duotone",
-//     //     class: "fs-4 me-1",
-//     //   },
-//     // },
-//   },
-//   import: {
-//     key: "import",
-//     name: "导入",
-//     show: props.btnImportShow,
-//     permission: props.btnImportPerm ?? defaultBtn.permission,
-//     clickFun: () => {
-//       if (props.btnImportFun) {
-//         props.btnImportFun()
-//       }
-//     },
-//     btnClass: "btn btn-light-warning",
-//     iconType: "class",
-//     icon: "bi bi-cloud-upload me-1",
-//     // iconType: "component",
-//     // icon: {
-//     //   name: "KTIcon",
-//     //   attr: {
-//     //     iconName: "cloud-add",
-//     //     iconType: "duotone",
-//     //     class: "fs-4 me-1",
-//     //   },
-//     // },
-//   },
-//   export: {
-//     key: "export",
-//     name: "导出",
-//     show: props.btnImportShow,
-//     permission: props.btnImportPerm ?? defaultBtn.permission,
-//     clickFun: () => {
-//       if (props.btnExportFun) {
-//         props.btnExportFun()
-//       }
-//     },
-//     disabledFun: (v: number) => v == 0,
-//     btnClass: "btn btn-light-info",
-//     iconType: "class",
-//     icon: "bi bi-cloud-download me-1",
-//     // iconType: "component",
-//     // icon: {
-//     //   name: "KTIcon",
-//     //   attr: {
-//     //     iconName: "cloud-download",
-//     //     iconType: "duotone",
-//     //     class: "fs-4 me-1",
-//     //   },
-//     // },
-//   },
-// }
 
 const btns = computed(() => {
-  //console.log("2", defaultToolBtns)
   const btns: Array<ToolBtn> = []
-  // if (props.toolBtns?.show || props.toolBtns?.show == undefined) {
-  //   Object.keys(defaultToolBtns).forEach((v) => {
-  //     let btn = Object.assign({}, defaultBtn, defaultToolBtns[v])
-  //     if (props.toolBtns && props.toolBtns[v]) {
-  //       btn = Object.assign(btn, props.toolBtns[v])
-  //     }
-  //     btns.push(btn)
-  //   })
-  // }
 
   props.customBtns?.forEach((v) => {
     const btn = Object.assign({}, defaultBtn, v)
     btns.push(btn)
   })
-  //console.log("BTNs", btns)
   return btns
 })
 function isCustomBtnSlot(v: string | number): boolean {

+ 0 - 42
UI/VA.Vue_V1.0/src/components/table/table-partials/table-toolbar/TableToolbar.vue

@@ -17,27 +17,6 @@ const props = withDefaults(
     searchFormSpan?: number
     resetSearchFormFun?: () => void
     queryTable?: () => void
-    // btnCreatePerm?: string
-    // btnEditPerm?: string
-    // btnDeletePerm?: string
-    // btnImportPerm?: string
-    // btnExportPerm?: string
-    // btnCreateShow?: boolean
-    // btnEditShow?: boolean
-    // btnDeleteShow?: boolean
-    // btnImportShow?: boolean
-    // btnExportShow?: boolean
-    // btnCreateFun?: () => void
-    // btnEditFun?: () => void
-    // btnDeleteFun?: () => void
-    // btnImportFun?: () => void
-    // btnExportFun?: () => void
-    // btnCreateDisabledFun?: (selectedRows: number) => boolean
-    // btnEditDisabledFun?: (selectedRows: number) => boolean
-    // btnDeleteDisabledFun?: (selectedRows: number) => boolean
-    // btnImportDisabledFun?: (selectedRows: number) => boolean
-    // btnExportDisabledFun?: (selectedRows: number) => boolean
-    // toolBtns?: DefaultToolBtns
     customBtns?: Array<ToolBtn>
   }>(),
   {
@@ -54,27 +33,6 @@ function customSearch() {
 }
 </script>
 <template>
-  <!-- :toolBtns="toolBtns"
-          :btnCreateShow="btnCreateShow"
-          :btnEditShow="btnEditShow"
-          :btnDeleteShow="btnDeleteShow"
-          :btnImportShow="btnImportShow"
-          :btnExportShow="btnExportShow"
-          :btnCreatePerm="btnCreatePerm"
-          :btnEditPerm="btnEditPerm"
-          :btnDeletePerm="btnDeletePerm"
-          :btnImportPerm="btnImportPerm"
-          :btnExportPerm="btnExportPerm"
-          :btnCreateFun="btnCreateFun"
-          :btnEditFun="btnEditFun"
-          :btnDeleteFun="btnDeleteFun"
-          :btnImportFun="btnImportFun"
-          :btnExportFun="btnExportFun"
-          :btnCreateDisabledFun="btnCreateDisabledFun"
-          :btnEditDisabledFun="btnEditDisabledFun"
-          :btnDeleteDisabledFun="btnDeleteDisabledFun"
-          :btnImportDisabledFun="btnImportDisabledFun"
-          :btnExportDisabledFun="btnExportDisabledFun" -->
   <div class="table-tool" :gutter="10">
     <transition-group name="fade">
       <TableSearchFrom

+ 20 - 7
UI/VA.Vue_V1.0/src/views/system/dept/index.vue

@@ -51,6 +51,16 @@ const opts = reactive({
     },
   ],
   permission: permissionNames.SystemDept,
+  handleBtns: [
+    {
+      key: "handleUpdate",
+      show: false,
+    },
+    {
+      key: "handleDelete",
+      show: false,
+    },
+  ],
   handleFuns: {
     handleCreate,
   },
@@ -117,12 +127,13 @@ function handleCreate(row?: any) {
 /** 修改按钮操作 */
 function handleUpdate(row: any) {
   reset()
-  const _deptId = row.deptId
-  apis.system.deptApi.getDept(_deptId).then((res: any) => {
-    form.value = res.data
-    modalRef.value.changePrefixTitle("修改")
-    modalRef.value.show()
-  })
+  if (row.deptId) {
+    apis.system.deptApi.getDept(row.deptId).then((res: any) => {
+      form.value = res.data
+      modalRef.value.changePrefixTitle("修改")
+      modalRef.value.show()
+    })
+  }
 }
 function getTreeselect() {
   deptOptions.value = []
@@ -185,15 +196,17 @@ function getTableData(q: any) {
       :no-page="true"
       :expand-depth="1"
       :interval-left="10"
+      :check-multiple="false"
+      :has-checkbox="true"
       :show-right-column-btn="false"
       :handle-perm="opts.permission"
+      :handle-btns="opts.handleBtns"
       :handle-funs="opts.handleFuns"
       :search-form-items="opts.searchFormItems"
       :header="opts.columns"
       :custom-btns="opts.customBtns"
       :remote-fun="opts.tableListFun"
       :query-params="queryParams"
-      :has-checkbox="false"
       :reset-search-form-fun="resetQuery"
       :custom-search-fun="handleQuery"
     >

+ 33 - 16
UI/VA.Vue_V1.0/src/views/system/menu/index.vue

@@ -70,11 +70,22 @@ const opts = reactive({
     },
   ],
   permission: permissionNames.SystemMenu,
+  handleBtns: [
+    {
+      key: "handleUpdate",
+      show: false,
+    },
+    {
+      key: "handleDelete",
+      show: false,
+    },
+  ],
   handleFuns: {
     handleCreate,
   },
   customBtns: [],
-  tableListFun: getTableData,
+  //tableListFun: getTableData,
+  tableListFun: apis.system.menuApi.listChildren,
   getEntityFun: apis.system.menuApi.getMenu,
   deleteEntityFun: apis.system.menuApi.delMenu,
   modalTitle: "菜单",
@@ -137,12 +148,13 @@ function handleCreate(row: any) {
 /** 修改按钮操作 */
 function handleUpdate(row: any) {
   reset()
-  const _menuId = row.menuId
-  apis.system.menuApi.getMenu(_menuId).then((res: any) => {
-    form.value = res.data
-    modalRef.value.changePrefixTitle("修改")
-    modalRef.value.show()
-  })
+  if (row.menuId) {
+    apis.system.menuApi.getMenu(row.menuId).then((res: any) => {
+      form.value = res.data
+      modalRef.value.changePrefixTitle("修改")
+      modalRef.value.show()
+    })
+  }
 }
 function getTreeselect() {
   menuOptions.value = []
@@ -212,14 +224,14 @@ function defaultBtnChange(v: any) {
   }
 }
 
-function getTableData(q: any) {
-  return new Promise((resolve) => {
-    apis.system.menuApi.listMenu(q).then((res) => {
-      res.data = handleTree(res.data, "menuId")
-      resolve(res)
-    })
-  })
-}
+// function getTableData(q: any) {
+//   return new Promise((resolve) => {
+//     apis.system.menuApi.listMenu(q).then((res) => {
+//       res.data = handleTree(res.data, "menuId")
+//       resolve(res)
+//     })
+//   })
+// }
 
 const showChooseIcon = ref(false)
 const iconSelectRef = ref()
@@ -251,20 +263,25 @@ function hideSelectIcon(event: any) {
       iconField="menuName"
       parentField="parentId"
       childrenField="children"
+      leaf-field="remark"
+      root-id="0"
+      :check-multiple="false"
+      :has-checkbox="true"
       :no-page="true"
       :expand-depth="1"
       :interval-left="10"
       :show-right-column-btn="false"
       :handle-perm="opts.permission"
+      :handle-btns="opts.handleBtns"
       :handle-funs="opts.handleFuns"
       :search-form-items="opts.searchFormItems"
       :header="opts.columns"
       :custom-btns="opts.customBtns"
       :remote-fun="opts.tableListFun"
       :query-params="queryParams"
-      :check-multiple="true"
       :reset-search-form-fun="resetQuery"
       :custom-search-fun="handleQuery"
+      :is-lazy="true"
     >
       <template #icon="{ row }">
         <i :class="`fs-4 text-primary bi bi-${row.icon}`"></i>

+ 1 - 0
UI/VA.Vue_V1.0/src/views/system/post/index.vue

@@ -207,6 +207,7 @@ const formItems = ref([
       v-model:form-data="form"
       :query-params="queryParams"
       :check-multiple="true"
+      :has-checkbox="true"
       :reset-search-form-fun="resetQuery"
       :custom-search-fun="handleQuery"
     >