|
@@ -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>
|