Jack Zhou 1 сар өмнө
parent
commit
3ea31d43c8

+ 3 - 1
src/api/index.ts

@@ -7,6 +7,7 @@ import * as notificationMessage from './module/notificationMessage'
 import * as system from './module/system'
 import * as system from './module/system'
 import * as AIRobot from './module/AIRobot'
 import * as AIRobot from './module/AIRobot'
 import * as Delivery from './module/Delivery'
 import * as Delivery from './module/Delivery'
+import * as report from './module/report'
 /**
 /**
  * api 对象接口定义
  * api 对象接口定义
  */
  */
@@ -27,7 +28,8 @@ const apis = generateApiMap({
   ...notificationMessage,
   ...notificationMessage,
   ...system,
   ...system,
   ...AIRobot,
   ...AIRobot,
-  ...Delivery
+  ...Delivery,
+  ...report
 })
 })
 export default {
 export default {
   ...apis // 取出所有可遍历属性赋值在新的对象上
   ...apis // 取出所有可遍历属性赋值在新的对象上

+ 34 - 0
src/api/module/report.ts

@@ -0,0 +1,34 @@
+import HttpAxios from '@/utils/axios'
+
+const base = import.meta.env.VITE_API_HOST
+const baseUrl = `${base}/main_new_version.php`
+
+/**
+ * 获取report template management表格列数据
+ */
+export const getReportTemplateManagementTable = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'report_config',
+      operate: 'search',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取Report Fields Configuration 列表数据
+ */
+export const getReportFieldsConfiguration = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'report_config',
+      operate: 'report_field_load',
+      ...params
+    },
+    config
+  )
+}

+ 31 - 22
src/views/TemplateManagement/src/TemplateManagement.vue

@@ -6,13 +6,11 @@ import { useRouter } from 'vue-router'
 const router = useRouter()
 const router = useRouter()
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const containerHeight = useCalculatingHeight(document.documentElement, 290, [filterRef])
 const containerHeight = useCalculatingHeight(document.documentElement, 290, [filterRef])
-const searchData = ref({
+const queryData = ref({
   text_search: '',
   text_search: '',
-  request_date_start: '',
-  request_date_end: '',
-  ai_model: '',
-  response_duration_type: '',
-  response_duration_num: null
+  is_active: '',
+  application_scope: '',
+  party_id: ''
 })
 })
 
 
 const aiModelList = [
 const aiModelList = [
@@ -26,25 +24,32 @@ const aiModelList = [
   }
   }
 ]
 ]
 
 
-const comparatorList = [
+const activeOptions = [
   {
   {
-    label: '>=',
-    value: 'thanOrEqual'
+    label: 'Yes',
+    value: 't'
   },
   },
   {
   {
-    label: '=',
-    value: 'equal'
+    label: 'No',
+    value: 'f'
+  }
+]
+
+const applicationScopeOptions = [
+  {
+    label: 'All Users',
+    value: 'all'
   },
   },
   {
   {
-    label: '<=',
-    value: 'lessOrEqual'
+    label: 'Specific Users',
+    value: 'specific'
   }
   }
 ]
 ]
 
 
 const tableRef = ref()
 const tableRef = ref()
 
 
 const Search = () => {
 const Search = () => {
-  tableRef.value.SearchOperationLog(searchData.value)
+  tableRef.value.SearchOperationLog(queryData.value)
 }
 }
 
 
 const handleCreate = () => {
 const handleCreate = () => {
@@ -67,7 +72,7 @@ const handleCreate = () => {
         <div class="input-tips_filter">
         <div class="input-tips_filter">
           <el-input
           <el-input
             placeholder="Search report name"
             placeholder="Search report name"
-            v-model="searchData.text_search"
+            v-model="queryData.text_search"
             class="log_input"
             class="log_input"
           >
           >
             <template #prefix>
             <template #prefix>
@@ -81,27 +86,31 @@ const handleCreate = () => {
         </div>
         </div>
 
 
         <div class="tips_filter">
         <div class="tips_filter">
-          <el-select v-model="searchData.ai_model" clearable placeholder="Is Active">
+          <el-select v-model="queryData.is_active" clearable placeholder="Is Active">
             <el-option
             <el-option
-              v-for="item in aiModelList"
-              :key="item.value"
+              v-for="item in activeOptions"
+              :key="item.label"
               :label="item.label"
               :label="item.label"
               :value="item.value"
               :value="item.value"
             />
             />
           </el-select>
           </el-select>
         </div>
         </div>
         <div class="tips_filter">
         <div class="tips_filter">
-          <el-select v-model="searchData.ai_model" clearable placeholder="Application Scope">
+          <el-select
+            v-model="queryData.application_scope"
+            clearable
+            placeholder="Application Scope"
+          >
             <el-option
             <el-option
-              v-for="item in aiModelList"
-              :key="item.value"
+              v-for="item in applicationScopeOptions"
+              :key="item.label"
               :label="item.label"
               :label="item.label"
               :value="item.value"
               :value="item.value"
             />
             />
           </el-select>
           </el-select>
         </div>
         </div>
         <div class="tips_filter">
         <div class="tips_filter">
-          <el-select v-model="searchData.ai_model" clearable placeholder="Party ID">
+          <el-select v-model="queryData.party_id" clearable placeholder="Party ID">
             <el-option
             <el-option
               v-for="item in aiModelList"
               v-for="item in aiModelList"
               :key="item.value"
               :key="item.value"

+ 27 - 22
src/views/TemplateManagement/src/components/CreateReportTemplate/src/CreateReportTemplate.vue

@@ -3,6 +3,7 @@ import { useRouter } from 'vue-router'
 import partyIDSelect from './components/partyIDSelect.vue'
 import partyIDSelect from './components/partyIDSelect.vue'
 import GroupNameSelect from './components/GroupNameSelect.vue'
 import GroupNameSelect from './components/GroupNameSelect.vue'
 import { VueDraggable } from 'vue-draggable-plus'
 import { VueDraggable } from 'vue-draggable-plus'
+import AdjustmentField from './components/AdjustmentField.vue'
 
 
 const router = useRouter()
 const router = useRouter()
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const filterRef: Ref<HTMLElement | null> = ref(null)
@@ -41,39 +42,40 @@ interface Field {
   isSort: boolean
   isSort: boolean
 }
 }
 const fieldsList = ref<Field[]>([])
 const fieldsList = ref<Field[]>([])
+const levelOptions = [
+  {
+    label: 'Shipment level',
+    value: 'Shipment level'
+  },
+  {
+    label: 'Container Level',
+    value: 'Container Level'
+  },
+  {
+    label: 'Item Level',
+    value: 'Item Level'
+  }
+]
 
 
 const handleDeleteField = (field: string) => {
 const handleDeleteField = (field: string) => {
   fieldsList.value = fieldsList.value.filter((item) => item.field !== field)
   fieldsList.value = fieldsList.value.filter((item) => item.field !== field)
 }
 }
 
 
-const CustomizeColumnsRef = ref()
+const AdjustmentFieldRef = ref()
 // 打开定制表格弹窗
 // 打开定制表格弹窗
 const handleCustomizeColumns = () => {
 const handleCustomizeColumns = () => {
   const params = {
   const params = {
-    getData: {
-      action: 'ocean_booking',
-      operate: 'setting_display'
-    },
-    saveData: {
-      action: 'ajax',
-      operate: 'save_setting_display',
-      model_name: 'Booking_Search'
-    }
+    serial_no: '',
+    level: infoData.value.reportLevel
   }
   }
-  CustomizeColumnsRef.value.openDialog(
+  AdjustmentFieldRef.value.openDialog(
     params,
     params,
     -220,
     -220,
     'Drag item over to this selection or click "add" icon to show the field on report template list'
     'Drag item over to this selection or click "add" icon to show the field on report template list'
   )
   )
 }
 }
 // 定制表格
 // 定制表格
-const customizeColumns = async () => {
-  await $api.getBookingTableColumns().then((res: any) => {
-    if (res.code === 200) {
-      fieldsList.value = res.data.BookingTableColumns
-    }
-  })
-}
+const customizeColumns = async () => {}
 
 
 const newFieldInfo = ref<{
 const newFieldInfo = ref<{
   name: string
   name: string
@@ -166,9 +168,12 @@ const handleRightRemove = () => {}
                 <span>Report Level</span>
                 <span>Report Level</span>
               </div>
               </div>
               <el-select v-model="infoData.reportLevel" placeholder="Please enter...">
               <el-select v-model="infoData.reportLevel" placeholder="Please enter...">
-                <el-option label="Level 1" value="level1"></el-option>
-                <el-option label="Level 2" value="level2"></el-option>
-                <el-option label="Level 3" value="level3"></el-option>
+                <el-option
+                  v-for="item in levelOptions"
+                  :label="item.label"
+                  :value="item.value"
+                  :key="item.value"
+                ></el-option>
               </el-select>
               </el-select>
             </div>
             </div>
           </div>
           </div>
@@ -309,7 +314,7 @@ const handleRightRemove = () => {}
       </div>
       </div>
     </div>
     </div>
 
 
-    <CustomizeColumns @customize="customizeColumns" ref="CustomizeColumnsRef" />
+    <AdjustmentField @customize="customizeColumns" ref="AdjustmentFieldRef" />
     <el-dialog
     <el-dialog
       class="add-new-field-dialog"
       class="add-new-field-dialog"
       title="Add New Field"
       title="Add New Field"

+ 798 - 0
src/views/TemplateManagement/src/components/CreateReportTemplate/src/components/AdjustmentField.vue

@@ -0,0 +1,798 @@
+<script setup lang="ts">
+import { VueDraggable } from 'vue-draggable-plus'
+import { useRoute } from 'vue-router'
+
+const route = useRoute()
+const dialogVisible = ref(false)
+// search筛选的字段
+const searchColumn = ref('')
+// search筛选的options
+const searchOptions: any = ref()
+
+// 右侧箭头消失所需要translateX的值
+const rightArrowHideDistance = ref(0)
+// 控制tab栏的左右切换箭头
+const handleTabArrow = () => {
+  const parentElement: HTMLElement | null = document.querySelector('.left-all-columns')
+  if (!parentElement) return
+
+  // 左侧切换箭头
+  const leftArrow: HTMLElement | null = parentElement.querySelector('.el-tabs__nav-prev')
+  // 右侧切换箭头
+  const rightArrow: HTMLElement | null = parentElement.querySelector('.el-tabs__nav-next')
+  const targetObserverElement = parentElement.querySelector('.el-tabs__nav')
+
+  if (!targetObserverElement || !leftArrow || !rightArrow) return
+
+  // 创建一个函数来获取 translateX
+  const getTranslateX = () => {
+    const style = window.getComputedStyle(targetObserverElement)
+    const matrix = style.transform
+
+    if (matrix !== 'none' && matrix) {
+      // 提取 matrix 中的 translateX 值
+      const values = matrix.match(/matrix\(([^)]+)\)/)?.[1].split(', ')
+      if (!values) return 0
+      const translateX = parseFloat(values[4])
+      return translateX
+    }
+    return 0 // 如果没有 transform 或 translateX,默认返回 0
+  }
+
+  // 检查并更新箭头显示状态
+  const updateArrowVisibility = () => {
+    const translateX = getTranslateX()
+    if (translateX === 0) {
+      leftArrow.style.display = 'none'
+    } else {
+      leftArrow.style.display = 'inline-block'
+    }
+
+    if (translateX === rightArrowHideDistance.value) {
+      rightArrow.style.display = 'none'
+    } else {
+      rightArrow.style.display = 'inline-block'
+    }
+  }
+
+  // 监听 transitionend 事件,等待动画结束后再获取 translateX 值
+  targetObserverElement.addEventListener('transitionend', (event: any) => {
+    if (event.propertyName === 'transform') {
+      // 只有 transform 动画结束时才触发
+      updateArrowVisibility()
+    }
+  })
+
+  // 初次运行时手动检查一次
+  updateArrowVisibility()
+}
+
+// 筛选选中时滚动到对应的元素
+const handleDocumentClick = (event: any) => {
+  if (!scrollTargetElement.value.contains(event.target)) {
+    scrollTargetElement.value.className = scrollTargetElement.value.className.replace(
+      'search-select-item',
+      ''
+    )
+    scrollTargetElement.value = null
+    document.removeEventListener('click', handleDocumentClick)
+  }
+}
+const scrollTargetElement = ref()
+const scrollToItem = (itemId: string) => {
+  if (activeName.value !== 'All') {
+    activeName.value = 'All'
+  }
+  setTimeout(() => {
+    // 重置
+    if (scrollTargetElement.value) {
+      scrollTargetElement.value.className = scrollTargetElement.value.className.replace(
+        'search-select-item',
+        ''
+      )
+    }
+    // 获取目标元素
+    scrollTargetElement.value = document.querySelector(`[data-field='${itemId}']`)
+    if (scrollTargetElement.value) {
+      // 使用 scrollIntoView 滚动到该元素
+      scrollTargetElement.value.scrollIntoView({ behavior: 'smooth', block: 'center' })
+      scrollTargetElement.value.className += ' search-select-item'
+      // 或者使用自定义滚动
+      // const container = this.$refs.dataContainer
+      // container.scrollTop = targetElement.offsetTop - container.offsetTop
+
+      document.addEventListener('click', handleDocumentClick)
+    }
+  }, 100)
+}
+
+// 系统首次加载时,会有引导操作
+let firstLoad = ref()
+const step1 = ref()
+const open1 = ref(false)
+const isShowStep1 = ref(false)
+const step2 = ref()
+const open2 = ref(false)
+const isShowStep2 = ref(false)
+const handleCloseTour = (stepStr: string) => {
+  if (stepStr === 'step1') {
+    isShowStep1.value = false
+    open1.value = false
+  } else {
+    isShowStep2.value = false
+    open2.value = false
+  }
+  localStorage.setItem('firstLoadCustomizeColumns', 'true')
+  // firstLoad = 'true'
+}
+
+// 左侧选中的tab
+const activeName = ref()
+// 分组列
+const groupColumns: any = ref([])
+// 所有数据
+const allDataCopy: any = ref()
+
+const loading = ref(false)
+// 获取数据
+const getData = async (reset?: string) => {
+  loading.value = true
+  let paramsData: any = { ...params.value.getData }
+  if (reset === 'yes') {
+    paramsData.reset = 'yes'
+  }
+  await $api.getReportFieldsConfiguration(paramsData).then((res: any) => {
+    if (res.code === 200) {
+      // allDataCopy就是所有的数据
+      allDataCopy.value = res.data.GroupColumnsAll
+      groupColumns.value = res.data.GroupColumnsLeft
+      console.log('groupColumns.value', groupColumns.value)
+      activeName.value = allDataCopy.value?.[0]?.name
+      searchOptions.value = res.data.GroupColumnsLeft?.[0]?.children
+      // 右侧选中的数据
+      selectColumns.value = res.data.GroupColumnsRight
+      nextTick(() => {
+        handleTabArrow()
+        // 八秒后关闭引导
+        if (!firstLoad.value) {
+          setTimeout(() => {
+            handleCloseTour('step1')
+            handleCloseTour('step2')
+          }, 8000)
+        }
+      })
+    }
+  })
+  loading.value = false
+}
+
+const params = ref()
+// rightDistance是右侧箭头消失所需要translateX的值
+const openDialog = async (paramsData: Object, rightDistance: number) => {
+  firstLoad.value = localStorage.getItem('firstLoadCustomizeColumns')
+  params.value = paramsData
+  dialogVisible.value = true
+  await getData()
+  rightArrowHideDistance.value = rightDistance
+  nextTick(() => {
+    if (!firstLoad.value) {
+      open1.value = true
+      isShowStep1.value = true
+      open2.value = true
+      isShowStep2.value = true
+    }
+  })
+}
+
+const selectColumns: any = ref([])
+
+// 左侧Icon的显隐
+const hoverAllIcon = ref('')
+// 右侧Icon的显隐
+const hoverSelectIcon = ref('')
+
+const handleAddSelect = (item: any) => {
+  groupColumns.value.forEach((groupItem: any) => {
+    groupItem.children.forEach((child: any, index: number) => {
+      if (child.field === item.field) {
+        groupItem.children.splice(index, 1)
+      }
+    })
+  })
+  selectColumns.value.push(item)
+}
+
+// 从左侧拖拽到右侧时,删除其他分组中相同的数据
+const handleLeftRemove = (e: any) => {
+  if (e.to === e.from) return
+  const curItem = e.data
+  groupColumns.value.forEach((groupItem: any) => {
+    groupItem.children.forEach((child: any, index: number) => {
+      if (child.field === curItem.field) {
+        groupItem.children.splice(index, 1)
+      }
+    })
+  })
+}
+
+// 从右侧拖拽到左侧时,左侧根据分组添加数据
+const handleRightRemove = (e: any) => {
+  if (e.to === e.from) return
+  const curItem = e.data
+  // 获取当前移动项移入到了那一组
+  const curGroup = groupColumns.value.find((item: any) => {
+    return item.name == activeName.value
+  })
+  // 获取当前项应该对应哪一组
+  const originalGroup = allDataCopy.value.find((item: any) => {
+    if (item.name === 'All') {
+      return false
+    }
+    const index = item.children.findIndex((child: any) => {
+      return child.field === curItem.field
+    })
+    return index !== -1
+  })
+
+  if (curGroup.name !== originalGroup?.name && curGroup.name !== 'All') {
+    // 从当前分组中删除移入的数据
+    curGroup.children.forEach((item: any, index: number) => {
+      item.field === curItem.field && curGroup.children.splice(index, 1)
+    })
+    // 在对应分组中添加移入的数据
+    groupColumns.value.forEach((item: any) => {
+      item.name === originalGroup?.name && item.children.push(curItem)
+    })
+    // 添加到All分组里
+    groupColumns.value[0].children.push(curItem)
+  } else if (curGroup.name === 'All') {
+    // 在对应分组中添加移入的数据
+    groupColumns.value.forEach((item: any) => {
+      item.name === originalGroup?.name && item.children.push(curItem)
+    })
+  } else if (curGroup.name === originalGroup?.name) {
+    groupColumns.value[0].children.push(curItem)
+  }
+}
+// 点击右侧的减号删除选中的列,并添加到左侧
+const handleDeleteSelect = (curItem: any) => {
+  selectColumns.value.forEach((item: any, index: number) => {
+    if (item.field === curItem.field) {
+      selectColumns.value.splice(index, 1)
+    }
+  })
+  // 获取当前项应该对应哪一组
+  const originalGroup = allDataCopy.value.find((item: any) => {
+    if (item.name === 'All') {
+      return false
+    }
+    const index = item.children.findIndex((child: any) => {
+      return child.field === curItem.field
+    })
+    return index !== -1
+  })
+  // 在对应分组中添加移入的数据
+  groupColumns.value.forEach((item: any) => {
+    item.name === originalGroup?.name && item.children.push(curItem)
+  })
+  // 添加到All分组里
+  groupColumns.value[0].children.push(curItem)
+}
+
+const handleMoveUpSelect = (item: any) => {
+  const index = selectColumns.value.findIndex((i: any) => i.field === item.field)
+  if (index === 0) return
+  const temp = selectColumns.value[index]
+  selectColumns.value[index] = selectColumns.value[index - 1]
+  selectColumns.value[index - 1] = temp
+}
+const handleMoveDownSelect = (item: any) => {
+  const index = selectColumns.value.findIndex((i: any) => i.field === item.field)
+  if (index === selectColumns.value.length - 1) return
+  const temp = selectColumns.value[index]
+  selectColumns.value[index] = selectColumns.value[index + 1]
+  selectColumns.value[index + 1] = temp
+}
+
+const emits = defineEmits<{
+  customize: []
+  reset: []
+}>()
+const handleReset = () => {
+  getData('yes')
+}
+const handleApply = () => {
+  // const columnsList = selectColumns.value.map((item: any) => {
+  //   return item.ids
+  // })
+  // $api
+  //   .saveTableSettingColumns({
+  //     ...params.value.saveData,
+  //     ids: columnsList
+  //   })
+  //   .then((res: any) => {
+  //     if (res.code === 200) {
+  //       // ElMessage.success('Save successfully')
+  //       emits('customize')
+  //       dialogVisible.value = false
+  //     }
+  //   })
+}
+
+const clearData = () => {
+  open1.value = false
+  open2.value = false
+  activeName.value = ''
+  groupColumns.value = []
+  selectColumns.value = []
+  searchColumn.value = ''
+}
+
+defineExpose({
+  openDialog
+})
+</script>
+
+<template>
+  <el-dialog
+    class="customize-columns"
+    v-model="dialogVisible"
+    :width="1000"
+    title="Add/Edit Field"
+    @close="clearData"
+  >
+    <div class="search-header">
+      <div class="search-input" ref="searchRef">
+        <el-select
+          v-model="searchColumn"
+          @change="scrollToItem"
+          filterable
+          placeholder="Search field"
+        >
+          <template #prefix>
+            <span class="font_family icon-icon_search_b"></span>
+          </template>
+          <el-option
+            v-for="item in searchOptions"
+            :key="item.field"
+            :label="item.label"
+            :value="item.field"
+          />
+        </el-select>
+      </div>
+      <div class="tips">
+        <span style="font-size: 16px">* </span>
+        <span
+          >Drag item over to this selection or click "add" icon to show the field on report template
+          list</span
+        >
+      </div>
+    </div>
+    <div class="draggable-list">
+      <div class="left-all-columns" v-vloading="loading">
+        <div class="tabs">
+          <el-tabs v-model="activeName">
+            <el-tab-pane
+              v-for="groupItem in groupColumns"
+              :key="groupItem.name"
+              :label="groupItem.name"
+              :name="groupItem.name"
+            >
+              <VueDraggable
+                v-model="groupItem.children"
+                class="column-list"
+                ghost-class="ghost-column"
+                :forceFallback="true"
+                fallbackClass="fallback-class"
+                group="customizeColumns"
+                item-key="field"
+                @end="handleLeftRemove"
+              >
+                <template v-for="(item, index) in groupItem.children" :key="item.field">
+                  <div
+                    :data-field="item.field"
+                    class="column-item"
+                    @mouseenter="hoverAllIcon = item.field"
+                    @mouseleave="hoverAllIcon = ''"
+                  >
+                    <span class="font_family icon-icon_dragsort__b draggable-icon"></span>
+                    <span class="title">{{ item.label }}</span>
+                    <span
+                      ref="step1"
+                      v-if="hoverAllIcon === item.field || (index === 0 && isShowStep1)"
+                      class="font_family icon-icon_add_b move-icon"
+                      @click="handleAddSelect(item)"
+                    ></span>
+                  </div>
+                </template>
+              </VueDraggable>
+            </el-tab-pane>
+          </el-tabs>
+        </div>
+      </div>
+      <div class="right-select-columns">
+        <div class="title">Selected fields on report template list</div>
+        <VueDraggable
+          v-vloading="loading"
+          v-model="selectColumns"
+          class="column-list"
+          ghost-class="ghost-column"
+          :forceFallback="true"
+          fallback-class="fallback-class"
+          group="customizeColumns"
+          item-key="field"
+          @end="handleRightRemove"
+        >
+          <template v-for="(item, index) in selectColumns" :key="item.field">
+            <div
+              class="column-item"
+              @mouseenter="hoverSelectIcon = item.field"
+              @mouseleave="hoverSelectIcon = ''"
+            >
+              <span
+                class="font_family icon-icon_dragsort__b draggable-icon"
+                style="font-size: 16px"
+              ></span>
+              <span class="title">{{ item.label }}</span>
+              <span
+                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
+                class="font_family icon-icon_moveup_b move-icon"
+                @click="handleMoveUpSelect(item)"
+              ></span>
+              <span
+                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
+                class="font_family icon-icon_movedown_b move-icon"
+                @click="handleMoveDownSelect(item)"
+              ></span>
+              <span
+                ref="step2"
+                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
+                class="font_family icon-icon_reduce_b move-icon"
+                @click="handleDeleteSelect(item)"
+              ></span>
+            </div>
+          </template>
+        </VueDraggable>
+      </div>
+    </div>
+    <template #footer>
+      <el-button
+        type="default"
+        style="height: 40px; padding: 8px 40px"
+        @click="dialogVisible = false"
+        >Cancel</el-button
+      >
+      <el-button type="default" style="height: 40px; padding: 8px 20px" @click="handleReset"
+        >Reset to default</el-button
+      >
+      <el-button
+        class="el-button--dark"
+        style="height: 40px; padding: 8px 40px"
+        @click="handleApply"
+      >
+        Apply
+      </el-button>
+    </template>
+    <el-tour
+      :target-area-clickable="false"
+      class="step1-tour"
+      v-model="open1"
+      :mask="false"
+      type="primary"
+      v-if="step1?.[0]"
+    >
+      <el-tour-step :show-close="false" :target="step1?.[0]">
+        <template #default>
+          <div class="description">
+            <span>Drag</span> items to the right group or click the "<span>Add</span>" icon to add
+            columns to the {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list.
+          </div>
+          <div class="got-it-text" @click="handleCloseTour('step1')">Got it</div>
+        </template>
+      </el-tour-step>
+    </el-tour>
+    <el-tour
+      :target-area-clickable="false"
+      class="step2-tour"
+      v-model="open2"
+      type="primary"
+      :mask="false"
+      v-if="step2?.[0]"
+    >
+      <el-tour-step :show-close="false" :target="step2?.[0]">
+        <template #default>
+          <div class="description">
+            <span>Drag</span> items to the left group or click the "<span>Remove</span>" icon to
+            delete columns from the
+            {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list.
+          </div>
+          <div class="description">
+            <span>Drag</span> items up or down to reorder the
+            {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list, or use the "<span
+              >Move up</span
+            >" and "<span>Move down</span>" icons.
+          </div>
+          <div class="got-it-text" @click="handleCloseTour('step2')">Got it</div>
+        </template>
+      </el-tour-step>
+    </el-tour>
+  </el-dialog>
+</template>
+
+<style lang="scss">
+.customize-columns {
+  .search-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 8px;
+    padding: 10px 0;
+
+    .search-input {
+      width: 50%;
+      padding-right: 16px;
+    }
+
+    .tips {
+      display: flex;
+      align-items: flex-start;
+      gap: 3px;
+      width: 50%;
+      padding-left: 5px;
+      vertical-align: middle;
+
+      span {
+        font-size: 12px;
+        color: var(--color-neutral-2);
+      }
+    }
+  }
+
+  .draggable-list {
+    display: flex;
+    user-select: none;
+    gap: 8px;
+  }
+}
+
+.right-select-columns,
+.left-all-columns {
+  width: 50%;
+
+  .column-list {
+    height: 400px;
+    overflow: auto;
+
+    .column-item {
+      display: flex;
+      align-items: center;
+      height: 40px;
+      margin-bottom: 5px;
+      padding-left: 12px;
+      border: 1px solid var(--color-border);
+      border-radius: 6px;
+      background-color: var(--color-customize-column-item-bg);
+
+      &:hover {
+        background-color: var(--color-customize-column-item-hover-bg);
+        box-shadow: 4px 4px 32px 0px rgba(0, 0, 0, 0.1);
+      }
+
+      & > .title {
+        flex: 1;
+      }
+
+      span.draggable-icon {
+        margin-right: 12px;
+        color: var(--color-customize-column-item-drag-icon);
+      }
+
+      .font_family {
+        font-size: 16px;
+        cursor: pointer;
+        margin-right: 16px;
+      }
+
+      .move-icon {
+        &:hover {
+          color: var(--color-theme);
+        }
+      }
+    }
+  }
+
+  .ghost-column {
+    cursor: move !important;
+    span {
+      opacity: 0;
+    }
+    border: 1px dashed var(--color-customize-column-item-drag-border) !important;
+    background-color: var(--color-customize-column-item-drag-bg) !important;
+    box-shadow: none !important;
+  }
+
+  .fallback-class {
+    opacity: 1 !important;
+    background-color: var(--color-customize-column-item-hover-bg) !important;
+    cursor: move !important;
+  }
+}
+
+.left-all-columns {
+  border: 1px solid var(--color-border);
+  border-radius: 12px;
+
+  .tabs {
+    position: relative;
+    height: 100%;
+
+    .el-tabs {
+      .el-tabs__header {
+        margin-bottom: 0px;
+        border-bottom: 1px solid var(--color-customize-column-tabs-header-border);
+      }
+
+      .el-tabs__item {
+        padding: 10px;
+      }
+    }
+  }
+
+  .column-list {
+    padding: 8px;
+    padding-bottom: 0px;
+  }
+
+  .search-select-item {
+    border: 1px solid var(--color-theme) !important;
+    box-shadow: 2px 2px 12px 0px rgba(237, 109, 0, 0.2);
+
+    .title {
+      color: var(--color-theme) !important;
+    }
+  }
+}
+
+.right-select-columns {
+  background-color: var(--color-customize-column-right-section-bg);
+  padding-top: 0;
+  border: 1px dashed var(--color-customize-column-right-section-border);
+  border-radius: 12px;
+
+  & > .title {
+    height: 40px;
+    padding: 8px;
+    line-height: 24px;
+    font-size: 16px;
+    font-weight: 700;
+  }
+
+  .column-list {
+    padding: 8px;
+    padding-bottom: 0px;
+  }
+}
+</style>
+<style lang="scss">
+.left-all-columns {
+  .el-tabs__nav-prev,
+  .el-tabs__nav-next {
+    height: 40px;
+    width: 40px;
+  }
+
+  .el-tabs__item {
+    color: var(--color-neutral-1);
+    font-weight: 400;
+    font-size: 14px;
+  }
+
+  .el-tabs__item.is-active,
+  .el-tabs__item:hover {
+    font-weight: 700;
+    font-size: 14px;
+    color: var(--color-neutral-1);
+  }
+
+  .el-tabs__nav-prev {
+    border-right: 1px solid var(--color-border);
+    box-shadow: 2px 0px 12px rgba(0, 0, 0, 0.3);
+    // .el-icon {
+    //   color: white;
+    // }
+    /* 左侧阴影 */
+  }
+
+  .el-tabs__nav-next {
+    border-left: 1px solid var(--color-border);
+    box-shadow: -2px 0px 12px rgba(0, 0, 0, 0.2);
+    /* 左侧阴影 */
+  }
+
+  .el-tabs__nav-wrap {
+    padding: 0 40px;
+  }
+
+  .el-tabs__item.is-active,
+  .el-tabs__item:hover {
+    color: var(--color-theme);
+  }
+
+  .el-tabs__active-bar {
+    background-color: var(--color-theme);
+  }
+}
+
+.search-header {
+  & > .search-input {
+    .el-select {
+      width: 100%;
+
+      .el-select__wrapper {
+        border-radius: 20px;
+      }
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.step1-tour {
+  .el-tour__content {
+    width: 240px;
+    height: 124px;
+    background-color: var(--color-theme);
+    z-index: 9999 !important;
+  }
+
+  .el-tour__arrow {
+    background-color: var(--color-theme);
+  }
+
+  .el-tour__footer {
+    display: none;
+  }
+}
+
+.step2-tour {
+  .el-tour__content {
+    width: 240px;
+    height: 200px;
+    background-color: var(--color-theme);
+    z-index: 9999 !important;
+  }
+
+  .el-tour__arrow {
+    background-color: var(--color-theme);
+  }
+
+  .el-tour__footer {
+    display: none;
+  }
+}
+
+.step1-tour,
+.step2-tour {
+  .el-tour__header {
+    display: none;
+  }
+
+  .description {
+    margin-bottom: 16px;
+    color: white;
+    line-height: 22px;
+
+    span {
+      color: white;
+      font-weight: 600;
+    }
+  }
+
+  .got-it-text {
+    float: right;
+    color: white;
+    font-weight: 700;
+    cursor: pointer;
+  }
+}
+</style>

+ 52 - 207
src/views/TemplateManagement/src/components/TableView/src/TableView.vue

@@ -1,11 +1,10 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { ref, nextTick, onMounted } from 'vue'
 import { ref, nextTick, onMounted } from 'vue'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
-import DownloadDialog from './components/DownloadDialog.vue'
 import { autoWidth } from '@/utils/table'
 import { autoWidth } from '@/utils/table'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
-import { formatTimezone, formatNumber } from '@/utils/tools'
+import { formatTimezone } from '@/utils/tools'
 import { useRouter } from 'vue-router'
 import { useRouter } from 'vue-router'
 
 
 const router = useRouter()
 const router = useRouter()
@@ -17,27 +16,56 @@ const props = defineProps({
 })
 })
 
 
 const tableOriginColumnsField = ref()
 const tableOriginColumnsField = ref()
-const handleColumns = (columns: any, status?: string) => {
+const tableColumns = [
+  {
+    title: 'Report Name',
+    type: 'normal',
+    field: 'name'
+  },
+  {
+    title: 'Report Level',
+    type: 'normal',
+    field: 'level'
+  },
+  {
+    title: 'Is Active',
+    type: 'status',
+    field: 'is_active'
+  },
+  {
+    title: 'Application Scope',
+    type: 'normal',
+    field: 'access_type'
+  },
+  {
+    title: 'Creation Date',
+    type: 'normal',
+    field: 'creation_time',
+    formatter: 'dateTime',
+    sortable: true
+  }
+]
+const handleColumns = (columns: any) => {
   const newColumns = columns.map((item: any) => {
   const newColumns = columns.map((item: any) => {
     let curColumn: any = {
     let curColumn: any = {
       title: item.title,
       title: item.title,
       field: item.field,
       field: item.field,
-      sortable: true,
+      sortable: item.sortable || false,
       minWidth: 120,
       minWidth: 120,
       showOverflow: true
       showOverflow: true
     }
     }
     // 设置插槽
     // 设置插槽
-    if (item.type === 'status' && status !== 'all') {
+    if (item.type === 'status') {
       curColumn = {
       curColumn = {
         ...curColumn,
         ...curColumn,
         slots: { default: 'status' }
         slots: { default: 'status' }
       }
       }
-    } else if (item.type === 'link' && status !== 'all') {
+    } else if (item.type === 'link') {
       curColumn = {
       curColumn = {
         ...curColumn,
         ...curColumn,
         slots: { default: 'link' }
         slots: { default: 'link' }
       }
       }
-    } else if (item.type === 'mode' && status !== 'all') {
+    } else if (item.type === 'mode') {
       curColumn = {
       curColumn = {
         ...curColumn,
         ...curColumn,
         slots: { default: 'mode' },
         slots: { default: 'mode' },
@@ -60,40 +88,18 @@ const handleColumns = (columns: any, status?: string) => {
 
 
 // 获取表格列
 // 获取表格列
 const getTableColumns = async () => {
 const getTableColumns = async () => {
-  tableLoadingColumn.value = true
-  await $api.getAIApiLogTableColumn().then((res: any) => {
-    if (res.code === 200) {
-      tableData.value.columns = [
-        { title: 'Action', width: 116, fixed: 'left', slots: { default: 'action' } },
-        ...handleColumns(res.data.OperationTableColumns)
-      ]
-      tableOriginColumnsField.value = res.data.OperationTableColumns
-    }
-  })
-  nextTick(() => {
-    tableRef.value && autoWidth(tableData.value, tableRef.value)
-    tableLoadingColumn.value = false
-    selectedNumber.value = 0
-    selectedTableData.value = []
-  })
+  tableData.value.columns = [
+    { title: 'Action', width: 116, fixed: 'left', slots: { default: 'action' } },
+    ...handleColumns(tableColumns)
+  ]
+  // tableRef.value && autoWidth(tableData.value, tableRef.value)
 }
 }
 
 
 const pageInfo = ref({ pageNo: 1, pageSize: 20, total: 0 })
 const pageInfo = ref({ pageNo: 1, pageSize: 20, total: 0 })
-const tempSearch = ref()
 // 获得表格数据后赋值
 // 获得表格数据后赋值
 const assignTableData = (data: any) => {
 const assignTableData = (data: any) => {
   tableData.value.data = data.searchData || []
   tableData.value.data = data.searchData || []
   pageInfo.value.total = Number(data.rc) || 0
   pageInfo.value.total = Number(data.rc) || 0
-  tempSearch.value = data.tmp_search
-  // 拥有所有字段的表格
-  setTimeout(() => {
-    allTable.value.columns = handleColumns(tableData.value.columns, 'all')
-    allTable.value.data = data.searchData || []
-    // 为了让导出的表格列宽度自适应
-    nextTick(() => {
-      allTableRef.value && autoWidth(allTable.value, allTableRef.value)
-    })
-  }, 1000)
 }
 }
 
 
 let searchdata: any = {}
 let searchdata: any = {}
@@ -102,7 +108,7 @@ const getTableData = async (isPageChange?: boolean) => {
   const rc = isPageChange ? pageInfo.value.total : -1
   const rc = isPageChange ? pageInfo.value.total : -1
   tableLoadingTableData.value = true
   tableLoadingTableData.value = true
   await $api
   await $api
-    .getAIApiLogTableData({
+    .getReportTemplateManagementTable({
       cp: pageInfo.value.pageNo,
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       ps: pageInfo.value.pageSize,
       rc,
       rc,
@@ -114,19 +120,17 @@ const getTableData = async (isPageChange?: boolean) => {
       }
       }
     })
     })
     .finally(() => {
     .finally(() => {
-      selectedNumber.value = 0
-      selectedTableData.value = []
       nextTick(() => {
       nextTick(() => {
-        tableRef.value && autoWidth(tableData.value, tableRef.value)
+        // tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
         tableLoadingTableData.value = false
       })
       })
     })
     })
 }
 }
-const SearchOperationLog = (val: any) => {
+const searchTableData = (val: any) => {
   searchdata = val
   searchdata = val
   tableLoadingTableData.value = true
   tableLoadingTableData.value = true
   $api
   $api
-    .getAIApiLogTableData({
+    .getReportTemplateManagementTable({
       cp: pageInfo.value.pageNo,
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       ps: pageInfo.value.pageSize,
       rc: -1,
       rc: -1,
@@ -138,19 +142,16 @@ const SearchOperationLog = (val: any) => {
       }
       }
     })
     })
     .finally(() => {
     .finally(() => {
-      selectedNumber.value = 0
-      selectedTableData.value = []
       nextTick(() => {
       nextTick(() => {
-        tableRef.value && autoWidth(tableData.value, tableRef.value)
+        // tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
         tableLoadingTableData.value = false
       })
       })
     })
     })
 }
 }
 onMounted(() => {
 onMounted(() => {
-  //
   Promise.all([getTableColumns(), getTableData(false)]).finally(() => {
   Promise.all([getTableColumns(), getTableData(false)]).finally(() => {
     nextTick(() => {
     nextTick(() => {
-      tableRef.value && autoWidth(tableData.value, tableRef.value)
+      // tableRef.value && autoWidth(tableData.value, tableRef.value)
     })
     })
   })
   })
 })
 })
@@ -229,137 +230,13 @@ const tableData = ref<VxeGridProps<any>>({
     modes: ['current', 'selected', 'all']
     modes: ['current', 'selected', 'all']
   }
   }
 })
 })
-const allTableRef = ref<VxeGridInstance>()
-const allTable = ref<VxeGridProps<any>>({
-  columns: [],
-  data: [],
-  showHeaderOverflow: true,
-  showOverflow: true,
-  scrollY: { enabled: true, oSize: 5, gt: 2 },
-  scrollX: { enabled: true, gt: 2 },
-  exportConfig: {
-    types: ['csv', 'html', 'txt', 'xlsx'],
-    modes: ['current', 'selected', 'all']
-  }
-})
 
 
 // 实现行点击样式
 // 实现行点击样式
 useRowClickStyle(tableRef)
 useRowClickStyle(tableRef)
 
 
-const downloadDialogRef = ref()
-const handleDownload = () => {
-  const curSelectedColumns: string[] = []
-  tableRef.value?.columns?.forEach((item: any) => {
-    if (item.field) {
-      curSelectedColumns.push(item.title)
-    }
-  })
-  downloadDialogRef.value.openDialog(
-    curSelectedColumns,
-    selectedNumber.value || pageInfo.value.total
-  )
-}
-
-const exportLoading = ref(false)
-// 获取导出表格数据
-const getExportTableData = (status: number) => {
-  // 如果有选中表格行数据,那么只到处选中的数据
-  if (selectedNumber.value > 0) {
-    exportTable(status)
-    return
-  }
-  exportLoading.value = true
-  const buildColumnString = (columns: any[]): string => {
-    return columns
-      .filter((item) => item.field)
-      .map((item) => item.title)
-      .join(',')
-  }
-
-  let column = ''
-  if (status === 1) {
-    column = buildColumnString(tableData.value.columns)
-  } else {
-    column = buildColumnString(allTable.value.columns)
-  }
-  $api
-    .getAIApiLogAllTableData({
-      selected_fields: column,
-      tmp_search: tempSearch.value
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        allTable.value.data = res.data.Data || []
-        nextTick(() => {
-          exportLoading.value = false
-          // 导出数据
-          exportTable(status)
-        })
-      }
-    })
-    .finally(() => {
-      exportLoading.value = false
-    })
-}
-// 导出表格 status: 1 导出当前表格 2 导出所有字段表格
-const exportTable = (status: number) => {
-  const exportConfig: any = {
-    type: 'xlsx',
-    message: false,
-    filename: `AI API Log_${dayjs().format('YYYYMMDDHH[h]mm[m]ss[s]')}`
-  }
-  if (status === 1) {
-    exportConfig.columnFilterMethod = ({ column }: any) => {
-      const index = tableData.value.columns.findIndex((item: any) => item.field === column.field)
-      // 排除复选框列
-      return column.field && index !== -1
-    }
-    exportConfig.columns = tableData.value.columns
-  }
-  if (selectedNumber.value > 0) {
-    exportConfig.dataFilterMethod = ({ row }: any) => {
-      const index = selectedTableData.value.findIndex(
-        (item: any) => item._X_ROW_KEY === row._X_ROW_KEY
-      )
-      return index !== -1
-    }
-  }
-  allTableRef.value?.exportData(exportConfig)
-}
-
 const tableLoadingColumn = ref(false)
 const tableLoadingColumn = ref(false)
 const tableLoadingTableData = ref(false)
 const tableLoadingTableData = ref(false)
 
 
-const selectedNumber = ref(0)
-const selectedTableData = ref([])
-// 复选框选中事件
-const handleCheckboxChange = ({ records }: any) => {
-  selectedNumber.value = records.length
-  selectedTableData.value = records
-}
-const handleCheckAllChange = ({ records }: any) => {
-  selectedNumber.value = records.length
-  selectedTableData.value = records
-}
-
-const logDialogRef = ref()
-const logLoading = ref(false)
-const handleLinkClick = (row) => {
-  logLoading.value = true
-  $api
-    .getAIApiLogDialog({
-      request_id: row['Request ID']
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        logLoading.value = false
-        const data = res.data.Data
-        // 打开日志详情对话框
-        logDialogRef.value.openDialog(data.request_content, data.ai_response_content)
-      }
-    })
-}
-
 const handleCreate = () => {
 const handleCreate = () => {
   router.push({
   router.push({
     name: 'Create Report Template'
     name: 'Create Report Template'
@@ -367,26 +244,18 @@ const handleCreate = () => {
 }
 }
 
 
 defineExpose({
 defineExpose({
-  SearchOperationLog
+  searchTableData
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
-  <div
-    class="table-box"
-    v-loading.fullscreen.lock="exportLoading"
-    element-loading-text="Loading..."
-    element-loading-custom-class="element-loading"
-    element-loading-background="rgb(43, 47, 54, 0.7)"
-  >
+  <div class="table-box">
     <vxe-grid
     <vxe-grid
       ref="tableRef"
       ref="tableRef"
       v-vloading="tableLoadingTableData || tableLoadingColumn"
       v-vloading="tableLoadingTableData || tableLoadingColumn"
       :height="props.height"
       :height="props.height"
       :style="{ border: 'none' }"
       :style="{ border: 'none' }"
       v-bind="tableData"
       v-bind="tableData"
-      @checkbox-change="handleCheckboxChange"
-      @checkbox-all="handleCheckAllChange"
     >
     >
       <!-- action操作栏的插槽 -->
       <!-- action操作栏的插槽 -->
       <template #action="{ row }">
       <template #action="{ row }">
@@ -427,6 +296,10 @@ defineExpose({
           ></span>
           ></span>
         </el-button>
         </el-button>
       </template>
       </template>
+      <!-- Status字段的插槽 -->
+      <template #status="{ row, column }">
+        <VTag :type="row[column.field]">{{ row[column.field] }}</VTag>
+      </template>
       <!-- 空数据时的插槽 -->
       <!-- 空数据时的插槽 -->
       <template #empty v-if="!tableLoadingTableData && tableData.data.length === 0">
       <template #empty v-if="!tableLoadingTableData && tableData.data.length === 0">
         <div class="empty-box">
         <div class="empty-box">
@@ -436,35 +309,7 @@ defineExpose({
           <p>Click the "Create New Report Template" button to add a report template.</p>
           <p>Click the "Create New Report Template" button to add a report template.</p>
         </div>
         </div>
       </template>
       </template>
-      <template #link="{ row, column }">
-        <span style="color: var(--color-theme); cursor: pointer" @click="handleLinkClick(row)">
-          {{ row[column.field] }}
-        </span>
-      </template>
     </vxe-grid>
     </vxe-grid>
-    <vxe-grid :height="10" ref="allTableRef" class="all-table" v-bind="allTable"> </vxe-grid>
-    <div class="bottom-pagination">
-      <div class="left-total-records">Total {{ formatNumber(pageInfo.total) }}</div>
-      <div class="right-pagination">
-        <el-pagination
-          v-model:current-page="pageInfo.pageNo"
-          v-model:page-size="pageInfo.pageSize"
-          :page-sizes="[20, 50, 100, 150]"
-          :pager-count="3"
-          background
-          layout="sizes, prev, pager, next"
-          :total="pageInfo.total"
-          @size-change="getTableData(true)"
-          @current-change="getTableData(true)"
-        />
-      </div>
-    </div>
-    <DownloadDialog
-      @export="getExportTableData"
-      :isHideSelectColumn="true"
-      ref="downloadDialogRef"
-    />
-    <LogDialog ref="logDialogRef" />
   </div>
   </div>
 </template>
 </template>
 
 

+ 0 - 196
src/views/TemplateManagement/src/components/TableView/src/components/DownloadDialog.vue

@@ -1,196 +0,0 @@
-<script setup lang="ts">
-const props = withDefaults(
-  defineProps<{
-    isHideSelectColumn: boolean
-  }>(),
-  { isHideSelectColumn: false }
-)
-const dialogVisible = ref(false)
-
-const openDialog = (selectedColumns: string[], slectedDataNumber: number) => {
-  selectedDataNumber.value = slectedDataNumber
-  columns.value = selectedColumns
-  dialogVisible.value = true
-}
-
-const isShowSelectColumn = ref(false)
-
-const downloadFilter = ref(1)
-const selectedDataNumber = ref(0)
-
-const columns = ref()
-
-const emits = defineEmits<{ export: [number] }>()
-const handleDownload = () => {
-  emits('export', downloadFilter.value)
-}
-
-const clearData = () => {
-  isShowSelectColumn.value = false
-  downloadFilter.value = 1
-}
-
-defineExpose({
-  openDialog,
-  handleDownload
-})
-</script>
-
-<template>
-  <div>
-    <el-dialog @close="clearData" v-model="dialogVisible" title="Download File" width="540">
-      <div class="download-dialog">
-        <div class="select-data">
-          <div style="display: inline-block">
-            Select data on your Opeartion Log list:<span style="color: var(--color-theme)">{{
-              selectedDataNumber
-            }}</span>
-          </div>
-        </div>
-        <div class="download-filter" v-if="!props.isHideSelectColumn">
-          <el-radio-group v-model="downloadFilter">
-            <el-radio :value="1"
-              >Download with selected columns
-              <span class="column-number">{{ columns.length }}</span>
-              <SeeAllIcon v-model="isShowSelectColumn" />
-            </el-radio>
-            <div
-              v-if="isShowSelectColumn"
-              class="select-columns"
-              :class="{ show: isShowSelectColumn }"
-            >
-              <div class="title">Selected columns</div>
-              <div class="content">
-                <div class="column-item" v-for="item in columns" :key="item">{{ item }}</div>
-              </div>
-            </div>
-            <el-radio :value="2">Download with all columns</el-radio>
-          </el-radio-group>
-        </div>
-      </div>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button class="cancel-btn" type="default" @click="dialogVisible = false"
-            >Cancel</el-button
-          >
-          <el-button class="download-btn el-button--dark" @click="handleDownload"
-            ><span style="margin-right: 8px" class="font_family icon-icon_download_b"></span>
-            Download</el-button
-          >
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<style lang="scss" scoped>
-.download-dialog {
-  color: var(--color-neutral-1);
-}
-
-.select-data {
-  font-weight: 700;
-}
-
-.data-filter {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 8px;
-  max-height: 120px;
-  margin-top: 8px;
-  overflow: auto;
-
-  .filter-item {
-    height: 22px;
-    padding: 0px 8px;
-    background-color: var(--color-download-file-filter-tag-bg);
-    border-radius: 12px;
-    line-height: 22px;
-    font-size: 12px;
-  }
-}
-
-.download-filter {
-  margin-top: 16px;
-
-  .el-radio-group {
-    display: flex;
-    flex-direction: column;
-    align-items: flex-start;
-
-    .el-radio {
-      height: 40px;
-      align-items: center;
-    }
-
-    :deep(.el-radio__label) {
-      margin-top: 2px;
-      font-weight: 700;
-      color: var(--color-neutral-1);
-    }
-
-    .column-number {
-      padding: 3px 5px;
-      background-color: var(--color-theme);
-      border-radius: 12px;
-      font-size: 12px;
-      font-weight: 700;
-      color: #fff;
-    }
-
-    .see-all-btn {
-      margin-left: 8px;
-      color: var(--color-theme);
-      font-size: 12px;
-    }
-
-    .select-columns {
-      max-height: 350px;
-      padding: 8px;
-      margin-top: 8px;
-      background-color: var(--color-dialog-header-bg);
-      border-radius: 6px;
-      overflow: hidden;
-
-      &.show {
-        max-height: 500px;
-      }
-
-      .title {
-        font-size: 12px;
-        font-weight: 700;
-      }
-
-      .content {
-        display: flex;
-        flex-wrap: wrap;
-        margin-top: 8px;
-        gap: 8px;
-
-        .column-item {
-          height: 22px;
-          padding: 0px 8px;
-          background-color: var(--color-download-file-selected-column-tag-bg);
-          line-height: 22px;
-          border-radius: 12px;
-          font-size: 12px;
-        }
-      }
-    }
-  }
-}
-
-.dialog-footer {
-  .el-button {
-    height: 40px;
-  }
-
-  .cancel-btn {
-    width: 115px;
-  }
-
-  .download-btn {
-    width: 136px;
-  }
-}
-</style>